Further refactor.

This commit is contained in:
chriseth 2018-04-28 00:26:56 +02:00
parent 86b7adc18f
commit be54f48197
2 changed files with 43 additions and 17 deletions

View File

@ -1083,18 +1083,36 @@ 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, "");
}
}
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 +1124,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(
@ -1489,16 +1507,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 +1557,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 +1591,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());

View File

@ -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 { return path.empty() && indices.empty(); }
};
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();