aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-21 18:16:18 +0800
committerChristian <c@ethdev.com>2015-01-26 17:23:39 +0800
commit19793dab093ae36b5f2b4d1cabfbf54bed3125b1 (patch)
tree94070079e892a1681fa82a0d4a9db315ce152573
parent570e49c03ab9e09d538218839696fc6159b0a2f1 (diff)
downloaddexon-solidity-19793dab093ae36b5f2b4d1cabfbf54bed3125b1.tar.gz
dexon-solidity-19793dab093ae36b5f2b4d1cabfbf54bed3125b1.tar.zst
dexon-solidity-19793dab093ae36b5f2b4d1cabfbf54bed3125b1.zip
Function modifier parsing.
-rw-r--r--AST.cpp5
-rwxr-xr-xAST.h53
-rw-r--r--ASTForward.h2
-rw-r--r--ASTPrinter.cpp24
-rw-r--r--ASTPrinter.h4
-rw-r--r--ASTVisitor.h8
-rw-r--r--AST_accept.h34
-rw-r--r--Parser.cpp44
-rw-r--r--Parser.h3
-rw-r--r--Token.h1
10 files changed, 174 insertions, 4 deletions
diff --git a/AST.cpp b/AST.cpp
index 82667367..a51bbd0c 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -183,6 +183,11 @@ string FunctionDefinition::getCanonicalSignature() const
return getName() + FunctionType(*this).getCanonicalSignature();
}
+void ModifierDefinition::checkTypeRequirements()
+{
+ m_body->checkTypeRequirements();
+}
+
void Block::checkTypeRequirements()
{
for (shared_ptr<Statement> const& statement: m_statements)
diff --git a/AST.h b/AST.h
index 754e9254..e48e45d3 100755
--- a/AST.h
+++ b/AST.h
@@ -161,12 +161,14 @@ public:
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
- std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions):
+ std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
+ std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers):
Declaration(_location, _name),
m_baseContracts(_baseContracts),
m_definedStructs(_definedStructs),
m_stateVariables(_stateVariables),
m_definedFunctions(_definedFunctions),
+ m_functionModifiers(_functionModifiers),
m_documentation(_documentation)
{}
@@ -207,6 +209,7 @@ private:
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;
std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions;
+ std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers;
ASTPointer<ASTString> m_documentation;
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
@@ -362,6 +365,39 @@ private:
};
/**
+ * Definition of a function modifier.
+ */
+class ModifierDefinition: public Declaration
+{
+public:
+ ModifierDefinition(Location const& _location,
+ ASTPointer<ASTString> const& _name,
+ ASTPointer<ASTString> const& _documentation,
+ ASTPointer<ParameterList> const& _parameters,
+ ASTPointer<Block> const& _body):
+ Declaration(_location, _name), m_documentation(_documentation),
+ m_parameters(_parameters), m_body(_body) {}
+
+ virtual void accept(ASTVisitor& _visitor) override;
+ virtual void accept(ASTConstVisitor& _visitor) const override;
+
+ std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); }
+ ParameterList const& getParameterList() const { return *m_parameters; }
+ Block const& getBody() const { return *m_body; }
+
+ /// @return A shared pointer of an ASTString.
+ /// Can contain a nullptr in which case indicates absence of documentation
+ ASTPointer<ASTString> const& getDocumentation() const { return m_documentation; }
+
+ void checkTypeRequirements();
+
+private:
+ ASTPointer<ASTString> m_documentation;
+ ASTPointer<ParameterList> m_parameters;
+ ASTPointer<Block> m_body;
+};
+
+/**
* Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
* functions when such an identifier is encountered. Will never have a valid location in the source code.
*/
@@ -503,6 +539,21 @@ private:
};
/**
+ * Special placeholder statement denoted by "_" used in function modifiers. This is replaced by
+ * the original function when the modifier is applied.
+ */
+class PlaceholderStatement: public Statement
+{
+public:
+ PlaceholderStatement(Location const& _location): Statement(_location) {}
+
+ virtual void accept(ASTVisitor& _visitor) override;
+ virtual void accept(ASTConstVisitor& _visitor) const override;
+
+ virtual void checkTypeRequirements() override { }
+};
+
+/**
* If-statement with an optional "else" part. Note that "else if" is modeled by having a new
* if-statement as the false (else) body.
*/
diff --git a/ASTForward.h b/ASTForward.h
index da0a8812..b86f18cf 100644
--- a/ASTForward.h
+++ b/ASTForward.h
@@ -43,6 +43,7 @@ class StructDefinition;
class ParameterList;
class FunctionDefinition;
class VariableDeclaration;
+class ModifierDefinition;
class MagicVariableDeclaration;
class TypeName;
class ElementaryTypeName;
@@ -50,6 +51,7 @@ class UserDefinedTypeName;
class Mapping;
class Statement;
class Block;
+class PlaceholderStatement;
class IfStatement;
class BreakableStatement;
class WhileStatement;
diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp
index 916fca1e..86cd028a 100644
--- a/ASTPrinter.cpp
+++ b/ASTPrinter.cpp
@@ -87,6 +87,13 @@ bool ASTPrinter::visit(VariableDeclaration const& _node)
return goDeeper();
}
+bool ASTPrinter::visit(ModifierDefinition const& _node)
+{
+ writeLine("ModifierDefinition \"" + _node.getName() + "\"");
+ printSourcePart(_node);
+ return goDeeper();
+}
+
bool ASTPrinter::visit(TypeName const& _node)
{
writeLine("TypeName");
@@ -129,6 +136,13 @@ bool ASTPrinter::visit(Block const& _node)
return goDeeper();
}
+bool ASTPrinter::visit(PlaceholderStatement const& _node)
+{
+ writeLine("PlaceholderStatement");
+ printSourcePart(_node);
+ return goDeeper();
+}
+
bool ASTPrinter::visit(IfStatement const& _node)
{
writeLine("IfStatement");
@@ -322,6 +336,11 @@ void ASTPrinter::endVisit(VariableDeclaration const&)
m_indentation--;
}
+void ASTPrinter::endVisit(ModifierDefinition const&)
+{
+ m_indentation--;
+}
+
void ASTPrinter::endVisit(TypeName const&)
{
m_indentation--;
@@ -352,6 +371,11 @@ void ASTPrinter::endVisit(Block const&)
m_indentation--;
}
+void ASTPrinter::endVisit(PlaceholderStatement const&)
+{
+ m_indentation--;
+}
+
void ASTPrinter::endVisit(IfStatement const&)
{
m_indentation--;
diff --git a/ASTPrinter.h b/ASTPrinter.h
index fc5fb4ac..ef5c5164 100644
--- a/ASTPrinter.h
+++ b/ASTPrinter.h
@@ -48,12 +48,14 @@ public:
bool visit(ParameterList const& _node) override;
bool visit(FunctionDefinition const& _node) override;
bool visit(VariableDeclaration const& _node) override;
+ bool visit(ModifierDefinition const& _node) override;
bool visit(TypeName const& _node) override;
bool visit(ElementaryTypeName const& _node) override;
bool visit(UserDefinedTypeName const& _node) override;
bool visit(Mapping const& _node) override;
bool visit(Statement const& _node) override;
bool visit(Block const& _node) override;
+ bool visit(PlaceholderStatement const& _node) override;
bool visit(IfStatement const& _node) override;
bool visit(BreakableStatement const& _node) override;
bool visit(WhileStatement const& _node) override;
@@ -82,12 +84,14 @@ public:
void endVisit(ParameterList const&) override;
void endVisit(FunctionDefinition const&) override;
void endVisit(VariableDeclaration const&) override;
+ void endVisit(ModifierDefinition const&) override;
void endVisit(TypeName const&) override;
void endVisit(ElementaryTypeName const&) override;
void endVisit(UserDefinedTypeName const&) override;
void endVisit(Mapping const&) override;
void endVisit(Statement const&) override;
void endVisit(Block const&) override;
+ void endVisit(PlaceholderStatement const&) override;
void endVisit(IfStatement const&) override;
void endVisit(BreakableStatement const&) override;
void endVisit(WhileStatement const&) override;
diff --git a/ASTVisitor.h b/ASTVisitor.h
index 33a8a338..94bb9e0b 100644
--- a/ASTVisitor.h
+++ b/ASTVisitor.h
@@ -49,12 +49,14 @@ public:
virtual bool visit(ParameterList&) { return true; }
virtual bool visit(FunctionDefinition&) { return true; }
virtual bool visit(VariableDeclaration&) { return true; }
+ virtual bool visit(ModifierDefinition&) { return true; }
virtual bool visit(TypeName&) { return true; }
virtual bool visit(ElementaryTypeName&) { return true; }
virtual bool visit(UserDefinedTypeName&) { return true; }
virtual bool visit(Mapping&) { return true; }
virtual bool visit(Statement&) { return true; }
virtual bool visit(Block&) { return true; }
+ virtual bool visit(PlaceholderStatement&) { return true; }
virtual bool visit(IfStatement&) { return true; }
virtual bool visit(BreakableStatement&) { return true; }
virtual bool visit(WhileStatement&) { return true; }
@@ -85,12 +87,14 @@ public:
virtual void endVisit(ParameterList&) { }
virtual void endVisit(FunctionDefinition&) { }
virtual void endVisit(VariableDeclaration&) { }
+ virtual void endVisit(ModifierDefinition&) { }
virtual void endVisit(TypeName&) { }
virtual void endVisit(ElementaryTypeName&) { }
virtual void endVisit(UserDefinedTypeName&) { }
virtual void endVisit(Mapping&) { }
virtual void endVisit(Statement&) { }
virtual void endVisit(Block&) { }
+ virtual void endVisit(PlaceholderStatement&) { }
virtual void endVisit(IfStatement&) { }
virtual void endVisit(BreakableStatement&) { }
virtual void endVisit(WhileStatement&) { }
@@ -125,12 +129,14 @@ public:
virtual bool visit(ParameterList const&) { return true; }
virtual bool visit(FunctionDefinition const&) { return true; }
virtual bool visit(VariableDeclaration const&) { return true; }
+ virtual bool visit(ModifierDefinition const&) { return true; }
virtual bool visit(TypeName const&) { return true; }
virtual bool visit(ElementaryTypeName const&) { return true; }
virtual bool visit(UserDefinedTypeName const&) { return true; }
virtual bool visit(Mapping const&) { return true; }
virtual bool visit(Statement const&) { return true; }
virtual bool visit(Block const&) { return true; }
+ virtual bool visit(PlaceholderStatement const&) { return true; }
virtual bool visit(IfStatement const&) { return true; }
virtual bool visit(BreakableStatement const&) { return true; }
virtual bool visit(WhileStatement const&) { return true; }
@@ -161,12 +167,14 @@ public:
virtual void endVisit(ParameterList const&) { }
virtual void endVisit(FunctionDefinition const&) { }
virtual void endVisit(VariableDeclaration const&) { }
+ virtual void endVisit(ModifierDefinition const&) { }
virtual void endVisit(TypeName const&) { }
virtual void endVisit(ElementaryTypeName const&) { }
virtual void endVisit(UserDefinedTypeName const&) { }
virtual void endVisit(Mapping const&) { }
virtual void endVisit(Statement const&) { }
virtual void endVisit(Block const&) { }
+ virtual void endVisit(PlaceholderStatement const&) { }
virtual void endVisit(IfStatement const&) { }
virtual void endVisit(BreakableStatement const&) { }
virtual void endVisit(WhileStatement const&) { }
diff --git a/AST_accept.h b/AST_accept.h
index b77cfe1c..89786d6f 100644
--- a/AST_accept.h
+++ b/AST_accept.h
@@ -65,6 +65,7 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
listAccept(m_definedStructs, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_definedFunctions, _visitor);
+ listAccept(m_functionModifiers, _visitor);
}
_visitor.endVisit(*this);
}
@@ -77,6 +78,7 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const
listAccept(m_definedStructs, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_definedFunctions, _visitor);
+ listAccept(m_functionModifiers, _visitor);
}
_visitor.endVisit(*this);
}
@@ -175,6 +177,26 @@ void VariableDeclaration::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
+void ModifierDefinition::accept(ASTVisitor& _visitor)
+{
+ if (_visitor.visit(*this))
+ {
+ m_parameters->accept(_visitor);
+ m_body->accept(_visitor);
+ }
+ _visitor.endVisit(*this);
+}
+
+void ModifierDefinition::accept(ASTConstVisitor& _visitor) const
+{
+ if (_visitor.visit(*this))
+ {
+ m_parameters->accept(_visitor);
+ m_body->accept(_visitor);
+ }
+ _visitor.endVisit(*this);
+}
+
void TypeName::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
@@ -245,6 +267,18 @@ void Block::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
+void PlaceholderStatement::accept(ASTVisitor& _visitor)
+{
+ _visitor.visit(*this);
+ _visitor.endVisit(*this);
+}
+
+void PlaceholderStatement::accept(ASTConstVisitor& _visitor) const
+{
+ _visitor.visit(*this);
+ _visitor.endVisit(*this);
+}
+
void IfStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
diff --git a/Parser.cpp b/Parser.cpp
index fcabdb29..a72a5dba 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -121,6 +121,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
vector<ASTPointer<StructDefinition>> structs;
vector<ASTPointer<VariableDeclaration>> stateVariables;
vector<ASTPointer<FunctionDefinition>> functions;
+ vector<ASTPointer<ModifierDefinition>> modifiers;
if (m_scanner->getCurrentToken() == Token::IS)
do
{
@@ -152,13 +153,15 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
stateVariables.push_back(parseVariableDeclaration(allowVar));
expectToken(Token::SEMICOLON);
}
+ else if (currentToken == Token::MODIFIER)
+ modifiers.push_back(parseModifierDefinition());
else
- BOOST_THROW_EXCEPTION(createParserError("Function, variable or struct declaration expected."));
+ BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
}
nodeFactory.markEndPosition();
expectToken(Token::RBRACE);
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs,
- stateVariables, functions);
+ stateVariables, functions, modifiers);
}
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
@@ -242,6 +245,33 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar)
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken());
}
+ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
+{
+ ScopeGuard resetModifierFlag([this]() { m_insideModifier = false; });
+ m_insideModifier = true;
+
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<ASTString> docstring;
+ if (m_scanner->getCurrentCommentLiteral() != "")
+ docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
+
+ expectToken(Token::MODIFIER);
+ ASTPointer<ASTString> name(expectIdentifierToken());
+ ASTPointer<ParameterList> parameters;
+ if (m_scanner->getCurrentToken() == Token::LPAREN)
+ parameters = parseParameterList();
+ else
+ {
+ // create an empty parameter list at a zero-length location
+ ASTNodeFactory nodeFactory(*this);
+ nodeFactory.setLocationEmpty();
+ parameters = nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
+ }
+ ASTPointer<Block> block = parseBlock();
+ nodeFactory.setEndPositionFromNode(block);
+ return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block);
+}
+
ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
{
ASTPointer<TypeName> type;
@@ -354,8 +384,16 @@ ASTPointer<Statement> Parser::parseStatement()
nodeFactory.setEndPositionFromNode(expression);
}
statement = nodeFactory.createNode<Return>(expression);
+ break;
}
- break;
+ case Token::IDENTIFIER:
+ if (m_insideModifier && m_scanner->getCurrentLiteral() == "_")
+ {
+ statement = ASTNodeFactory(*this).createNode<PlaceholderStatement>();
+ m_scanner->next();
+ return statement;
+ }
+ // fall-through
default:
statement = parseVarDefOrExprStmt();
}
diff --git a/Parser.h b/Parser.h
index 5905a042..cccf3b3b 100644
--- a/Parser.h
+++ b/Parser.h
@@ -53,6 +53,7 @@ private:
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName);
ASTPointer<StructDefinition> parseStructDefinition();
ASTPointer<VariableDeclaration> parseVariableDeclaration(bool _allowVar);
+ ASTPointer<ModifierDefinition> parseModifierDefinition();
ASTPointer<TypeName> parseTypeName(bool _allowVar);
ASTPointer<Mapping> parseMapping();
ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true);
@@ -90,6 +91,8 @@ private:
ParserError createParserError(std::string const& _description) const;
std::shared_ptr<Scanner> m_scanner;
+ /// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.
+ bool m_insideModifier = false;
};
}
diff --git a/Token.h b/Token.h
index 552e9a75..55ec8e8e 100644
--- a/Token.h
+++ b/Token.h
@@ -159,6 +159,7 @@ namespace solidity
K(IF, "if", 0) \
K(IMPORT, "import", 0) \
K(MAPPING, "mapping", 0) \
+ K(MODIFIER, "modifier", 0) \
K(NEW, "new", 0) \
K(PUBLIC, "public", 0) \
K(PRIVATE, "private", 0) \