AST printer and command line tool, some fixes.

This commit is contained in:
Christian 2014-10-10 16:37:54 +02:00
parent 924f7c62bd
commit 98bdd74299
8 changed files with 955 additions and 55 deletions

232
AST.cpp
View File

@ -21,3 +21,235 @@
*/
#include <libsolidity/AST.h>
#include <libsolidity/ASTVisitor.h>
namespace dev {
namespace solidity {
void ContractDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
listAccept(m_definedStructs, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_definedFunctions, _visitor);
}
_visitor.endVisit(*this);
}
void StructDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
listAccept(m_members, _visitor);
}
_visitor.endVisit(*this);
}
void ParameterList::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
listAccept(m_parameters, _visitor);
}
_visitor.endVisit(*this);
}
void FunctionDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_parameters->accept(_visitor);
if (m_returnParameters)
m_returnParameters->accept(_visitor);
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}
void VariableDeclaration::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
if (m_type)
m_type->accept(_visitor);
}
_visitor.endVisit(*this);
}
void TypeName::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void ElementaryTypeName::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void UserDefinedTypeName::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Mapping::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_keyType->accept(_visitor);
m_valueType->accept(_visitor);
}
_visitor.endVisit(*this);
}
void Statement::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Block::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
listAccept(m_statements, _visitor);
}
_visitor.endVisit(*this);
}
void IfStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_condition->accept(_visitor);
m_trueBody->accept(_visitor);
if (m_falseBody)
m_falseBody->accept(_visitor);
}
_visitor.endVisit(*this);
}
void BreakableStatement::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void WhileStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_condition->accept(_visitor);
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}
void Continue::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Break::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Return::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
if (m_expression)
m_expression->accept(_visitor);
}
_visitor.endVisit(*this);
}
void VariableDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_variable->accept(_visitor);
if (m_value)
m_value->accept(_visitor);
}
_visitor.endVisit(*this);
}
void Expression::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Assignment::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_leftHandSide->accept(_visitor);
m_rightHandSide->accept(_visitor);
}
_visitor.endVisit(*this);
}
void UnaryOperation::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_subExpression->accept(_visitor);
}
_visitor.endVisit(*this);
}
void BinaryOperation::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_left->accept(_visitor);
m_right->accept(_visitor);
}
_visitor.endVisit(*this);
}
void FunctionCall::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_expression->accept(_visitor);
listAccept(m_arguments, _visitor);
}
_visitor.endVisit(*this);
}
void MemberAccess::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_expression->accept(_visitor);
}
_visitor.endVisit(*this);
}
void IndexAccess::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this)) {
m_base->accept(_visitor);
m_index->accept(_visitor);
}
_visitor.endVisit(*this);
}
void PrimaryExpression::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Identifier::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void ElementaryTypeNameExpression::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void Literal::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
} }

118
AST.h
View File

@ -26,26 +26,14 @@
#include <vector>
#include <memory>
#include <libsolidity/ASTForward.h>
#include <libsolidity/BaseTypes.h>
#include <libsolidity/Token.h>
namespace dev {
namespace solidity {
// Used as pointers to AST nodes, to be replaced by more clever pointers, e.g. pointers which do
// not do reference counting but point to a special memory area that is completely released
// explicitly.
template <class T>
using ptr = std::shared_ptr<T>;
template <class T>
using vecptr = std::vector<ptr<T>>;
class VariableDeclaration;
class StructDefinition;
class FunctionDefinition;
class TypeName;
class Block;
class Expression;
class ASTVisitor;
class ASTNode
{
@ -56,7 +44,13 @@ public:
virtual ~ASTNode() {}
Location getLocation() const { return m_location; }
virtual void accept(ASTVisitor& _visitor) = 0;
template <class T>
static void listAccept(vecptr<T>& _list, ASTVisitor& _visitor) {
for (ptr<T>& element : _list) element->accept(_visitor);
}
Location const& getLocation() const { return m_location; }
private:
Location m_location;
};
@ -65,7 +59,7 @@ class ContractDefinition : public ASTNode
{
public:
ContractDefinition(Location const& _location,
std::string const& _name,
ptr<ASTString> const& _name,
vecptr<StructDefinition> const& _definedStructs,
vecptr<VariableDeclaration> const& _stateVariables,
vecptr<FunctionDefinition> const& _definedFunctions)
@ -75,8 +69,11 @@ public:
m_definedFunctions(_definedFunctions)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getName() const { return *m_name; }
private:
std::string m_name;
ptr<ASTString> m_name;
vecptr<StructDefinition> m_definedStructs;
vecptr<VariableDeclaration> m_stateVariables;
vecptr<FunctionDefinition> m_definedFunctions;
@ -86,12 +83,15 @@ class StructDefinition : public ASTNode
{
public:
StructDefinition(Location const& _location,
std::string const& _name,
ptr<ASTString> const& _name,
vecptr<VariableDeclaration> const& _members)
: ASTNode(_location), m_name(_name), m_members(_members)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getName() const { return *m_name; }
private:
std::string m_name;
ptr<ASTString> m_name;
vecptr<VariableDeclaration> m_members;
};
@ -104,6 +104,7 @@ public:
ParameterList(Location const& _location, vecptr<VariableDeclaration> const& _parameters)
: ASTNode(_location), m_parameters(_parameters)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
vecptr<VariableDeclaration> m_parameters;
};
@ -111,7 +112,7 @@ private:
class FunctionDefinition : public ASTNode
{
public:
FunctionDefinition(Location const& _location, std::string const& _name, bool _isPublic,
FunctionDefinition(Location const& _location, ptr<ASTString> const& _name, bool _isPublic,
ptr<ParameterList> const& _parameters,
bool _isDeclaredConst,
ptr<ParameterList> const& _returnParameters,
@ -120,8 +121,13 @@ public:
m_isDeclaredConst(_isDeclaredConst), m_returnParameters(_returnParameters),
m_body(_body)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getName() const { return *m_name; }
bool isPublic() const { return m_isPublic; }
bool isDeclaredConst() const { return m_isDeclaredConst; }
private:
std::string m_name;
ptr<ASTString> m_name;
bool m_isPublic;
ptr<ParameterList> m_parameters;
bool m_isDeclaredConst;
@ -134,12 +140,15 @@ class VariableDeclaration : public ASTNode
public:
VariableDeclaration(Location const& _location,
ptr<TypeName> const& _type,
std::string const& _name)
ptr<ASTString> const& _name)
: ASTNode(_location), m_type(_type), m_name(_name)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getName() const { return *m_name; }
private:
ptr<TypeName> m_type; ///< can be empty ("var")
std::string m_name;
ptr<ASTString> m_name;
};
/// types
@ -149,6 +158,7 @@ class TypeName : public ASTNode
{
public:
explicit TypeName(Location const& _location) : ASTNode(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
/// any pre-defined type that is not a mapping
@ -158,6 +168,9 @@ public:
explicit ElementaryTypeName(Location const& _location, Token::Value _type)
: TypeName(_location), m_type(_type)
{}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getType() const { return m_type; }
private:
Token::Value m_type;
};
@ -165,11 +178,14 @@ private:
class UserDefinedTypeName : public TypeName
{
public:
UserDefinedTypeName(Location const& _location, std::string const& _name)
UserDefinedTypeName(Location const& _location, ptr<ASTString> const& _name)
: TypeName(_location), m_name(_name)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getName() const { return *m_name; }
private:
std::string m_name;
ptr<ASTString> m_name;
};
class Mapping : public TypeName
@ -179,6 +195,7 @@ public:
ptr<TypeName> const& _valueType)
: TypeName(_location), m_keyType(_keyType), m_valueType(_valueType)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<ElementaryTypeName> m_keyType;
ptr<TypeName> m_valueType;
@ -193,6 +210,7 @@ class Statement : public ASTNode
{
public:
explicit Statement(Location const& _location) : ASTNode(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
class Block : public Statement
@ -201,6 +219,7 @@ public:
Block(Location const& _location, vecptr<Statement> const& _statements)
: Statement(_location), m_statements(_statements)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
vecptr<Statement> m_statements;
};
@ -213,16 +232,18 @@ public:
: Statement(_location), m_condition(_condition),
m_trueBody(_trueBody), m_falseBody(_falseBody)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<Expression> m_condition;
ptr<Statement> m_trueBody;
ptr<Statement> m_falseBody;
ptr<Statement> m_falseBody; //< "else" part, optional
};
class BreakableStatement : public Statement
{
public:
BreakableStatement(Location const& _location) : Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
class WhileStatement : public BreakableStatement
@ -232,6 +253,7 @@ public:
ptr<Statement> const& _body)
: BreakableStatement(_location), m_condition(_condition), m_body(_body)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<Expression> m_condition;
ptr<Statement> m_body;
@ -241,12 +263,14 @@ class Continue : public Statement
{
public:
Continue(Location const& _location) : Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
class Break : public Statement
{
public:
Break(Location const& _location) : Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
class Return : public Statement
@ -255,8 +279,9 @@ public:
Return(Location const& _location, ptr<Expression> _expression)
: Statement(_location), m_expression(_expression)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<Expression> m_expression;
ptr<Expression> m_expression; //< value to return, optional
};
class VariableDefinition : public Statement
@ -266,6 +291,7 @@ public:
ptr<Expression> _value)
: Statement(_location), m_variable(_variable), m_value(_value)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<VariableDeclaration> m_variable;
ptr<Expression> m_value; ///< can be missing
@ -275,6 +301,7 @@ class Expression : public Statement
{
public:
Expression(Location const& _location) : Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
/// @}
@ -290,6 +317,9 @@ public:
: Expression(_location), m_leftHandSide(_leftHandSide),
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide)
{}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getAssignmentOperator() const { return m_assigmentOperator; }
private:
ptr<Expression> m_leftHandSide;
Token::Value m_assigmentOperator;
@ -304,7 +334,10 @@ public:
: Expression(_location), m_operator(_operator),
m_subExpression(_subExpression), m_isPrefix(_isPrefix)
{}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getOperator() const { return m_operator; }
bool isPrefixOperation() const { return m_isPrefix; }
private:
Token::Value m_operator;
ptr<Expression> m_subExpression;
@ -318,6 +351,9 @@ public:
Token::Value _operator, ptr<Expression> const& _right)
: Expression(_location), m_left(_left), m_operator(_operator), m_right(_right)
{}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getOperator() const { return m_operator; }
private:
ptr<Expression> m_left;
Token::Value m_operator;
@ -332,6 +368,7 @@ public:
vecptr<Expression> const& _arguments)
: Expression(_location), m_expression(_expression), m_arguments(_arguments)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<Expression> m_expression;
vecptr<Expression> m_arguments;
@ -341,12 +378,14 @@ class MemberAccess : public Expression
{
public:
MemberAccess(Location const& _location, ptr<Expression> _expression,
std::string const& _memberName)
ptr<ASTString> const& _memberName)
: Expression(_location), m_expression(_expression), m_memberName(_memberName)
{}
virtual void accept(ASTVisitor& _visitor) override;
const ASTString& getMemberName() const { return *m_memberName; }
private:
ptr<Expression> m_expression;
std::string m_memberName;
ptr<ASTString> m_memberName;
};
class IndexAccess : public Expression
@ -356,6 +395,7 @@ public:
ptr<Expression> const& _index)
: Expression(_location), m_base(_base), m_index(_index)
{}
virtual void accept(ASTVisitor& _visitor) override;
private:
ptr<Expression> m_base;
ptr<Expression> m_index;
@ -365,15 +405,19 @@ class PrimaryExpression : public Expression
{
public:
PrimaryExpression(Location const& _location) : Expression(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
};
class Identifier : public PrimaryExpression
{
public:
Identifier(Location const& _location, std::string const& _name)
Identifier(Location const& _location, ptr<ASTString> const& _name)
: PrimaryExpression(_location), m_name(_name) {}
virtual void accept(ASTVisitor& _visitor) override;
ASTString const& getName() const { return *m_name; }
private:
std::string m_name;
ptr<ASTString> m_name;
};
class ElementaryTypeNameExpression : public PrimaryExpression
@ -381,6 +425,9 @@ class ElementaryTypeNameExpression : public PrimaryExpression
public:
ElementaryTypeNameExpression(Location const& _location, Token::Value _type)
: PrimaryExpression(_location), m_type(_type) {}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getType() const { return m_type; }
private:
Token::Value m_type;
};
@ -388,15 +435,18 @@ private:
class Literal : public PrimaryExpression
{
public:
Literal(Location const& _location, Token::Value _token, std::string const& _value)
Literal(Location const& _location, Token::Value _token, ptr<ASTString> const& _value)
: PrimaryExpression(_location), m_token(_token), m_value(_value)
{}
virtual void accept(ASTVisitor& _visitor) override;
Token::Value getToken() const { return m_token; }
ASTString const& getValue() const { return *m_value; }
private:
Token::Value m_token;
std::string m_value;
ptr<ASTString> m_value;
};
/// @}
} }

53
ASTForward.h Normal file
View File

@ -0,0 +1,53 @@
#pragma once
#include <string>
#include <memory>
#include <vector>
// Forward-declare all AST node types
namespace dev {
namespace solidity {
class ASTNode;
class ContractDefinition;
class StructDefinition;
class ParameterList;
class FunctionDefinition;
class VariableDeclaration;
class TypeName;
class ElementaryTypeName;
class UserDefinedTypeName;
class Mapping;
class Statement;
class Block;
class IfStatement;
class BreakableStatement;
class WhileStatement;
class Continue;
class Break;
class Return;
class VariableDefinition;
class Expression;
class Assignment;
class UnaryOperation;
class BinaryOperation;
class FunctionCall;
class MemberAccess;
class IndexAccess;
class PrimaryExpression;
class ElementaryTypeNameExpression;
class Literal;
// Used as pointers to AST nodes, to be replaced by more clever pointers, e.g. pointers which do
// not do reference counting but point to a special memory area that is completely released
// explicitly.
template <class T>
using ptr = std::shared_ptr<T>;
template <class T>
using vecptr = std::vector<ptr<T>>;
using ASTString = std::string;
} }

388
ASTPrinter.cpp Normal file
View File

@ -0,0 +1,388 @@
#include <libsolidity/ASTPrinter.h>
#include <libsolidity/AST.h>
namespace dev {
namespace solidity {
ASTPrinter::ASTPrinter(ptr<ASTNode> _ast, const std::string& _source)
: m_indentation(0), m_source(_source), m_ast(_ast)
{
}
void ASTPrinter::print(std::ostream& _stream)
{
m_ostream = &_stream;
m_ast->accept(*this);
m_ostream = nullptr;
}
bool ASTPrinter::visit(ContractDefinition& _node)
{
writeLine("ContractDefinition \"" + _node.getName() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(StructDefinition& _node)
{
writeLine("StructDefinition \"" + _node.getName() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(ParameterList& _node)
{
writeLine("ParameterList");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(FunctionDefinition& _node)
{
writeLine("FunctionDefinition \"" + _node.getName() + "\"" +
(_node.isPublic() ? " - public" : "") +
(_node.isDeclaredConst() ? " - const" : ""));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(VariableDeclaration& _node)
{
writeLine("VariableDeclaration \"" + _node.getName() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(TypeName& _node)
{
writeLine("TypeName");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(ElementaryTypeName& _node)
{
writeLine(std::string("ElementaryTypeName ") + Token::String(_node.getType()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(UserDefinedTypeName& _node)
{
writeLine("UserDefinedTypeName \"" + _node.getName() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Mapping& _node)
{
writeLine("Mapping");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Statement& _node)
{
writeLine("Statement");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Block& _node)
{
writeLine("Block");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(IfStatement& _node)
{
writeLine("IfStatement");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(BreakableStatement& _node)
{
writeLine("BreakableStatement");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(WhileStatement& _node)
{
writeLine("WhileStatement");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Continue& _node)
{
writeLine("Continue");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Break& _node)
{
writeLine("Break");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Return& _node)
{
writeLine("Return");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(VariableDefinition& _node)
{
writeLine("VariableDefinition");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Expression& _node)
{
writeLine("Expression");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Assignment& _node)
{
writeLine(std::string("Assignment using operator ") + Token::String(_node.getAssignmentOperator()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(UnaryOperation& _node)
{
writeLine(std::string("UnaryOperation (") + (_node.isPrefixOperation() ? "prefix" : "postfix") +
") " + Token::String(_node.getOperator()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(BinaryOperation& _node)
{
writeLine(std::string("BinaryOperation using operator ") + Token::String(_node.getOperator()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(FunctionCall& _node)
{
writeLine("FunctionCall");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(MemberAccess& _node)
{
writeLine("MemberAccess to member " + _node.getMemberName());
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(IndexAccess& _node)
{
writeLine("IndexAccess");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(PrimaryExpression& _node)
{
writeLine("PrimaryExpression");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(ElementaryTypeNameExpression& _node)
{
writeLine(std::string("ElementaryTypeNameExpression ") + Token::String(_node.getType()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Literal& _node)
{
const char* tokenString = Token::String(_node.getToken());
if (tokenString == nullptr)
tokenString = "----";
writeLine(std::string("Literal, token: ") + tokenString + " value: " + _node.getValue());
printSourcePart(_node);
return goDeeper();
}
void ASTPrinter::endVisit(ASTNode&)
{
m_indentation--;
}
// @todo instead of this, we could make the default implementation of endVisit call the
// superclass' endVisit
void ASTPrinter::endVisit(ContractDefinition&)
{
m_indentation--;
}
void ASTPrinter::endVisit(StructDefinition&)
{
m_indentation--;
}
void ASTPrinter::endVisit(ParameterList&)
{
m_indentation--;
}
void ASTPrinter::endVisit(FunctionDefinition&)
{
m_indentation--;
}
void ASTPrinter::endVisit(VariableDeclaration&)
{
m_indentation--;
}
void ASTPrinter::endVisit(TypeName&)
{
m_indentation--;
}
void ASTPrinter::endVisit(ElementaryTypeName&)
{
m_indentation--;
}
void ASTPrinter::endVisit(UserDefinedTypeName&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Mapping&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Statement&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Block&)
{
m_indentation--;
}
void ASTPrinter::endVisit(IfStatement&)
{
m_indentation--;
}
void ASTPrinter::endVisit(BreakableStatement&)
{
m_indentation--;
}
void ASTPrinter::endVisit(WhileStatement&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Continue&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Break&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Return&)
{
m_indentation--;
}
void ASTPrinter::endVisit(VariableDefinition&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Expression&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Assignment&)
{
m_indentation--;
}
void ASTPrinter::endVisit(UnaryOperation&)
{
m_indentation--;
}
void ASTPrinter::endVisit(BinaryOperation&)
{
m_indentation--;
}
void ASTPrinter::endVisit(FunctionCall&)
{
m_indentation--;
}
void ASTPrinter::endVisit(MemberAccess&)
{
m_indentation--;
}
void ASTPrinter::endVisit(IndexAccess&)
{
m_indentation--;
}
void ASTPrinter::endVisit(PrimaryExpression&)
{
m_indentation--;
}
void ASTPrinter::endVisit(ElementaryTypeNameExpression&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Literal&)
{
m_indentation--;
}
void ASTPrinter::printSourcePart(ASTNode const& _node)
{
if (!m_source.empty()) {
Location const& location(_node.getLocation());
*m_ostream << getIndentation() << " Source: |"
<< m_source.substr(location.start, location.end - location.start) << "|\n";
}
}
std::string ASTPrinter::getIndentation() const
{
return std::string(m_indentation * 2, ' ');
}
void ASTPrinter::writeLine(const std::string& _line)
{
*m_ostream << getIndentation() << _line << '\n';
}
} }

88
ASTPrinter.h Normal file
View File

@ -0,0 +1,88 @@
#pragma once
#include <ostream>
#include <libsolidity/ASTVisitor.h>
namespace dev {
namespace solidity {
class ASTPrinter : public ASTVisitor
{
public:
/// Create a printer for the given abstract syntax tree. If the source is specified,
/// the corresponding parts of the source are printed with each node.
ASTPrinter(ptr<ASTNode> _ast, const std::string& _source = std::string());
/// Output the string representation of the AST to _stream.
void print(std::ostream& _stream);
bool visit(ContractDefinition& _node);
bool visit(StructDefinition& _node);
bool visit(ParameterList& _node);
bool visit(FunctionDefinition& _node);
bool visit(VariableDeclaration& _node);
bool visit(TypeName& _node);
bool visit(ElementaryTypeName& _node);
bool visit(UserDefinedTypeName& _node);
bool visit(Mapping& _node);
bool visit(Statement& _node);
bool visit(Block& _node);
bool visit(IfStatement& _node);
bool visit(BreakableStatement& _node);
bool visit(WhileStatement& _node);
bool visit(Continue& _node);
bool visit(Break& _node);
bool visit(Return& _node);
bool visit(VariableDefinition& _node);
bool visit(Expression& _node);
bool visit(Assignment& _node);
bool visit(UnaryOperation& _node);
bool visit(BinaryOperation& _node);
bool visit(FunctionCall& _node);
bool visit(MemberAccess& _node);
bool visit(IndexAccess& _node);
bool visit(PrimaryExpression& _node);
bool visit(ElementaryTypeNameExpression& _node);
bool visit(Literal& _node);
void endVisit(ASTNode & _node);
void endVisit(ContractDefinition&);
void endVisit(StructDefinition&);
void endVisit(ParameterList&);
void endVisit(FunctionDefinition&);
void endVisit(VariableDeclaration&);
void endVisit(TypeName&);
void endVisit(ElementaryTypeName&);
void endVisit(UserDefinedTypeName&);
void endVisit(Mapping&);
void endVisit(Statement&);
void endVisit(Block&);
void endVisit(IfStatement&);
void endVisit(BreakableStatement&);
void endVisit(WhileStatement&);
void endVisit(Continue&);
void endVisit(Break&);
void endVisit(Return&);
void endVisit(VariableDefinition&);
void endVisit(Expression&);
void endVisit(Assignment&);
void endVisit(UnaryOperation&);
void endVisit(BinaryOperation&);
void endVisit(FunctionCall&);
void endVisit(MemberAccess&);
void endVisit(IndexAccess&);
void endVisit(PrimaryExpression&);
void endVisit(ElementaryTypeNameExpression&);
void endVisit(Literal&);
private:
void printSourcePart(ASTNode const& _node);
std::string getIndentation() const;
void writeLine(std::string const& _line);
bool goDeeper() { m_indentation++; return true; }
int m_indentation;
std::string m_source;
ptr<ASTNode> m_ast;
std::ostream* m_ostream;
};
} }

76
ASTVisitor.h Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include <libsolidity/ASTForward.h>
#include <string>
namespace dev {
namespace solidity {
class ASTVisitor {
public:
/// These functions are called after a call to ASTNode::accept,
/// first visit, then (if visit returns true) recursively for all
/// child nodes in document order (exception for contracts) and then
/// endVisit.
virtual bool visit(ASTNode&) { return true; }
virtual bool visit(ContractDefinition&) { return true; }
virtual bool visit(StructDefinition&) { return true; }
virtual bool visit(ParameterList&) { return true; }
virtual bool visit(FunctionDefinition&) { return true; }
virtual bool visit(VariableDeclaration&) { 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(IfStatement&) { return true; }
virtual bool visit(BreakableStatement&) { return true; }
virtual bool visit(WhileStatement&) { return true; }
virtual bool visit(Continue&) { return true; }
virtual bool visit(Break&) { return true; }
virtual bool visit(Return&) { return true; }
virtual bool visit(VariableDefinition&) { return true; }
virtual bool visit(Expression&) { return true; }
virtual bool visit(Assignment&) { return true; }
virtual bool visit(UnaryOperation&) { return true; }
virtual bool visit(BinaryOperation&) { return true; }
virtual bool visit(FunctionCall&) { return true; }
virtual bool visit(MemberAccess&) { return true; }
virtual bool visit(IndexAccess&) { return true; }
virtual bool visit(PrimaryExpression&) { return true; }
virtual bool visit(ElementaryTypeNameExpression&) { return true; }
virtual bool visit(Literal&) { return true; }
virtual void endVisit(ASTNode&) { }
virtual void endVisit(ContractDefinition&) { }
virtual void endVisit(StructDefinition&) { }
virtual void endVisit(ParameterList&) { }
virtual void endVisit(FunctionDefinition&) { }
virtual void endVisit(VariableDeclaration&) { }
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(IfStatement&) { }
virtual void endVisit(BreakableStatement&) { }
virtual void endVisit(WhileStatement&) { }
virtual void endVisit(Continue&) { }
virtual void endVisit(Break&) { }
virtual void endVisit(Return&) { }
virtual void endVisit(VariableDefinition&) { }
virtual void endVisit(Expression&) { }
virtual void endVisit(Assignment&) { }
virtual void endVisit(UnaryOperation&) { }
virtual void endVisit(BinaryOperation&) { }
virtual void endVisit(FunctionCall&) { }
virtual void endVisit(MemberAccess&) { }
virtual void endVisit(IndexAccess&) { }
virtual void endVisit(PrimaryExpression&) { }
virtual void endVisit(ElementaryTypeNameExpression&) { }
virtual void endVisit(Literal&) { }
};
} }

View File

@ -57,7 +57,8 @@ public:
template <class NodeType, typename... Args>
ptr<NodeType> createNode(Args&&... _args)
{
if (m_location.end < 0) markEndPosition();
if (m_location.end < 0)
markEndPosition();
return std::make_shared<NodeType>(m_location, std::forward<Args>(_args)...);
}
@ -82,7 +83,7 @@ ptr<ContractDefinition> Parser::parseContractDefinition()
ASTNodeFactory nodeFactory(*this);
expectToken(Token::CONTRACT);
std::string name = expectIdentifier();
ptr<ASTString> name = expectIdentifierToken();
expectToken(Token::LBRACE);
vecptr<StructDefinition> structs;
@ -111,7 +112,7 @@ ptr<ContractDefinition> Parser::parseContractDefinition()
}
nodeFactory.markEndPosition();
m_scanner->next();
expectToken(Token::RBRACE);
expectToken(Token::EOS);
return nodeFactory.createNode<ContractDefinition>(name, structs, stateVariables, functions);
@ -122,7 +123,7 @@ ptr<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic)
ASTNodeFactory nodeFactory(*this);
expectToken(Token::FUNCTION);
std::string name(expectIdentifier());
ptr<ASTString> name(expectIdentifierToken());
ptr<ParameterList> parameters(parseParameterList());
bool isDeclaredConst = false;
if (m_scanner->getCurrentToken() == Token::CONST) {
@ -145,7 +146,7 @@ ptr<StructDefinition> Parser::parseStructDefinition()
ASTNodeFactory nodeFactory(*this);
expectToken(Token::STRUCT);
std::string name = expectIdentifier();
ptr<ASTString> name = expectIdentifierToken();
vecptr<VariableDeclaration> members;
expectToken(Token::LBRACE);
while (m_scanner->getCurrentToken() != Token::RBRACE) {
@ -164,8 +165,7 @@ ptr<VariableDeclaration> Parser::parseVariableDeclaration()
ptr<TypeName> type = parseTypeName();
nodeFactory.markEndPosition();
std::string name = expectIdentifier();
return nodeFactory.createNode<VariableDeclaration>(type, name);
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken());
}
ptr<TypeName> Parser::parseTypeName()
@ -181,8 +181,9 @@ ptr<TypeName> Parser::parseTypeName()
} else if (token == Token::MAPPING) {
type = parseMapping();
} else if (token == Token::IDENTIFIER) {
type = ASTNodeFactory(*this).createNode<UserDefinedTypeName>(m_scanner->getCurrentLiteral());
m_scanner->next();
ASTNodeFactory nodeFactory(*this);
nodeFactory.markEndPosition();
type = nodeFactory.createNode<UserDefinedTypeName>(expectIdentifierToken());
} else {
throwExpectationError("Expected type name");
}
@ -410,8 +411,7 @@ ptr<Expression> Parser::parseLeftHandSideExpression()
{
m_scanner->next();
nodeFactory.markEndPosition();
std::string memberName = expectIdentifier();
expression = nodeFactory.createNode<MemberAccess>(expression, memberName);
expression = nodeFactory.createNode<MemberAccess>(expression, expectIdentifierToken());
}
break;
case Token::LPAREN:
@ -431,19 +431,25 @@ ptr<Expression> Parser::parseLeftHandSideExpression()
ptr<Expression> Parser::parsePrimaryExpression()
{
ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken();
ptr<Expression> expression;
switch (token) {
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
expression = nodeFactory.createNode<Literal>(token, ptr<ASTString>());
m_scanner->next();
return ASTNodeFactory(*this).createNode<Literal>(token, std::string());
break;
case Token::NUMBER:
case Token::STRING_LITERAL:
m_scanner->next();
return ASTNodeFactory(*this).createNode<Literal>(token, m_scanner->getCurrentLiteral());
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break;
case Token::IDENTIFIER:
m_scanner->next();
return ASTNodeFactory(*this).createNode<Identifier>(m_scanner->getCurrentLiteral());
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Identifier>(getLiteralAndAdvance());
break;
case Token::LPAREN:
{
m_scanner->next();
@ -454,13 +460,14 @@ ptr<Expression> Parser::parsePrimaryExpression()
default:
if (Token::IsElementaryTypeName(token)) {
// used for casts
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(token);
m_scanner->next();
return ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(token);
} else {
throwExpectationError("Expected primary expression.");
return ptr<Expression>(); // this is not reached
}
}
return expression;
}
vecptr<Expression> Parser::parseFunctionCallArguments()
@ -492,14 +499,19 @@ Token::Value Parser::expectAssignmentOperator()
return op;
}
std::string Parser::expectIdentifier()
ptr<ASTString> Parser::expectIdentifierToken()
{
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
throwExpectationError("Expected identifier");
std::string literal = m_scanner->getCurrentLiteral();
return getLiteralAndAdvance();
}
ptr<ASTString> Parser::getLiteralAndAdvance()
{
ptr<ASTString> identifier = std::make_shared<ASTString>(m_scanner->getCurrentLiteral());
m_scanner->next();
return literal;
return identifier;
}
void Parser::throwExpectationError(const std::string& _description)

View File

@ -69,7 +69,8 @@ private:
/// If current token value is not _value, throw exception otherwise advance token.
void expectToken(Token::Value _value);
Token::Value expectAssignmentOperator();
std::string expectIdentifier();
ptr<ASTString> expectIdentifierToken();
ptr<ASTString> getLiteralAndAdvance();
void throwExpectationError(const std::string& _description);
/// @}