トップ «前の日記(2011-03-17) 最新 次の日記(2011-03-30)» 編集

Route 477



2011-03-29

[ruby] Ruby用のPEGパーサParslet

via @frsyuki

Ruby用のPEGパーサには既にTreetopがあるけど、エラー表示が改善されてたりするようだ。

Treetopは独自の文法だったけど、ParsletはRubyの内部DSLになっている。 また、Treetopは文法と同じところにアクションも書くけれど、Parsletは「Parser」と「Transformer」を別々に定義して組み合わせるというAPIになっている。

チュートリアルを見れば雰囲気はだいたい分かると思う。

とりあえず電卓(足し算だけだけど)。

Parserは構文木をHashとして返す。"1"@0みたいなのはParslet::Sliceのインスタンスで、0行目にある"1"という文字列を表している。.as(:foo)みたいに名前を付けたノードだけが構文木に含まれるようだ。

TransformerはHashに対しパターンマッチを行う。「simple」というのはHashでもArrayでもないもののことらしい。公式のチュートリアルでは各ノードごとにStructを定義していたけど、 簡単なものならTransformerに直接アクションを書けばいいと思う。

ところで、Struct.newの返り値を親クラスにするという発想はなかった。

 class IntLit < Struct.new(:int)
    def eval; int.to_i; end
  end

これよりはまだ気持ち悪くないと思う。

 IntLit = Struct.new(:int) do
   def eval; int.to_i; end
 end