aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing/Parser.cpp
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-08-25 02:50:37 +0800
committerGitHub <noreply@github.com>2017-08-25 02:50:37 +0800
commitd7661dd97460250b4e1127b9e7ea91e116143780 (patch)
tree0d909e7aeec373b0559b9d80f8ae9a9e03bdd92b /libsolidity/parsing/Parser.cpp
parentbbb8e64fbee632d1594f6c132b1174591b961207 (diff)
parentdd67e5966f41be0b2ef52041ea726930af74f7e9 (diff)
downloaddexon-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.cpp121
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>>());