Loop parsing
This commit is contained in:
@@ -194,6 +194,10 @@ shared_ptr<Token> Lexer::nextToken() {
|
|||||||
token = match(TokenKind::RETURN, "ret", true);
|
token = match(TokenKind::RETURN, "ret", true);
|
||||||
if (token != nullptr)
|
if (token != nullptr)
|
||||||
return token;
|
return token;
|
||||||
|
|
||||||
|
token = match(TokenKind::REPEAT, "rep", true);
|
||||||
|
if (token != nullptr)
|
||||||
|
return token;
|
||||||
|
|
||||||
// literal
|
// literal
|
||||||
token = match(TokenKind::BOOL, "true", true);
|
token = match(TokenKind::BOOL, "true", true);
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ string Token::toString() {
|
|||||||
return "FUNCTION";
|
return "FUNCTION";
|
||||||
case TokenKind::RETURN:
|
case TokenKind::RETURN:
|
||||||
return "RETURN";
|
return "RETURN";
|
||||||
|
case TokenKind::REPEAT:
|
||||||
|
return "REPEAT";
|
||||||
|
|
||||||
case TokenKind::M_EXTERN:
|
case TokenKind::M_EXTERN:
|
||||||
return "@EXTERN";
|
return "@EXTERN";
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ enum class TokenKind {
|
|||||||
|
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
RETURN,
|
RETURN,
|
||||||
|
REPEAT,
|
||||||
|
|
||||||
BOOL,
|
BOOL,
|
||||||
INTEGER_DEC,
|
INTEGER_DEC,
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
#include "ExpressionBinary.h"
|
#include "ExpressionBinary.h"
|
||||||
|
|
||||||
ExpressionBinary::ExpressionBinary(shared_ptr<Token> token, shared_ptr<Expression> left, shared_ptr<Expression> right):
|
ExpressionBinary::ExpressionBinary(shared_ptr<Token> token, shared_ptr<Expression> left, shared_ptr<Expression> right):
|
||||||
Expression(ExpressionKind::BINARY, ValueType::NONE), left(left), right(right) {
|
Expression(ExpressionKind::BINARY, ValueType::NONE), operation(ExpressionBinaryOperation::INVALID), 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);
|
|
||||||
|
|
||||||
switch (token->getKind()) {
|
switch (token->getKind()) {
|
||||||
case TokenKind::EQUAL:
|
case TokenKind::EQUAL:
|
||||||
operation = ExpressionBinaryOperation::EQUAL;
|
operation = ExpressionBinaryOperation::EQUAL;
|
||||||
@@ -56,8 +48,16 @@ Expression(ExpressionKind::BINARY, ValueType::NONE), left(left), right(right) {
|
|||||||
valueType = left->getValueType();
|
valueType = left->getValueType();
|
||||||
break;
|
break;
|
||||||
default:
|
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() {
|
ExpressionBinaryOperation ExpressionBinary::getOperation() {
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ enum class ExpressionBinaryOperation {
|
|||||||
SUB,
|
SUB,
|
||||||
MUL,
|
MUL,
|
||||||
DIV,
|
DIV,
|
||||||
MOD
|
MOD,
|
||||||
|
INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExpressionBinary: public Expression {
|
class ExpressionBinary: public Expression {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "Parser/Statement/StatementExpression.h"
|
#include "Parser/Statement/StatementExpression.h"
|
||||||
#include "Parser/Statement/StatementMetaExternFunction.h"
|
#include "Parser/Statement/StatementMetaExternFunction.h"
|
||||||
#include "Parser/Statement/StatementBlock.h"
|
#include "Parser/Statement/StatementBlock.h"
|
||||||
|
#include "Parser/Statement/StatementLoop.h"
|
||||||
#include "Parser/Statement/StatementInvalid.h"
|
#include "Parser/Statement/StatementInvalid.h"
|
||||||
|
|
||||||
Parser::Parser(vector<shared_ptr<Token>> tokens): tokens(tokens) {
|
Parser::Parser(vector<shared_ptr<Token>> tokens): tokens(tokens) {
|
||||||
@@ -53,6 +54,10 @@ shared_ptr<Statement> Parser::nextStatement() {
|
|||||||
statement = matchStatementReturn();
|
statement = matchStatementReturn();
|
||||||
if (statement != nullptr)
|
if (statement != nullptr)
|
||||||
return statement;
|
return statement;
|
||||||
|
|
||||||
|
statement = matchStatementLoop();
|
||||||
|
if (statement != nullptr)
|
||||||
|
return statement;
|
||||||
|
|
||||||
statement = matchStatementExpression();
|
statement = matchStatementExpression();
|
||||||
if (statement != nullptr)
|
if (statement != nullptr)
|
||||||
@@ -151,8 +156,8 @@ shared_ptr<Statement> Parser::matchStatementVariable() {
|
|||||||
if (expression == nullptr || !expression->isValid())
|
if (expression == nullptr || !expression->isValid())
|
||||||
return matchStatementInvalid();
|
return matchStatementInvalid();
|
||||||
|
|
||||||
// Expect new line
|
// Expect comma or new line
|
||||||
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true))
|
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, false) && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true))
|
||||||
return matchStatementInvalid("Expected a new line after variable declaration");
|
return matchStatementInvalid("Expected a new line after variable declaration");
|
||||||
|
|
||||||
return make_shared<StatementVariable>(identifierToken->getLexme(), valueType, expression);
|
return make_shared<StatementVariable>(identifierToken->getLexme(), valueType, expression);
|
||||||
@@ -174,6 +179,50 @@ shared_ptr<Statement> Parser::matchStatementReturn() {
|
|||||||
return make_shared<StatementReturn>(expression);
|
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<Statement> Parser::matchStatementExpression() {
|
||||||
shared_ptr<Expression> expression = nextExpression();
|
shared_ptr<Expression> expression = nextExpression();
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ private:
|
|||||||
shared_ptr<Statement> matchStatementFunction();
|
shared_ptr<Statement> matchStatementFunction();
|
||||||
shared_ptr<Statement> matchStatementVariable();
|
shared_ptr<Statement> matchStatementVariable();
|
||||||
shared_ptr<Statement> matchStatementReturn();
|
shared_ptr<Statement> matchStatementReturn();
|
||||||
|
shared_ptr<Statement> matchStatementLoop();
|
||||||
shared_ptr<Statement> matchStatementExpression();
|
shared_ptr<Statement> matchStatementExpression();
|
||||||
shared_ptr<Statement> matchStatementMetaExternFunction();
|
shared_ptr<Statement> matchStatementMetaExternFunction();
|
||||||
shared_ptr<Statement> matchStatementBlock(vector<TokenKind> terminalTokenKinds, bool shouldConsumeTerminal);
|
shared_ptr<Statement> matchStatementBlock(vector<TokenKind> terminalTokenKinds, bool shouldConsumeTerminal);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ enum class StatementKind {
|
|||||||
RETURN,
|
RETURN,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
VARIABLE,
|
VARIABLE,
|
||||||
|
LOOP,
|
||||||
META_EXTERN_FUNCTION,
|
META_EXTERN_FUNCTION,
|
||||||
INVALID
|
INVALID
|
||||||
};
|
};
|
||||||
|
|||||||
39
src/Parser/Statement/StatementLoop.cpp
Normal file
39
src/Parser/Statement/StatementLoop.cpp
Normal 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;
|
||||||
|
}
|
||||||
20
src/Parser/Statement/StatementLoop.h
Normal file
20
src/Parser/Statement/StatementLoop.h
Normal 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;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user