diff options
Diffstat (limited to 'libsolidity/parsing/Parser.cpp')
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 49745e29..d1be13a5 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1083,18 +1083,46 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString) { RecursionGuard recursionGuard(*this); + LookAheadInfo statementType; + IndexAccessedPath iap; + + tie(statementType, iap) = tryParseIndexAccessedPath(); + switch (statementType) + { + case LookAheadInfo::VariableDeclaration: + return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); + case LookAheadInfo::Expression: + return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); + default: + solAssert(false, ""); + } +} + +bool Parser::IndexAccessedPath::empty() const +{ + if (!indices.empty()) + { + solAssert(!path.empty(), ""); + } + return path.empty() && indices.empty(); +} + + +pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAccessedPath() +{ // These two cases are very hard to distinguish: - // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9; + // x[7 * 20 + 3] a; and x[7 * 20 + 3] = 9; // In the first case, x is a type name, in the second it is the name of a variable. // As an extension, we can even have: // `x.y.z[1][2] a;` and `x.y.z[1][2] = 10;` // Where in the first, x.y.z leads to a type name where in the second, it accesses structs. - switch (peekStatementType()) + + auto statementType = peekStatementType(); + switch (statementType) { - case LookAheadInfo::VariableDeclarationStatement: - return parseVariableDeclarationStatement(_docString); - case LookAheadInfo::ExpressionStatement: - return parseExpressionStatement(_docString); + case LookAheadInfo::VariableDeclaration: + case LookAheadInfo::Expression: + return make_pair(statementType, IndexAccessedPath()); default: break; } @@ -1106,9 +1134,9 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& IndexAccessedPath iap = parseIndexAccessedPath(); if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken())) - return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); + return make_pair(LookAheadInfo::VariableDeclaration, move(iap)); else - return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); + return make_pair(LookAheadInfo::Expression, move(iap)); } ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement( @@ -1178,20 +1206,20 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme ASTPointer<ExpressionStatement> Parser::parseExpressionStatement( ASTPointer<ASTString> const& _docString, - ASTPointer<Expression> const& _lookAheadIndexAccessStructure + ASTPointer<Expression> const& _partialParserResult ) { RecursionGuard recursionGuard(*this); - ASTPointer<Expression> expression = parseExpression(_lookAheadIndexAccessStructure); + ASTPointer<Expression> expression = parseExpression(_partialParserResult); return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression); } ASTPointer<Expression> Parser::parseExpression( - ASTPointer<Expression> const& _lookAheadIndexAccessStructure + ASTPointer<Expression> const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTPointer<Expression> expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); + ASTPointer<Expression> expression = parseBinaryExpression(4, _partiallyParsedExpression); if (Token::isAssignmentOp(m_scanner->currentToken())) { Token::Value assignmentOperator = m_scanner->currentToken(); @@ -1217,11 +1245,11 @@ ASTPointer<Expression> Parser::parseExpression( ASTPointer<Expression> Parser::parseBinaryExpression( int _minPrecedence, - ASTPointer<Expression> const& _lookAheadIndexAccessStructure + ASTPointer<Expression> const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTPointer<Expression> expression = parseUnaryExpression(_lookAheadIndexAccessStructure); + ASTPointer<Expression> expression = parseUnaryExpression(_partiallyParsedExpression); ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->currentToken()); for (; precedence >= _minPrecedence; --precedence) @@ -1237,14 +1265,14 @@ ASTPointer<Expression> Parser::parseBinaryExpression( } ASTPointer<Expression> Parser::parseUnaryExpression( - ASTPointer<Expression> const& _lookAheadIndexAccessStructure + ASTPointer<Expression> const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? - ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); + ASTNodeFactory nodeFactory = _partiallyParsedExpression ? + ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this); Token::Value token = m_scanner->currentToken(); - if (!_lookAheadIndexAccessStructure && (Token::isUnaryOp(token) || Token::isCountOp(token))) + if (!_partiallyParsedExpression && (Token::isUnaryOp(token) || Token::isCountOp(token))) { // prefix expression m_scanner->next(); @@ -1255,7 +1283,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression( else { // potential postfix expression - ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure); + ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_partiallyParsedExpression); token = m_scanner->currentToken(); if (!Token::isCountOp(token)) return subExpression; @@ -1266,16 +1294,16 @@ ASTPointer<Expression> Parser::parseUnaryExpression( } ASTPointer<Expression> Parser::parseLeftHandSideExpression( - ASTPointer<Expression> const& _lookAheadIndexAccessStructure + ASTPointer<Expression> const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? - ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); + ASTNodeFactory nodeFactory = _partiallyParsedExpression ? + ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this); ASTPointer<Expression> expression; - if (_lookAheadIndexAccessStructure) - expression = _lookAheadIndexAccessStructure; + if (_partiallyParsedExpression) + expression = _partiallyParsedExpression; else if (m_scanner->currentToken() == Token::New) { expectToken(Token::New); @@ -1489,16 +1517,16 @@ Parser::LookAheadInfo Parser::peekStatementType() const bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); if (token == Token::Mapping || token == Token::Function || token == Token::Var) - return LookAheadInfo::VariableDeclarationStatement; + return LookAheadInfo::VariableDeclaration; if (mightBeTypeName) { Token::Value next = m_scanner->peekNextToken(); if (next == Token::Identifier || Token::isLocationSpecifier(next)) - return LookAheadInfo::VariableDeclarationStatement; + return LookAheadInfo::VariableDeclaration; if (next == Token::LBrack || next == Token::Period) return LookAheadInfo::IndexAccessStructure; } - return LookAheadInfo::ExpressionStatement; + return LookAheadInfo::Expression; } Parser::IndexAccessedPath Parser::parseIndexAccessedPath() @@ -1539,7 +1567,9 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath() ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap) { - solAssert(!_iap.path.empty(), ""); + if (_iap.empty()) + return {}; + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); SourceLocation location = _iap.path.front()->location(); @@ -1571,7 +1601,9 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure( Parser::IndexAccessedPath const& _iap ) { - solAssert(!_iap.path.empty(), ""); + if (_iap.empty()) + return {}; + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this, _iap.path.front()); ASTPointer<Expression> expression(_iap.path.front()); |