Adds support for parenthesized expressions
This commit is contained in:
@@ -97,7 +97,7 @@ ParsedExpression* Parser::ParseBinaryExpression(IToken* current, OperatorPrecede
|
||||
}
|
||||
auto operatorKind = GetBinaryOperatorKind(next -> GetKind());
|
||||
this -> Next();
|
||||
auto right = ParseBinaryExpression(this -> Next(), binaryPrecedence);
|
||||
auto right = this -> ParseBinaryExpression(this -> Next(), binaryPrecedence);
|
||||
auto startPos = left -> GetStartPosition();
|
||||
left = new BinaryExpression(operatorKind, left, right, startPos, right -> GetEndPosition() - startPos);
|
||||
}
|
||||
@@ -110,6 +110,7 @@ ParsedExpression *Parser::ParsePrimaryExpression(IToken *current) {
|
||||
case TokenKind ::Float: return new LiteralFloatExpression((FloatToken*)current);
|
||||
case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current);
|
||||
case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current);
|
||||
case TokenKind ::OpenParenthesis: return this -> ParseParenthesizedExpression(current);
|
||||
// If we find a bad token here, we should have already logged it in the lexer, so don't log another error.
|
||||
case TokenKind ::BadToken: return new BadExpression(current->GetStartPosition(), current->GetLength());
|
||||
default:
|
||||
@@ -118,6 +119,18 @@ ParsedExpression *Parser::ParsePrimaryExpression(IToken *current) {
|
||||
}
|
||||
}
|
||||
|
||||
ParsedExpression *Parser::ParseParenthesizedExpression(IToken *current) {
|
||||
auto next = this -> Next();
|
||||
auto expression = this -> ParseExpression(next);
|
||||
auto closeToken = this -> Next();
|
||||
if (closeToken -> GetKind() != TokenKind::CloseParenthesis){
|
||||
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, closeToken->GetStartPosition(), closeToken->GetLength());
|
||||
return new BadExpression(closeToken->GetStartPosition(), closeToken->GetLength());
|
||||
}
|
||||
auto start = current -> GetStartPosition();
|
||||
return new ParenthesizedExpression(expression, start, closeToken->GetEndPosition() - start);
|
||||
}
|
||||
|
||||
|
||||
IToken *Parser::Peek() {
|
||||
return this -> _tokens[_position];
|
||||
@@ -128,127 +141,3 @@ IToken *Parser::Next() {
|
||||
return this -> _tokens[_position - 1];
|
||||
}
|
||||
|
||||
#ifdef TESTS_BUILD
|
||||
#include <catch.hpp>
|
||||
|
||||
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, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::LiteralBool);
|
||||
auto boolean = ((LiteralBoolExpression*)expression);
|
||||
REQUIRE(boolean->GetValue() == true);
|
||||
}
|
||||
|
||||
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, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::LiteralBool);
|
||||
auto boolean = ((LiteralBoolExpression*)expression);
|
||||
REQUIRE(boolean->GetValue() == false);
|
||||
}
|
||||
|
||||
TEST_CASE( "Parse simple addition", "[parser]" ) {
|
||||
vector<IToken*> v {
|
||||
new IntegerToken(5, 0, 0),
|
||||
new SimpleToken(TokenKind::PlusToken,0,0),
|
||||
new IntegerToken(10, 0, 0),
|
||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||
};
|
||||
Parser parser = Parser(v, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::Binary);
|
||||
auto binary = ((BinaryExpression*)expression);
|
||||
CHECK(binary -> GetOperatorKind() == BinaryOperatorKind::Addition);
|
||||
auto left = binary->GetLeft();
|
||||
auto right = binary->GetRight();
|
||||
REQUIRE(left->GetKind() == ParsedExpressionKind::LiteralInteger);
|
||||
REQUIRE(right->GetKind() == ParsedExpressionKind::LiteralInteger);
|
||||
CHECK(((LiteralIntegerExpression*)left)->GetValue() == 5);
|
||||
CHECK(((LiteralIntegerExpression*)right)->GetValue() == 10);
|
||||
}
|
||||
|
||||
TEST_CASE( "Parse simple negation", "[parser]" ) {
|
||||
vector<IToken*> v {
|
||||
new SimpleToken(TokenKind::MinusToken,0,0),
|
||||
new IntegerToken(10, 0, 0),
|
||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||
};
|
||||
Parser parser = Parser(v, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::Unary);
|
||||
auto unary = ((UnaryExpression*)expression);
|
||||
CHECK(unary -> GetOperatorKind() == UnaryOperatorKind::Negation);
|
||||
auto operand = unary->GetOperand();
|
||||
REQUIRE(operand->GetKind() == ParsedExpressionKind::LiteralInteger);
|
||||
CHECK(((LiteralIntegerExpression*)operand)->GetValue() == 10);
|
||||
}
|
||||
|
||||
TEST_CASE( "Parse logical negation", "[parser]" ) {
|
||||
vector<IToken*> v {
|
||||
new SimpleToken(TokenKind::NotKeyword,0,0),
|
||||
new SimpleToken(TokenKind::FalseKeyword,0,0),
|
||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||
};
|
||||
Parser parser = Parser(v, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::Unary);
|
||||
auto unary = ((UnaryExpression*)expression);
|
||||
CHECK(unary -> GetOperatorKind() == UnaryOperatorKind::LogicalNegation);
|
||||
auto operand = unary->GetOperand();
|
||||
REQUIRE(operand->GetKind() == ParsedExpressionKind::LiteralBool);
|
||||
CHECK(((LiteralBoolExpression*)operand)->GetValue() == false);
|
||||
}
|
||||
|
||||
TEST_CASE( "Assert binary precedence", "[parser]" ) {
|
||||
vector<IToken*> v {
|
||||
new IntegerToken(5, 0, 0),
|
||||
new SimpleToken(TokenKind::PlusToken,0,0),
|
||||
new IntegerToken(10, 0, 0),
|
||||
new SimpleToken(TokenKind::StarToken,0,0),
|
||||
new IntegerToken(6, 0, 0),
|
||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||
};
|
||||
Parser parser = Parser(v, nullptr);
|
||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||
REQUIRE(parsedStatements.size() == 1);
|
||||
auto firstStatement = parsedStatements[0];
|
||||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Expression);
|
||||
auto expression = ((ParsedExpressionStatement*)firstStatement)->GetExpression();
|
||||
REQUIRE(expression -> GetKind() == ParsedExpressionKind::Binary);
|
||||
auto binary = ((BinaryExpression*)expression);
|
||||
CHECK(binary -> GetOperatorKind() == BinaryOperatorKind::Addition);
|
||||
auto left = binary->GetLeft();
|
||||
auto right = binary->GetRight();
|
||||
REQUIRE(left->GetKind() == ParsedExpressionKind::LiteralInteger);
|
||||
REQUIRE(right->GetKind() == ParsedExpressionKind::Binary);
|
||||
CHECK(((LiteralIntegerExpression*)left)->GetValue() == 5);
|
||||
left = ((BinaryExpression*)right)->GetLeft();
|
||||
right = ((BinaryExpression*)right)->GetRight();
|
||||
CHECK(((LiteralIntegerExpression*)left)->GetValue() == 10);
|
||||
CHECK(((LiteralIntegerExpression*)right)->GetValue() == 6);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user