mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #2312 from ethereum/parser-cleanup
Parser cleanup (remove dependency on Solidity AST)
This commit is contained in:
commit
4a5dc6a4ea
@ -50,16 +50,16 @@ assembly::Block Parser::parseBlock()
|
|||||||
{
|
{
|
||||||
assembly::Block block = createWithLocation<Block>();
|
assembly::Block block = createWithLocation<Block>();
|
||||||
expectToken(Token::LBrace);
|
expectToken(Token::LBrace);
|
||||||
while (m_scanner->currentToken() != Token::RBrace)
|
while (currentToken() != Token::RBrace)
|
||||||
block.statements.emplace_back(parseStatement());
|
block.statements.emplace_back(parseStatement());
|
||||||
block.location.end = endPosition();
|
block.location.end = endPosition();
|
||||||
m_scanner->next();
|
advance();
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
assembly::Statement Parser::parseStatement()
|
assembly::Statement Parser::parseStatement()
|
||||||
{
|
{
|
||||||
switch (m_scanner->currentToken())
|
switch (currentToken())
|
||||||
{
|
{
|
||||||
case Token::Let:
|
case Token::Let:
|
||||||
return parseVariableDeclaration();
|
return parseVariableDeclaration();
|
||||||
@ -92,10 +92,10 @@ assembly::Statement Parser::parseStatement()
|
|||||||
if (m_julia)
|
if (m_julia)
|
||||||
break;
|
break;
|
||||||
assembly::StackAssignment assignment = createWithLocation<assembly::StackAssignment>();
|
assembly::StackAssignment assignment = createWithLocation<assembly::StackAssignment>();
|
||||||
m_scanner->next();
|
advance();
|
||||||
expectToken(Token::Colon);
|
expectToken(Token::Colon);
|
||||||
assignment.variableName.location = location();
|
assignment.variableName.location = location();
|
||||||
assignment.variableName.name = m_scanner->currentLiteral();
|
assignment.variableName.name = currentLiteral();
|
||||||
if (!m_julia && instructions().count(assignment.variableName.name))
|
if (!m_julia && instructions().count(assignment.variableName.name))
|
||||||
fatalParserError("Identifier expected, got instruction name.");
|
fatalParserError("Identifier expected, got instruction name.");
|
||||||
assignment.location.end = endPosition();
|
assignment.location.end = endPosition();
|
||||||
@ -110,7 +110,7 @@ assembly::Statement Parser::parseStatement()
|
|||||||
// literal,
|
// literal,
|
||||||
// identifier (might turn into label or functional assignment)
|
// identifier (might turn into label or functional assignment)
|
||||||
Statement statement(parseElementaryOperation(false));
|
Statement statement(parseElementaryOperation(false));
|
||||||
switch (m_scanner->currentToken())
|
switch (currentToken())
|
||||||
{
|
{
|
||||||
case Token::LParen:
|
case Token::LParen:
|
||||||
return parseCall(std::move(statement));
|
return parseCall(std::move(statement));
|
||||||
@ -119,15 +119,15 @@ assembly::Statement Parser::parseStatement()
|
|||||||
if (statement.type() != typeid(assembly::Identifier))
|
if (statement.type() != typeid(assembly::Identifier))
|
||||||
fatalParserError("Label name / variable name must precede \":\".");
|
fatalParserError("Label name / variable name must precede \":\".");
|
||||||
assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
|
assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
|
||||||
m_scanner->next();
|
advance();
|
||||||
// identifier:=: should be parsed as identifier: =: (i.e. a label),
|
// identifier:=: should be parsed as identifier: =: (i.e. a label),
|
||||||
// while identifier:= (being followed by a non-colon) as identifier := (assignment).
|
// while identifier:= (being followed by a non-colon) as identifier := (assignment).
|
||||||
if (m_scanner->currentToken() == Token::Assign && m_scanner->peekNextToken() != Token::Colon)
|
if (currentToken() == Token::Assign && peekNextToken() != Token::Colon)
|
||||||
{
|
{
|
||||||
assembly::Assignment assignment = createWithLocation<assembly::Assignment>(identifier.location);
|
assembly::Assignment assignment = createWithLocation<assembly::Assignment>(identifier.location);
|
||||||
if (!m_julia && instructions().count(identifier.name))
|
if (!m_julia && instructions().count(identifier.name))
|
||||||
fatalParserError("Cannot use instruction names for identifier names.");
|
fatalParserError("Cannot use instruction names for identifier names.");
|
||||||
m_scanner->next();
|
advance();
|
||||||
assignment.variableName = identifier;
|
assignment.variableName = identifier;
|
||||||
assignment.value.reset(new Statement(parseExpression()));
|
assignment.value.reset(new Statement(parseExpression()));
|
||||||
assignment.location.end = locationOf(*assignment.value).end;
|
assignment.location.end = locationOf(*assignment.value).end;
|
||||||
@ -174,7 +174,7 @@ assembly::Case Parser::parseCase()
|
|||||||
assembly::Statement Parser::parseExpression()
|
assembly::Statement Parser::parseExpression()
|
||||||
{
|
{
|
||||||
Statement operation = parseElementaryOperation(true);
|
Statement operation = parseElementaryOperation(true);
|
||||||
if (m_scanner->currentToken() == Token::LParen)
|
if (currentToken() == Token::LParen)
|
||||||
return parseCall(std::move(operation));
|
return parseCall(std::move(operation));
|
||||||
else
|
else
|
||||||
return operation;
|
return operation;
|
||||||
@ -207,7 +207,7 @@ std::map<string, dev::solidity::Instruction> const& Parser::instructions()
|
|||||||
assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
||||||
{
|
{
|
||||||
Statement ret;
|
Statement ret;
|
||||||
switch (m_scanner->currentToken())
|
switch (currentToken())
|
||||||
{
|
{
|
||||||
case Token::Identifier:
|
case Token::Identifier:
|
||||||
case Token::Return:
|
case Token::Return:
|
||||||
@ -215,14 +215,14 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
|||||||
case Token::Address:
|
case Token::Address:
|
||||||
{
|
{
|
||||||
string literal;
|
string literal;
|
||||||
if (m_scanner->currentToken() == Token::Return)
|
if (currentToken() == Token::Return)
|
||||||
literal = "return";
|
literal = "return";
|
||||||
else if (m_scanner->currentToken() == Token::Byte)
|
else if (currentToken() == Token::Byte)
|
||||||
literal = "byte";
|
literal = "byte";
|
||||||
else if (m_scanner->currentToken() == Token::Address)
|
else if (currentToken() == Token::Address)
|
||||||
literal = "address";
|
literal = "address";
|
||||||
else
|
else
|
||||||
literal = m_scanner->currentLiteral();
|
literal = currentLiteral();
|
||||||
// first search the set of instructions.
|
// first search the set of instructions.
|
||||||
if (!m_julia && instructions().count(literal))
|
if (!m_julia && instructions().count(literal))
|
||||||
{
|
{
|
||||||
@ -237,7 +237,7 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = Identifier{location(), literal};
|
ret = Identifier{location(), literal};
|
||||||
m_scanner->next();
|
advance();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token::StringLiteral:
|
case Token::StringLiteral:
|
||||||
@ -246,7 +246,7 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
|||||||
case Token::FalseLiteral:
|
case Token::FalseLiteral:
|
||||||
{
|
{
|
||||||
LiteralKind kind = LiteralKind::Number;
|
LiteralKind kind = LiteralKind::Number;
|
||||||
switch (m_scanner->currentToken())
|
switch (currentToken())
|
||||||
{
|
{
|
||||||
case Token::StringLiteral:
|
case Token::StringLiteral:
|
||||||
kind = LiteralKind::String;
|
kind = LiteralKind::String;
|
||||||
@ -265,10 +265,10 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
|
|||||||
Literal literal{
|
Literal literal{
|
||||||
location(),
|
location(),
|
||||||
kind,
|
kind,
|
||||||
m_scanner->currentLiteral(),
|
currentLiteral(),
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
m_scanner->next();
|
advance();
|
||||||
if (m_julia)
|
if (m_julia)
|
||||||
{
|
{
|
||||||
expectToken(Token::Colon);
|
expectToken(Token::Colon);
|
||||||
@ -297,7 +297,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration()
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
varDecl.variables.emplace_back(parseTypedName());
|
varDecl.variables.emplace_back(parseTypedName());
|
||||||
if (m_scanner->currentToken() == Token::Comma)
|
if (currentToken() == Token::Comma)
|
||||||
expectToken(Token::Comma);
|
expectToken(Token::Comma);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -315,22 +315,22 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
|
|||||||
expectToken(Token::Function);
|
expectToken(Token::Function);
|
||||||
funDef.name = expectAsmIdentifier();
|
funDef.name = expectAsmIdentifier();
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
while (m_scanner->currentToken() != Token::RParen)
|
while (currentToken() != Token::RParen)
|
||||||
{
|
{
|
||||||
funDef.arguments.emplace_back(parseTypedName());
|
funDef.arguments.emplace_back(parseTypedName());
|
||||||
if (m_scanner->currentToken() == Token::RParen)
|
if (currentToken() == Token::RParen)
|
||||||
break;
|
break;
|
||||||
expectToken(Token::Comma);
|
expectToken(Token::Comma);
|
||||||
}
|
}
|
||||||
expectToken(Token::RParen);
|
expectToken(Token::RParen);
|
||||||
if (m_scanner->currentToken() == Token::Sub)
|
if (currentToken() == Token::Sub)
|
||||||
{
|
{
|
||||||
expectToken(Token::Sub);
|
expectToken(Token::Sub);
|
||||||
expectToken(Token::GreaterThan);
|
expectToken(Token::GreaterThan);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
funDef.returns.emplace_back(parseTypedName());
|
funDef.returns.emplace_back(parseTypedName());
|
||||||
if (m_scanner->currentToken() == Token::LBrace)
|
if (currentToken() == Token::LBrace)
|
||||||
break;
|
break;
|
||||||
expectToken(Token::Comma);
|
expectToken(Token::Comma);
|
||||||
}
|
}
|
||||||
@ -359,7 +359,7 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
|
|||||||
for (unsigned i = 0; i < args; ++i)
|
for (unsigned i = 0; i < args; ++i)
|
||||||
{
|
{
|
||||||
/// check for premature closing parentheses
|
/// check for premature closing parentheses
|
||||||
if (m_scanner->currentToken() == Token::RParen)
|
if (currentToken() == Token::RParen)
|
||||||
fatalParserError(string(
|
fatalParserError(string(
|
||||||
"Expected expression (" +
|
"Expected expression (" +
|
||||||
instrInfo.name +
|
instrInfo.name +
|
||||||
@ -371,7 +371,7 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
|
|||||||
ret.arguments.emplace_back(parseExpression());
|
ret.arguments.emplace_back(parseExpression());
|
||||||
if (i != args - 1)
|
if (i != args - 1)
|
||||||
{
|
{
|
||||||
if (m_scanner->currentToken() != Token::Comma)
|
if (currentToken() != Token::Comma)
|
||||||
fatalParserError(string(
|
fatalParserError(string(
|
||||||
"Expected comma (" +
|
"Expected comma (" +
|
||||||
instrInfo.name +
|
instrInfo.name +
|
||||||
@ -380,11 +380,11 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
|
|||||||
" arguments)"
|
" arguments)"
|
||||||
));
|
));
|
||||||
else
|
else
|
||||||
m_scanner->next();
|
advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.location.end = endPosition();
|
ret.location.end = endPosition();
|
||||||
if (m_scanner->currentToken() == Token::Comma)
|
if (currentToken() == Token::Comma)
|
||||||
fatalParserError(
|
fatalParserError(
|
||||||
string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)")
|
string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)")
|
||||||
);
|
);
|
||||||
@ -397,10 +397,10 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
|
|||||||
ret.functionName = std::move(boost::get<Identifier>(_instruction));
|
ret.functionName = std::move(boost::get<Identifier>(_instruction));
|
||||||
ret.location = ret.functionName.location;
|
ret.location = ret.functionName.location;
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
while (m_scanner->currentToken() != Token::RParen)
|
while (currentToken() != Token::RParen)
|
||||||
{
|
{
|
||||||
ret.arguments.emplace_back(parseExpression());
|
ret.arguments.emplace_back(parseExpression());
|
||||||
if (m_scanner->currentToken() == Token::RParen)
|
if (currentToken() == Token::RParen)
|
||||||
break;
|
break;
|
||||||
expectToken(Token::Comma);
|
expectToken(Token::Comma);
|
||||||
}
|
}
|
||||||
@ -433,12 +433,12 @@ TypedName Parser::parseTypedName()
|
|||||||
|
|
||||||
string Parser::expectAsmIdentifier()
|
string Parser::expectAsmIdentifier()
|
||||||
{
|
{
|
||||||
string name = m_scanner->currentLiteral();
|
string name = currentLiteral();
|
||||||
if (m_julia)
|
if (m_julia)
|
||||||
{
|
{
|
||||||
if (m_scanner->currentToken() == Token::Bool)
|
if (currentToken() == Token::Bool)
|
||||||
{
|
{
|
||||||
m_scanner->next();
|
advance();
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1437,5 +1437,49 @@ ASTPointer<ParameterList> Parser::createEmptyParameterList()
|
|||||||
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
|
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string Parser::currentTokenName()
|
||||||
|
{
|
||||||
|
Token::Value token = m_scanner->currentToken();
|
||||||
|
if (Token::isElementaryTypeName(token)) //for the sake of accuracy in reporting
|
||||||
|
{
|
||||||
|
ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
|
||||||
|
return elemTypeName.toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Token::name(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::Value Parser::expectAssignmentOperator()
|
||||||
|
{
|
||||||
|
Token::Value op = m_scanner->currentToken();
|
||||||
|
if (!Token::isAssignmentOp(op))
|
||||||
|
fatalParserError(
|
||||||
|
string("Expected assignment operator, got '") +
|
||||||
|
currentTokenName() +
|
||||||
|
string("'")
|
||||||
|
);
|
||||||
|
m_scanner->next();
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPointer<ASTString> Parser::expectIdentifierToken()
|
||||||
|
{
|
||||||
|
Token::Value id = m_scanner->currentToken();
|
||||||
|
if (id != Token::Identifier)
|
||||||
|
fatalParserError(
|
||||||
|
string("Expected identifier, got '") +
|
||||||
|
currentTokenName() +
|
||||||
|
string("'")
|
||||||
|
);
|
||||||
|
return getLiteralAndAdvance();
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPointer<ASTString> Parser::getLiteralAndAdvance()
|
||||||
|
{
|
||||||
|
ASTPointer<ASTString> identifier = make_shared<ASTString>(m_scanner->currentLiteral());
|
||||||
|
m_scanner->next();
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,11 @@ private:
|
|||||||
std::vector<ASTPointer<PrimaryExpression>> const& _path,
|
std::vector<ASTPointer<PrimaryExpression>> const& _path,
|
||||||
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
|
std::vector<std::pair<ASTPointer<Expression>, SourceLocation>> const& _indices
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std::string currentTokenName();
|
||||||
|
Token::Value expectAssignmentOperator();
|
||||||
|
ASTPointer<ASTString> expectIdentifierToken();
|
||||||
|
ASTPointer<ASTString> getLiteralAndAdvance();
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
|
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
|
||||||
|
@ -80,62 +80,6 @@ void ParserBase::expectToken(Token::Value _value)
|
|||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
Token::Value ParserBase::expectAssignmentOperator()
|
|
||||||
{
|
|
||||||
Token::Value op = m_scanner->currentToken();
|
|
||||||
if (!Token::isAssignmentOp(op))
|
|
||||||
{
|
|
||||||
if (Token::isElementaryTypeName(op)) //for the sake of accuracy in reporting
|
|
||||||
{
|
|
||||||
ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
|
|
||||||
fatalParserError(
|
|
||||||
string("Expected assignment operator, got '") +
|
|
||||||
elemTypeName.toString() +
|
|
||||||
string("'")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fatalParserError(
|
|
||||||
string("Expected assignment operator, got '") +
|
|
||||||
string(Token::name(m_scanner->currentToken())) +
|
|
||||||
string("'")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
m_scanner->next();
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTPointer<ASTString> ParserBase::expectIdentifierToken()
|
|
||||||
{
|
|
||||||
Token::Value id = m_scanner->currentToken();
|
|
||||||
if (id != Token::Identifier)
|
|
||||||
{
|
|
||||||
if (Token::isElementaryTypeName(id)) //for the sake of accuracy in reporting
|
|
||||||
{
|
|
||||||
ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
|
|
||||||
fatalParserError(
|
|
||||||
string("Expected identifier, got '") +
|
|
||||||
elemTypeName.toString() +
|
|
||||||
string("'")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fatalParserError(
|
|
||||||
string("Expected identifier, got '") +
|
|
||||||
string(Token::name(id)) +
|
|
||||||
string("'")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return getLiteralAndAdvance();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTPointer<ASTString> ParserBase::getLiteralAndAdvance()
|
|
||||||
{
|
|
||||||
ASTPointer<ASTString> identifier = make_shared<ASTString>(m_scanner->currentLiteral());
|
|
||||||
m_scanner->next();
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParserBase::parserError(string const& _description)
|
void ParserBase::parserError(string const& _description)
|
||||||
{
|
{
|
||||||
auto err = make_shared<Error>(Error::Type::ParserError);
|
auto err = make_shared<Error>(Error::Type::ParserError);
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <libsolidity/interface/Exceptions.h>
|
#include <libsolidity/interface/Exceptions.h>
|
||||||
|
#include <libsolidity/parsing/Scanner.h>
|
||||||
#include <libsolidity/parsing/Token.h>
|
#include <libsolidity/parsing/Token.h>
|
||||||
#include <libsolidity/ast/ASTForward.h>
|
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
@ -47,14 +47,14 @@ protected:
|
|||||||
/// End position of the current token
|
/// End position of the current token
|
||||||
int endPosition() const;
|
int endPosition() const;
|
||||||
|
|
||||||
|
|
||||||
///@{
|
///@{
|
||||||
///@name Helper functions
|
///@name Helper functions
|
||||||
/// If current token value is not _value, throw exception otherwise advance token.
|
/// If current token value is not _value, throw exception otherwise advance token.
|
||||||
void expectToken(Token::Value _value);
|
void expectToken(Token::Value _value);
|
||||||
Token::Value expectAssignmentOperator();
|
Token::Value currentToken() const { return m_scanner->currentToken(); }
|
||||||
ASTPointer<ASTString> expectIdentifierToken();
|
Token::Value peekNextToken() const { return m_scanner->peekNextToken(); }
|
||||||
ASTPointer<ASTString> getLiteralAndAdvance();
|
std::string currentLiteral() const { return m_scanner->currentLiteral(); }
|
||||||
|
Token::Value advance() { return m_scanner->next(); }
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// Creates a @ref ParserError and annotates it with the current position and the
|
/// Creates a @ref ParserError and annotates it with the current position and the
|
||||||
|
Loading…
Reference in New Issue
Block a user