From a295417f3476428c286f96433a42a96bfe29fee3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 9 Feb 2015 18:08:56 +0100 Subject: [PATCH] Parsing enums for Solidity - WIP --- AST.cpp | 16 ++++++++++++++++ AST.h | 38 ++++++++++++++++++++++++++++++++++++++ ASTForward.h | 2 ++ ASTPrinter.cpp | 22 ++++++++++++++++++++++ ASTPrinter.h | 4 ++++ ASTVisitor.h | 4 ++++ AST_accept.h | 12 ++++++++++++ Parser.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- Parser.h | 3 +++ 9 files changed, 141 insertions(+), 1 deletion(-) diff --git a/AST.cpp b/AST.cpp index 3c6b6007c..0c34cea38 100644 --- a/AST.cpp +++ b/AST.cpp @@ -255,6 +255,22 @@ void StructDefinition::checkRecursion() const } } +void EnumDefinition::checkValidityOfMembers() const +{ +#if 0 // LTODO: Make this work for the Declarations + vector> members = getMembers(); + sort(begin(members), end(members)); + for (size_t i = 0; i < members.size(); ++i) + if (members[i] == members[i + 1]) + BOOST_THROW_EXCEPTION(createTypeError("Duplicate member detected in Enum")); +#endif +} + +TypePointer EnumDefinition::getType(ContractDefinition const*) const +{ + return make_shared(make_shared(*this)); +} + TypePointer FunctionDefinition::getType(ContractDefinition const*) const { return make_shared(*this); diff --git a/AST.h b/AST.h index 4e79026e8..d3a7853a4 100644 --- a/AST.h +++ b/AST.h @@ -165,6 +165,18 @@ private: Declaration const* m_scope; }; +/** + * Declaration of an Enum Value + */ +class EnumDeclaration : public Declaration +{ + EnumDeclaration(Location const& _location, + ASTPointer const& _name): + Declaration(_location, _name) {} + + TypePointer getType(ContractDefinition const*) const; +}; + /** * Abstract class that is added to each AST node that can store local variables. */ @@ -209,6 +221,7 @@ public: ASTPointer const& _documentation, std::vector> const& _baseContracts, std::vector> const& _definedStructs, + std::vector> const& _definedEnums, std::vector> const& _stateVariables, std::vector> const& _definedFunctions, std::vector> const& _functionModifiers, @@ -216,6 +229,7 @@ public: Declaration(_location, _name), Documented(_documentation), m_baseContracts(_baseContracts), m_definedStructs(_definedStructs), + m_definedEnums(_definedEnums), m_stateVariables(_stateVariables), m_definedFunctions(_definedFunctions), m_functionModifiers(_functionModifiers), @@ -227,6 +241,7 @@ public: std::vector> const& getBaseContracts() const { return m_baseContracts; } std::vector> const& getDefinedStructs() const { return m_definedStructs; } + std::vector> const& getDefinedEnums() const { return m_definedEnums; } std::vector> const& getStateVariables() const { return m_stateVariables; } std::vector> const& getFunctionModifiers() const { return m_functionModifiers; } std::vector> const& getDefinedFunctions() const { return m_definedFunctions; } @@ -260,6 +275,7 @@ private: std::vector> m_baseContracts; std::vector> m_definedStructs; + std::vector> m_definedEnums; std::vector> m_stateVariables; std::vector> m_definedFunctions; std::vector> m_functionModifiers; @@ -315,6 +331,28 @@ private: std::vector> m_members; }; +class EnumDefinition: public Declaration +{ +public: + EnumDefinition(Location const& _location, + ASTPointer const& _name, + std::vector> const& _members): + Declaration(_location, _name), m_members(_members) {} + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + + std::vector> const& getMembers() const { return m_members; } + + virtual TypePointer getType(ContractDefinition const*) const override; + + /// Checks that the members do not include any duplicate names + void checkValidityOfMembers() const; + +private: + + std::vector> m_members; +}; + /** * Parameter list, used as function parameter list and return list. * None of the parameters is allowed to contain mappings (not even recursively diff --git a/ASTForward.h b/ASTForward.h index 22015f26b..a0a6f6832 100644 --- a/ASTForward.h +++ b/ASTForward.h @@ -40,6 +40,8 @@ class Declaration; class ContractDefinition; class InheritanceSpecifier; class StructDefinition; +class EnumDefinition; +class EnumDeclaration; class ParameterList; class FunctionDefinition; class VariableDeclaration; diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp index 949740e89..34cd12a98 100644 --- a/ASTPrinter.cpp +++ b/ASTPrinter.cpp @@ -71,6 +71,18 @@ bool ASTPrinter::visit(StructDefinition const& _node) return goDeeper(); } +bool ASTPrinter::visit(EnumDefinition const& _node) +{ + writeLine("EnumDefinition \"" + _node.getName() + "\""); + return goDeeper(); +} + +bool ASTPrinter::visit(EnuumDeclaration const& _node) +{ + writeLine("EnumValue \"" + _node.getName() + "\""); + return goDeeper(); +} + bool ASTPrinter::visit(ParameterList const& _node) { writeLine("ParameterList"); @@ -347,6 +359,16 @@ void ASTPrinter::endVisit(StructDefinition const&) m_indentation--; } +void ASTPrinter::endVisit(EnumDefinition const&) +{ + m_indentation--; +} + +void ASTPrinter::endVisit(EnumDeclaration const&) +{ + m_indentation--; +} + void ASTPrinter::endVisit(ParameterList const&) { m_indentation--; diff --git a/ASTPrinter.h b/ASTPrinter.h index ebc163e31..a306e90b5 100644 --- a/ASTPrinter.h +++ b/ASTPrinter.h @@ -46,6 +46,8 @@ public: bool visit(ContractDefinition const& _node) override; bool visit(InheritanceSpecifier const& _node) override; bool visit(StructDefinition const& _node) override; + bool visit(EnumDefinition const& _node) override; + bool visit(EnumDeclaration const& _node) override; bool visit(ParameterList const& _node) override; bool visit(FunctionDefinition const& _node) override; bool visit(VariableDeclaration const& _node) override; @@ -85,6 +87,8 @@ public: void endVisit(ContractDefinition const&) override; void endVisit(InheritanceSpecifier const&) override; void endVisit(StructDefinition const&) override; + void endVisit(EnumDefinition const&) override; + void endVisit(EnumDeclaration const&) override; void endVisit(ParameterList const&) override; void endVisit(FunctionDefinition const&) override; void endVisit(VariableDeclaration const&) override; diff --git a/ASTVisitor.h b/ASTVisitor.h index 294902778..b05ec6580 100644 --- a/ASTVisitor.h +++ b/ASTVisitor.h @@ -47,6 +47,7 @@ public: virtual bool visit(ContractDefinition&) { return true; } virtual bool visit(InheritanceSpecifier&) { return true; } virtual bool visit(StructDefinition&) { return true; } + virtual bool visit(EnumDefinition&) { return true; } virtual bool visit(ParameterList&) { return true; } virtual bool visit(FunctionDefinition&) { return true; } virtual bool visit(VariableDeclaration&) { return true; } @@ -88,6 +89,7 @@ public: virtual void endVisit(ContractDefinition&) { } virtual void endVisit(InheritanceSpecifier&) { } virtual void endVisit(StructDefinition&) { } + virtual void endVisit(EnumDefinition&) { } virtual void endVisit(ParameterList&) { } virtual void endVisit(FunctionDefinition&) { } virtual void endVisit(VariableDeclaration&) { } @@ -133,6 +135,7 @@ public: virtual bool visit(ContractDefinition const&) { return true; } virtual bool visit(InheritanceSpecifier const&) { return true; } virtual bool visit(StructDefinition const&) { return true; } + virtual bool visit(EnumDefinition const&) { return true; } virtual bool visit(ParameterList const&) { return true; } virtual bool visit(FunctionDefinition const&) { return true; } virtual bool visit(VariableDeclaration const&) { return true; } @@ -174,6 +177,7 @@ public: virtual void endVisit(ContractDefinition const&) { } virtual void endVisit(InheritanceSpecifier const&) { } virtual void endVisit(StructDefinition const&) { } + virtual void endVisit(EnumDefinition const&) { } virtual void endVisit(ParameterList const&) { } virtual void endVisit(FunctionDefinition const&) { } virtual void endVisit(VariableDeclaration const&) { } diff --git a/AST_accept.h b/AST_accept.h index 38108cd72..15f6b7eeb 100644 --- a/AST_accept.h +++ b/AST_accept.h @@ -112,6 +112,18 @@ void StructDefinition::accept(ASTVisitor& _visitor) _visitor.endVisit(*this); } +void EnumDefinition::accept(ASTVisitor& _visitor) +{ + _visitor.visit(*this) + _visitor.endVisit(*this); +} + +void EnumDefinition::accept(ASTConstVisitor& _visitor) const +{ + _visitor.visit(*this) + _visitor.endVisit(*this); +} + void StructDefinition::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) diff --git a/Parser.cpp b/Parser.cpp index f076df876..2f0796d6d 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -119,6 +119,7 @@ ASTPointer Parser::parseContractDefinition() ASTPointer name = expectIdentifierToken(); vector> baseContracts; vector> structs; + vector> enums; vector> stateVariables; vector> functions; vector> modifiers; @@ -140,6 +141,8 @@ ASTPointer Parser::parseContractDefinition() functions.push_back(parseFunctionDefinition(name.get())); else if (currentToken == Token::Struct) structs.push_back(parseStructDefinition()); + else if (currentToken == Token::Enum) + enums.push_back(parseEnumDefinition()); else if (currentToken == Token::Identifier || currentToken == Token::Mapping || Token::isElementaryTypeName(currentToken)) { @@ -157,7 +160,7 @@ ASTPointer Parser::parseContractDefinition() } nodeFactory.markEndPosition(); expectToken(Token::RBrace); - return nodeFactory.createNode(name, docString, baseContracts, structs, + return nodeFactory.createNode(name, docString, baseContracts, structs, enums, stateVariables, functions, modifiers, events); } @@ -263,6 +266,35 @@ ASTPointer Parser::parseStructDefinition() return nodeFactory.createNode(name, members); } +ASTPointer Parser::parseEnumDeclaration() +{ + ASTNodeFactory nodeFactory(*this); + ASTPointer name = expectIdentifierToken(); + nodeFactory.markEndPosition(); + return nodeFactory.createNode(name); +} + +ASTPointer Parser::parseEnumDefinition() +{ + ASTNodeFactory nodeFactory(*this); + expectToken(Token::Enum); + ASTPointer name = expectIdentifierToken(); + vector> members; + expectToken(Token::LBrace); + + while (m_scanner->getCurrentToken() == Token::Identifier) + { + members.push_back(parseEnumDeclaration()); + if (m_scanner->getCurrentToken() == Token::RBrace) + break; + expectToken(Token::Comma); + } + + nodeFactory.markEndPosition(); + expectToken(Token::RBrace); + return nodeFactory.createNode(name, members); +} + ASTPointer Parser::parseVariableDeclaration(VarDeclParserOptions const& _options) { ASTNodeFactory nodeFactory(*this); @@ -823,6 +855,13 @@ ASTPointer Parser::expectIdentifierToken() return getLiteralAndAdvance(); } +ASTPointer Parser::peekIdentifierToken() +{ + if (m_scanner->getCurrentToken() != Token::Identifier) + return nullptr; + return getLiteralAndAdvance(); +} + ASTPointer Parser::getLiteralAndAdvance() { ASTPointer identifier = make_shared(m_scanner->getCurrentLiteral()); diff --git a/Parser.h b/Parser.h index 5816fec40..734bdd57e 100644 --- a/Parser.h +++ b/Parser.h @@ -61,6 +61,8 @@ private: Declaration::Visibility parseVisibilitySpecifier(Token::Value _token); ASTPointer parseFunctionDefinition(ASTString const* _contractName); ASTPointer parseStructDefinition(); + ASTPointer parseEnumDefinition(); + ASTPointer parseEnumDeclaration(); ASTPointer parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); ASTPointer parseModifierDefinition(); ASTPointer parseEventDefinition(); @@ -96,6 +98,7 @@ private: void expectToken(Token::Value _value); Token::Value expectAssignmentOperator(); ASTPointer expectIdentifierToken(); + ASTPointer peekIdentifierToken(); ASTPointer getLiteralAndAdvance(); ///@}