1
0
mirror of synced 2024-11-28 09:30:51 +01:00

patterns: Added for loops

This commit is contained in:
WerWolv 2021-10-10 13:47:48 +02:00
parent 69ca14bf46
commit ec9715f326
6 changed files with 95 additions and 17 deletions

View File

@ -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;
};
};

View File

@ -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();

View File

@ -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)

View File

@ -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")

View File

@ -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) }

View File

@ -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);