Adds support for parenthesized expressions

This commit is contained in:
2019-05-21 17:16:53 +02:00
parent ae25598864
commit aec07bd29a
7 changed files with 186 additions and 127 deletions

View File

@@ -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