Merge pull request #4047 from ethereum/refactorToMulti

Refactor to allow implementing multi variable declarations.
This commit is contained in:
Alex Beregszaszi 2018-05-09 15:37:19 +01:00 committed by GitHub
commit 868d449c38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 38 deletions

View File

@ -1083,18 +1083,46 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString) ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
{ {
RecursionGuard recursionGuard(*this); 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, "");
}
}
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: // 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. // 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: // As an extension, we can even have:
// `x.y.z[1][2] a;` and `x.y.z[1][2] = 10;` // `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. // 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: case LookAheadInfo::VariableDeclaration:
return parseVariableDeclarationStatement(_docString); case LookAheadInfo::Expression:
case LookAheadInfo::ExpressionStatement: return make_pair(statementType, IndexAccessedPath());
return parseExpressionStatement(_docString);
default: default:
break; break;
} }
@ -1106,9 +1134,9 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
IndexAccessedPath iap = parseIndexAccessedPath(); IndexAccessedPath iap = parseIndexAccessedPath();
if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken())) if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken()))
return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap)); return make_pair(LookAheadInfo::VariableDeclaration, move(iap));
else else
return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap)); return make_pair(LookAheadInfo::Expression, move(iap));
} }
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement( ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
@ -1178,20 +1206,20 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
ASTPointer<ExpressionStatement> Parser::parseExpressionStatement( ASTPointer<ExpressionStatement> Parser::parseExpressionStatement(
ASTPointer<ASTString> const& _docString, ASTPointer<ASTString> const& _docString,
ASTPointer<Expression> const& _lookAheadIndexAccessStructure ASTPointer<Expression> const& _partialParserResult
) )
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTPointer<Expression> expression = parseExpression(_lookAheadIndexAccessStructure); ASTPointer<Expression> expression = parseExpression(_partialParserResult);
return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression); return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression);
} }
ASTPointer<Expression> Parser::parseExpression( ASTPointer<Expression> Parser::parseExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure ASTPointer<Expression> const& _partiallyParsedExpression
) )
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTPointer<Expression> expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); ASTPointer<Expression> expression = parseBinaryExpression(4, _partiallyParsedExpression);
if (Token::isAssignmentOp(m_scanner->currentToken())) if (Token::isAssignmentOp(m_scanner->currentToken()))
{ {
Token::Value assignmentOperator = m_scanner->currentToken(); Token::Value assignmentOperator = m_scanner->currentToken();
@ -1217,11 +1245,11 @@ ASTPointer<Expression> Parser::parseExpression(
ASTPointer<Expression> Parser::parseBinaryExpression( ASTPointer<Expression> Parser::parseBinaryExpression(
int _minPrecedence, int _minPrecedence,
ASTPointer<Expression> const& _lookAheadIndexAccessStructure ASTPointer<Expression> const& _partiallyParsedExpression
) )
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTPointer<Expression> expression = parseUnaryExpression(_lookAheadIndexAccessStructure); ASTPointer<Expression> expression = parseUnaryExpression(_partiallyParsedExpression);
ASTNodeFactory nodeFactory(*this, expression); ASTNodeFactory nodeFactory(*this, expression);
int precedence = Token::precedence(m_scanner->currentToken()); int precedence = Token::precedence(m_scanner->currentToken());
for (; precedence >= _minPrecedence; --precedence) for (; precedence >= _minPrecedence; --precedence)
@ -1237,14 +1265,14 @@ ASTPointer<Expression> Parser::parseBinaryExpression(
} }
ASTPointer<Expression> Parser::parseUnaryExpression( ASTPointer<Expression> Parser::parseUnaryExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure ASTPointer<Expression> const& _partiallyParsedExpression
) )
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
Token::Value token = m_scanner->currentToken(); Token::Value token = m_scanner->currentToken();
if (!_lookAheadIndexAccessStructure && (Token::isUnaryOp(token) || Token::isCountOp(token))) if (!_partiallyParsedExpression && (Token::isUnaryOp(token) || Token::isCountOp(token)))
{ {
// prefix expression // prefix expression
m_scanner->next(); m_scanner->next();
@ -1255,7 +1283,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
else else
{ {
// potential postfix expression // potential postfix expression
ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure); ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_partiallyParsedExpression);
token = m_scanner->currentToken(); token = m_scanner->currentToken();
if (!Token::isCountOp(token)) if (!Token::isCountOp(token))
return subExpression; return subExpression;
@ -1266,16 +1294,16 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
} }
ASTPointer<Expression> Parser::parseLeftHandSideExpression( ASTPointer<Expression> Parser::parseLeftHandSideExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure ASTPointer<Expression> const& _partiallyParsedExpression
) )
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
ASTPointer<Expression> expression; ASTPointer<Expression> expression;
if (_lookAheadIndexAccessStructure) if (_partiallyParsedExpression)
expression = _lookAheadIndexAccessStructure; expression = _partiallyParsedExpression;
else if (m_scanner->currentToken() == Token::New) else if (m_scanner->currentToken() == Token::New)
{ {
expectToken(Token::New); expectToken(Token::New);
@ -1489,16 +1517,16 @@ Parser::LookAheadInfo Parser::peekStatementType() const
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
if (token == Token::Mapping || token == Token::Function || token == Token::Var) if (token == Token::Mapping || token == Token::Function || token == Token::Var)
return LookAheadInfo::VariableDeclarationStatement; return LookAheadInfo::VariableDeclaration;
if (mightBeTypeName) if (mightBeTypeName)
{ {
Token::Value next = m_scanner->peekNextToken(); Token::Value next = m_scanner->peekNextToken();
if (next == Token::Identifier || Token::isLocationSpecifier(next)) if (next == Token::Identifier || Token::isLocationSpecifier(next))
return LookAheadInfo::VariableDeclarationStatement; return LookAheadInfo::VariableDeclaration;
if (next == Token::LBrack || next == Token::Period) if (next == Token::LBrack || next == Token::Period)
return LookAheadInfo::IndexAccessStructure; return LookAheadInfo::IndexAccessStructure;
} }
return LookAheadInfo::ExpressionStatement; return LookAheadInfo::Expression;
} }
Parser::IndexAccessedPath Parser::parseIndexAccessedPath() Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
@ -1539,7 +1567,9 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap) ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap)
{ {
solAssert(!_iap.path.empty(), ""); if (_iap.empty())
return {};
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
SourceLocation location = _iap.path.front()->location(); SourceLocation location = _iap.path.front()->location();
@ -1571,7 +1601,9 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
Parser::IndexAccessedPath const& _iap Parser::IndexAccessedPath const& _iap
) )
{ {
solAssert(!_iap.path.empty(), ""); if (_iap.empty())
return {};
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this, _iap.path.front()); ASTNodeFactory nodeFactory(*this, _iap.path.front());
ASTPointer<Expression> expression(_iap.path.front()); ASTPointer<Expression> expression(_iap.path.front());

View File

@ -118,19 +118,19 @@ private:
); );
ASTPointer<ExpressionStatement> parseExpressionStatement( ASTPointer<ExpressionStatement> parseExpressionStatement(
ASTPointer<ASTString> const& _docString, ASTPointer<ASTString> const& _docString,
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>() ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
); );
ASTPointer<Expression> parseExpression( ASTPointer<Expression> parseExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>() ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
); );
ASTPointer<Expression> parseBinaryExpression(int _minPrecedence = 4, ASTPointer<Expression> parseBinaryExpression(int _minPrecedence = 4,
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>() ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
); );
ASTPointer<Expression> parseUnaryExpression( ASTPointer<Expression> parseUnaryExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>() ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
); );
ASTPointer<Expression> parseLeftHandSideExpression( ASTPointer<Expression> parseLeftHandSideExpression(
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>() ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
); );
ASTPointer<Expression> parsePrimaryExpression(); ASTPointer<Expression> parsePrimaryExpression();
std::vector<ASTPointer<Expression>> parseFunctionCallListArguments(); std::vector<ASTPointer<Expression>> parseFunctionCallListArguments();
@ -143,16 +143,18 @@ private:
/// Used as return value of @see peekStatementType. /// Used as return value of @see peekStatementType.
enum class LookAheadInfo 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 /// 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 struct IndexAccessedPath
{ {
std::vector<ASTPointer<PrimaryExpression>> path; std::vector<ASTPointer<PrimaryExpression>> path;
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> indices; std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> indices;
bool empty() const;
}; };
std::pair<LookAheadInfo, IndexAccessedPath> tryParseIndexAccessedPath();
/// Performs limited look-ahead to distinguish between variable declaration and expression statement. /// 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 /// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to
/// decide with constant look-ahead. /// decide with constant look-ahead.
@ -160,9 +162,11 @@ private:
/// @returns an IndexAccessedPath as a prestage to parsing a variable declaration (type name) /// @returns an IndexAccessedPath as a prestage to parsing a variable declaration (type name)
/// or an expression; /// or an expression;
IndexAccessedPath parseIndexAccessedPath(); 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<TypeName> typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer<TypeName> 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<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
ASTPointer<ASTString> expectIdentifierToken(); ASTPointer<ASTString> expectIdentifierToken();