ここ三日くらいの寝不足により、こんなのが動くようになった。
require 'racc'
grammar = Racc::Grammar.define {
g = self
g.precedence_table {
prechigh
left '*', '/'
left '+', '-'
preclow
}
g.target = rule(:exp) | rule() { 0 }
g.exp = rule(:exp, '+', :exp) {|x,_,y| x + y }\
| rule(:exp, '-', :exp) {|x,_,y| x - y }\
| rule(:exp, '*', :exp) {|x,_,y| x * y }\
| rule(:exp, '/', :exp) {|x,_,y| x / y }\
| rule('(', :exp, ')') {|_,n,_| n }\
| rule('-', :NUMBER) {|_,n| -n }\
| rule(:NUMBER)
}
Calculator = grammar.parser_class
この仕組み自体より、腐ったコードを書き直すほうに時間を取られてしまった。
(01:21)
どうせなら「n 回以上の繰り返し」とか「省略可能」とかも実装したいところだが、 インターフェイスをどーしたもんかなー。 現状の rule(:exp, '+', :exp) {....} てのもベストとは言い難いし。
(01:27)