mirror of https://github.com/WerWolv/ImHex.git
patterns: Added continue and break statements to arrays of structs
This commit is contained in:
parent
3ce0f8f4a8
commit
0884025b82
|
@ -561,7 +561,10 @@ namespace hex::pl {
|
||||||
for (auto &statement : other.m_body)
|
for (auto &statement : other.m_body)
|
||||||
this->m_body.push_back(statement->clone());
|
this->m_body.push_back(statement->clone());
|
||||||
|
|
||||||
this->m_postExpression = other.m_postExpression->clone();
|
if (other.m_postExpression != nullptr)
|
||||||
|
this->m_postExpression = other.m_postExpression->clone();
|
||||||
|
else
|
||||||
|
this->m_postExpression = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ASTNode* clone() const override {
|
[[nodiscard]] ASTNode* clone() const override {
|
||||||
|
@ -974,6 +977,13 @@ namespace hex::pl {
|
||||||
evaluator->handleAbort();
|
evaluator->handleAbort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto discardEntry = [&] {
|
||||||
|
delete entries.back();
|
||||||
|
entries.pop_back();
|
||||||
|
entryIndex--;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
if (this->m_size != nullptr) {
|
if (this->m_size != nullptr) {
|
||||||
auto sizeNode = this->m_size->evaluate(evaluator);
|
auto sizeNode = this->m_size->evaluate(evaluator);
|
||||||
ON_SCOPE_EXIT { delete sizeNode; };
|
ON_SCOPE_EXIT { delete sizeNode; };
|
||||||
|
@ -990,9 +1000,18 @@ namespace hex::pl {
|
||||||
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
||||||
|
|
||||||
for (u64 i = 0; i < entryCount; i++) {
|
for (u64 i = 0; i < entryCount; i++) {
|
||||||
auto pattern = this->m_type->createPatterns(evaluator).front();
|
auto patterns = this->m_type->createPatterns(evaluator);
|
||||||
|
|
||||||
addEntry(pattern);
|
if (!patterns.empty())
|
||||||
|
addEntry(patterns.front());
|
||||||
|
|
||||||
|
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
|
||||||
|
if (ctrlFlow == ControlFlowStatement::Break)
|
||||||
|
break;
|
||||||
|
else if (ctrlFlow == ControlFlowStatement::Continue) {
|
||||||
|
discardEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) {
|
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) {
|
||||||
while (whileStatement->evaluateCondition(evaluator)) {
|
while (whileStatement->evaluateCondition(evaluator)) {
|
||||||
|
@ -1000,9 +1019,18 @@ namespace hex::pl {
|
||||||
if (entryIndex > limit)
|
if (entryIndex > limit)
|
||||||
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
||||||
|
|
||||||
auto pattern = this->m_type->createPatterns(evaluator).front();
|
auto patterns = this->m_type->createPatterns(evaluator);
|
||||||
|
|
||||||
addEntry(pattern);
|
if (!patterns.empty())
|
||||||
|
addEntry(patterns.front());
|
||||||
|
|
||||||
|
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
|
||||||
|
if (ctrlFlow == ControlFlowStatement::Break)
|
||||||
|
break;
|
||||||
|
else if (ctrlFlow == ControlFlowStatement::Continue) {
|
||||||
|
discardEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1011,26 +1039,39 @@ namespace hex::pl {
|
||||||
if (entryIndex > limit)
|
if (entryIndex > limit)
|
||||||
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this);
|
||||||
|
|
||||||
auto pattern = this->m_type->createPatterns(evaluator).front();
|
auto patterns = this->m_type->createPatterns(evaluator);
|
||||||
std::vector<u8> buffer(pattern->getSize());
|
|
||||||
|
|
||||||
if (evaluator->dataOffset() >= evaluator->getProvider()->getActualSize() - buffer.size()) {
|
if (!patterns.empty()) {
|
||||||
delete pattern;
|
auto pattern = patterns.front();
|
||||||
LogConsole::abortEvaluation("reached end of file before finding end of unsized array", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntry(pattern);
|
std::vector<u8> buffer(pattern->getSize());
|
||||||
|
|
||||||
evaluator->getProvider()->read(evaluator->dataOffset() - pattern->getSize(), buffer.data(), buffer.size());
|
if (evaluator->dataOffset() >= evaluator->getProvider()->getActualSize() - buffer.size()) {
|
||||||
bool reachedEnd = true;
|
delete pattern;
|
||||||
for (u8 &byte : buffer) {
|
LogConsole::abortEvaluation("reached end of file before finding end of unsized array", this);
|
||||||
if (byte != 0x00) {
|
|
||||||
reachedEnd = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (reachedEnd) break;
|
addEntry(pattern);
|
||||||
|
|
||||||
|
auto ctrlFlow = evaluator->getCurrentControlFlowStatement();
|
||||||
|
if (ctrlFlow == ControlFlowStatement::Break)
|
||||||
|
break;
|
||||||
|
else if (ctrlFlow == ControlFlowStatement::Continue) {
|
||||||
|
discardEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluator->getProvider()->read(evaluator->dataOffset() - pattern->getSize(), buffer.data(), buffer.size());
|
||||||
|
bool reachedEnd = true;
|
||||||
|
for (u8 &byte : buffer) {
|
||||||
|
if (byte != 0x00) {
|
||||||
|
reachedEnd = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reachedEnd) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2044,7 +2085,11 @@ namespace hex::pl {
|
||||||
|
|
||||||
ASTNodeControlFlowStatement(const ASTNodeControlFlowStatement &other) : ASTNode(other) {
|
ASTNodeControlFlowStatement(const ASTNodeControlFlowStatement &other) : ASTNode(other) {
|
||||||
this->m_type = other.m_type;
|
this->m_type = other.m_type;
|
||||||
this->m_rvalue = other.m_rvalue->clone();
|
|
||||||
|
if (other.m_rvalue != nullptr)
|
||||||
|
this->m_rvalue = other.m_rvalue->clone();
|
||||||
|
else
|
||||||
|
this->m_rvalue = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ASTNode* clone() const override {
|
[[nodiscard]] ASTNode* clone() const override {
|
||||||
|
@ -2059,6 +2104,13 @@ namespace hex::pl {
|
||||||
return this->m_rvalue;
|
return this->m_rvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
|
||||||
|
|
||||||
|
this->execute(evaluator);
|
||||||
|
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
FunctionResult execute(Evaluator *evaluator) const override {
|
FunctionResult execute(Evaluator *evaluator) const override {
|
||||||
auto returnValue = this->getReturnValue();
|
auto returnValue = this->getReturnValue();
|
||||||
|
|
||||||
|
|
|
@ -880,6 +880,10 @@ namespace hex::pl {
|
||||||
return parseConditional();
|
return parseConditional();
|
||||||
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
||||||
throwParseError("unexpected end of program", -2);
|
throwParseError("unexpected end of program", -2);
|
||||||
|
else if (MATCHES(sequence(KEYWORD_BREAK)))
|
||||||
|
member = new ASTNodeControlFlowStatement(ControlFlowStatement::Break, nullptr);
|
||||||
|
else if (MATCHES(sequence(KEYWORD_CONTINUE)))
|
||||||
|
member = new ASTNodeControlFlowStatement(ControlFlowStatement::Continue, nullptr);
|
||||||
else
|
else
|
||||||
throwParseError("invalid struct member", 0);
|
throwParseError("invalid struct member", 0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue