Loop parsing

This commit is contained in:
Rafał Grodziński
2025-06-24 18:40:50 +09:00
parent 981854835e
commit 0c31072115
10 changed files with 131 additions and 13 deletions

View File

@@ -194,6 +194,10 @@ shared_ptr<Token> Lexer::nextToken() {
token = match(TokenKind::RETURN, "ret", true);
if (token != nullptr)
return token;
token = match(TokenKind::REPEAT, "rep", true);
if (token != nullptr)
return token;
// literal
token = match(TokenKind::BOOL, "true", true);

View File

@@ -140,6 +140,8 @@ string Token::toString() {
return "FUNCTION";
case TokenKind::RETURN:
return "RETURN";
case TokenKind::REPEAT:
return "REPEAT";
case TokenKind::M_EXTERN:
return "@EXTERN";

View File

@@ -33,6 +33,7 @@ enum class TokenKind {
FUNCTION,
RETURN,
REPEAT,
BOOL,
INTEGER_DEC,

View File

@@ -1,15 +1,7 @@
#include "ExpressionBinary.h"
ExpressionBinary::ExpressionBinary(shared_ptr<Token> token, shared_ptr<Expression> left, shared_ptr<Expression> right):
Expression(ExpressionKind::BINARY, ValueType::NONE), left(left), right(right) {
// Types must match
if (left->getValueType() != right->getValueType())
exit(1);
// Booleans can only do = or !=
if (valueType == ValueType::BOOL && (token->getKind() != TokenKind::EQUAL || token->getKind() != TokenKind::NOT_EQUAL))
exit(1);
Expression(ExpressionKind::BINARY, ValueType::NONE), operation(ExpressionBinaryOperation::INVALID), left(left), right(right) {
switch (token->getKind()) {
case TokenKind::EQUAL:
operation = ExpressionBinaryOperation::EQUAL;
@@ -56,8 +48,16 @@ Expression(ExpressionKind::BINARY, ValueType::NONE), left(left), right(right) {
valueType = left->getValueType();
break;
default:
exit(1);
break;
}
// Types must match
if (left->getValueType() != right->getValueType())
valueType = ValueType::NONE;
// Booleans can only do = or !=
if (valueType == ValueType::BOOL && (token->getKind() != TokenKind::EQUAL || token->getKind() != TokenKind::NOT_EQUAL))
valueType = ValueType::NONE;
}
ExpressionBinaryOperation ExpressionBinary::getOperation() {

View File

@@ -11,7 +11,8 @@ enum class ExpressionBinaryOperation {
SUB,
MUL,
DIV,
MOD
MOD,
INVALID
};
class ExpressionBinary: public Expression {

View File

@@ -15,6 +15,7 @@
#include "Parser/Statement/StatementExpression.h"
#include "Parser/Statement/StatementMetaExternFunction.h"
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementLoop.h"
#include "Parser/Statement/StatementInvalid.h"
Parser::Parser(vector<shared_ptr<Token>> tokens): tokens(tokens) {
@@ -53,6 +54,10 @@ shared_ptr<Statement> Parser::nextStatement() {
statement = matchStatementReturn();
if (statement != nullptr)
return statement;
statement = matchStatementLoop();
if (statement != nullptr)
return statement;
statement = matchStatementExpression();
if (statement != nullptr)
@@ -151,8 +156,8 @@ shared_ptr<Statement> Parser::matchStatementVariable() {
if (expression == nullptr || !expression->isValid())
return matchStatementInvalid();
// Expect new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true))
// Expect comma or new line
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, false) && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true))
return matchStatementInvalid("Expected a new line after variable declaration");
return make_shared<StatementVariable>(identifierToken->getLexme(), valueType, expression);
@@ -174,6 +179,50 @@ shared_ptr<Statement> Parser::matchStatementReturn() {
return make_shared<StatementReturn>(expression);
}
shared_ptr<Statement> Parser::matchStatementLoop() {
if (!tryMatchingTokenKinds({TokenKind::REPEAT}, true, true))
return nullptr;
// initial
shared_ptr<Statement> initStatement = matchStatementVariable();
if (initStatement != nullptr && !initStatement->isValid())
initStatement = nullptr;
// got initial, expect comma
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
return matchStatementInvalid("Expected comma after initial statement");
// pre condition
shared_ptr<Expression> preConditionExpression = nextExpression();
if (preConditionExpression == nullptr || !preConditionExpression->isValid())
return matchStatementInvalid("Expected pre-condition expression");
// post condition
shared_ptr<Expression> postConditionExpression;
if (tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
postConditionExpression = nextExpression();
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
return matchStatementInvalid("Expected post-condition expression");
}
// epxect new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line");
// body
shared_ptr<Statement> bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON}, true);
if (bodyBlockStatement == nullptr)
return matchStatementInvalid("Expected block statement");
else if (!bodyBlockStatement->isValid())
return bodyBlockStatement;
// epxect new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line");
return make_shared<StatementLoop>(initStatement, preConditionExpression, postConditionExpression, dynamic_pointer_cast<StatementBlock>(bodyBlockStatement));
}
shared_ptr<Statement> Parser::matchStatementExpression() {
shared_ptr<Expression> expression = nextExpression();

View File

@@ -22,6 +22,7 @@ private:
shared_ptr<Statement> matchStatementFunction();
shared_ptr<Statement> matchStatementVariable();
shared_ptr<Statement> matchStatementReturn();
shared_ptr<Statement> matchStatementLoop();
shared_ptr<Statement> matchStatementExpression();
shared_ptr<Statement> matchStatementMetaExternFunction();
shared_ptr<Statement> matchStatementBlock(vector<TokenKind> terminalTokenKinds, bool shouldConsumeTerminal);

View File

@@ -13,6 +13,7 @@ enum class StatementKind {
RETURN,
FUNCTION,
VARIABLE,
LOOP,
META_EXTERN_FUNCTION,
INVALID
};

View File

@@ -0,0 +1,39 @@
#include "StatementLoop.h"
#include "Parser/Expression/Expression.h"
#include "Parser/Statement/StatementBlock.h"
StatementLoop::StatementLoop(shared_ptr<Statement> initStatement, shared_ptr<Expression> preConditionExpression, shared_ptr<Expression> postConditionExpression, shared_ptr<StatementBlock> bodyBlockStatement):
Statement(StatementKind::LOOP), initStatement(initStatement), preConditionExpression(preConditionExpression), postConditionExpression(postConditionExpression), bodyBlockStatement(bodyBlockStatement) { }
shared_ptr<Statement> StatementLoop::getInitStatement() {
return initStatement;
}
shared_ptr<Expression> StatementLoop::getPreConditionExpression() {
return preConditionExpression;
}
shared_ptr<Expression> StatementLoop::getPostConditionExpression() {
return postConditionExpression;
}
shared_ptr<StatementBlock> StatementLoop::getBodyBlockStatement() {
return bodyBlockStatement;
}
string StatementLoop::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += "REP(";
if (initStatement != nullptr)
value += initStatement->toString(0), ", ";
if (preConditionExpression != nullptr)
value += preConditionExpression->toString(0) + ", ";
if (postConditionExpression != nullptr)
value += postConditionExpression->toString(0);
value += "):\n";
value += bodyBlockStatement->toString(indent+1);
return value;
}

View File

@@ -0,0 +1,20 @@
#include "Statement.h"
class Expression;
class StatementBlock;
class StatementLoop: public Statement {
private:
shared_ptr<Statement> initStatement;
shared_ptr<Expression> preConditionExpression;
shared_ptr<Expression> postConditionExpression;
shared_ptr<StatementBlock> bodyBlockStatement;
public:
StatementLoop(shared_ptr<Statement> initStatement, shared_ptr<Expression> preConditionExpression, shared_ptr<Expression> postConditionExpression, shared_ptr<StatementBlock> bodyBlockStatement);
shared_ptr<Statement> getInitStatement();
shared_ptr<Expression> getPreConditionExpression();
shared_ptr<Expression> getPostConditionExpression();
shared_ptr<StatementBlock> getBodyBlockStatement();
string toString(int indent) override;
};