diff options
author | Christian <c@ethdev.com> | 2014-10-09 02:53:50 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-10-09 02:53:50 +0800 |
commit | 0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df (patch) | |
tree | dcc068f33caaa625872b1c1e612f6c362b13145f /Parser.cpp | |
parent | 56e9cc8db71f8af949123e13e6a97cc056cf766d (diff) | |
download | dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar.gz dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar.bz2 dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar.lz dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar.xz dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.tar.zst dexon-solidity-0a1ebe4f516a5c1e8ebc12798a94529bdda9b6df.zip |
Parse everything up to function bodies and report parser errors with location.
Diffstat (limited to 'Parser.cpp')
-rw-r--r-- | Parser.cpp | 137 |
1 files changed, 117 insertions, 20 deletions
@@ -20,6 +20,7 @@ * Solidity parser. */ +#include "libdevcore/Log.h" #include "libsolidity/BaseTypes.h" #include "libsolidity/Parser.h" #include "libsolidity/Scanner.h" @@ -27,9 +28,9 @@ namespace dev { namespace solidity { -ptr<ASTNode> Parser::parse(Scanner& _scanner) +ptr<ASTNode> Parser::parse(std::shared_ptr<Scanner> const& _scanner) { - m_scanner = &_scanner; + m_scanner = _scanner; return parseContractDefinition(); } @@ -41,20 +42,22 @@ class Parser::ASTNodeFactory { public: ASTNodeFactory(const Parser& _parser) - : m_parser(_parser), - m_location(_parser.getPosition(), -1) + : m_parser(_parser), m_location(_parser.getPosition(), -1) {} - void markEndPosition() + void markEndPosition() { m_location.end = m_parser.getEndPosition(); } + + /// Set the end position to the one of the given node. + void setEndPositionFromNode(const ptr<ASTNode>& _node) { - m_location.end_pos = m_parser.getEndPosition(); + m_location.end = _node->getLocation().end; } /// @todo: check that this actually uses perfect forwarding template <class NodeType, typename... Args> ptr<NodeType> createNode(Args&&... _args) { - if (m_location.end_pos < 0) markEndPosition(); + if (m_location.end < 0) markEndPosition(); return std::make_shared<NodeType>(m_location, std::forward<Args>(_args)...); } @@ -65,12 +68,12 @@ private: int Parser::getPosition() const { - return m_scanner->getCurrentLocation().beg_pos; + return m_scanner->getCurrentLocation().start; } int Parser::getEndPosition() const { - return m_scanner->getCurrentLocation().end_pos; + return m_scanner->getCurrentLocation().end; } @@ -98,7 +101,6 @@ ptr<ContractDefinition> Parser::parseContractDefinition() functions.push_back(parseFunctionDefinition(visibilityIsPublic)); } else if (currentToken == Token::STRUCT) { structs.push_back(parseStructDefinition()); - expectToken(Token::SEMICOLON); } else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING || Token::IsElementaryTypeName(currentToken)) { stateVariables.push_back(parseVariableDeclaration()); @@ -117,19 +119,57 @@ ptr<ContractDefinition> Parser::parseContractDefinition() ptr<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic) { - (void) _isPublic; - throwExpectationError("Function parsing is not yet implemented."); + ASTNodeFactory nodeFactory(*this); + + expectToken(Token::FUNCTION); + std::string name(expectIdentifier()); + ptr<ParameterList> parameters(parseParameterList()); + bool isDeclaredConst = false; + if (m_scanner->getCurrentToken() == Token::CONST) { + isDeclaredConst = true; + m_scanner->next(); + } + ptr<ParameterList> returnParameters; + if (m_scanner->getCurrentToken() == Token::RETURNS) { + m_scanner->next(); + returnParameters = parseParameterList(); + } + ptr<Block> block = parseBlock(); + nodeFactory.setEndPositionFromNode(block); + return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, parameters, + isDeclaredConst, returnParameters, block); } ptr<StructDefinition> Parser::parseStructDefinition() { - throwExpectationError("Struct definition parsing is not yet implemented."); + ASTNodeFactory nodeFactory(*this); + + expectToken(Token::STRUCT); + std::string name = expectIdentifier(); + vecptr<VariableDeclaration> members; + expectToken(Token::LBRACE); + while (m_scanner->getCurrentToken() != Token::RBRACE) { + members.push_back(parseVariableDeclaration()); + expectToken(Token::SEMICOLON); + } + nodeFactory.markEndPosition(); + expectToken(Token::RBRACE); + + return nodeFactory.createNode<StructDefinition>(name, members); } ptr<VariableDeclaration> Parser::parseVariableDeclaration() { ASTNodeFactory nodeFactory(*this); + ptr<TypeName> type = parseTypeName(); + nodeFactory.markEndPosition(); + std::string name = expectIdentifier(); + return nodeFactory.createNode<VariableDeclaration>(type, name); +} + +ptr<TypeName> Parser::parseTypeName() +{ ptr<TypeName> type; Token::Value token = m_scanner->getCurrentToken(); if (Token::IsElementaryTypeName(token)) { @@ -139,17 +179,67 @@ ptr<VariableDeclaration> Parser::parseVariableDeclaration() type = ASTNodeFactory(*this).createNode<TypeName>(); m_scanner->next(); } else if (token == Token::MAPPING) { - // TODO - throwExpectationError("mappings are not yet implemented"); + type = parseMapping(); } else if (token == Token::IDENTIFIER) { type = ASTNodeFactory(*this).createNode<UserDefinedTypeName>(m_scanner->getCurrentLiteral()); m_scanner->next(); } else { - throwExpectationError("Expected variable declaration"); + throwExpectationError("Expected type name"); } + + return type; +} + +ptr<Mapping> Parser::parseMapping() +{ + ASTNodeFactory nodeFactory(*this); + + expectToken(Token::MAPPING); + expectToken(Token::LPAREN); + + if (!Token::IsElementaryTypeName(m_scanner->getCurrentToken())) + throwExpectationError("Expected elementary type name for mapping key type"); + ptr<ElementaryTypeName> keyType; + keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(m_scanner->getCurrentToken()); + m_scanner->next(); + + expectToken(Token::ARROW); + ptr<TypeName> valueType = parseTypeName(); nodeFactory.markEndPosition(); - std::string name = expectIdentifier(); - return nodeFactory.createNode<VariableDeclaration>(type, name); + expectToken(Token::RPAREN); + + return nodeFactory.createNode<Mapping>(keyType, valueType); +} + +ptr<ParameterList> Parser::parseParameterList() +{ + ASTNodeFactory nodeFactory(*this); + + vecptr<VariableDeclaration> parameters; + expectToken(Token::LPAREN); + if (m_scanner->getCurrentToken() != Token::RPAREN) { + parameters.push_back(parseVariableDeclaration()); + while (m_scanner->getCurrentToken() != Token::RPAREN) { + expectToken(Token::COMMA); + parameters.push_back(parseVariableDeclaration()); + } + } + nodeFactory.markEndPosition(); + m_scanner->next(); + return nodeFactory.createNode<ParameterList>(parameters); +} + +ptr<Block> Parser::parseBlock() +{ + ASTNodeFactory nodeFactory(*this); + expectToken(Token::LBRACE); + while (m_scanner->getCurrentToken() != Token::RBRACE) { + m_scanner->next(); + // @todo + } + nodeFactory.markEndPosition(); + expectToken(Token::RBRACE); + return nodeFactory.createNode<Block>(); } void Parser::expectToken(Token::Value _value) @@ -171,9 +261,16 @@ std::string Parser::expectIdentifier() void Parser::throwExpectationError(const std::string& _description) { - (void) _description; + int line, column; + std::tie(line, column) = m_scanner->translatePositionToLineColumn(getPosition()); + cwarn << "Solidity parser error: " << _description + << "at line " << (line + 1) + << ", column " << (column + 1); + cwarn << m_scanner->getLineAtPosition(getPosition()); + cwarn << std::string(column, ' ') << "^"; + /// @todo make a proper exception hierarchy - throw std::exception();//_description); + throw std::exception(); } |