diff --git a/docs/Solidity.g4 b/docs/Solidity.g4 index a415c19f9..239cbbdd3 100644 --- a/docs/Solidity.g4 +++ b/docs/Solidity.g4 @@ -8,7 +8,17 @@ grammar Solidity; sourceUnit - : (pragmaDirective | importDirective | structDefinition | enumDefinition | contractDefinition)* EOF ; + : globalDefinition* EOF ; + +globalDefinition + : pragmaDirective + | contractDefinition + | enumDefinition + | importDirective + | interfaceDefinition + | libraryDefinition + | structDefinition + ; pragmaDirective : 'pragma' pragmaName pragmaValue ';' ; @@ -36,10 +46,25 @@ importDirective importDeclaration : identifier ('as' identifier)? ; +interfaceDefinition + : 'interface' identifier 'from' StringLiteralFragment + | 'interface' identifier 'as' AbiString + | 'interface' identifier contractInheritanceDefinition? contractBody ; + +AbiString + : StringLiteral ; + +libraryDefinition + : 'abstract'? 'library' identifier contractInheritanceDefinition? contractBody ; + contractDefinition - : 'abstract'? ( 'contract' | 'interface' | 'library' ) identifier - ( 'is' inheritanceSpecifier (',' inheritanceSpecifier )* )? - '{' contractPart* '}' ; + : 'abstract'? 'contract' identifier contractInheritanceDefinition? contractBody ; + +contractInheritanceDefinition + : ( 'is' inheritanceSpecifier (',' inheritanceSpecifier )* ) ; + +contractBody + : '{' contractPart* '}' ; inheritanceSpecifier : userDefinedTypeName ( '(' expressionList? ')' )? ; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index c429ba786..b79a04732 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -94,8 +94,10 @@ ASTPointer Parser::parse(shared_ptr const& _scanner) case Token::Import: nodes.push_back(parseImportDirective()); break; - case Token::Abstract: case Token::Interface: + // nodes.push_back(parseInterfaceDefinition()); + // break; + case Token::Abstract: case Token::Contract: case Token::Library: nodes.push_back(parseContractDefinition()); @@ -290,6 +292,35 @@ std::pair Parser::parseContractKind() return std::make_pair(kind, abstract); } +ASTPointer Parser::parseInterfaceDefinition() +{ + // interfaceDefinition + // : 'interface' identifier 'from' StringLiteralFragment + // | 'interface' identifier 'as' AbiString + // | 'interface' identifier contractInheritanceDefinition? contractBody ; + + m_scanner->next(); + + RecursionGuard recursionGuard(*this); + ASTNodeFactory nodeFactory(*this); + + ASTPointer name = expectIdentifierToken(); + + ASTPointer documentation = parseStructuredDocumentation(); + + vector> baseContracts; + vector> subNodes;//TODO = parseContractBody(); + + return nodeFactory.createNode( + name, + documentation, + baseContracts, + subNodes, + ContractKind::Interface, + false + ); +} + ASTPointer Parser::parseContractDefinition() { RecursionGuard recursionGuard(*this); @@ -311,6 +342,84 @@ ASTPointer Parser::parseContractDefinition() baseContracts.push_back(parseInheritanceSpecifier()); } while (m_scanner->currentToken() == Token::Comma); +#if 0 + parseContractBody(subNodes); + //subNodes = parseContractBody(); +#else + expectToken(Token::LBrace); + while (true) + { + Token currentTokenValue = m_scanner->currentToken(); + if (currentTokenValue == Token::RBrace) + break; + else if ( + (currentTokenValue == Token::Function && m_scanner->peekNextToken() != Token::LParen) || + currentTokenValue == Token::Constructor || + currentTokenValue == Token::Receive || + currentTokenValue == Token::Fallback + ) + subNodes.push_back(parseFunctionDefinition()); + else if (currentTokenValue == Token::Struct) + subNodes.push_back(parseStructDefinition()); + else if (currentTokenValue == Token::Enum) + subNodes.push_back(parseEnumDefinition()); + else if ( + currentTokenValue == Token::Identifier || + currentTokenValue == Token::Mapping || + TokenTraits::isElementaryTypeName(currentTokenValue) || + (currentTokenValue == Token::Function && m_scanner->peekNextToken() == Token::LParen) + ) + { + VarDeclParserOptions options; + options.isStateVariable = true; + options.allowInitialValue = true; + subNodes.push_back(parseVariableDeclaration(options)); + expectToken(Token::Semicolon); + } + else if (currentTokenValue == Token::Modifier) + subNodes.push_back(parseModifierDefinition()); + else if (currentTokenValue == Token::Event) + subNodes.push_back(parseEventDefinition()); + else if (currentTokenValue == Token::Using) + subNodes.push_back(parseUsingDirective()); + else + fatalParserError(9182_error, "Function, variable, struct or modifier declaration expected."); + } +#endif + } + catch (FatalError const&) + { + if ( + !m_errorReporter.hasErrors() || + !m_parserErrorRecovery || + m_errorReporter.hasExcessiveErrors() + ) + BOOST_THROW_EXCEPTION(FatalError()); /* Don't try to recover here. */ + nodeFactory.markEndPosition(); + expectTokenOrConsumeUntil(Token::RBrace, "ContractDefinition"); + m_inParserRecovery = true; + } + nodeFactory.markEndPosition(); + if (m_inParserRecovery) + expectTokenOrConsumeUntil(Token::RBrace, "ContractDefinition"); + else + expectToken(Token::RBrace); + return nodeFactory.createNode( + name, + documentation, + baseContracts, + subNodes, + contractKind.first, + contractKind.second + ); +} + +void Parser::parseContractBody(vector>& subNodes) +{ + //vector> subNodes; + + try + { expectToken(Token::LBrace); while (true) { @@ -353,6 +462,7 @@ ASTPointer Parser::parseContractDefinition() } catch (FatalError const&) { + printf("FatalError: in parser recovery\n"); if ( !m_errorReporter.hasErrors() || !m_parserErrorRecovery || @@ -361,19 +471,13 @@ ASTPointer Parser::parseContractDefinition() BOOST_THROW_EXCEPTION(FatalError()); /* Don't try to recover here. */ m_inParserRecovery = true; } - nodeFactory.markEndPosition(); + if (m_inParserRecovery) expectTokenOrConsumeUntil(Token::RBrace, "ContractDefinition"); else expectToken(Token::RBrace); - return nodeFactory.createNode( - name, - documentation, - baseContracts, - subNodes, - contractKind.first, - contractKind.second - ); + + //return subNodes; } ASTPointer Parser::parseInheritanceSpecifier() diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index f66754045..4721b5809 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -87,6 +87,9 @@ private: /// result.second is set to true, if an abstract contract was parsed, false otherwise. std::pair parseContractKind(); ASTPointer parseContractDefinition(); + ASTPointer parseInterfaceDefinition(); + //std::vector> parseContractBody(); + void parseContractBody(std::vector>& _result); ASTPointer parseInheritanceSpecifier(); Visibility parseVisibilitySpecifier(); ASTPointer parseOverrideSpecifier();