Ruby によるパーサ・コンビネータ rparsec
Java による parsec の実装 JParsec を Ruby に移植した rparsec を勉強中。
パーサ・コンビネータ
Parsec、パーサ・コンビネータについては「最強のパーザー、Parser Combinator - 純粋関数型雑記帳」が参考になる。
Yacc や Bison などのコンパイラ・コンパイラと比較したときのパーサ・コンビネータの強味としては、
- パーサを実装言語と同じ言語で書ける
- プログラムがそのまま文法定義のように読める
- パーサは普通の関数やオブジェクトなので、パーサをラップした別のパーサを生成する関数を定義したりするのも簡単にできる
などがあるようだ。
rparsec のインストール
普通に RubyForge で gem がホスティングされているので、gem
コマンド一発でインストールできる。
% sudo gem install rparsec
四則演算デモ
まずは公式ページにもデモとして紹介されている四則演算から。
#!/usr/local/bin/ruby
require 'rubygems'
require 'rparsec'
class Calculator
include Parsers
include Functors
def parser
ops = OperatorTable.new.
infixl(char(?+) >> Plus, 20).
infixl(char(?-) >> Minus, 20).
infixl(char(?*) >> Mul, 40).
infixl(char(?/) >> Div, 40).
prefix(char(?-) >> Neg, 60)
expr = nil
term = integer.map(&To_i) | char('(') >> lazy{expr} << char (')')
delim = whitespace.many_
expr = delim >> Expressions.build(term, ops, delim)
end
end
これを calc.rb として保存し、irb から簡単な数式を処理させてみる。
% irb
irb(main):001:0> require 'calc'
=> true
irb(main):002:0> Calculator.new.parser.parse '1+2*(3-1)'
=> 5
# => 5