続き
昨日のは「まだマッチしていない」時と「マッチしなかった」時を区別できていなかった。
修正。
ParseResult = Struct.new(:value,:deriv) class Deriv def Deriv.eval(str) d = Deriv.new(str) if pr = d.parse_add then pr.value else nil end end def initialize(rest_str) @add_value = nil @mult_value = nil @prim_value = nil @dec_value = nil if rest_str.empty? then @char_value = nil else @char_value = ParseResult.new(rest_str[0],Deriv.new(rest_str[1..-1])) end end def match_sequence(*items) if items.empty? then res = nil if block_given? then res = yield end return ParseResult.new(res,deriv) end results = [] cur_deriv = self items.each{| item | pr = nil if item.kind_of?(Symbol) then pr = cur_deriv.send("parse_#{item}") return false unless pr else pr = cur_deriv.parse_char return false unless pr and item === pr.value end results.push(pr.value) cur_deriv = pr.deriv } res = nil if block_given? then res = yield(*results) else res = results.first end ParseResult.new(res, cur_deriv) end private :match_sequence def parse_add return @add_value unless @add_value.nil? @add_value = match_sequence(:mult,?+,:add){|x,_,y| x + y } || match_sequence(:mult) end def parse_mult return @mult_value unless @mult_value.nil? @mult_value = match_sequence(:prim,?*,:mult){|x,_,y| x * y} || match_sequence(:prim) end def parse_prim return @prim_value unless @prim_value.nil? @prim_value = match_sequence(?(,:add,?)){|_,x,_| x } || match_sequence(:dec) end def parse_dec return @dec_value unless @dec_value.nil? @dec_value = match_sequence(?0..?9){|x| x - ?0 } end def parse_char @char_value end end def test_expr(expr) if Deriv.eval(expr) == eval(expr) then puts "ok" else puts "failed : #{expr}" end end test_expr('2*3+(4+5)*2') test_expr('2+3+4*5') test_expr('3*7+5+3')