patterns: Added for loops
This commit is contained in:
parent
69ca14bf46
commit
ec9715f326
@ -2051,7 +2051,7 @@ namespace hex::pl {
|
||||
class ASTNodeCompoundStatement : public ASTNode {
|
||||
public:
|
||||
|
||||
ASTNodeCompoundStatement(std::vector<ASTNode*> statements) : m_statements(std::move(statements)) {
|
||||
ASTNodeCompoundStatement(std::vector<ASTNode*> statements, bool newScope = false) : m_statements(std::move(statements)), m_newScope(newScope) {
|
||||
|
||||
}
|
||||
|
||||
@ -2096,17 +2096,37 @@ namespace hex::pl {
|
||||
FunctionResult execute(Evaluator *evaluator) override {
|
||||
FunctionResult result;
|
||||
|
||||
auto variables = *evaluator->getScope(0).scope;
|
||||
u32 startVariableCount = variables.size();
|
||||
|
||||
if (this->m_newScope) {
|
||||
evaluator->pushScope(nullptr, variables);
|
||||
}
|
||||
|
||||
for (const auto &statement : this->m_statements) {
|
||||
result = statement->execute(evaluator);
|
||||
if (result.first)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (this->m_newScope) {
|
||||
s64 stackSize = evaluator->getStack().size();
|
||||
for (u32 i = startVariableCount; i < variables.size(); i++) {
|
||||
stackSize--;
|
||||
delete variables[i];
|
||||
}
|
||||
if (stackSize < 0) LogConsole::abortEvaluation("stack pointer underflow!", this);
|
||||
evaluator->getStack().resize(stackSize);
|
||||
|
||||
evaluator->popScope();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<ASTNode*> m_statements;
|
||||
bool m_newScope;
|
||||
};
|
||||
|
||||
};
|
@ -90,12 +90,14 @@ namespace hex::pl {
|
||||
ASTNode* parseMathematicalExpression();
|
||||
|
||||
ASTNode* parseFunctionDefinition();
|
||||
ASTNode* parseFunctionVariableDecl();
|
||||
ASTNode* parseFunctionStatement();
|
||||
ASTNode* parseFunctionVariableAssignment();
|
||||
ASTNode* parseFunctionReturnStatement();
|
||||
std::vector<ASTNode*> parseStatementBody();
|
||||
ASTNode* parseFunctionConditional();
|
||||
ASTNode* parseFunctionWhileLoop();
|
||||
ASTNode* parseFunctionForLoop();
|
||||
|
||||
void parseAttribute(Attributable *currNode);
|
||||
ASTNode* parseConditional();
|
||||
|
@ -37,6 +37,7 @@ namespace hex::pl {
|
||||
Parent,
|
||||
This,
|
||||
While,
|
||||
For,
|
||||
Function,
|
||||
Return,
|
||||
Namespace
|
||||
@ -280,6 +281,7 @@ namespace hex::pl {
|
||||
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
||||
#define KEYWORD_THIS COMPONENT(Keyword, This)
|
||||
#define KEYWORD_WHILE COMPONENT(Keyword, While)
|
||||
#define KEYWORD_FOR COMPONENT(Keyword, For)
|
||||
#define KEYWORD_FUNCTION COMPONENT(Keyword, Function)
|
||||
#define KEYWORD_RETURN COMPONENT(Keyword, Return)
|
||||
#define KEYWORD_NAMESPACE COMPONENT(Keyword, Namespace)
|
||||
|
@ -408,6 +408,8 @@ namespace hex::pl {
|
||||
tokens.emplace_back(TOKEN(Keyword, This));
|
||||
else if (identifier == "while")
|
||||
tokens.emplace_back(TOKEN(Keyword, While));
|
||||
else if (identifier == "for")
|
||||
tokens.emplace_back(TOKEN(Keyword, For));
|
||||
else if (identifier == "fn")
|
||||
tokens.emplace_back(TOKEN(Keyword, Function));
|
||||
else if (identifier == "return")
|
||||
|
@ -470,6 +470,26 @@ namespace hex::pl {
|
||||
return create(new ASTNodeFunctionDefinition(getNamespacePrefixedName(functionName), params, body));
|
||||
}
|
||||
|
||||
ASTNode* Parser::parseFunctionVariableDecl() {
|
||||
ASTNode *statement;
|
||||
auto type = parseType(true);
|
||||
|
||||
if (MATCHES(sequence(IDENTIFIER))) {
|
||||
auto identifier = getValue<Token::Identifier>(-1).get();
|
||||
statement = parseMemberVariable(type);
|
||||
|
||||
if (MATCHES(sequence(OPERATOR_ASSIGNMENT))) {
|
||||
auto expression = parseMathematicalExpression();
|
||||
|
||||
statement = create(new ASTNodeCompoundStatement({ statement, create(new ASTNodeAssignment(identifier, expression)) }));
|
||||
}
|
||||
}
|
||||
else
|
||||
throwParseError("invalid variable declaration");
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
ASTNode* Parser::parseFunctionStatement() {
|
||||
bool needsSemicolon = true;
|
||||
ASTNode *statement;
|
||||
@ -484,6 +504,9 @@ namespace hex::pl {
|
||||
} else if (MATCHES(sequence(KEYWORD_WHILE, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
statement = parseFunctionWhileLoop();
|
||||
needsSemicolon = false;
|
||||
} else if (MATCHES(sequence(KEYWORD_FOR, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
statement = parseFunctionForLoop();
|
||||
needsSemicolon = false;
|
||||
} else if (MATCHES(sequence(IDENTIFIER))) {
|
||||
auto originalPos = this->m_curr;
|
||||
parseNamespaceResolution();
|
||||
@ -494,24 +517,11 @@ namespace hex::pl {
|
||||
statement = parseFunctionCall();
|
||||
}
|
||||
else {
|
||||
statement = parseMemberVariable(parseType(true));
|
||||
statement = parseFunctionVariableDecl();
|
||||
}
|
||||
}
|
||||
else if (peek(KEYWORD_BE) || peek(KEYWORD_LE) || peek(VALUETYPE_ANY)) {
|
||||
auto type = parseType(true);
|
||||
|
||||
if (MATCHES(sequence(IDENTIFIER))) {
|
||||
auto identifier = getValue<Token::Identifier>(-1).get();
|
||||
statement = parseMemberVariable(type);
|
||||
|
||||
if (MATCHES(sequence(OPERATOR_ASSIGNMENT))) {
|
||||
auto expression = parseMathematicalExpression();
|
||||
|
||||
statement = new ASTNodeCompoundStatement({ statement, new ASTNodeAssignment(identifier, expression) });
|
||||
}
|
||||
}
|
||||
else
|
||||
throwParseError("invalid variable declaration");
|
||||
statement = parseFunctionVariableDecl();
|
||||
}
|
||||
else
|
||||
throwParseError("invalid sequence", 0);
|
||||
@ -608,6 +618,48 @@ namespace hex::pl {
|
||||
return create(new ASTNodeWhileStatement(condition, body));
|
||||
}
|
||||
|
||||
ASTNode* Parser::parseFunctionForLoop() {
|
||||
auto variable = parseFunctionVariableDecl();
|
||||
auto variableCleanup = SCOPE_GUARD { delete variable; };
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_COMMA)))
|
||||
throwParseError("expected ',' after for loop variable declaration");
|
||||
|
||||
auto condition = parseMathematicalExpression();
|
||||
auto conditionCleanup = SCOPE_GUARD { delete condition; };
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_COMMA)))
|
||||
throwParseError("expected ',' after for loop condition");
|
||||
|
||||
if (!MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT)))
|
||||
throwParseError("expected for loop variable assignment");
|
||||
|
||||
auto postExpression = parseFunctionVariableAssignment();
|
||||
auto postExpressionCleanup = SCOPE_GUARD { delete postExpression; };
|
||||
|
||||
std::vector<ASTNode*> body;
|
||||
|
||||
auto bodyCleanup = SCOPE_GUARD {
|
||||
delete condition;
|
||||
for (auto &statement : body)
|
||||
delete statement;
|
||||
};
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE)))
|
||||
throwParseError("expected closing ')' after statement head");
|
||||
|
||||
body = parseStatementBody();
|
||||
|
||||
body.push_back(postExpression);
|
||||
|
||||
variableCleanup.release();
|
||||
conditionCleanup.release();
|
||||
postExpressionCleanup.release();
|
||||
bodyCleanup.release();
|
||||
|
||||
return create(new ASTNodeCompoundStatement({ variable, create(new ASTNodeWhileStatement(condition, body)) }, true));
|
||||
}
|
||||
|
||||
/* Control flow */
|
||||
|
||||
// if ((parseMathematicalExpression)) { (parseMember) }
|
||||
|
@ -24,7 +24,7 @@ namespace hex {
|
||||
static TextEditor::LanguageDefinition langDef;
|
||||
if (!initialized) {
|
||||
static const char* const keywords[] = {
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "this", "parent", "addressof", "sizeof", "$", "while", "fn", "return", "namespace"
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "this", "parent", "addressof", "sizeof", "$", "while", "for", "fn", "return", "namespace"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
Loading…
Reference in New Issue
Block a user