aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/parsing/Parser.cpp')
-rw-r--r--libsolidity/parsing/Parser.cpp83
1 files changed, 50 insertions, 33 deletions
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index df3ed7b2..421e358f 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -288,59 +288,61 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
return visibility;
}
-ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
+Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers)
{
- ASTNodeFactory nodeFactory(*this);
- ASTPointer<ASTString> docstring;
- if (m_scanner->currentCommentLiteral() != "")
- docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
-
+ FunctionHeaderParserResult result;
expectToken(Token::Function);
- ASTPointer<ASTString> name;
- if (m_scanner->currentToken() == Token::LParen)
- name = make_shared<ASTString>(); // anonymous function
+ if (_forceEmptyName || m_scanner->currentToken() == Token::LParen)
+ result.name = make_shared<ASTString>(); // anonymous function
else
- name = expectIdentifierToken();
+ result.name = expectIdentifierToken();
VarDeclParserOptions options;
options.allowLocationSpecifier = true;
- ASTPointer<ParameterList> parameters(parseParameterList(options));
- bool isDeclaredConst = false;
- bool isPayable = false;
- Declaration::Visibility visibility(Declaration::Visibility::Default);
- vector<ASTPointer<ModifierInvocation>> modifiers;
+ result.parameters = parseParameterList(options);
while (true)
{
Token::Value token = m_scanner->currentToken();
if (token == Token::Const)
{
- isDeclaredConst = true;
+ result.isDeclaredConst = true;
m_scanner->next();
}
else if (m_scanner->currentToken() == Token::Payable)
{
- isPayable = true;
+ result.isPayable = true;
m_scanner->next();
}
- else if (token == Token::Identifier)
- modifiers.push_back(parseModifierInvocation());
+ else if (_allowModifiers && token == Token::Identifier)
+ result.modifiers.push_back(parseModifierInvocation());
else if (Token::isVisibilitySpecifier(token))
{
- if (visibility != Declaration::Visibility::Default)
+ if (result.visibility != Declaration::Visibility::Default)
fatalParserError(string("Multiple visibility specifiers."));
- visibility = parseVisibilitySpecifier(token);
+ result.visibility = parseVisibilitySpecifier(token);
}
else
break;
}
- ASTPointer<ParameterList> returnParameters;
if (m_scanner->currentToken() == Token::Returns)
{
bool const permitEmptyParameterList = false;
m_scanner->next();
- returnParameters = parseParameterList(options, permitEmptyParameterList);
+ result.returnParameters = parseParameterList(options, permitEmptyParameterList);
}
else
- returnParameters = createEmptyParameterList();
+ result.returnParameters = createEmptyParameterList();
+ return result;
+}
+
+ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<ASTString> docstring;
+ if (m_scanner->currentCommentLiteral() != "")
+ docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
+
+ FunctionHeaderParserResult header = parseFunctionHeader(false, true);
+
ASTPointer<Block> block = ASTPointer<Block>();
nodeFactory.markEndPosition();
if (m_scanner->currentToken() != Token::Semicolon)
@@ -350,17 +352,17 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const*
}
else
m_scanner->next(); // just consume the ';'
- bool const c_isConstructor = (_contractName && *name == *_contractName);
+ bool const c_isConstructor = (_contractName && *header.name == *_contractName);
return nodeFactory.createNode<FunctionDefinition>(
- name,
- visibility,
+ header.name,
+ header.visibility,
c_isConstructor,
docstring,
- parameters,
- isDeclaredConst,
- modifiers,
- returnParameters,
- isPayable,
+ header.parameters,
+ header.isDeclaredConst,
+ header.modifiers,
+ header.returnParameters,
+ header.isPayable,
block
);
}
@@ -631,6 +633,8 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
fatalParserError(string("Expected explicit type name."));
m_scanner->next();
}
+ else if (token == Token::Function)
+ type = parseFunctionType();
else if (token == Token::Mapping)
type = parseMapping();
else if (token == Token::Identifier)
@@ -653,6 +657,19 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
return type;
}
+ASTPointer<FunctionTypeName> Parser::parseFunctionType()
+{
+ ASTNodeFactory nodeFactory(*this);
+ FunctionHeaderParserResult header = parseFunctionHeader(true, false);
+ return nodeFactory.createNode<FunctionTypeName>(
+ header.parameters,
+ header.returnParameters,
+ header.visibility,
+ header.isDeclaredConst,
+ header.isPayable
+ );
+}
+
ASTPointer<Mapping> Parser::parseMapping()
{
ASTNodeFactory nodeFactory(*this);
@@ -1278,7 +1295,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
Token::Value token(m_scanner->currentToken());
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
- if (token == Token::Mapping || token == Token::Var)
+ if (token == Token::Mapping || token == Token::Function || token == Token::Var)
return LookAheadInfo::VariableDeclarationStatement;
if (mightBeTypeName)
{