diff options
-rw-r--r-- | AST.h | 110 | ||||
-rw-r--r-- | Parser.cpp | 233 | ||||
-rw-r--r-- | Parser.h | 10 | ||||
-rw-r--r-- | grammar.txt | 13 |
4 files changed, 338 insertions, 28 deletions
@@ -54,6 +54,8 @@ public: : m_location(_location) {} + virtual ~ASTNode() {} + Location getLocation() const { return m_location; } private: Location m_location; @@ -146,9 +148,7 @@ private: class TypeName : public ASTNode { public: - explicit TypeName(Location const& _location) - : ASTNode(_location) - {} + explicit TypeName(Location const& _location) : ASTNode(_location) {} }; /// any pre-defined type that is not a mapping @@ -192,15 +192,13 @@ private: class Statement : public ASTNode { public: - explicit Statement(Location const& _location) - : ASTNode(_location) - {} + explicit Statement(Location const& _location) : ASTNode(_location) {} }; class Block : public Statement { public: - explicit Block(Location const& _location, vecptr<Statement> const& _statements) + Block(Location const& _location, vecptr<Statement> const& _statements) : Statement(_location), m_statements(_statements) {} private: @@ -209,7 +207,12 @@ private: class IfStatement : public Statement { - +public: + IfStatement(Location const& _location, ptr<Expression> const& _condition, + ptr<Statement> const& _trueBody, ptr<Statement> const& _falseBody) + : Statement(_location), m_condition(_condition), + m_trueBody(_trueBody), m_falseBody(_falseBody) + {} private: ptr<Expression> m_condition; ptr<Statement> m_trueBody; @@ -218,11 +221,17 @@ private: class BreakableStatement : public Statement { - +public: + BreakableStatement(Location const& _location) : Statement(_location) {} }; class WhileStatement : public BreakableStatement { +public: + WhileStatement(Location const& _location, ptr<Expression> const& _condition, + ptr<Statement> const& _body) + : BreakableStatement(_location), m_condition(_condition), m_body(_body) + {} private: ptr<Expression> m_condition; ptr<Statement> m_body; @@ -230,31 +239,42 @@ private: class Continue : public Statement { - +public: + Continue(Location const& _location) : Statement(_location) {} }; class Break : public Statement { - +public: + Break(Location const& _location) : Statement(_location) {} }; class Return : public Statement { +public: + Return(Location const& _location, ptr<Expression> _expression) + : Statement(_location), m_expression(_expression) + {} private: ptr<Expression> m_expression; }; -class VariableAssignment : public Statement +class VariableDefinition : public Statement { +public: + VariableDefinition(Location const& _location, ptr<VariableDeclaration> _variable, + ptr<Expression> _value) + : Statement(_location), m_variable(_variable), m_value(_value) + {} private: ptr<VariableDeclaration> m_variable; - Token::Value m_assigmentOperator; - ptr<Expression> m_rightHandSide; ///< can be missing + ptr<Expression> m_value; ///< can be missing }; class Expression : public Statement { -private: +public: + Expression(Location const& _location) : Statement(_location) {} }; /// @} @@ -264,6 +284,12 @@ private: class Assignment : public Expression { +public: + Assignment(Location const& _location, ptr<Expression> const& _leftHandSide, + Token::Value _assignmentOperator, ptr<Expression> const& _rightHandSide) + : Expression(_location), m_leftHandSide(_leftHandSide), + m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide) + {} private: ptr<Expression> m_leftHandSide; Token::Value m_assigmentOperator; @@ -272,31 +298,52 @@ private: class UnaryOperation : public Expression { +public: + UnaryOperation(Location const& _location, Token::Value _operator, + ptr<Expression> const& _subExpression, bool _isPrefix) + : Expression(_location), m_operator(_operator), + m_subExpression(_subExpression), m_isPrefix(_isPrefix) + {} + private: Token::Value m_operator; ptr<Expression> m_subExpression; - bool isPrefix; + bool m_isPrefix; }; class BinaryOperation : public Expression { +public: + BinaryOperation(Location const& _location, ptr<Expression> const& _left, + Token::Value _operator, ptr<Expression> const& _right) + : Expression(_location), m_left(_left), m_operator(_operator), m_right(_right) + {} private: ptr<Expression> m_left; - ptr<Expression> m_right; Token::Value m_operator; + ptr<Expression> m_right; }; /// Can be ordinary function call, type cast or struct construction. class FunctionCall : public Expression { +public: + FunctionCall(Location const& _location, ptr<Expression> const& _expression, + vecptr<Expression> const& _arguments) + : Expression(_location), m_expression(_expression), m_arguments(_arguments) + {} private: - // if m_functionName is the name of a type, store the token directly - std::string m_functionName; // "in place" calls of return values are not possible for now + ptr<Expression> m_expression; vecptr<Expression> m_arguments; }; class MemberAccess : public Expression { +public: + MemberAccess(Location const& _location, ptr<Expression> _expression, + std::string const& _memberName) + : Expression(_location), m_expression(_expression), m_memberName(_memberName) + {} private: ptr<Expression> m_expression; std::string m_memberName; @@ -304,23 +351,48 @@ private: class IndexAccess : public Expression { +public: + IndexAccess(Location const& _location, ptr<Expression> const& _base, + ptr<Expression> const& _index) + : Expression(_location), m_base(_base), m_index(_index) + {} +private: ptr<Expression> m_base; ptr<Expression> m_index; }; class PrimaryExpression : public Expression { +public: + PrimaryExpression(Location const& _location) : Expression(_location) {} }; class Identifier : public PrimaryExpression { +public: + Identifier(Location const& _location, std::string const& _name) + : PrimaryExpression(_location), m_name(_name) {} private: std::string m_name; }; +class ElementaryTypeNameExpression : public PrimaryExpression +{ +public: + ElementaryTypeNameExpression(Location const& _location, Token::Value _type) + : PrimaryExpression(_location), m_type(_type) {} +private: + Token::Value m_type; +}; + class Literal : public PrimaryExpression { +public: + Literal(Location const& _location, Token::Value _token, std::string const& _value) + : PrimaryExpression(_location), m_token(_token), m_value(_value) + {} private: + Token::Value m_token; std::string m_value; }; @@ -231,12 +231,10 @@ ptr<ParameterList> Parser::parseParameterList() ptr<Block> Parser::parseBlock() { - ASTNodeFactory nodeFactory(*this); expectToken(Token::LBRACE); vecptr<Statement> statements; while (m_scanner->getCurrentToken() != Token::RBRACE) { - m_scanner->next(); statements.push_back(parseStatement()); } nodeFactory.markEndPosition(); @@ -246,6 +244,7 @@ ptr<Block> Parser::parseBlock() ptr<Statement> Parser::parseStatement() { + ptr<Statement> statement; switch (m_scanner->getCurrentToken()) { case Token::IF: @@ -254,12 +253,229 @@ ptr<Statement> Parser::parseStatement() return parseWhileStatement(); case Token::LBRACE: return parseBlock(); + // starting from here, all statements must be terminated by a semicolon - case Token::CONTINUE: // all following - return + case Token::CONTINUE: + statement = ASTNodeFactory(*this).createNode<Continue>(); + break; + case Token::BREAK: + statement = ASTNodeFactory(*this).createNode<Break>(); + break; + case Token::RETURN: + { + ASTNodeFactory nodeFactory(*this); + ptr<Expression> expression; + if (m_scanner->next() != Token::SEMICOLON) { + expression = parseExpression(); + nodeFactory.setEndPositionFromNode(expression); + } + statement = nodeFactory.createNode<Return>(expression); + } + break; + default: + // distinguish between variable definition (and potentially assignment) and expressions + // (which include assignments to other expressions and pre-declared variables) + // We have a variable definition if we ge a keyword that specifies a type name, or + // in the case of a user-defined type, we have two identifiers following each other. + if (m_scanner->getCurrentToken() == Token::MAPPING || + m_scanner->getCurrentToken() == Token::VAR || + Token::IsElementaryTypeName(m_scanner->getCurrentToken()) || + (m_scanner->getCurrentToken() == Token::IDENTIFIER && + m_scanner->peek() == Token::IDENTIFIER)) { + statement = parseVariableDefinition(); + } else { + // "ordinary" expression + statement = parseExpression(); + } + } + expectToken(Token::SEMICOLON); + return statement; +} + +ptr<IfStatement> Parser::parseIfStatement() +{ + ASTNodeFactory nodeFactory(*this); + expectToken(Token::IF); + expectToken(Token::LPAREN); + ptr<Expression> condition = parseExpression(); + expectToken(Token::RPAREN); + ptr<Statement> trueBody = parseStatement(); + ptr<Statement> falseBody; + if (m_scanner->getCurrentToken() == Token::ELSE) { + m_scanner->next(); + falseBody = parseStatement(); + nodeFactory.setEndPositionFromNode(falseBody); + } else { + nodeFactory.setEndPositionFromNode(trueBody); + } + return nodeFactory.createNode<IfStatement>(condition, trueBody, falseBody); +} + +ptr<WhileStatement> Parser::parseWhileStatement() +{ + ASTNodeFactory nodeFactory(*this); + expectToken(Token::WHILE); + expectToken(Token::LPAREN); + ptr<Expression> condition = parseExpression(); + expectToken(Token::RPAREN); + ptr<Statement> body = parseStatement(); + nodeFactory.setEndPositionFromNode(body); + return nodeFactory.createNode<WhileStatement>(condition, body); +} + +ptr<VariableDefinition> Parser::parseVariableDefinition() +{ + ASTNodeFactory nodeFactory(*this); + ptr<VariableDeclaration> variable = parseVariableDeclaration(); + ptr<Expression> value; + if (m_scanner->getCurrentToken() == Token::ASSIGN) { + m_scanner->next(); + value = parseExpression(); + nodeFactory.setEndPositionFromNode(value); + } else { + nodeFactory.setEndPositionFromNode(variable); + } + return nodeFactory.createNode<VariableDefinition>(variable, value); +} + +ptr<Expression> Parser::parseExpression() +{ + ASTNodeFactory nodeFactory(*this); + ptr<Expression> expression = parseBinaryExpression(); + if (!Token::IsAssignmentOp(m_scanner->getCurrentToken())) + return expression; + + Token::Value assignmentOperator = expectAssignmentOperator(); + ptr<Expression> rightHandSide = parseExpression(); + nodeFactory.setEndPositionFromNode(rightHandSide); + return nodeFactory.createNode<Assignment>(expression, assignmentOperator, rightHandSide); +} + +ptr<Expression> Parser::parseBinaryExpression(int _minPrecedence) +{ + ASTNodeFactory nodeFactory(*this); + ptr<Expression> expression = parseUnaryExpression(); + int precedence = Token::Precedence(m_scanner->getCurrentToken()); + for (; precedence >= _minPrecedence; --precedence) { + while (Token::Precedence(m_scanner->getCurrentToken()) == precedence) { + Token::Value op = m_scanner->getCurrentToken(); + m_scanner->next(); + ptr<Expression> right = parseBinaryExpression(precedence + 1); + nodeFactory.setEndPositionFromNode(right); + expression = nodeFactory.createNode<BinaryOperation>(expression, op, right); + } + } + return expression; +} + +ptr<Expression> Parser::parseUnaryExpression() +{ + ASTNodeFactory nodeFactory(*this); + Token::Value token = m_scanner->getCurrentToken(); + if (Token::IsUnaryOp(token) || Token::IsCountOp(token)) { + // prefix expression + m_scanner->next(); + ptr<Expression> subExpression = parseUnaryExpression(); + nodeFactory.setEndPositionFromNode(subExpression); + return nodeFactory.createNode<UnaryOperation>(token, subExpression, true); + } else { + // potential postfix expression + ptr<Expression> subExpression = parseLeftHandSideExpression(); + token = m_scanner->getCurrentToken(); + if (!Token::IsCountOp(token)) + return subExpression; + nodeFactory.markEndPosition(); + m_scanner->next(); + return nodeFactory.createNode<UnaryOperation>(token, subExpression, false); + } +} + +ptr<Expression> Parser::parseLeftHandSideExpression() +{ + ASTNodeFactory nodeFactory(*this); + ptr<Expression> expression = parsePrimaryExpression(); + + while (true) { + switch (m_scanner->getCurrentToken()) { + case Token::LBRACK: + { + m_scanner->next(); + ptr<Expression> index = parseExpression(); + nodeFactory.markEndPosition(); + expectToken(Token::RBRACK); + expression = nodeFactory.createNode<IndexAccess>(expression, index); + } + break; + case Token::PERIOD: + { + m_scanner->next(); + nodeFactory.markEndPosition(); + std::string memberName = expectIdentifier(); + expression = nodeFactory.createNode<MemberAccess>(expression, memberName); + } + break; + case Token::LPAREN: + { + m_scanner->next(); + vecptr<Expression> arguments = parseFunctionCallArguments(); + nodeFactory.markEndPosition(); + expectToken(Token::RPAREN); + expression = nodeFactory.createNode<FunctionCall>(expression, arguments); + } + break; + default: + return expression; + } + } +} + +ptr<Expression> Parser::parsePrimaryExpression() +{ + Token::Value token = m_scanner->getCurrentToken(); + switch (token) { + case Token::TRUE_LITERAL: + case Token::FALSE_LITERAL: + m_scanner->next(); + return ASTNodeFactory(*this).createNode<Literal>(token, std::string()); + case Token::NUMBER: + case Token::STRING_LITERAL: + m_scanner->next(); + return ASTNodeFactory(*this).createNode<Literal>(token, m_scanner->getCurrentLiteral()); + case Token::IDENTIFIER: + m_scanner->next(); + return ASTNodeFactory(*this).createNode<Identifier>(m_scanner->getCurrentLiteral()); + case Token::LPAREN: + { + m_scanner->next(); + ptr<Expression> expression = parseExpression(); + expectToken(Token::RPAREN); + return expression; + } + default: + if (Token::IsElementaryTypeName(token)) { + // used for casts + m_scanner->next(); + return ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(token); + } else { + throwExpectationError("Expected primary expression."); + return ptr<Expression>(); // this is not reached + } } } +vecptr<Expression> Parser::parseFunctionCallArguments() +{ + vecptr<Expression> arguments; + if (m_scanner->getCurrentToken() != Token::RPAREN) { + arguments.push_back(parseExpression()); + while (m_scanner->getCurrentToken() != Token::RPAREN) { + expectToken(Token::COMMA); + arguments.push_back(parseExpression()); + } + } + return arguments; +} + void Parser::expectToken(Token::Value _value) { if (m_scanner->getCurrentToken() != _value) @@ -267,6 +483,15 @@ void Parser::expectToken(Token::Value _value) m_scanner->next(); } +Token::Value Parser::expectAssignmentOperator() +{ + Token::Value op = m_scanner->getCurrentToken(); + if (!Token::IsAssignmentOp(op)) + throwExpectationError(std::string("Expected assignment operator")); + m_scanner->next(); + return op; +} + std::string Parser::expectIdentifier() { if (m_scanner->getCurrentToken() != Token::IDENTIFIER) @@ -53,12 +53,22 @@ private: ptr<ParameterList> parseParameterList(); ptr<Block> parseBlock(); ptr<Statement> parseStatement(); + ptr<IfStatement> parseIfStatement(); + ptr<WhileStatement> parseWhileStatement(); + ptr<VariableDefinition> parseVariableDefinition(); + ptr<Expression> parseExpression(); + ptr<Expression> parseBinaryExpression(int _minPrecedence = 4); + ptr<Expression> parseUnaryExpression(); + ptr<Expression> parseLeftHandSideExpression(); + ptr<Expression> parsePrimaryExpression(); + vecptr<Expression> parseFunctionCallArguments(); /// @} /// Helper functions /// @{ /// If current token value is not _value, throw exception otherwise advance token. void expectToken(Token::Value _value); + Token::Value expectAssignmentOperator(); std::string expectIdentifier(); void throwExpectationError(const std::string& _description); /// @} diff --git a/grammar.txt b/grammar.txt index 1946325f..c0ab0607 100644 --- a/grammar.txt +++ b/grammar.txt @@ -15,18 +15,21 @@ TypeName = ElementaryTypeName | Identifier | Mapping Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' Block = '{' Statement* '}' -Statement = IfStatement | WhileStatement | Continue | Break | Return | VariableAssignment | Expression ';' | Block +Statement = IfStatement | WhileStatement | Block | + ( Continue | Break | Return | VariableDefinition | Expression ) ';' IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? WhileStatement = 'while' '(' Expression ')' Statement Continue = 'continue' ';' Break = 'break' ';' Return = 'return' Expression? ';' -VariableAssignment = VariableDeclaration ( AssignmentOp Expression )? ';' +VariableDefinition = VariableDeclaration ( = Expression )? ';' -Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess | MemberAccess | PrimaryExpression +Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess | + MemberAccess | PrimaryExpression +// The expression syntax is actually much more complicated Assignment = Expression (AssignmentOp Expression) -FunctionCall = Identifier '(' ( Expression ( ',' Expression )* ) ')' +FunctionCall = Expression '(' ( Expression ( ',' Expression )* ) ')' MemberAccess = Expression '.' Identifier IndexAccess = Expression '[' Expresison ']' -PrimaryExpression = Identifier | NumberLiteral | StringLiteral | '(' Expression ')' +PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')' |