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)
|
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());
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user