diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index def8b9ac4..221d8a12a 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -625,11 +625,13 @@ ASTPointer Parser::parseSimpleStatement() // 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) + switch (peekStatementType()) + { + case LookAheadInfo::VariableDeclarationStatement: return parseVariableDeclarationStatement(); - else if (isVariableDeclaration == -1) + case LookAheadInfo::ExpressionStatement: return parseExpressionStatement(); + } // At this point, we have '(Identifier|ElementaryTypeName) "["'. // We parse '(Identifier|ElementaryTypeName) ( "[" Expression "]" )+' and then decide whether to hand this over @@ -658,9 +660,9 @@ ASTPointer Parser::parseSimpleStatement() while (m_scanner->getCurrentToken() == Token::LBrack); if (m_scanner->getCurrentToken() == Token::Identifier) - return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices)); + return parseVariableDeclarationStatement(typeNameIndexAccessStructure(primary, indices)); else - return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices)); + return parseExpressionStatement(expressionFromIndexAccessStructure(primary, indices)); } ASTPointer Parser::parseVariableDeclarationStatement( @@ -675,16 +677,16 @@ ASTPointer Parser::parseVariableDeclarationStateme } ASTPointer Parser::parseExpressionStatement( - ASTPointer const& _lookAheadArrayExpression) + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTPointer expression = parseExpression(_lookAheadArrayExpression); + ASTPointer expression = parseExpression(_lookAheadIndexAccessStructure); return ASTNodeFactory(*this, expression).createNode(expression); } ASTPointer Parser::parseExpression( - ASTPointer const& _lookAheadArrayExpression) + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTPointer expression = parseBinaryExpression(4, _lookAheadArrayExpression); + ASTPointer expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); if (!Token::isAssignmentOp(m_scanner->getCurrentToken())) return expression; Token::Value assignmentOperator = expectAssignmentOperator(); @@ -695,9 +697,9 @@ ASTPointer Parser::parseExpression( } ASTPointer Parser::parseBinaryExpression(int _minPrecedence, - ASTPointer const& _lookAheadArrayExpression) + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTPointer expression = parseUnaryExpression(_lookAheadArrayExpression); + ASTPointer expression = parseUnaryExpression(_lookAheadIndexAccessStructure); ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->getCurrentToken()); for (; precedence >= _minPrecedence; --precedence) @@ -713,12 +715,12 @@ ASTPointer Parser::parseBinaryExpression(int _minPrecedence, } ASTPointer Parser::parseUnaryExpression( - ASTPointer const& _lookAheadArrayExpression) + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory = _lookAheadArrayExpression ? - ASTNodeFactory(*this, _lookAheadArrayExpression) : ASTNodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? + ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); - if (!_lookAheadArrayExpression && (Token::isUnaryOp(token) || Token::isCountOp(token))) + if (!_lookAheadIndexAccessStructure && (Token::isUnaryOp(token) || Token::isCountOp(token))) { // prefix expression m_scanner->next(); @@ -729,7 +731,7 @@ ASTPointer Parser::parseUnaryExpression( else { // potential postfix expression - ASTPointer subExpression = parseLeftHandSideExpression(_lookAheadArrayExpression); + ASTPointer subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure); token = m_scanner->getCurrentToken(); if (!Token::isCountOp(token)) return subExpression; @@ -740,14 +742,14 @@ ASTPointer Parser::parseUnaryExpression( } ASTPointer Parser::parseLeftHandSideExpression( - ASTPointer const& _lookAheadArrayExpression) + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory = _lookAheadArrayExpression ? - ASTNodeFactory(*this, _lookAheadArrayExpression) : ASTNodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? + ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); ASTPointer expression; - if (_lookAheadArrayExpression) - expression = _lookAheadArrayExpression; + if (_lookAheadIndexAccessStructure) + expression = _lookAheadIndexAccessStructure; else if (m_scanner->getCurrentToken() == Token::New) { expectToken(Token::New); @@ -889,7 +891,7 @@ pair>, vector>> Parser::pars return ret; } -int Parser::peekVariableDeclarationStatement() const +Parser::LookAheadInfo Parser::peekStatementType() const { // Distinguish between variable declaration (and potentially assignment) and expression statement // (which include assignments to other expressions and pre-declared variables). @@ -902,13 +904,13 @@ int Parser::peekVariableDeclarationStatement() const bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); if (token == Token::Mapping || token == Token::Var || (mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier)) - return 1; + return LookAheadInfo::VariableDeclarationStatement; if (mightBeTypeName && m_scanner->peekNextToken() == Token::LBrack) - return 0; - return -1; + return LookAheadInfo::IndexAccessStructure; + return LookAheadInfo::ExpressionStatement; } -ASTPointer Parser::typeNameFromArrayIndexStructure( +ASTPointer Parser::typeNameIndexAccessStructure( ASTPointer const& _primary, vector, Location>> const& _indices) { ASTNodeFactory nodeFactory(*this, _primary); @@ -927,7 +929,7 @@ ASTPointer Parser::typeNameFromArrayIndexStructure( return type; } -ASTPointer Parser::expressionFromArrayIndexStructure( +ASTPointer Parser::expressionFromIndexAccessStructure( ASTPointer const& _primary, vector, Location>> const& _indices) { ASTNodeFactory nodeFactory(*this, _primary); diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 8726decb8..b6a7851ec 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -84,15 +84,15 @@ private: ASTPointer parseVariableDeclarationStatement( ASTPointer const& _lookAheadArrayType = ASTPointer()); ASTPointer parseExpressionStatement( - ASTPointer const& _lookAheadArrayExpression = ASTPointer()); + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parseExpression( - ASTPointer const& _lookAheadArrayExpression = ASTPointer()); + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parseBinaryExpression(int _minPrecedence = 4, - ASTPointer const& _lookAheadArrayExpression = ASTPointer()); + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parseUnaryExpression( - ASTPointer const& _lookAheadArrayExpression = ASTPointer()); + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parseLeftHandSideExpression( - ASTPointer const& _lookAheadArrayExpression = ASTPointer()); + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parsePrimaryExpression(); std::vector> parseFunctionCallListArguments(); std::pair>, std::vector>> parseFunctionCallArguments(); @@ -101,16 +101,22 @@ private: ///@{ ///@name Helper functions + /// Used as return value of @see peekStatementType. + enum class LookAheadInfo + { + IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement + }; + /// Performs limited look-ahead to distinguish between variable declaration and expression statement. - /// @returns 1 if it is a variable declaration, -1 if it is an expression statement and 0 if - /// it might be an array-typed variable declaration or an index access to an existing variable. - int peekVariableDeclarationStatement() const; + /// For source code of the form "a[][8]" ("IndexAccessStructure"), this it is not possible to + /// decide with constant look-ahead. + LookAheadInfo peekStatementType() const; /// Returns a typename parsed in look-ahead fashion from something like "a[8][2**70]". - ASTPointer typeNameFromArrayIndexStructure( + ASTPointer typeNameIndexAccessStructure( ASTPointer const& _primary, std::vector, Location>> const& _indices); /// Returns an expression parsed in look-ahead fashion from something like "a[8][2**70]". - ASTPointer expressionFromArrayIndexStructure( + ASTPointer expressionFromIndexAccessStructure( ASTPointer const& _primary, std::vector, Location>> const& _indices); /// If current token value is not _value, throw exception otherwise advance token. diff --git a/libsolidity/Types.h b/libsolidity/Types.h index b13f3517e..7e02f878d 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -279,7 +279,8 @@ public: }; /** - * The type of a byte array, prototype for a general array. + * The type of an array, the flavours are byte array (bytes), statically- ([]) + * and dynamically-sized array ([]). */ class ArrayType: public Type {