2

私はRubyで書かれたコンパイラーに取り組んでおり、現在セマンティック分析段階(タイプチェック)にいます。事前注文と事後注文の2つの方法で訪問する必要のあるASTがあります。これを行うための最良の方法は、Rubyで何であるか疑問に思いました。ブロックを渡すのは基本的にVisitorPatternであることは知っていeachますが、2つの方法(pre、post)で訪問する必要があり、Rubyはメソッドのオーバーロードをサポートしていないため、これにアプローチする方法がわかりません。

(注:Nodeオブジェクトに訪問方法を制御させようとしているので、訪問者が肥大化することはありません)

これが私が試みることについて考えていることです:

ノードクラスごとに2つの受け入れメソッドがあり、他のノードの対応するメソッドとメソッドaccept_preaccept_post呼び出します。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

これを行うためのより良い方法はありますか?.each2つの注文が必要なのに、で行うことはできますか?

どんな助けでもいただければ幸いです。

4

1 に答える 1

4

トラバーサル オプション arg を使用して、2 つの順序付けを 1 つの受け入れに折りたたむことができます。ノードのメンバーに対して each を使用して、子の受け入れをディスパッチできます。

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 に答える