From 86b7adc18f14049c7ea4aed9eaaa9b0368d8ec9e Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 28 Apr 2018 00:17:35 +0200 Subject: Refactor expression parser. --- libsolidity/parsing/Parser.cpp | 32 ++++++++++++++++---------------- libsolidity/parsing/Parser.h | 10 +++++----- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'libsolidity/parsing') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 49745e29..70567998 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1178,20 +1178,20 @@ ASTPointer Parser::parseVariableDeclarationStateme ASTPointer Parser::parseExpressionStatement( ASTPointer const& _docString, - ASTPointer const& _lookAheadIndexAccessStructure + ASTPointer const& _partialParserResult ) { RecursionGuard recursionGuard(*this); - ASTPointer expression = parseExpression(_lookAheadIndexAccessStructure); + ASTPointer expression = parseExpression(_partialParserResult); return ASTNodeFactory(*this, expression).createNode(_docString, expression); } ASTPointer Parser::parseExpression( - ASTPointer const& _lookAheadIndexAccessStructure + ASTPointer const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTPointer expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); + ASTPointer expression = parseBinaryExpression(4, _partiallyParsedExpression); if (Token::isAssignmentOp(m_scanner->currentToken())) { Token::Value assignmentOperator = m_scanner->currentToken(); @@ -1217,11 +1217,11 @@ ASTPointer Parser::parseExpression( ASTPointer Parser::parseBinaryExpression( int _minPrecedence, - ASTPointer const& _lookAheadIndexAccessStructure + ASTPointer const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTPointer expression = parseUnaryExpression(_lookAheadIndexAccessStructure); + ASTPointer expression = parseUnaryExpression(_partiallyParsedExpression); ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->currentToken()); for (; precedence >= _minPrecedence; --precedence) @@ -1237,14 +1237,14 @@ ASTPointer Parser::parseBinaryExpression( } ASTPointer Parser::parseUnaryExpression( - ASTPointer const& _lookAheadIndexAccessStructure + ASTPointer 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 +1255,7 @@ ASTPointer Parser::parseUnaryExpression( else { // potential postfix expression - ASTPointer subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure); + ASTPointer subExpression = parseLeftHandSideExpression(_partiallyParsedExpression); token = m_scanner->currentToken(); if (!Token::isCountOp(token)) return subExpression; @@ -1266,16 +1266,16 @@ ASTPointer Parser::parseUnaryExpression( } ASTPointer Parser::parseLeftHandSideExpression( - ASTPointer const& _lookAheadIndexAccessStructure + ASTPointer const& _partiallyParsedExpression ) { RecursionGuard recursionGuard(*this); - ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? - ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); + ASTNodeFactory nodeFactory = _partiallyParsedExpression ? + ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this); ASTPointer expression; - if (_lookAheadIndexAccessStructure) - expression = _lookAheadIndexAccessStructure; + if (_partiallyParsedExpression) + expression = _partiallyParsedExpression; else if (m_scanner->currentToken() == Token::New) { expectToken(Token::New); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 7f02d895..7a1a390e 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -118,19 +118,19 @@ private: ); ASTPointer parseExpressionStatement( ASTPointer const& _docString, - ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer() + ASTPointer const& _partiallyParsedExpression = ASTPointer() ); ASTPointer parseExpression( - ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer() + ASTPointer const& _partiallyParsedExpression = ASTPointer() ); ASTPointer parseBinaryExpression(int _minPrecedence = 4, - ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer() + ASTPointer const& _partiallyParsedExpression = ASTPointer() ); ASTPointer parseUnaryExpression( - ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer() + ASTPointer const& _partiallyParsedExpression = ASTPointer() ); ASTPointer parseLeftHandSideExpression( - ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer() + ASTPointer const& _partiallyParsedExpression = ASTPointer() ); ASTPointer parsePrimaryExpression(); std::vector> parseFunctionCallListArguments(); -- cgit From be54f4819713ce5737a271bbdc43ac0a73a8e456 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 28 Apr 2018 00:26:56 +0200 Subject: Further refactor. --- libsolidity/parsing/Parser.cpp | 48 ++++++++++++++++++++++++++++++------------ libsolidity/parsing/Parser.h | 12 +++++++---- 2 files changed, 43 insertions(+), 17 deletions(-) (limited to 'libsolidity/parsing') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 70567998..38ef32d5 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1083,18 +1083,36 @@ ASTPointer Parser::parseEmitStatement(ASTPointer const ASTPointer Parser::parseSimpleStatement(ASTPointer 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, ""); + } +} + +pair 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 +1124,9 @@ ASTPointer Parser::parseSimpleStatement(ASTPointer 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 Parser::parseVariableDeclarationStatement( @@ -1489,16 +1507,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 +1557,9 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath() ASTPointer 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 +1591,9 @@ ASTPointer 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(_iap.path.front()); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 7a1a390e..902312e8 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -143,16 +143,18 @@ private: /// Used as return value of @see peekStatementType. enum class LookAheadInfo { - IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement + IndexAccessStructure, VariableDeclaration, Expression }; /// Structure that represents a.b.c[x][y][z]. Can be converted either to an expression - /// or to a type name. Path cannot be empty, but indices can be empty. + /// or to a type name. For this to be valid, path cannot be empty, but indices can be empty. struct IndexAccessedPath { std::vector> path; std::vector, SourceLocation>> indices; + bool empty() const { return path.empty() && indices.empty(); } }; + std::pair tryParseIndexAccessedPath(); /// Performs limited look-ahead to distinguish between variable declaration and expression statement. /// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to /// decide with constant look-ahead. @@ -160,9 +162,11 @@ private: /// @returns an IndexAccessedPath as a prestage to parsing a variable declaration (type name) /// or an expression; IndexAccessedPath parseIndexAccessedPath(); - /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]". + /// @returns a typename parsed in look-ahead fashion from something like "a.b[8][2**70]", + /// or an empty pointer if an empty @a _pathAndIncides has been supplied. ASTPointer typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); - /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]". + /// @returns an expression parsed in look-ahead fashion from something like "a.b[8][2**70]", + /// or an empty pointer if an empty @a _pathAndIncides has been supplied. ASTPointer expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer expectIdentifierToken(); -- cgit From fe8f38a7a47241f4f910ef229e6655de7648c98b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 9 May 2018 14:55:36 +0200 Subject: Assert integrity of empty IndexAccessPath structure. --- libsolidity/parsing/Parser.cpp | 10 ++++++++++ libsolidity/parsing/Parser.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'libsolidity/parsing') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 38ef32d5..d1be13a5 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1098,6 +1098,16 @@ ASTPointer Parser::parseSimpleStatement(ASTPointer const& } } +bool Parser::IndexAccessedPath::empty() const +{ + if (!indices.empty()) + { + solAssert(!path.empty(), ""); + } + return path.empty() && indices.empty(); +} + + pair Parser::tryParseIndexAccessedPath() { // These two cases are very hard to distinguish: diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 902312e8..08653364 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -151,7 +151,7 @@ private: { std::vector> path; std::vector, SourceLocation>> indices; - bool empty() const { return path.empty() && indices.empty(); } + bool empty() const; }; std::pair tryParseIndexAccessedPath(); -- cgit