2

我正在开发一个用 Ruby 编写的编译器,目前正处于语义分析阶段(类型检查)。我有一个 AST,我需要通过两种方式访问​​:预购和后购,我想知道在 Ruby 中最好的方法是什么。我知道将块传递给each本质上是访问者模式,但由于我需要以两种方式(前、后)访问,而 Ruby 不支持方法重载,我不知道如何处理这个问题。

(注意:我试图让 Node 对象控制它们的访问方式,所以我的访问者不会臃肿)

这是我正在考虑的尝试:

每个 Node 类有两个 accept 方法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即使我需要两个订单,它也可以完成吗?

任何帮助,将不胜感激。

4

1 回答 1

4

您可以使用遍历选项 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
于 2013-03-23T17:01:18.687 回答