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