|
|
|
|
@@ -7,24 +7,24 @@
|
|
|
|
|
ParsedScriptStatement* Parser::Parse() {
|
|
|
|
|
vector<ParsedStatement*> statements;
|
|
|
|
|
while (true){
|
|
|
|
|
auto next = Parser::Next();
|
|
|
|
|
auto next = this -> Next();
|
|
|
|
|
if (next->GetKind() == TokenKind::EndOfFile){
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (next->GetKind() == TokenKind::WhiteSpace){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
statements.push_back(Parser::ParseStatement(next));
|
|
|
|
|
statements.push_back(this -> ParseStatement(next));
|
|
|
|
|
}
|
|
|
|
|
return new ParsedScriptStatement(statements);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParsedStatement* Parser::ParseStatement(IToken* current){
|
|
|
|
|
return new ParsedExpressionStatement(Parser::ParseExpression(current));
|
|
|
|
|
return new ParsedExpressionStatement(this -> ParseExpression(current));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParsedExpression* Parser::ParseExpression(IToken* current){
|
|
|
|
|
return Parser::ParseBinaryExpression(current, OperatorPrecedence::No);
|
|
|
|
|
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -44,7 +44,7 @@ UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind){
|
|
|
|
|
case TokenKind::PlusToken: return UnaryOperatorKind::Identity;
|
|
|
|
|
case TokenKind::MinusToken: return UnaryOperatorKind::Negation;
|
|
|
|
|
case TokenKind::NotKeyword: return UnaryOperatorKind::LogicalNegation;
|
|
|
|
|
default:
|
|
|
|
|
default: // This should never trigger, so throw.
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -58,7 +58,7 @@ BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){
|
|
|
|
|
case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality;
|
|
|
|
|
case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd;
|
|
|
|
|
case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr;
|
|
|
|
|
default:
|
|
|
|
|
default: // This should never trigger, so throw.
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -82,22 +82,22 @@ ParsedExpression* Parser::ParseBinaryExpression(IToken* current, OperatorPrecede
|
|
|
|
|
ParsedExpression* left;
|
|
|
|
|
if (unaryPrecedence != OperatorPrecedence::No && unaryPrecedence >= parentPrecedence){
|
|
|
|
|
UnaryOperatorKind operatorKind = GetUnaryOperatorKind(current -> GetKind());
|
|
|
|
|
auto next = Parser::Next();
|
|
|
|
|
auto operand = Parser::ParseBinaryExpression(next, unaryPrecedence);
|
|
|
|
|
auto next = this -> Next();
|
|
|
|
|
auto operand = this -> ParseBinaryExpression(next, unaryPrecedence);
|
|
|
|
|
auto startPos = current -> GetStartPosition();
|
|
|
|
|
left = new UnaryExpression(operatorKind, operand, startPos, operand -> GetEndPosition() - startPos);
|
|
|
|
|
} else{
|
|
|
|
|
left = Parser::ParsePrimaryExpression(current);
|
|
|
|
|
left = this -> ParsePrimaryExpression(current);
|
|
|
|
|
}
|
|
|
|
|
while (true){
|
|
|
|
|
auto next = Parser::Peek();
|
|
|
|
|
auto next = this -> Peek();
|
|
|
|
|
OperatorPrecedence binaryPrecedence = GetBinaryPrecedence(next -> GetKind());
|
|
|
|
|
if (binaryPrecedence == OperatorPrecedence::No || binaryPrecedence <= parentPrecedence){
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
auto operatorKind = GetBinaryOperatorKind(next -> GetKind());
|
|
|
|
|
Parser::Next();
|
|
|
|
|
auto right = ParseBinaryExpression(Parser::Next(), binaryPrecedence);
|
|
|
|
|
this -> Next();
|
|
|
|
|
auto right = ParseBinaryExpression(this -> Next(), binaryPrecedence);
|
|
|
|
|
auto startPos = left -> GetStartPosition();
|
|
|
|
|
left = new BinaryExpression(operatorKind, left, right, startPos, right -> GetEndPosition() - startPos);
|
|
|
|
|
}
|
|
|
|
|
@@ -111,18 +111,19 @@ ParsedExpression *Parser::ParsePrimaryExpression(IToken *current) {
|
|
|
|
|
case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current);
|
|
|
|
|
case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current);
|
|
|
|
|
default:
|
|
|
|
|
throw;
|
|
|
|
|
this -> ScriptData -> Diagnostics.LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(), current->GetLength());
|
|
|
|
|
return new BadExpression(current->GetStartPosition(), current->GetLength());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IToken *Parser::Peek() {
|
|
|
|
|
return Parser::_tokens[_position];
|
|
|
|
|
return this -> _tokens[_position];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IToken *Parser::Next() {
|
|
|
|
|
Parser::_position++;
|
|
|
|
|
return Parser::_tokens[_position - 1];
|
|
|
|
|
this -> _position++;
|
|
|
|
|
return this -> _tokens[_position - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef TESTS_BUILD
|
|
|
|
|
@@ -130,7 +131,7 @@ IToken *Parser::Next() {
|
|
|
|
|
|
|
|
|
|
TEST_CASE( "Parse single true keyword", "[parser]" ) {
|
|
|
|
|
vector<IToken*> v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
@@ -143,7 +144,7 @@ TEST_CASE( "Parse single true keyword", "[parser]" ) {
|
|
|
|
|
|
|
|
|
|
TEST_CASE( "Parse single false keyword", "[parser]" ) {
|
|
|
|
|
vector<IToken*> v {new SimpleToken(TokenKind::FalseKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
@@ -161,7 +162,7 @@ TEST_CASE( "Parse simple addition", "[parser]" ) {
|
|
|
|
|
new IntegerToken(10, 0, 0),
|
|
|
|
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
|
|
|
|
};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
@@ -184,7 +185,7 @@ TEST_CASE( "Parse simple negation", "[parser]" ) {
|
|
|
|
|
new IntegerToken(10, 0, 0),
|
|
|
|
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
|
|
|
|
};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
@@ -204,7 +205,7 @@ TEST_CASE( "Parse logical negation", "[parser]" ) {
|
|
|
|
|
new SimpleToken(TokenKind::FalseKeyword,0,0),
|
|
|
|
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
|
|
|
|
};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
@@ -227,7 +228,7 @@ TEST_CASE( "Assert binary precedence", "[parser]" ) {
|
|
|
|
|
new IntegerToken(6, 0, 0),
|
|
|
|
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
|
|
|
|
};
|
|
|
|
|
Parser parser = Parser(v);
|
|
|
|
|
Parser parser = Parser(v, nullptr);
|
|
|
|
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
|
|
|
|
REQUIRE(parsedStatements.size() == 1);
|
|
|
|
|
auto firstStatement = parsedStatements[0];
|
|
|
|
|
|