From d44fb033221e29a2e648ea248f85604cb9619237 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 26 Apr 2018 10:42:56 +0200 Subject: Refactor parser. --- libsolidity/parsing/Parser.cpp | 119 +++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 58 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 618a0896..a9ee9016 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1057,16 +1057,16 @@ ASTPointer Parser::parseEmitStatement(ASTPointer const if (m_scanner->currentToken() != Token::Identifier) fatalParserError("Expected event name or path."); - vector> path; + IndexAccessedPath iap; while (true) { - path.push_back(parseIdentifier()); + iap.path.push_back(parseIdentifier()); if (m_scanner->currentToken() != Token::Period) break; m_scanner->next(); }; - auto eventName = expressionFromIndexAccessStructure(path, {}); + auto eventName = expressionFromIndexAccessStructure(iap); expectToken(Token::LParen); vector> arguments; @@ -1098,46 +1098,17 @@ ASTPointer Parser::parseSimpleStatement(ASTPointer const& default: break; } + // At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'. - // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )+' + // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )*' // until we can decide whether to hand this over to ExpressionStatement or create a // VariableDeclarationStatement out of it. - vector> path; - bool startedWithElementary = false; - if (m_scanner->currentToken() == Token::Identifier) - path.push_back(parseIdentifier()); - else - { - startedWithElementary = true; - unsigned firstNum; - unsigned secondNum; - tie(firstNum, secondNum) = m_scanner->currentTokenInfo(); - ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum); - path.push_back(ASTNodeFactory(*this).createNode(elemToken)); - m_scanner->next(); - } - while (!startedWithElementary && m_scanner->currentToken() == Token::Period) - { - m_scanner->next(); - path.push_back(parseIdentifier()); - } - vector, SourceLocation>> indices; - while (m_scanner->currentToken() == Token::LBrack) - { - expectToken(Token::LBrack); - ASTPointer index; - if (m_scanner->currentToken() != Token::RBrack) - index = parseExpression(); - SourceLocation indexLocation = path.front()->location(); - indexLocation.end = endPosition(); - indices.push_back(make_pair(index, indexLocation)); - expectToken(Token::RBrack); - } + IndexAccessedPath iap = parseIndexAccessedPath(); if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken())) - return parseVariableDeclarationStatement(_docString, typeNameIndexAccessStructure(path, indices)); + return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); else - return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(path, indices)); + return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); } ASTPointer Parser::parseVariableDeclarationStatement( @@ -1529,32 +1500,65 @@ Parser::LookAheadInfo Parser::peekStatementType() const return LookAheadInfo::ExpressionStatement; } -ASTPointer Parser::typeNameIndexAccessStructure( - vector> const& _path, - vector, SourceLocation>> const& _indices -) +Parser::IndexAccessedPath Parser::parseIndexAccessedPath() +{ + IndexAccessedPath iap; + if (m_scanner->currentToken() == Token::Identifier) + { + iap.path.push_back(parseIdentifier()); + while (m_scanner->currentToken() == Token::Period) + { + m_scanner->next(); + iap.path.push_back(parseIdentifier()); + } + } + else + { + unsigned firstNum; + unsigned secondNum; + tie(firstNum, secondNum) = m_scanner->currentTokenInfo(); + ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum); + iap.path.push_back(ASTNodeFactory(*this).createNode(elemToken)); + m_scanner->next(); + } + while (m_scanner->currentToken() == Token::LBrack) + { + expectToken(Token::LBrack); + ASTPointer index; + if (m_scanner->currentToken() != Token::RBrack) + index = parseExpression(); + SourceLocation indexLocation = iap.path.front()->location(); + indexLocation.end = endPosition(); + iap.indices.push_back(make_pair(index, indexLocation)); + expectToken(Token::RBrack); + } + + return iap; +} + +ASTPointer Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap) { - solAssert(!_path.empty(), ""); + solAssert(!_iap.path.empty(), ""); RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); - SourceLocation location = _path.front()->location(); - location.end = _path.back()->location().end; + SourceLocation location = _iap.path.front()->location(); + location.end = _iap.path.back()->location().end; nodeFactory.setLocation(location); ASTPointer type; - if (auto typeName = dynamic_cast(_path.front().get())) + if (auto typeName = dynamic_cast(_iap.path.front().get())) { - solAssert(_path.size() == 1, ""); + solAssert(_iap.path.size() == 1, ""); type = nodeFactory.createNode(typeName->typeName()); } else { vector path; - for (auto const& el: _path) + for (auto const& el: _iap.path) path.push_back(dynamic_cast(*el).name()); type = nodeFactory.createNode(path); } - for (auto const& lengthExpression: _indices) + for (auto const& lengthExpression: _iap.indices) { nodeFactory.setLocation(lengthExpression.second); type = nodeFactory.createNode(type, lengthExpression.first); @@ -1563,26 +1567,25 @@ ASTPointer Parser::typeNameIndexAccessStructure( } ASTPointer Parser::expressionFromIndexAccessStructure( - vector> const& _path, - vector, SourceLocation>> const& _indices + Parser::IndexAccessedPath const& _iap ) { - solAssert(!_path.empty(), ""); + solAssert(!_iap.path.empty(), ""); RecursionGuard recursionGuard(*this); - ASTNodeFactory nodeFactory(*this, _path.front()); - ASTPointer expression(_path.front()); - for (size_t i = 1; i < _path.size(); ++i) + ASTNodeFactory nodeFactory(*this, _iap.path.front()); + ASTPointer expression(_iap.path.front()); + for (size_t i = 1; i < _iap.path.size(); ++i) { - SourceLocation location(_path.front()->location()); - location.end = _path[i]->location().end; + SourceLocation location(_iap.path.front()->location()); + location.end = _iap.path[i]->location().end; nodeFactory.setLocation(location); - Identifier const& identifier = dynamic_cast(*_path[i]); + Identifier const& identifier = dynamic_cast(*_iap.path[i]); expression = nodeFactory.createNode( expression, make_shared(identifier.name()) ); } - for (auto const& index: _indices) + for (auto const& index: _iap.indices) { nodeFactory.setLocation(index.second); expression = nodeFactory.createNode(expression, index.first); -- cgit v1.2.3 From 73c99d15cdf5ef0589096d6d42025a21502fc8d9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 2 May 2018 20:18:11 +0100 Subject: Remove useless helper expectAssignmentOperator in parser --- libsolidity/parsing/Parser.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index a9ee9016..411466cd 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1194,7 +1194,8 @@ ASTPointer Parser::parseExpression( ASTPointer expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); if (Token::isAssignmentOp(m_scanner->currentToken())) { - Token::Value assignmentOperator = expectAssignmentOperator(); + Token::Value assignmentOperator = m_scanner->currentToken(); + m_scanner->next(); ASTPointer rightHandSide = parseExpression(); ASTNodeFactory nodeFactory(*this, expression); nodeFactory.setEndPositionFromNode(rightHandSide); @@ -1613,19 +1614,6 @@ string Parser::currentTokenName() return Token::name(token); } -Token::Value Parser::expectAssignmentOperator() -{ - Token::Value op = m_scanner->currentToken(); - if (!Token::isAssignmentOp(op)) - fatalParserError( - string("Expected assignment operator, got '") + - currentTokenName() + - string("'") - ); - m_scanner->next(); - return op; -} - ASTPointer Parser::expectIdentifierToken() { Token::Value id = m_scanner->currentToken(); -- cgit v1.2.3 From ed9f80690bde53e56c6ef5cb046fb20713f3f780 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 2 May 2018 20:42:26 +0100 Subject: Simplify expectIdentifierToken by using expectToken --- libsolidity/parsing/Parser.cpp | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 411466cd..37732a37 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1602,27 +1602,10 @@ ASTPointer Parser::createEmptyParameterList() return nodeFactory.createNode(vector>()); } -string Parser::currentTokenName() -{ - Token::Value token = m_scanner->currentToken(); - if (Token::isElementaryTypeName(token)) //for the sake of accuracy in reporting - { - ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken(); - return elemTypeName.toString(); - } - else - return Token::name(token); -} - ASTPointer Parser::expectIdentifierToken() { - Token::Value id = m_scanner->currentToken(); - if (id != Token::Identifier) - fatalParserError( - string("Expected identifier, got '") + - currentTokenName() + - string("'") - ); + // do not advance on success + expectToken(Token::Identifier, false); return getLiteralAndAdvance(); } -- cgit v1.2.3 From cc108390737dfb8d774622d76e69e94485b0f7b5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 2 May 2018 19:59:05 +0100 Subject: Have more uniform parser errors --- libsolidity/parsing/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 37732a37..49745e29 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -528,7 +528,7 @@ ASTPointer Parser::parseEnumDefinition() break; expectToken(Token::Comma); if (m_scanner->currentToken() != Token::Identifier) - fatalParserError(string("Expected Identifier after ','")); + fatalParserError(string("Expected identifier after ','")); } if (members.size() == 0) parserError({"enum with no members is not allowed."}); -- cgit v1.2.3 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 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') 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); -- cgit v1.2.3 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 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') 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()); -- cgit v1.2.3 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 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'libsolidity/parsing/Parser.cpp') 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: -- cgit v1.2.3 From 67d208d144a179e52e1aab3fbd1bd67fe20176b7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 26 Apr 2018 10:43:11 +0200 Subject: Parse multi variable declaration statement. --- libsolidity/parsing/Parser.cpp | 83 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 8 deletions(-) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index d1be13a5..01c1fa99 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1086,15 +1086,79 @@ ASTPointer Parser::parseSimpleStatement(ASTPointer const& LookAheadInfo statementType; IndexAccessedPath iap; - tie(statementType, iap) = tryParseIndexAccessedPath(); - switch (statementType) + if (m_scanner->currentToken() == Token::LParen) { - case LookAheadInfo::VariableDeclaration: - return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); - case LookAheadInfo::Expression: - return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); - default: - solAssert(false, ""); + ASTNodeFactory nodeFactory(*this); + size_t emptyComponents = 0; + // First consume all empty components. + expectToken(Token::LParen); + while (m_scanner->currentToken() == Token::Comma) + { + m_scanner->next(); + emptyComponents++; + } + + // Now see whether we have a variable declaration or an expression. + tie(statementType, iap) = tryParseIndexAccessedPath(); + switch (statementType) + { + case LookAheadInfo::VariableDeclaration: + { + vector> variables; + ASTPointer value; + // We have already parsed something like `(,,,,a.b.c[2][3]` + VarDeclParserOptions options; + options.allowLocationSpecifier = true; + variables = vector>(emptyComponents, nullptr); + variables.push_back(parseVariableDeclaration(options, typeNameFromIndexAccessStructure(iap))); + + while (m_scanner->currentToken() != Token::RParen) + { + expectToken(Token::Comma); + if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen) + variables.push_back(nullptr); + else + variables.push_back(parseVariableDeclaration(options)); + } + expectToken(Token::RParen); + expectToken(Token::Assign); + value = parseExpression(); + nodeFactory.setEndPositionFromNode(value); + return nodeFactory.createNode(_docString, variables, value); + } + case LookAheadInfo::Expression: + { + // Complete parsing the expression in the current component. + vector> components(emptyComponents, nullptr); + components.push_back(parseExpression(expressionFromIndexAccessStructure(iap))); + while (m_scanner->currentToken() != Token::RParen) + { + expectToken(Token::Comma); + if (m_scanner->currentToken() == Token::Comma || m_scanner->currentToken() == Token::RParen) + components.push_back(ASTPointer()); + else + components.push_back(parseExpression()); + } + nodeFactory.markEndPosition(); + expectToken(Token::RParen); + return parseExpressionStatement(_docString, nodeFactory.createNode(components, false)); + } + default: + solAssert(false, ""); + } + } + else + { + 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, ""); + } } } @@ -1144,6 +1208,9 @@ ASTPointer Parser::parseVariableDeclarationStateme ASTPointer const& _lookAheadArrayType ) { + // This does not parse multi variable declaration statements starting directly with + // `(`, they are parsed in parseSimpleStatement, because they are hard to distinguish + // from tuple expressions. RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); if (_lookAheadArrayType) -- cgit v1.2.3 From 3ca6738114f9ae410c7488a1b1d66eeec92833c6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 30 Apr 2018 15:26:25 +0200 Subject: Add assert about source location. --- libsolidity/parsing/Parser.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'libsolidity/parsing/Parser.cpp') diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 01c1fa99..e2e1eebc 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -54,6 +54,7 @@ public: template ASTPointer createNode(Args&& ... _args) { + solAssert(m_location.sourceName, ""); if (m_location.end < 0) markEndPosition(); return make_shared(m_location, forward(_args)...); -- cgit v1.2.3