预订和下订单访客

时间:2013-03-23 15:07:40

标签: ruby compiler-construction abstract-syntax-tree visitor-pattern

我正在研究用Ruby编写的编译器,目前我处于语义分析阶段(类型检查)。我有一个AST需要以两种方式访问​​:预订和后期订单,我想知道在Ruby中最好的方法是什么。我知道将块传递给each本质上就是访问者模式,但由于我需要以两种方式访问​​(pre,post)并且Ruby不支持方法重载,所以我不确定如何处理它。

(注意:我正在尝试让Node对象控制它们的访问方式,因此我的访问者不会膨胀)

以下是我正在考虑的尝试:

为调用其他节点的相应accept_preaccept_post方法的每个Node类accept_preaccept_post提供两种接受方法

class Node
  def initialize(a, b, c)
    @a, @b, @c = a, b, c
  end

  def accept_pre(visitor)
    @a.accept_pre visitor
    @b.accept_pre visitor
    @c.accept_pre visitor
    vistor.visit_node(self)
  end

  def accept_post(visitor)
    visitor.visit_node(self)
    @c.accept_post visitor
    @b.accept_post visitor
    @a.accept_post visitor
  end
end

有更好的方法吗?可以用.each来完成,即使我需要两个订单吗?

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

您可以使用遍历选项arg将两个排序折叠成一个接受。您当然可以通过节点成员使用每个成员来分派孩子的接受。

class Node
  def initialize(a, b, c)
    @a, @b, @c = a, b, c
  end

  def accept(visitor, traversal=:pre)
    visitor.visit(self) if traversal == :pre

    order = traversal == :pre ? :each : :reverse_each
    [@a,@b,@c].send(order) { |e| e.accept(visitor, traversal) }

    visitor.visit(self) if traversal == :post
  end
end