diff options
Diffstat (limited to 'Parser.cpp')
-rw-r--r-- | Parser.cpp | 195 |
1 files changed, 149 insertions, 46 deletions
@@ -41,8 +41,11 @@ class Parser::ASTNodeFactory public: ASTNodeFactory(Parser const& _parser): m_parser(_parser), m_location(_parser.getPosition(), -1, _parser.getSourceName()) {} + ASTNodeFactory(Parser const& _parser, ASTPointer<ASTNode> const& _childNode): + m_parser(_parser), m_location(_childNode->getLocation()) {} void markEndPosition() { m_location.end = m_parser.getEndPosition(); } + void setLocation(Location const& _location) { m_location = _location; } void setLocationEmpty() { m_location.end = m_location.start; } /// Set the end position to the one of the given node. void setEndPositionFromNode(ASTPointer<ASTNode> const& _node) { m_location.end = _node->getLocation().end; } @@ -299,12 +302,20 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition() return nodeFactory.createNode<EnumDefinition>(name, members); } -ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options) +ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( + VarDeclParserOptions const& _options, ASTPointer<TypeName> const& _lookAheadArrayType) { - ASTNodeFactory nodeFactory(*this); - ASTPointer<TypeName> type = parseTypeName(_options.allowVar); - if (type != nullptr) - nodeFactory.setEndPositionFromNode(type); + ASTNodeFactory nodeFactory = _lookAheadArrayType ? + ASTNodeFactory(*this, _lookAheadArrayType) : ASTNodeFactory(*this); + ASTPointer<TypeName> type; + if (_lookAheadArrayType) + type = _lookAheadArrayType; + else + { + type = parseTypeName(_options.allowVar); + if (type != nullptr) + nodeFactory.setEndPositionFromNode(type); + } bool isIndexed = false; ASTPointer<ASTString> identifier; Token::Value token = m_scanner->getCurrentToken(); @@ -407,6 +418,7 @@ ASTPointer<Identifier> Parser::parseIdentifier() ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) { + ASTNodeFactory nodeFactory(*this); ASTPointer<TypeName> type; Token::Value token = m_scanner->getCurrentToken(); if (Token::isElementaryTypeName(token)) @@ -421,9 +433,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) m_scanner->next(); } else if (token == Token::Mapping) - { type = parseMapping(); - } else if (token == Token::Identifier) { ASTNodeFactory nodeFactory(*this); @@ -432,6 +442,18 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) } else BOOST_THROW_EXCEPTION(createParserError("Expected type name")); + + // Parse "[...]" postfixes for arrays. + while (m_scanner->getCurrentToken() == Token::LBrack) + { + m_scanner->next(); + ASTPointer<Expression> length; + if (m_scanner->getCurrentToken() != Token::RBrack) + length = parseExpression(); + nodeFactory.markEndPosition(); + expectToken(Token::RBrack); + type = nodeFactory.createNode<ArrayTypeName>(type, length); + } return type; } @@ -530,7 +552,7 @@ ASTPointer<Statement> Parser::parseStatement() } // fall-through default: - statement = parseVarDeclOrExprStmt(); + statement = parseSimpleStatement(); } expectToken(Token::Semicolon); return statement; @@ -579,7 +601,7 @@ ASTPointer<ForStatement> Parser::parseForStatement() // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RParen? if (m_scanner->getCurrentToken() != Token::Semicolon) - initExpression = parseVarDeclOrExprStmt(); + initExpression = parseSimpleStatement(); expectToken(Token::Semicolon); if (m_scanner->getCurrentToken() != Token::Semicolon) @@ -598,48 +620,88 @@ ASTPointer<ForStatement> Parser::parseForStatement() body); } -ASTPointer<Statement> Parser::parseVarDeclOrExprStmt() +ASTPointer<Statement> Parser::parseSimpleStatement() { - if (peekVariableDeclarationStatement()) + // These two cases are very hard to distinguish: + // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9; + // In the first case, x is a type name, in the second it is the name of a variable. + int isVariableDeclaration = peekVariableDeclarationStatement(); + if (isVariableDeclaration == 1) return parseVariableDeclarationStatement(); - else + else if (isVariableDeclaration == -1) return parseExpressionStatement(); + + // At this point, we have '(Identifier|ElementaryTypeName) "["'. + // We parse '(Identifier|ElementaryTypeName) ( "[" Expression "]" )+' and then decide whether to hand this over + // to ExpressionStatement or create a VariableDeclarationStatement out of it. + ASTPointer<PrimaryExpression> primary; + if (m_scanner->getCurrentToken() == Token::Identifier) + primary = parseIdentifier(); + else + { + primary = ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(m_scanner->getCurrentToken()); + m_scanner->next(); + } + vector<pair<ASTPointer<Expression>, Location>> indices; + solAssert(m_scanner->getCurrentToken() == Token::LBrack, ""); + Location indexLocation = primary->getLocation(); + bool encounteredEmptyBrackets = false; + do + { + expectToken(Token::LBrack); + ASTPointer<Expression> index; + if (m_scanner->getCurrentToken() == Token::RBrack) + encounteredEmptyBrackets = true; + else + index = parseExpression(); + indexLocation.end = getEndPosition(); + indices.push_back(make_pair(index, indexLocation)); + expectToken(Token::RBrack); + } + while (m_scanner->getCurrentToken() == Token::LBrack); + + if (m_scanner->getCurrentToken() == Token::Identifier || encounteredEmptyBrackets) + return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices)); + else + return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices)); } -ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement() +ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement( + ASTPointer<TypeName> const& _lookAheadArrayType) { - ASTNodeFactory nodeFactory(*this); VarDeclParserOptions options; options.allowVar = true; options.allowInitialValue = true; - ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options); + ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options, _lookAheadArrayType); + ASTNodeFactory nodeFactory(*this, variable); return nodeFactory.createNode<VariableDeclarationStatement>(variable); } -ASTPointer<ExpressionStatement> Parser::parseExpressionStatement() +ASTPointer<ExpressionStatement> Parser::parseExpressionStatement( + ASTPointer<Expression> const& _lookAheadArrayExpression) { - ASTNodeFactory nodeFactory(*this); - ASTPointer<Expression> expression = parseExpression(); - nodeFactory.setEndPositionFromNode(expression); - return nodeFactory.createNode<ExpressionStatement>(expression); + ASTPointer<Expression> expression = parseExpression(_lookAheadArrayExpression); + return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(expression); } -ASTPointer<Expression> Parser::parseExpression() +ASTPointer<Expression> Parser::parseExpression( + ASTPointer<Expression> const& _lookAheadArrayExpression) { - ASTNodeFactory nodeFactory(*this); - ASTPointer<Expression> expression = parseBinaryExpression(); + ASTPointer<Expression> expression = parseBinaryExpression(4, _lookAheadArrayExpression); if (!Token::isAssignmentOp(m_scanner->getCurrentToken())) return expression; Token::Value assignmentOperator = expectAssignmentOperator(); ASTPointer<Expression> rightHandSide = parseExpression(); + ASTNodeFactory nodeFactory(*this, expression); nodeFactory.setEndPositionFromNode(rightHandSide); return nodeFactory.createNode<Assignment>(expression, assignmentOperator, rightHandSide); } -ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence) +ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence, + ASTPointer<Expression> const& _lookAheadArrayExpression) { - ASTNodeFactory nodeFactory(*this); - ASTPointer<Expression> expression = parseUnaryExpression(); + ASTPointer<Expression> expression = parseUnaryExpression(_lookAheadArrayExpression); + ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->getCurrentToken()); for (; precedence >= _minPrecedence; --precedence) while (Token::precedence(m_scanner->getCurrentToken()) == precedence) @@ -653,11 +715,13 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence) return expression; } -ASTPointer<Expression> Parser::parseUnaryExpression() +ASTPointer<Expression> Parser::parseUnaryExpression( + ASTPointer<Expression> const& _lookAheadArrayExpression) { - ASTNodeFactory nodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadArrayExpression ? + ASTNodeFactory(*this, _lookAheadArrayExpression) : ASTNodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); - if (Token::isUnaryOp(token) || Token::isCountOp(token)) + if (!_lookAheadArrayExpression && (Token::isUnaryOp(token) || Token::isCountOp(token))) { // prefix expression m_scanner->next(); @@ -668,7 +732,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression() else { // potential postfix expression - ASTPointer<Expression> subExpression = parseLeftHandSideExpression(); + ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_lookAheadArrayExpression); token = m_scanner->getCurrentToken(); if (!Token::isCountOp(token)) return subExpression; @@ -678,11 +742,16 @@ ASTPointer<Expression> Parser::parseUnaryExpression() } } -ASTPointer<Expression> Parser::parseLeftHandSideExpression() +ASTPointer<Expression> Parser::parseLeftHandSideExpression( + ASTPointer<Expression> const& _lookAheadArrayExpression) { - ASTNodeFactory nodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadArrayExpression ? + ASTNodeFactory(*this, _lookAheadArrayExpression) : ASTNodeFactory(*this); + ASTPointer<Expression> expression; - if (m_scanner->getCurrentToken() == Token::New) + if (_lookAheadArrayExpression) + expression = _lookAheadArrayExpression; + else if (m_scanner->getCurrentToken() == Token::New) { expectToken(Token::New); ASTPointer<Identifier> contractName(parseIdentifier()); @@ -774,10 +843,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() m_scanner->next(); } else - { BOOST_THROW_EXCEPTION(createParserError("Expected primary expression.")); - return ASTPointer<Expression>(); // this is not reached - } break; } return expression; @@ -824,18 +890,55 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars return ret; } +int Parser::peekVariableDeclarationStatement() const +{ + // Distinguish between variable declaration (and potentially assignment) and expression statement + // (which include assignments to other expressions and pre-declared variables). + // We have a variable declaration if we get a keyword that specifies a type name. + // If it is an identifier or an elementary type name followed by an identifier, we also have + // a variable declaration. + // If we get an identifier followed by a "[", it can be both ("type[9] a;" or "arr[9] = 7;"). + // In all other cases, we have an expression statement. + Token::Value token(m_scanner->getCurrentToken()); + bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); + if (token == Token::Mapping || token == Token::Var || + (mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier)) + return 1; + if (mightBeTypeName && m_scanner->peekNextToken() == Token::LBrack) + return 0; + return -1; +} -bool Parser::peekVariableDeclarationStatement() +ASTPointer<TypeName> Parser::typeNameFromArrayIndexStructure( + ASTPointer<PrimaryExpression> const& _primary, vector<pair<ASTPointer<Expression>, Location>> const& _indices) { - // distinguish between variable declaration (and potentially assignment) and expression statement - // (which include assignments to other expressions and pre-declared variables) - // We have a variable declaration if we get a keyword that specifies a type name, or - // in the case of a user-defined type, we have two identifiers following each other. - return (m_scanner->getCurrentToken() == Token::Mapping || - m_scanner->getCurrentToken() == Token::Var || - ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) || - m_scanner->getCurrentToken() == Token::Identifier) && - m_scanner->peekNextToken() == Token::Identifier)); + ASTNodeFactory nodeFactory(*this, _primary); + ASTPointer<TypeName> type; + if (auto identifier = dynamic_cast<Identifier const*>(_primary.get())) + type = nodeFactory.createNode<UserDefinedTypeName>(make_shared<ASTString>(identifier->getName())); + else if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_primary.get())) + type = nodeFactory.createNode<ElementaryTypeName>(typeName->getTypeToken()); + else + solAssert(false, "Invalid type name for array look-ahead."); + for (auto const& lengthExpression: _indices) + { + nodeFactory.setLocation(lengthExpression.second); + type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.first); + } + return type; +} + +ASTPointer<Expression> Parser::expressionFromArrayIndexStructure( + ASTPointer<PrimaryExpression> const& _primary, vector<pair<ASTPointer<Expression>, Location>> const& _indices) +{ + ASTNodeFactory nodeFactory(*this, _primary); + ASTPointer<Expression> expression(_primary); + for (auto const& index: _indices) + { + nodeFactory.setLocation(index.second); + expression = nodeFactory.createNode<IndexAccess>(expression, index.first); + } + return expression; } void Parser::expectToken(Token::Value _value) |