patterns: Added for loops
This commit is contained in:
parent
69ca14bf46
commit
ec9715f326
@ -2051,7 +2051,7 @@ namespace hex::pl {
|
|||||||
class ASTNodeCompoundStatement : public ASTNode {
|
class ASTNodeCompoundStatement : public ASTNode {
|
||||||
public:
|
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 execute(Evaluator *evaluator) override {
|
||||||
FunctionResult result;
|
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) {
|
for (const auto &statement : this->m_statements) {
|
||||||
result = statement->execute(evaluator);
|
result = statement->execute(evaluator);
|
||||||
if (result.first)
|
if (result.first)
|
||||||
return result;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<ASTNode*> m_statements;
|
std::vector<ASTNode*> m_statements;
|
||||||
|
bool m_newScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
@ -90,12 +90,14 @@ namespace hex::pl {
|
|||||||
ASTNode* parseMathematicalExpression();
|
ASTNode* parseMathematicalExpression();
|
||||||
|
|
||||||
ASTNode* parseFunctionDefinition();
|
ASTNode* parseFunctionDefinition();
|
||||||
|
ASTNode* parseFunctionVariableDecl();
|
||||||
ASTNode* parseFunctionStatement();
|
ASTNode* parseFunctionStatement();
|
||||||
ASTNode* parseFunctionVariableAssignment();
|
ASTNode* parseFunctionVariableAssignment();
|
||||||
ASTNode* parseFunctionReturnStatement();
|
ASTNode* parseFunctionReturnStatement();
|
||||||
std::vector<ASTNode*> parseStatementBody();
|
std::vector<ASTNode*> parseStatementBody();
|
||||||
ASTNode* parseFunctionConditional();
|
ASTNode* parseFunctionConditional();
|
||||||
ASTNode* parseFunctionWhileLoop();
|
ASTNode* parseFunctionWhileLoop();
|
||||||
|
ASTNode* parseFunctionForLoop();
|
||||||
|
|
||||||
void parseAttribute(Attributable *currNode);
|
void parseAttribute(Attributable *currNode);
|
||||||
ASTNode* parseConditional();
|
ASTNode* parseConditional();
|
||||||
|
@ -37,6 +37,7 @@ namespace hex::pl {
|
|||||||
Parent,
|
Parent,
|
||||||
This,
|
This,
|
||||||
While,
|
While,
|
||||||
|
For,
|
||||||
Function,
|
Function,
|
||||||
Return,
|
Return,
|
||||||
Namespace
|
Namespace
|
||||||
@ -280,6 +281,7 @@ namespace hex::pl {
|
|||||||
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
||||||
#define KEYWORD_THIS COMPONENT(Keyword, This)
|
#define KEYWORD_THIS COMPONENT(Keyword, This)
|
||||||
#define KEYWORD_WHILE COMPONENT(Keyword, While)
|
#define KEYWORD_WHILE COMPONENT(Keyword, While)
|
||||||
|
#define KEYWORD_FOR COMPONENT(Keyword, For)
|
||||||
#define KEYWORD_FUNCTION COMPONENT(Keyword, Function)
|
#define KEYWORD_FUNCTION COMPONENT(Keyword, Function)
|
||||||
#define KEYWORD_RETURN COMPONENT(Keyword, Return)
|
#define KEYWORD_RETURN COMPONENT(Keyword, Return)
|
||||||
#define KEYWORD_NAMESPACE COMPONENT(Keyword, Namespace)
|
#define KEYWORD_NAMESPACE COMPONENT(Keyword, Namespace)
|
||||||
|
@ -408,6 +408,8 @@ namespace hex::pl {
|
|||||||
tokens.emplace_back(TOKEN(Keyword, This));
|
tokens.emplace_back(TOKEN(Keyword, This));
|
||||||
else if (identifier == "while")
|
else if (identifier == "while")
|
||||||
tokens.emplace_back(TOKEN(Keyword, While));
|
tokens.emplace_back(TOKEN(Keyword, While));
|
||||||
|
else if (identifier == "for")
|
||||||
|
tokens.emplace_back(TOKEN(Keyword, For));
|
||||||
else if (identifier == "fn")
|
else if (identifier == "fn")
|
||||||
tokens.emplace_back(TOKEN(Keyword, Function));
|
tokens.emplace_back(TOKEN(Keyword, Function));
|
||||||
else if (identifier == "return")
|
else if (identifier == "return")
|
||||||
|
@ -470,6 +470,26 @@ namespace hex::pl {
|
|||||||
return create(new ASTNodeFunctionDefinition(getNamespacePrefixedName(functionName), params, body));
|
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() {
|
ASTNode* Parser::parseFunctionStatement() {
|
||||||
bool needsSemicolon = true;
|
bool needsSemicolon = true;
|
||||||
ASTNode *statement;
|
ASTNode *statement;
|
||||||
@ -484,6 +504,9 @@ namespace hex::pl {
|
|||||||
} else if (MATCHES(sequence(KEYWORD_WHILE, SEPARATOR_ROUNDBRACKETOPEN))) {
|
} else if (MATCHES(sequence(KEYWORD_WHILE, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||||
statement = parseFunctionWhileLoop();
|
statement = parseFunctionWhileLoop();
|
||||||
needsSemicolon = false;
|
needsSemicolon = false;
|
||||||
|
} else if (MATCHES(sequence(KEYWORD_FOR, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||||
|
statement = parseFunctionForLoop();
|
||||||
|
needsSemicolon = false;
|
||||||
} else if (MATCHES(sequence(IDENTIFIER))) {
|
} else if (MATCHES(sequence(IDENTIFIER))) {
|
||||||
auto originalPos = this->m_curr;
|
auto originalPos = this->m_curr;
|
||||||
parseNamespaceResolution();
|
parseNamespaceResolution();
|
||||||
@ -494,24 +517,11 @@ namespace hex::pl {
|
|||||||
statement = parseFunctionCall();
|
statement = parseFunctionCall();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
statement = parseMemberVariable(parseType(true));
|
statement = parseFunctionVariableDecl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (peek(KEYWORD_BE) || peek(KEYWORD_LE) || peek(VALUETYPE_ANY)) {
|
else if (peek(KEYWORD_BE) || peek(KEYWORD_LE) || peek(VALUETYPE_ANY)) {
|
||||||
auto type = parseType(true);
|
statement = parseFunctionVariableDecl();
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throwParseError("invalid sequence", 0);
|
throwParseError("invalid sequence", 0);
|
||||||
@ -608,6 +618,48 @@ namespace hex::pl {
|
|||||||
return create(new ASTNodeWhileStatement(condition, body));
|
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 */
|
/* Control flow */
|
||||||
|
|
||||||
// if ((parseMathematicalExpression)) { (parseMember) }
|
// if ((parseMathematicalExpression)) { (parseMember) }
|
||||||
|
@ -24,7 +24,7 @@ namespace hex {
|
|||||||
static TextEditor::LanguageDefinition langDef;
|
static TextEditor::LanguageDefinition langDef;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
static const char* const keywords[] = {
|
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)
|
for (auto& k : keywords)
|
||||||
langDef.mKeywords.insert(k);
|
langDef.mKeywords.insert(k);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user