diff options
Diffstat (limited to 'Parser.cpp')
-rw-r--r-- | Parser.cpp | 79 |
1 files changed, 71 insertions, 8 deletions
@@ -121,6 +121,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() vector<ASTPointer<StructDefinition>> structs; vector<ASTPointer<VariableDeclaration>> stateVariables; vector<ASTPointer<FunctionDefinition>> functions; + vector<ASTPointer<ModifierDefinition>> modifiers; if (m_scanner->getCurrentToken() == Token::IS) do { @@ -152,13 +153,15 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() stateVariables.push_back(parseVariableDeclaration(allowVar)); expectToken(Token::SEMICOLON); } + else if (currentToken == Token::MODIFIER) + modifiers.push_back(parseModifierDefinition()); 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, baseContracts, structs, - stateVariables, functions); + stateVariables, functions, modifiers); } ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() @@ -189,10 +192,18 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A ASTPointer<ASTString> name(expectIdentifierToken()); ASTPointer<ParameterList> parameters(parseParameterList()); bool isDeclaredConst = false; - if (m_scanner->getCurrentToken() == Token::CONST) + vector<ASTPointer<ModifierInvocation>> modifiers; + while (true) { - isDeclaredConst = true; - m_scanner->next(); + if (m_scanner->getCurrentToken() == Token::CONST) + { + isDeclaredConst = true; + m_scanner->next(); + } + else if (m_scanner->getCurrentToken() == Token::IDENTIFIER) + modifiers.push_back(parseModifierInvocation()); + else + break; } ASTPointer<ParameterList> returnParameters; if (m_scanner->getCurrentToken() == Token::RETURNS) @@ -212,8 +223,8 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A nodeFactory.setEndPositionFromNode(block); bool const c_isConstructor = (_contractName && *name == *_contractName); return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, c_isConstructor, docstring, - parameters, - isDeclaredConst, returnParameters, block); + parameters, isDeclaredConst, modifiers, + returnParameters, block); } ASTPointer<StructDefinition> Parser::parseStructDefinition() @@ -242,6 +253,50 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar) return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken()); } +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 + { + // create an empty parameter list at a zero-length location + ASTNodeFactory nodeFactory(*this); + nodeFactory.setLocationEmpty(); + parameters = nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>()); + } + ASTPointer<Block> block = parseBlock(); + nodeFactory.setEndPositionFromNode(block); + return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block); +} + +ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() +{ + ASTNodeFactory nodeFactory(*this); + ASTPointer<Identifier> name = ASTNodeFactory(*this).createNode<Identifier>(expectIdentifierToken()); + vector<ASTPointer<Expression>> arguments; + if (m_scanner->getCurrentToken() == Token::LPAREN) + { + m_scanner->next(); + arguments = parseFunctionCallArguments(); + nodeFactory.markEndPosition(); + expectToken(Token::RPAREN); + } + else + nodeFactory.setEndPositionFromNode(name); + return nodeFactory.createNode<ModifierInvocation>(name, arguments); +} + ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) { ASTPointer<TypeName> type; @@ -354,8 +409,16 @@ ASTPointer<Statement> Parser::parseStatement() 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(); } |