aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/parsing/Parser.cpp')
-rw-r--r--libsolidity/parsing/Parser.cpp158
1 files changed, 129 insertions, 29 deletions
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 49745e29..e2e1eebc 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -54,6 +54,7 @@ public:
template <class NodeType, typename... Args>
ASTPointer<NodeType> createNode(Args&& ... _args)
{
+ solAssert(m_location.sourceName, "");
if (m_location.end < 0)
markEndPosition();
return make_shared<NodeType>(m_location, forward<Args>(_args)...);
@@ -1083,18 +1084,110 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
{
RecursionGuard recursionGuard(*this);
+ LookAheadInfo statementType;
+ IndexAccessedPath iap;
+
+ if (m_scanner->currentToken() == Token::LParen)
+ {
+ 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<ASTPointer<VariableDeclaration>> variables;
+ ASTPointer<Expression> value;
+ // We have already parsed something like `(,,,,a.b.c[2][3]`
+ VarDeclParserOptions options;
+ options.allowLocationSpecifier = true;
+ variables = vector<ASTPointer<VariableDeclaration>>(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<VariableDeclarationStatement>(_docString, variables, value);
+ }
+ case LookAheadInfo::Expression:
+ {
+ // Complete parsing the expression in the current component.
+ vector<ASTPointer<Expression>> 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<Expression>());
+ else
+ components.push_back(parseExpression());
+ }
+ nodeFactory.markEndPosition();
+ expectToken(Token::RParen);
+ return parseExpressionStatement(_docString, nodeFactory.createNode<TupleExpression>(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, "");
+ }
+ }
+}
+
+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 +1199,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(
@@ -1116,6 +1209,9 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
ASTPointer<TypeName> 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)
@@ -1178,20 +1274,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 +1313,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 +1333,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 +1351,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 +1362,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 +1585,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 +1635,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 +1669,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());