aboutsummaryrefslogtreecommitdiffstats
path: root/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Parser.cpp')
-rw-r--r--Parser.cpp507
1 files changed, 370 insertions, 137 deletions
diff --git a/Parser.cpp b/Parser.cpp
index e287319d..72334c6c 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -69,10 +69,10 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
{
switch (m_scanner->getCurrentToken())
{
- case Token::IMPORT:
+ case Token::Import:
nodes.push_back(parseImportDirective());
break;
- case Token::CONTRACT:
+ case Token::Contract:
nodes.push_back(parseContractDefinition());
break;
default:
@@ -100,119 +100,298 @@ int Parser::getEndPosition() const
ASTPointer<ImportDirective> Parser::parseImportDirective()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::IMPORT);
- if (m_scanner->getCurrentToken() != Token::STRING_LITERAL)
+ expectToken(Token::Import);
+ if (m_scanner->getCurrentToken() != Token::StringLiteral)
BOOST_THROW_EXCEPTION(createParserError("Expected string literal (URL)."));
ASTPointer<ASTString> url = getLiteralAndAdvance();
nodeFactory.markEndPosition();
- expectToken(Token::SEMICOLON);
+ expectToken(Token::Semicolon);
return nodeFactory.createNode<ImportDirective>(url);
}
ASTPointer<ContractDefinition> Parser::parseContractDefinition()
{
ASTNodeFactory nodeFactory(*this);
- ASTPointer<ASTString> docstring;
+ ASTPointer<ASTString> docString;
if (m_scanner->getCurrentCommentLiteral() != "")
- docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
- expectToken(Token::CONTRACT);
+ docString = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
+ expectToken(Token::Contract);
ASTPointer<ASTString> name = expectIdentifierToken();
- expectToken(Token::LBRACE);
+ vector<ASTPointer<InheritanceSpecifier>> baseContracts;
vector<ASTPointer<StructDefinition>> structs;
+ vector<ASTPointer<EnumDefinition>> enums;
vector<ASTPointer<VariableDeclaration>> stateVariables;
vector<ASTPointer<FunctionDefinition>> functions;
- bool visibilityIsPublic = true;
+ vector<ASTPointer<ModifierDefinition>> modifiers;
+ vector<ASTPointer<EventDefinition>> events;
+ if (m_scanner->getCurrentToken() == Token::Is)
+ do
+ {
+ m_scanner->next();
+ baseContracts.push_back(parseInheritanceSpecifier());
+ }
+ while (m_scanner->getCurrentToken() == Token::Comma);
+ expectToken(Token::LBrace);
while (true)
{
Token::Value currentToken = m_scanner->getCurrentToken();
- if (currentToken == Token::RBRACE)
+ if (currentToken == Token::RBrace)
break;
- else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE)
- {
- visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC);
- m_scanner->next();
- expectToken(Token::COLON);
- }
- else if (currentToken == Token::FUNCTION)
- functions.push_back(parseFunctionDefinition(visibilityIsPublic));
- else if (currentToken == Token::STRUCT)
+ else if (currentToken == Token::Function)
+ functions.push_back(parseFunctionDefinition(name.get()));
+ else if (currentToken == Token::Struct)
structs.push_back(parseStructDefinition());
- else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
+ else if (currentToken == Token::Enum)
+ enums.push_back(parseEnumDefinition());
+ else if (currentToken == Token::Identifier || currentToken == Token::Mapping ||
Token::isElementaryTypeName(currentToken))
{
- bool const allowVar = false;
- stateVariables.push_back(parseVariableDeclaration(allowVar));
- expectToken(Token::SEMICOLON);
+ VarDeclParserOptions options;
+ options.isStateVariable = true;
+ stateVariables.push_back(parseVariableDeclaration(options));
+ expectToken(Token::Semicolon);
}
+ else if (currentToken == Token::Modifier)
+ modifiers.push_back(parseModifierDefinition());
+ else if (currentToken == Token::Event)
+ events.push_back(parseEventDefinition());
else
- BOOST_THROW_EXCEPTION(createParserError("Function, variable or struct declaration expected."));
+ BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
}
nodeFactory.markEndPosition();
- expectToken(Token::RBRACE);
- return nodeFactory.createNode<ContractDefinition>(name, docstring, structs, stateVariables, functions);
+ expectToken(Token::RBrace);
+ return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, enums,
+ stateVariables, functions, modifiers, events);
}
-ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic)
+ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<Identifier> name(parseIdentifier());
+ vector<ASTPointer<Expression>> arguments;
+ if (m_scanner->getCurrentToken() == Token::LParen)
+ {
+ m_scanner->next();
+ arguments = parseFunctionCallListArguments();
+ nodeFactory.markEndPosition();
+ expectToken(Token::RParen);
+ }
+ else
+ nodeFactory.setEndPositionFromNode(name);
+ return nodeFactory.createNode<InheritanceSpecifier>(name, arguments);
+}
+
+Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
+{
+ Declaration::Visibility visibility(Declaration::Visibility::Default);
+ if (_token == Token::Public)
+ visibility = Declaration::Visibility::Public;
+ else if (_token == Token::Inheritable)
+ visibility = Declaration::Visibility::Inheritable;
+ else if (_token == Token::Private)
+ visibility = Declaration::Visibility::Private;
+ else if (_token == Token::External)
+ visibility = Declaration::Visibility::External;
+ else
+ solAssert(false, "Invalid visibility specifier.");
+ m_scanner->next();
+ return visibility;
+}
+
+ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<ASTString> docstring;
if (m_scanner->getCurrentCommentLiteral() != "")
docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
- expectToken(Token::FUNCTION);
- ASTPointer<ASTString> name(expectIdentifierToken());
+ expectToken(Token::Function);
+ ASTPointer<ASTString> name;
+ if (m_scanner->getCurrentToken() == Token::LParen)
+ name = make_shared<ASTString>(); // anonymous function
+ else
+ name = expectIdentifierToken();
ASTPointer<ParameterList> parameters(parseParameterList());
bool isDeclaredConst = false;
- if (m_scanner->getCurrentToken() == Token::CONST)
+ Declaration::Visibility visibility(Declaration::Visibility::Default);
+ vector<ASTPointer<ModifierInvocation>> modifiers;
+ while (true)
{
- isDeclaredConst = true;
- m_scanner->next();
+ Token::Value token = m_scanner->getCurrentToken();
+ if (token == Token::Const)
+ {
+ isDeclaredConst = true;
+ m_scanner->next();
+ }
+ else if (token == Token::Identifier)
+ modifiers.push_back(parseModifierInvocation());
+ else if (Token::isVisibilitySpecifier(token))
+ {
+ if (visibility != Declaration::Visibility::Default)
+ BOOST_THROW_EXCEPTION(createParserError("Multiple visibility specifiers."));
+ visibility = parseVisibilitySpecifier(token);
+ }
+ else
+ break;
}
ASTPointer<ParameterList> returnParameters;
- if (m_scanner->getCurrentToken() == Token::RETURNS)
+ if (m_scanner->getCurrentToken() == Token::Returns)
{
bool const permitEmptyParameterList = false;
m_scanner->next();
returnParameters = parseParameterList(permitEmptyParameterList);
}
else
- {
- // create an empty parameter list at a zero-length location
- ASTNodeFactory nodeFactory(*this);
- nodeFactory.setLocationEmpty();
- returnParameters = nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
- }
+ returnParameters = createEmptyParameterList();
ASTPointer<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block);
- return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, docstring,
- parameters,
- isDeclaredConst, returnParameters, block);
+ bool const c_isConstructor = (_contractName && *name == *_contractName);
+ return nodeFactory.createNode<FunctionDefinition>(name, visibility, c_isConstructor, docstring,
+ parameters, isDeclaredConst, modifiers,
+ returnParameters, block);
}
ASTPointer<StructDefinition> Parser::parseStructDefinition()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::STRUCT);
+ expectToken(Token::Struct);
ASTPointer<ASTString> name = expectIdentifierToken();
vector<ASTPointer<VariableDeclaration>> members;
- expectToken(Token::LBRACE);
- while (m_scanner->getCurrentToken() != Token::RBRACE)
+ expectToken(Token::LBrace);
+ while (m_scanner->getCurrentToken() != Token::RBrace)
{
- bool const allowVar = false;
- members.push_back(parseVariableDeclaration(allowVar));
- expectToken(Token::SEMICOLON);
+ members.push_back(parseVariableDeclaration());
+ expectToken(Token::Semicolon);
}
nodeFactory.markEndPosition();
- expectToken(Token::RBRACE);
+ expectToken(Token::RBrace);
return nodeFactory.createNode<StructDefinition>(name, members);
}
-ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar)
+ASTPointer<EnumValue> Parser::parseEnumValue()
{
ASTNodeFactory nodeFactory(*this);
- ASTPointer<TypeName> type = parseTypeName(_allowVar);
nodeFactory.markEndPosition();
- return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken());
+ return nodeFactory.createNode<EnumValue>(expectIdentifierToken());
+}
+
+ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
+{
+ ASTNodeFactory nodeFactory(*this);
+ expectToken(Token::Enum);
+ ASTPointer<ASTString> name = expectIdentifierToken();
+ vector<ASTPointer<EnumValue>> members;
+ expectToken(Token::LBrace);
+
+ while (m_scanner->getCurrentToken() != Token::RBrace)
+ {
+ members.push_back(parseEnumValue());
+ if (m_scanner->getCurrentToken() == Token::RBrace)
+ break;
+ expectToken(Token::Comma);
+ if (m_scanner->getCurrentToken() != Token::Identifier)
+ BOOST_THROW_EXCEPTION(createParserError("Expected Identifier after ','"));
+ }
+
+ nodeFactory.markEndPosition();
+ expectToken(Token::RBrace);
+ return nodeFactory.createNode<EnumDefinition>(name, members);
+}
+
+ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options)
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
+ if (type != nullptr)
+ nodeFactory.setEndPositionFromNode(type);
+ bool isIndexed = false;
+ ASTPointer<ASTString> identifier;
+ Token::Value token = m_scanner->getCurrentToken();
+ Declaration::Visibility visibility(Declaration::Visibility::Default);
+ if (_options.isStateVariable && Token::isVariableVisibilitySpecifier(token))
+ visibility = parseVisibilitySpecifier(token);
+ if (_options.allowIndexed && token == Token::Indexed)
+ {
+ isIndexed = true;
+ m_scanner->next();
+ }
+ nodeFactory.markEndPosition();
+ if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::Identifier)
+ {
+ identifier = make_shared<ASTString>("");
+ solAssert(type != nullptr, "");
+ nodeFactory.setEndPositionFromNode(type);
+ }
+ else
+ identifier = expectIdentifierToken();
+ return nodeFactory.createNode<VariableDeclaration>(type, identifier,
+ visibility, _options.isStateVariable,
+ isIndexed);
+}
+
+ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
+{
+ ScopeGuard resetModifierFlag([this]() { m_insideModifier = false; });
+ m_insideModifier = true;
+
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<ASTString> docstring;
+ if (m_scanner->getCurrentCommentLiteral() != "")
+ docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
+
+ expectToken(Token::Modifier);
+ ASTPointer<ASTString> name(expectIdentifierToken());
+ ASTPointer<ParameterList> parameters;
+ if (m_scanner->getCurrentToken() == Token::LParen)
+ parameters = parseParameterList();
+ else
+ parameters = createEmptyParameterList();
+ ASTPointer<Block> block = parseBlock();
+ nodeFactory.setEndPositionFromNode(block);
+ return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block);
+}
+
+ASTPointer<EventDefinition> Parser::parseEventDefinition()
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<ASTString> docstring;
+ if (m_scanner->getCurrentCommentLiteral() != "")
+ docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
+
+ expectToken(Token::Event);
+ ASTPointer<ASTString> name(expectIdentifierToken());
+ ASTPointer<ParameterList> parameters;
+ if (m_scanner->getCurrentToken() == Token::LParen)
+ parameters = parseParameterList(true, true);
+ else
+ parameters = createEmptyParameterList();
+ nodeFactory.markEndPosition();
+ expectToken(Token::Semicolon);
+ return nodeFactory.createNode<EventDefinition>(name, docstring, parameters);
+}
+
+ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<Identifier> name(parseIdentifier());
+ vector<ASTPointer<Expression>> arguments;
+ if (m_scanner->getCurrentToken() == Token::LParen)
+ {
+ m_scanner->next();
+ arguments = parseFunctionCallListArguments();
+ nodeFactory.markEndPosition();
+ expectToken(Token::RParen);
+ }
+ else
+ nodeFactory.setEndPositionFromNode(name);
+ return nodeFactory.createNode<ModifierInvocation>(name, arguments);
+}
+
+ASTPointer<Identifier> Parser::parseIdentifier()
+{
+ ASTNodeFactory nodeFactory(*this);
+ nodeFactory.markEndPosition();
+ return nodeFactory.createNode<Identifier>(expectIdentifierToken());
}
ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
@@ -224,17 +403,17 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
type = ASTNodeFactory(*this).createNode<ElementaryTypeName>(token);
m_scanner->next();
}
- else if (token == Token::VAR)
+ else if (token == Token::Var)
{
if (!_allowVar)
BOOST_THROW_EXCEPTION(createParserError("Expected explicit type name."));
m_scanner->next();
}
- else if (token == Token::MAPPING)
+ else if (token == Token::Mapping)
{
type = parseMapping();
}
- else if (token == Token::IDENTIFIER)
+ else if (token == Token::Identifier)
{
ASTNodeFactory nodeFactory(*this);
nodeFactory.markEndPosition();
@@ -248,34 +427,36 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
ASTPointer<Mapping> Parser::parseMapping()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::MAPPING);
- expectToken(Token::LPAREN);
+ expectToken(Token::Mapping);
+ expectToken(Token::LParen);
if (!Token::isElementaryTypeName(m_scanner->getCurrentToken()))
BOOST_THROW_EXCEPTION(createParserError("Expected elementary type name for mapping key type"));
ASTPointer<ElementaryTypeName> keyType;
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(m_scanner->getCurrentToken());
m_scanner->next();
- expectToken(Token::ARROW);
+ expectToken(Token::Arrow);
bool const allowVar = false;
ASTPointer<TypeName> valueType = parseTypeName(allowVar);
nodeFactory.markEndPosition();
- expectToken(Token::RPAREN);
+ expectToken(Token::RParen);
return nodeFactory.createNode<Mapping>(keyType, valueType);
}
-ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty)
+ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty, bool _allowIndexed)
{
ASTNodeFactory nodeFactory(*this);
vector<ASTPointer<VariableDeclaration>> parameters;
- expectToken(Token::LPAREN);
- if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN)
+ VarDeclParserOptions options;
+ options.allowIndexed = _allowIndexed;
+ options.allowEmptyName = true;
+ expectToken(Token::LParen);
+ if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RParen)
{
- bool const allowVar = false;
- parameters.push_back(parseVariableDeclaration(allowVar));
- while (m_scanner->getCurrentToken() != Token::RPAREN)
+ parameters.push_back(parseVariableDeclaration(options));
+ while (m_scanner->getCurrentToken() != Token::RParen)
{
- expectToken(Token::COMMA);
- parameters.push_back(parseVariableDeclaration(allowVar));
+ expectToken(Token::Comma);
+ parameters.push_back(parseVariableDeclaration(options));
}
}
nodeFactory.markEndPosition();
@@ -286,12 +467,12 @@ ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty)
ASTPointer<Block> Parser::parseBlock()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::LBRACE);
+ expectToken(Token::LBrace);
vector<ASTPointer<Statement>> statements;
- while (m_scanner->getCurrentToken() != Token::RBRACE)
+ while (m_scanner->getCurrentToken() != Token::RBrace)
statements.push_back(parseStatement());
nodeFactory.markEndPosition();
- expectToken(Token::RBRACE);
+ expectToken(Token::RBrace);
return nodeFactory.createNode<Block>(statements);
}
@@ -300,52 +481,60 @@ ASTPointer<Statement> Parser::parseStatement()
ASTPointer<Statement> statement;
switch (m_scanner->getCurrentToken())
{
- case Token::IF:
+ case Token::If:
return parseIfStatement();
- case Token::WHILE:
+ case Token::While:
return parseWhileStatement();
- case Token::FOR:
+ case Token::For:
return parseForStatement();
- case Token::LBRACE:
+ case Token::LBrace:
return parseBlock();
// starting from here, all statements must be terminated by a semicolon
- case Token::CONTINUE:
+ case Token::Continue:
statement = ASTNodeFactory(*this).createNode<Continue>();
m_scanner->next();
break;
- case Token::BREAK:
+ case Token::Break:
statement = ASTNodeFactory(*this).createNode<Break>();
m_scanner->next();
break;
- case Token::RETURN:
+ case Token::Return:
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<Expression> expression;
- if (m_scanner->next() != Token::SEMICOLON)
+ if (m_scanner->next() != Token::Semicolon)
{
expression = parseExpression();
nodeFactory.setEndPositionFromNode(expression);
}
statement = nodeFactory.createNode<Return>(expression);
+ break;
}
- break;
+ case Token::Identifier:
+ if (m_insideModifier && m_scanner->getCurrentLiteral() == "_")
+ {
+ statement = ASTNodeFactory(*this).createNode<PlaceholderStatement>();
+ m_scanner->next();
+ return statement;
+ }
+ // fall-through
default:
statement = parseVarDefOrExprStmt();
}
- expectToken(Token::SEMICOLON);
+ expectToken(Token::Semicolon);
return statement;
}
ASTPointer<IfStatement> Parser::parseIfStatement()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::IF);
- expectToken(Token::LPAREN);
+ expectToken(Token::If);
+ expectToken(Token::LParen);
ASTPointer<Expression> condition = parseExpression();
- expectToken(Token::RPAREN);
+ expectToken(Token::RParen);
ASTPointer<Statement> trueBody = parseStatement();
ASTPointer<Statement> falseBody;
- if (m_scanner->getCurrentToken() == Token::ELSE)
+ if (m_scanner->getCurrentToken() == Token::Else)
{
m_scanner->next();
falseBody = parseStatement();
@@ -359,10 +548,10 @@ ASTPointer<IfStatement> Parser::parseIfStatement()
ASTPointer<WhileStatement> Parser::parseWhileStatement()
{
ASTNodeFactory nodeFactory(*this);
- expectToken(Token::WHILE);
- expectToken(Token::LPAREN);
+ expectToken(Token::While);
+ expectToken(Token::LParen);
ASTPointer<Expression> condition = parseExpression();
- expectToken(Token::RPAREN);
+ expectToken(Token::RParen);
ASTPointer<Statement> body = parseStatement();
nodeFactory.setEndPositionFromNode(body);
return nodeFactory.createNode<WhileStatement>(condition, body);
@@ -374,21 +563,21 @@ ASTPointer<ForStatement> Parser::parseForStatement()
ASTPointer<Statement> initExpression;
ASTPointer<Expression> conditionExpression;
ASTPointer<ExpressionStatement> loopExpression;
- expectToken(Token::FOR);
- expectToken(Token::LPAREN);
+ expectToken(Token::For);
+ expectToken(Token::LParen);
- // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RPAREN?
- if (m_scanner->getCurrentToken() != Token::SEMICOLON)
+ // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RParen?
+ if (m_scanner->getCurrentToken() != Token::Semicolon)
initExpression = parseVarDefOrExprStmt();
- expectToken(Token::SEMICOLON);
+ expectToken(Token::Semicolon);
- if (m_scanner->getCurrentToken() != Token::SEMICOLON)
+ if (m_scanner->getCurrentToken() != Token::Semicolon)
conditionExpression = parseExpression();
- expectToken(Token::SEMICOLON);
+ expectToken(Token::Semicolon);
- if (m_scanner->getCurrentToken() != Token::RPAREN)
+ if (m_scanner->getCurrentToken() != Token::RParen)
loopExpression = parseExpressionStatement();
- expectToken(Token::RPAREN);
+ expectToken(Token::RParen);
ASTPointer<Statement> body = parseStatement();
nodeFactory.setEndPositionFromNode(body);
@@ -409,10 +598,11 @@ ASTPointer<Statement> Parser::parseVarDefOrExprStmt()
ASTPointer<VariableDefinition> Parser::parseVariableDefinition()
{
ASTNodeFactory nodeFactory(*this);
- bool const allowVar = true;
- ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(allowVar);
+ VarDeclParserOptions options;
+ options.allowVar = true;
+ ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options);
ASTPointer<Expression> value;
- if (m_scanner->getCurrentToken() == Token::ASSIGN)
+ if (m_scanner->getCurrentToken() == Token::Assign)
{
m_scanner->next();
value = parseExpression();
@@ -449,7 +639,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
ASTPointer<Expression> expression = parseUnaryExpression();
int precedence = Token::precedence(m_scanner->getCurrentToken());
for (; precedence >= _minPrecedence; --precedence)
- {
while (Token::precedence(m_scanner->getCurrentToken()) == precedence)
{
Token::Value op = m_scanner->getCurrentToken();
@@ -458,7 +647,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
nodeFactory.setEndPositionFromNode(right);
expression = nodeFactory.createNode<BinaryOperation>(expression, op, right);
}
- }
return expression;
}
@@ -466,17 +654,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression()
{
ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken();
- if (token == Token::NEW)
- {
- expectToken(Token::NEW);
- ASTPointer<Identifier> contractName = ASTNodeFactory(*this).createNode<Identifier>(expectIdentifierToken());
- expectToken(Token::LPAREN);
- vector<ASTPointer<Expression>> arguments(parseFunctionCallArguments());
- expectToken(Token::RPAREN);
- nodeFactory.markEndPosition();
- return nodeFactory.createNode<NewExpression>(contractName, arguments);
- }
- else if (Token::isUnaryOp(token) || Token::isCountOp(token))
+ if (Token::isUnaryOp(token) || Token::isCountOp(token))
{
// prefix expression
m_scanner->next();
@@ -500,34 +678,46 @@ ASTPointer<Expression> Parser::parseUnaryExpression()
ASTPointer<Expression> Parser::parseLeftHandSideExpression()
{
ASTNodeFactory nodeFactory(*this);
- ASTPointer<Expression> expression = parsePrimaryExpression();
+ ASTPointer<Expression> expression;
+ if (m_scanner->getCurrentToken() == Token::New)
+ {
+ expectToken(Token::New);
+ ASTPointer<Identifier> contractName(parseIdentifier());
+ nodeFactory.setEndPositionFromNode(contractName);
+ expression = nodeFactory.createNode<NewExpression>(contractName);
+ }
+ else
+ expression = parsePrimaryExpression();
+
while (true)
{
switch (m_scanner->getCurrentToken())
{
- case Token::LBRACK:
+ case Token::LBrack:
{
m_scanner->next();
ASTPointer<Expression> index = parseExpression();
nodeFactory.markEndPosition();
- expectToken(Token::RBRACK);
+ expectToken(Token::RBrack);
expression = nodeFactory.createNode<IndexAccess>(expression, index);
}
break;
- case Token::PERIOD:
+ case Token::Period:
{
m_scanner->next();
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<MemberAccess>(expression, expectIdentifierToken());
}
break;
- case Token::LPAREN:
+ case Token::LParen:
{
m_scanner->next();
- vector<ASTPointer<Expression>> arguments = parseFunctionCallArguments();
+ vector<ASTPointer<Expression>> arguments;
+ vector<ASTPointer<ASTString>> names;
+ std::tie(arguments, names) = parseFunctionCallArguments();
nodeFactory.markEndPosition();
- expectToken(Token::RPAREN);
- expression = nodeFactory.createNode<FunctionCall>(expression, arguments);
+ expectToken(Token::RParen);
+ expression = nodeFactory.createNode<FunctionCall>(expression, arguments, names);
}
break;
default:
@@ -543,24 +733,34 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
ASTPointer<Expression> expression;
switch (token)
{
- case Token::TRUE_LITERAL:
- case Token::FALSE_LITERAL:
+ case Token::TrueLiteral:
+ case Token::FalseLiteral:
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break;
- case Token::NUMBER:
- case Token::STRING_LITERAL:
+ case Token::Number:
+ if (Token::isEtherSubdenomination(m_scanner->peekNextToken()))
+ {
+ ASTPointer<ASTString> literal = getLiteralAndAdvance();
+ nodeFactory.markEndPosition();
+ Literal::SubDenomination subdenomination = static_cast<Literal::SubDenomination>(m_scanner->getCurrentToken());
+ m_scanner->next();
+ expression = nodeFactory.createNode<Literal>(token, literal, subdenomination);
+ break;
+ }
+ // fall-through
+ case Token::StringLiteral:
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break;
- case Token::IDENTIFIER:
+ case Token::Identifier:
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Identifier>(getLiteralAndAdvance());
break;
- case Token::LPAREN:
+ case Token::LParen:
{
m_scanner->next();
ASTPointer<Expression> expression = parseExpression();
- expectToken(Token::RPAREN);
+ expectToken(Token::RParen);
return expression;
}
default:
@@ -580,21 +780,47 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
return expression;
}
-vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
+vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
{
vector<ASTPointer<Expression>> arguments;
- if (m_scanner->getCurrentToken() != Token::RPAREN)
+ if (m_scanner->getCurrentToken() != Token::RParen)
{
arguments.push_back(parseExpression());
- while (m_scanner->getCurrentToken() != Token::RPAREN)
+ while (m_scanner->getCurrentToken() != Token::RParen)
{
- expectToken(Token::COMMA);
+ expectToken(Token::Comma);
arguments.push_back(parseExpression());
}
}
return arguments;
}
+pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseFunctionCallArguments()
+{
+ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret;
+ Token::Value token = m_scanner->getCurrentToken();
+ if (token == Token::LBrace)
+ {
+ // call({arg1 : 1, arg2 : 2 })
+ expectToken(Token::LBrace);
+ while (m_scanner->getCurrentToken() != Token::RBrace)
+ {
+ ret.second.push_back(expectIdentifierToken());
+ expectToken(Token::Colon);
+ ret.first.push_back(parseExpression());
+
+ if (m_scanner->getCurrentToken() == Token::Comma)
+ expectToken(Token::Comma);
+ else
+ break;
+ }
+ expectToken(Token::RBrace);
+ }
+ else
+ ret.first = parseFunctionCallListArguments();
+ return ret;
+}
+
bool Parser::peekVariableDefinition()
{
@@ -602,11 +828,11 @@ bool Parser::peekVariableDefinition()
// (which include assignments to other expressions and pre-declared variables)
// We have a variable definition if we get a keyword that specifies a type name, or
// in the case of a user-defined type, we have two identifiers following each other.
- return (m_scanner->getCurrentToken() == Token::MAPPING ||
- m_scanner->getCurrentToken() == Token::VAR ||
+ return (m_scanner->getCurrentToken() == Token::Mapping ||
+ m_scanner->getCurrentToken() == Token::Var ||
((Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
- m_scanner->getCurrentToken() == Token::IDENTIFIER) &&
- m_scanner->peekNextToken() == Token::IDENTIFIER));
+ m_scanner->getCurrentToken() == Token::Identifier) &&
+ m_scanner->peekNextToken() == Token::Identifier));
}
void Parser::expectToken(Token::Value _value)
@@ -627,7 +853,7 @@ Token::Value Parser::expectAssignmentOperator()
ASTPointer<ASTString> Parser::expectIdentifierToken()
{
- if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
+ if (m_scanner->getCurrentToken() != Token::Identifier)
BOOST_THROW_EXCEPTION(createParserError("Expected identifier"));
return getLiteralAndAdvance();
}
@@ -639,6 +865,13 @@ ASTPointer<ASTString> Parser::getLiteralAndAdvance()
return identifier;
}
+ASTPointer<ParameterList> Parser::createEmptyParameterList()
+{
+ ASTNodeFactory nodeFactory(*this);
+ nodeFactory.setLocationEmpty();
+ return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
+}
+
ParserError Parser::createParserError(string const& _description) const
{
return ParserError() << errinfo_sourceLocation(Location(getPosition(), getPosition(), getSourceName()))