第36回 Ruby/Rails勉強会@関西に参加したので Racc を使ってみる
第36回 Ruby/Rails勉強会@関西に参加した。その中で「Racc でおてがる構文解析」というのがあったのでさっそく試してみた。
Racc とは
Racc とはパーサージェネレータの一種で、yacc の Ruby 版。僕もあんまりよく分かってないけど、とりあえず使ってみることにする。詳しくは Racc ユーザマニュアル参照。
Racc のインストール
gem で Racc をインストールする。
gem install racc
ここで gem install rack
と間違えててだいぶはまった。
あと、 僕は Ubuntu を使ってて mkmf
がないよ、とかそんなエラーが出てきたので、 apt-get install ruby1.8-dev
してからもう一度 gem コマンドでインストールした。
拡張子 y のファイルを書く
Rubyist Magazine - Ruby Library Report 【第 6 回】 正規表現と構文解析 の 「試用レポート -- racc」 というところを参考にして書いてみた。
四則演算をする文法ファイル。calc.y という名前でファイルを作った。
class Calc token NUM prechigh left '*' '/' left '+' '-' preclow rule expr : expr '+' expr { result = val[0] + val[2] } | expr '-' expr { result = val[0] - val[2] } | expr '*' expr { result = val[0] * val[2] } | expr '/' expr { result = val[0] / val[2] } | prim { result = val[0] } prim : NUM { result = val[0] } | '(' expr ')' { result = val[1] } end ---- inner def parse(str) @tokens = str.split(/([\(\)\+\-\*\/])/).select{|c| !c.nil? && c != ""} do_parse() end def next_token() token = @tokens.shift() case token when /^\d+\z/ return [:NUM, token.to_i] when nil return nil else return [token, nil] end end
写経した。
パーサークラスを作る
以下のコマンドで y ファイルからパーサークラスを作る。これで新しく calc.rb ファイルが作成される。
racc -o calc.rb calc.y
ちらっとパーサークラスの中身を開いてみた。何か黒いものを見てしまったような気がした。
実際に使ってみる
ここまできたら、あとは使うだけ。
require 'calc' calc = Calc.new() puts calc.parse("1+2*3") # かけ算が優先されるはず puts calc.parse("3*(8+5*(6-2))/2") # かっこの中が先に計算されるはず # 3 * (8 + 5 * 4) / 2 = 3 * 28 / 2 = 42
実行してみる。
% ruby do_calc.rb 7 42
うん、ちゃんと計算できてる。
まとめ
なんか結構難しいと思う。でも雰囲気はつかめた。とりあえずこういうものもあることを覚えておこう。
あと、スーパープレ記法で Racc ファイルがちゃんとハイライトされた。うれしい。