我想使用访问者模式来执行我的编译器的AST的操作,但我似乎无法弄清楚将正常工作的实现。访问者模式为AST
AST类摘录:
class AstNode
{
public:
AstNode() {}
};
class Program : public AstNode
{
public:
std::vector<std::shared_ptr<Class>> classes;
Program(const std::vector<std::shared_ptr<Class>>&);
void accept(AstNodeVisitor& visitor) const { visitor.visit(*this); }
};
class Expression : public AstNode
{
public:
Expression() {}
};
class Method : public Feature
{
public:
Symbol name;
Symbol return_type;
std::vector<std::shared_ptr<Formal>> params;
std::shared_ptr<Expression> body;
Method(const Symbol&, const Symbol&, const std::vector<std::shared_ptr<Formal>>&,
const std::shared_ptr<Expression>&);
feature_type get_type() const;
};
class Class : public AstNode
{
public:
Symbol name;
Symbol parent;
Symbol filename;
std::vector<std::shared_ptr<Feature>> features;
Class(const Symbol&, const Symbol&, const Symbol&,
const std::vector<std::shared_ptr<Feature>>&);
};
class Assign : public Expression
{
public:
Symbol name;
std::shared_ptr<Expression> rhs;
Assign(const Symbol&, const std::shared_ptr<Expression>&);
};
游客(部分实现):
class AstNodeVisitor
{
public:
virtual void visit(const Program&) = 0;
virtual void visit(const Class&) = 0;
virtual void visit(const Attribute&) = 0;
virtual void visit(const Formal&) = 0;
virtual void visit(const Method&) = 0;
};
class AstNodePrintVisitor : public AstNodeVisitor
{
private:
size_t depth;
public:
void visit(const Program& node) {
for (auto cs : node.classes)
visit(*cs);
}
void visit(const Class&);
void visit(const Attribute&);
void visit(const Formal&);
void visit(const Method&);
};
我如何使用它:
AstNodePrintVisitor print;
ast_root->accept(print); // ast_root is a shared_ptr<Program>
问题:
的方法节点包含一个bo类型Expression的dy成员 - 这是一个基类。我将如何访问它?
我想也许我可以简单地为每个AST节点编写一个接受方法,然后进行遍历。 (即,不是在访问者中调用visit(),而是在可访问的调用访问(* this)中调用accept(),以便调用将是多态的,访问者的正确访问方法将被调用。但是,如果我这样做,我将无法选择自顶向下(操作然后递归)或自下而上(递归操作),因为我必须仅选择一个。因此,我的意思是一个PrintVisitor例如需要一个AST自顶向下遍历,但TypeCheck需要自下而上的方法。
有没有办法解决这个问题?或者我过度设计了一些东西?现在我认为最快的方法就是实现方法在节点本身。
或者只是使用野牛。 – 2012-07-13 05:55:21
@ H2CO3是的,我使用Bison进行解析,这就是AST的创建过程。我目前正在执行语义分析(类型检查,范围,..),并且需要考虑代码gen。 – 2012-07-13 06:02:58
哦OK :)顺便说一句,你不能使用自顶向下的方法进行类型检查吗? – 2012-07-13 06:08:30