mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4047 from ethereum/refactorToMulti
Refactor to allow implementing multi variable declarations.
This commit is contained in:
commit
868d449c38
@ -1083,18 +1083,46 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
|
||||
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> 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, "");
|
||||
}
|
||||
}
|
||||
|
||||
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 +1134,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(
|
||||
@ -1178,20 +1206,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 +1245,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 +1265,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 +1283,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 +1294,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 +1517,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 +1567,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 +1601,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());
|
||||
|
@ -118,19 +118,19 @@ private:
|
||||
);
|
||||
ASTPointer<ExpressionStatement> parseExpressionStatement(
|
||||
ASTPointer<ASTString> const& _docString,
|
||||
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
|
||||
ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
|
||||
);
|
||||
ASTPointer<Expression> parseExpression(
|
||||
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
|
||||
ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
|
||||
);
|
||||
ASTPointer<Expression> parseBinaryExpression(int _minPrecedence = 4,
|
||||
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
|
||||
ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
|
||||
);
|
||||
ASTPointer<Expression> parseUnaryExpression(
|
||||
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
|
||||
ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
|
||||
);
|
||||
ASTPointer<Expression> parseLeftHandSideExpression(
|
||||
ASTPointer<Expression> const& _lookAheadIndexAccessStructure = ASTPointer<Expression>()
|
||||
ASTPointer<Expression> const& _partiallyParsedExpression = ASTPointer<Expression>()
|
||||
);
|
||||
ASTPointer<Expression> parsePrimaryExpression();
|
||||
std::vector<ASTPointer<Expression>> parseFunctionCallListArguments();
|
||||
@ -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<ASTPointer<PrimaryExpression>> path;
|
||||
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.
|
||||
/// 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<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<ASTString> expectIdentifierToken();
|
||||
|
Loading…
Reference in New Issue
Block a user