Refactor parser.

This commit is contained in:
chriseth 2018-04-26 10:42:56 +02:00
parent ef2111a2fe
commit d44fb03322
2 changed files with 73 additions and 66 deletions

View File

@ -1057,16 +1057,16 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
if (m_scanner->currentToken() != Token::Identifier) if (m_scanner->currentToken() != Token::Identifier)
fatalParserError("Expected event name or path."); fatalParserError("Expected event name or path.");
vector<ASTPointer<PrimaryExpression>> path; IndexAccessedPath iap;
while (true) while (true)
{ {
path.push_back(parseIdentifier()); iap.path.push_back(parseIdentifier());
if (m_scanner->currentToken() != Token::Period) if (m_scanner->currentToken() != Token::Period)
break; break;
m_scanner->next(); m_scanner->next();
}; };
auto eventName = expressionFromIndexAccessStructure(path, {}); auto eventName = expressionFromIndexAccessStructure(iap);
expectToken(Token::LParen); expectToken(Token::LParen);
vector<ASTPointer<Expression>> arguments; vector<ASTPointer<Expression>> arguments;
@ -1098,46 +1098,17 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
default: default:
break; break;
} }
// At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'. // At this point, we have 'Identifier "["' or 'Identifier "." Identifier' or 'ElementoryTypeName "["'.
// We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )+' // We parse '(Identifier ("." Identifier)* |ElementaryTypeName) ( "[" Expression "]" )*'
// until we can decide whether to hand this over to ExpressionStatement or create a // until we can decide whether to hand this over to ExpressionStatement or create a
// VariableDeclarationStatement out of it. // VariableDeclarationStatement out of it.
vector<ASTPointer<PrimaryExpression>> path; IndexAccessedPath iap = parseIndexAccessedPath();
bool startedWithElementary = false;
if (m_scanner->currentToken() == Token::Identifier)
path.push_back(parseIdentifier());
else
{
startedWithElementary = true;
unsigned firstNum;
unsigned secondNum;
tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
m_scanner->next();
}
while (!startedWithElementary && m_scanner->currentToken() == Token::Period)
{
m_scanner->next();
path.push_back(parseIdentifier());
}
vector<pair<ASTPointer<Expression>, SourceLocation>> indices;
while (m_scanner->currentToken() == Token::LBrack)
{
expectToken(Token::LBrack);
ASTPointer<Expression> index;
if (m_scanner->currentToken() != Token::RBrack)
index = parseExpression();
SourceLocation indexLocation = path.front()->location();
indexLocation.end = endPosition();
indices.push_back(make_pair(index, indexLocation));
expectToken(Token::RBrack);
}
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, typeNameIndexAccessStructure(path, indices)); return parseVariableDeclarationStatement(_docString, typeNameFromIndexAccessStructure(iap));
else else
return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(path, indices)); return parseExpressionStatement(_docString, expressionFromIndexAccessStructure(iap));
} }
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement( ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
@ -1529,32 +1500,65 @@ Parser::LookAheadInfo Parser::peekStatementType() const
return LookAheadInfo::ExpressionStatement; return LookAheadInfo::ExpressionStatement;
} }
ASTPointer<TypeName> Parser::typeNameIndexAccessStructure( Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
vector<ASTPointer<PrimaryExpression>> const& _path,
vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
)
{ {
solAssert(!_path.empty(), ""); IndexAccessedPath iap;
if (m_scanner->currentToken() == Token::Identifier)
{
iap.path.push_back(parseIdentifier());
while (m_scanner->currentToken() == Token::Period)
{
m_scanner->next();
iap.path.push_back(parseIdentifier());
}
}
else
{
unsigned firstNum;
unsigned secondNum;
tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
m_scanner->next();
}
while (m_scanner->currentToken() == Token::LBrack)
{
expectToken(Token::LBrack);
ASTPointer<Expression> index;
if (m_scanner->currentToken() != Token::RBrack)
index = parseExpression();
SourceLocation indexLocation = iap.path.front()->location();
indexLocation.end = endPosition();
iap.indices.push_back(make_pair(index, indexLocation));
expectToken(Token::RBrack);
}
return iap;
}
ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAccessedPath const& _iap)
{
solAssert(!_iap.path.empty(), "");
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
SourceLocation location = _path.front()->location(); SourceLocation location = _iap.path.front()->location();
location.end = _path.back()->location().end; location.end = _iap.path.back()->location().end;
nodeFactory.setLocation(location); nodeFactory.setLocation(location);
ASTPointer<TypeName> type; ASTPointer<TypeName> type;
if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_path.front().get())) if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_iap.path.front().get()))
{ {
solAssert(_path.size() == 1, ""); solAssert(_iap.path.size() == 1, "");
type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeName()); type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeName());
} }
else else
{ {
vector<ASTString> path; vector<ASTString> path;
for (auto const& el: _path) for (auto const& el: _iap.path)
path.push_back(dynamic_cast<Identifier const&>(*el).name()); path.push_back(dynamic_cast<Identifier const&>(*el).name());
type = nodeFactory.createNode<UserDefinedTypeName>(path); type = nodeFactory.createNode<UserDefinedTypeName>(path);
} }
for (auto const& lengthExpression: _indices) for (auto const& lengthExpression: _iap.indices)
{ {
nodeFactory.setLocation(lengthExpression.second); nodeFactory.setLocation(lengthExpression.second);
type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.first); type = nodeFactory.createNode<ArrayTypeName>(type, lengthExpression.first);
@ -1563,26 +1567,25 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure(
} }
ASTPointer<Expression> Parser::expressionFromIndexAccessStructure( ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
vector<ASTPointer<PrimaryExpression>> const& _path, Parser::IndexAccessedPath const& _iap
vector<pair<ASTPointer<Expression>, SourceLocation>> const& _indices
) )
{ {
solAssert(!_path.empty(), ""); solAssert(!_iap.path.empty(), "");
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this, _path.front()); ASTNodeFactory nodeFactory(*this, _iap.path.front());
ASTPointer<Expression> expression(_path.front()); ASTPointer<Expression> expression(_iap.path.front());
for (size_t i = 1; i < _path.size(); ++i) for (size_t i = 1; i < _iap.path.size(); ++i)
{ {
SourceLocation location(_path.front()->location()); SourceLocation location(_iap.path.front()->location());
location.end = _path[i]->location().end; location.end = _iap.path[i]->location().end;
nodeFactory.setLocation(location); nodeFactory.setLocation(location);
Identifier const& identifier = dynamic_cast<Identifier const&>(*_path[i]); Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
expression = nodeFactory.createNode<MemberAccess>( expression = nodeFactory.createNode<MemberAccess>(
expression, expression,
make_shared<ASTString>(identifier.name()) make_shared<ASTString>(identifier.name())
); );
} }
for (auto const& index: _indices) for (auto const& index: _iap.indices)
{ {
nodeFactory.setLocation(index.second); nodeFactory.setLocation(index.second);
expression = nodeFactory.createNode<IndexAccess>(expression, index.first); expression = nodeFactory.createNode<IndexAccess>(expression, index.first);

View File

@ -145,21 +145,25 @@ private:
{ {
IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement
}; };
/// 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.
struct IndexAccessedPath
{
std::vector<ASTPointer<PrimaryExpression>> path;
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> indices;
};
/// 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.
LookAheadInfo peekStatementType() const; LookAheadInfo peekStatementType() const;
/// @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]".
ASTPointer<TypeName> typeNameIndexAccessStructure( ASTPointer<TypeName> typeNameFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
std::vector<ASTPointer<PrimaryExpression>> const& _path,
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
);
/// @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]".
ASTPointer<Expression> expressionFromIndexAccessStructure( ASTPointer<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
std::vector<ASTPointer<PrimaryExpression>> const& _path,
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
);
std::string currentTokenName(); std::string currentTokenName();
Token::Value expectAssignmentOperator(); Token::Value expectAssignmentOperator();