diff options
author | chriseth <chris@ethereum.org> | 2017-08-25 02:50:37 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-25 02:50:37 +0800 |
commit | d7661dd97460250b4e1127b9e7ea91e116143780 (patch) | |
tree | 0d909e7aeec373b0559b9d80f8ae9a9e03bdd92b /libsolidity/parsing/Parser.cpp | |
parent | bbb8e64fbee632d1594f6c132b1174591b961207 (diff) | |
parent | dd67e5966f41be0b2ef52041ea726930af74f7e9 (diff) | |
download | dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar.gz dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar.bz2 dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar.lz dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar.xz dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.tar.zst dexon-solidity-d7661dd97460250b4e1127b9e7ea91e116143780.zip |
Merge pull request #2802 from ethereum/develop
Merge develop into release for 0.4.16
Diffstat (limited to 'libsolidity/parsing/Parser.cpp')
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 121 |
1 files changed, 92 insertions, 29 deletions
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b98991f3..ddfdb667 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -40,7 +40,7 @@ namespace solidity class Parser::ASTNodeFactory { public: - ASTNodeFactory(Parser const& _parser): + explicit ASTNodeFactory(Parser const& _parser): m_parser(_parser), m_location(_parser.position(), -1, _parser.sourceName()) {} ASTNodeFactory(Parser const& _parser, ASTPointer<ASTNode> const& _childNode): m_parser(_parser), m_location(_childNode->location()) {} @@ -68,6 +68,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner) { try { + m_recursionDepth = 0; m_scanner = _scanner; ASTNodeFactory nodeFactory(*this); vector<ASTPointer<ASTNode>> nodes; @@ -90,6 +91,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner) fatalParserError(string("Expected pragma, import directive or contract/interface/library definition.")); } } + solAssert(m_recursionDepth == 0, ""); return nodeFactory.createNode<SourceUnit>(nodes); } catch (FatalError const&) @@ -102,6 +104,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner) ASTPointer<PragmaDirective> Parser::parsePragmaDirective() { + RecursionGuard recursionGuard(*this); // pragma anything* ; // Currently supported: // pragma solidity ^0.4.0 || ^0.3.0; @@ -132,6 +135,7 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective() ASTPointer<ImportDirective> Parser::parseImportDirective() { + RecursionGuard recursionGuard(*this); // import "abc" [as x]; // import * as x from "abc"; // import {a as b, c} from "abc"; @@ -212,6 +216,7 @@ ContractDefinition::ContractKind Parser::tokenToContractKind(Token::Value _token ASTPointer<ContractDefinition> Parser::parseContractDefinition(Token::Value _expectedKind) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<ASTString> docString; if (m_scanner->currentCommentLiteral() != "") @@ -275,6 +280,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(Token::Value _exp ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<UserDefinedTypeName> name(parseUserDefinedTypeName()); vector<ASTPointer<Expression>> arguments; @@ -307,8 +313,25 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) return visibility; } +StateMutability Parser::parseStateMutability(Token::Value _token) +{ + StateMutability stateMutability(StateMutability::NonPayable); + if (_token == Token::Payable) + stateMutability = StateMutability::Payable; + // FIXME: constant should be removed at the next breaking release + else if (_token == Token::View || _token == Token::Constant) + stateMutability = StateMutability::View; + else if (_token == Token::Pure) + stateMutability = StateMutability::Pure; + else + solAssert(false, "Invalid state mutability specifier."); + m_scanner->next(); + return stateMutability; +} + Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers) { + RecursionGuard recursionGuard(*this); FunctionHeaderParserResult result; expectToken(Token::Function); if (_forceEmptyName || m_scanner->currentToken() == Token::LParen) @@ -321,23 +344,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN while (true) { Token::Value token = m_scanner->currentToken(); - if (token == Token::Const) - { - if (result.isDeclaredConst) - parserError(string("Multiple \"constant\" specifiers.")); - - result.isDeclaredConst = true; - m_scanner->next(); - } - else if (m_scanner->currentToken() == Token::Payable) - { - if (result.isPayable) - parserError(string("Multiple \"payable\" specifiers.")); - - result.isPayable = true; - m_scanner->next(); - } - else if (_allowModifiers && token == Token::Identifier) + if (_allowModifiers && token == Token::Identifier) { // This can either be a modifier (function declaration) or the name of the // variable (function type name plus variable). @@ -354,12 +361,30 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN { if (result.visibility != Declaration::Visibility::Default) { - parserError(string("Multiple visibility specifiers.")); + parserError(string( + "Visibility already specified as \"" + + Declaration::visibilityToString(result.visibility) + + "\"." + )); m_scanner->next(); } else result.visibility = parseVisibilitySpecifier(token); } + else if (Token::isStateMutabilitySpecifier(token)) + { + if (result.stateMutability != StateMutability::NonPayable) + { + parserError(string( + "State mutability already specified as \"" + + stateMutabilityToString(result.stateMutability) + + "\"." + )); + m_scanner->next(); + } + else + result.stateMutability = parseStateMutability(token); + } else break; } @@ -376,6 +401,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(ASTString const* _contractName) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<ASTString> docstring; if (m_scanner->currentCommentLiteral() != "") @@ -404,13 +430,12 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A return nodeFactory.createNode<FunctionDefinition>( header.name, header.visibility, + header.stateMutability, c_isConstructor, docstring, header.parameters, - header.isDeclaredConst, header.modifiers, header.returnParameters, - header.isPayable, block ); } @@ -421,8 +446,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A header.parameters, header.returnParameters, header.visibility, - header.isDeclaredConst, - header.isPayable + header.stateMutability ); type = parseTypeNameSuffix(type, nodeFactory); VarDeclParserOptions options; @@ -436,6 +460,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A ASTPointer<StructDefinition> Parser::parseStructDefinition() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Struct); ASTPointer<ASTString> name = expectIdentifierToken(); @@ -453,6 +478,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition() ASTPointer<EnumValue> Parser::parseEnumValue() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); nodeFactory.markEndPosition(); return nodeFactory.createNode<EnumValue>(expectIdentifierToken()); @@ -460,6 +486,7 @@ ASTPointer<EnumValue> Parser::parseEnumValue() ASTPointer<EnumDefinition> Parser::parseEnumDefinition() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Enum); ASTPointer<ASTString> name = expectIdentifierToken(); @@ -488,6 +515,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( ASTPointer<TypeName> const& _lookAheadArrayType ) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory = _lookAheadArrayType ? ASTNodeFactory(*this, _lookAheadArrayType) : ASTNodeFactory(*this); ASTPointer<TypeName> type; @@ -512,7 +540,11 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( { if (visibility != Declaration::Visibility::Default) { - parserError(string("Visibility already specified.")); + parserError(string( + "Visibility already specified as \"" + + Declaration::visibilityToString(visibility) + + "\"." + )); m_scanner->next(); } else @@ -522,7 +554,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( { if (_options.allowIndexed && token == Token::Indexed) isIndexed = true; - else if (token == Token::Const) + else if (token == Token::Constant) isDeclaredConst = true; else if (_options.allowLocationSpecifier && Token::isLocationSpecifier(token)) { @@ -576,6 +608,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() { + RecursionGuard recursionGuard(*this); ScopeGuard resetModifierFlag([this]() { m_insideModifier = false; }); m_insideModifier = true; @@ -603,6 +636,7 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() ASTPointer<EventDefinition> Parser::parseEventDefinition() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<ASTString> docstring; if (m_scanner->currentCommentLiteral() != "") @@ -632,6 +666,7 @@ ASTPointer<EventDefinition> Parser::parseEventDefinition() ASTPointer<UsingForDirective> Parser::parseUsingDirective() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Using); @@ -649,6 +684,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective() ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<Identifier> name(parseIdentifier()); vector<ASTPointer<Expression>> arguments; @@ -666,6 +702,7 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() ASTPointer<Identifier> Parser::parseIdentifier() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); nodeFactory.markEndPosition(); return nodeFactory.createNode<Identifier>(expectIdentifierToken()); @@ -673,6 +710,7 @@ ASTPointer<Identifier> Parser::parseIdentifier() ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); nodeFactory.markEndPosition(); vector<ASTString> identifierPath{*expectIdentifierToken()}; @@ -687,6 +725,7 @@ ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName() ASTPointer<TypeName> Parser::parseTypeNameSuffix(ASTPointer<TypeName> type, ASTNodeFactory& nodeFactory) { + RecursionGuard recursionGuard(*this); while (m_scanner->currentToken() == Token::LBrack) { m_scanner->next(); @@ -702,6 +741,7 @@ ASTPointer<TypeName> Parser::parseTypeNameSuffix(ASTPointer<TypeName> type, ASTN ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<TypeName> type; Token::Value token = m_scanner->currentToken(); @@ -737,19 +777,20 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) ASTPointer<FunctionTypeName> Parser::parseFunctionType() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); FunctionHeaderParserResult header = parseFunctionHeader(true, false); return nodeFactory.createNode<FunctionTypeName>( header.parameters, header.returnParameters, header.visibility, - header.isDeclaredConst, - header.isPayable + header.stateMutability ); } ASTPointer<Mapping> Parser::parseMapping() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Mapping); expectToken(Token::LParen); @@ -776,6 +817,7 @@ ASTPointer<ParameterList> Parser::parseParameterList( bool _allowEmpty ) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); vector<ASTPointer<VariableDeclaration>> parameters; VarDeclParserOptions options(_options); @@ -797,6 +839,7 @@ ASTPointer<ParameterList> Parser::parseParameterList( ASTPointer<Block> Parser::parseBlock(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::LBrace); vector<ASTPointer<Statement>> statements; @@ -809,6 +852,7 @@ ASTPointer<Block> Parser::parseBlock(ASTPointer<ASTString> const& _docString) ASTPointer<Statement> Parser::parseStatement() { + RecursionGuard recursionGuard(*this); ASTPointer<ASTString> docString; if (m_scanner->currentCommentLiteral() != "") docString = make_shared<ASTString>(m_scanner->currentCommentLiteral()); @@ -871,6 +915,7 @@ ASTPointer<Statement> Parser::parseStatement() ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Assembly); if (m_scanner->currentToken() == Token::StringLiteral) @@ -888,6 +933,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::If); expectToken(Token::LParen); @@ -908,6 +954,7 @@ ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _d ASTPointer<WhileStatement> Parser::parseWhileStatement(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::While); expectToken(Token::LParen); @@ -920,6 +967,7 @@ ASTPointer<WhileStatement> Parser::parseWhileStatement(ASTPointer<ASTString> con ASTPointer<WhileStatement> Parser::parseDoWhileStatement(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); expectToken(Token::Do); ASTPointer<Statement> body = parseStatement(); @@ -935,6 +983,7 @@ ASTPointer<WhileStatement> Parser::parseDoWhileStatement(ASTPointer<ASTString> c ASTPointer<ForStatement> Parser::parseForStatement(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); ASTPointer<Statement> initExpression; ASTPointer<Expression> conditionExpression; @@ -968,6 +1017,7 @@ ASTPointer<ForStatement> Parser::parseForStatement(ASTPointer<ASTString> const& ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString) { + RecursionGuard recursionGuard(*this); // These two cases are very hard to distinguish: // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9; // In the first case, x is a type name, in the second it is the name of a variable. @@ -1030,6 +1080,7 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme ASTPointer<TypeName> const& _lookAheadArrayType ) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); if (_lookAheadArrayType) nodeFactory.setLocation(_lookAheadArrayType->location()); @@ -1093,6 +1144,7 @@ ASTPointer<ExpressionStatement> Parser::parseExpressionStatement( ASTPointer<Expression> const& _lookAheadIndexAccessStructure ) { + RecursionGuard recursionGuard(*this); ASTPointer<Expression> expression = parseExpression(_lookAheadIndexAccessStructure); return ASTNodeFactory(*this, expression).createNode<ExpressionStatement>(_docString, expression); } @@ -1101,6 +1153,7 @@ ASTPointer<Expression> Parser::parseExpression( ASTPointer<Expression> const& _lookAheadIndexAccessStructure ) { + RecursionGuard recursionGuard(*this); ASTPointer<Expression> expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); if (Token::isAssignmentOp(m_scanner->currentToken())) { @@ -1129,6 +1182,7 @@ ASTPointer<Expression> Parser::parseBinaryExpression( ASTPointer<Expression> const& _lookAheadIndexAccessStructure ) { + RecursionGuard recursionGuard(*this); ASTPointer<Expression> expression = parseUnaryExpression(_lookAheadIndexAccessStructure); ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->currentToken()); @@ -1148,6 +1202,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression( ASTPointer<Expression> const& _lookAheadIndexAccessStructure ) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); Token::Value token = m_scanner->currentToken(); @@ -1176,6 +1231,7 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression( ASTPointer<Expression> const& _lookAheadIndexAccessStructure ) { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); @@ -1233,6 +1289,7 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression( ASTPointer<Expression> Parser::parsePrimaryExpression() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); Token::Value token = m_scanner->currentToken(); ASTPointer<Expression> expression; @@ -1292,10 +1349,11 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() parserError("Expected expression (inline array elements cannot be omitted)."); else components.push_back(ASTPointer<Expression>()); + if (m_scanner->currentToken() == oppositeToken) break; - else if (m_scanner->currentToken() == Token::Comma) - m_scanner->next(); + + expectToken(Token::Comma); } nodeFactory.markEndPosition(); expectToken(oppositeToken); @@ -1322,6 +1380,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments() { + RecursionGuard recursionGuard(*this); vector<ASTPointer<Expression>> arguments; if (m_scanner->currentToken() != Token::RParen) { @@ -1337,6 +1396,7 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments() pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseFunctionCallArguments() { + RecursionGuard recursionGuard(*this); pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret; Token::Value token = m_scanner->currentToken(); if (token == Token::LBrace) @@ -1403,6 +1463,7 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure( ) { solAssert(!_path.empty(), ""); + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); SourceLocation location = _path.front()->location(); location.end = _path.back()->location().end; @@ -1435,6 +1496,7 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure( ) { solAssert(!_path.empty(), ""); + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this, _path.front()); ASTPointer<Expression> expression(_path.front()); for (size_t i = 1; i < _path.size(); ++i) @@ -1458,6 +1520,7 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure( ASTPointer<ParameterList> Parser::createEmptyParameterList() { + RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); nodeFactory.setLocationEmpty(); return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>()); |