diff options
Diffstat (limited to 'Parser.cpp')
-rw-r--r-- | Parser.cpp | 507 |
1 files changed, 370 insertions, 137 deletions
@@ -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())) |