エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

パーサ、なんどでも、なんどでも

昨日のエントリの続き。

サブクラスを定義する。


calc.tt

grammar Arithmetic
  rule additive
    multitive r:( op:[+-] multitive )* <Additive>
  end

  rule multitive
    primary r:( op:[*/%] primary )* <Multitive>
  end

  rule primary
    '(' additive ')' <Parenthesized> / number
  end

  rule number
    '-'? [1-9] [0-9]* <Number>
  end
end

calc.rb

require 'treetop'

module Arithmetic
  class Additive < Treetop::Runtime::SyntaxNode
    def to_i
      r.elements.reduce(multitive.to_i) do |s, e|
        s.send(e.op.text_value, e.multitive.to_i)
      end
    end
  end

  class Multitive < Treetop::Runtime::SyntaxNode
    def to_i
      r.elements.reduce(primary.to_i) do |s, e|
        s.send(e.op.text_value, e.primary.to_i)
      end
    end
  end

  class  Parenthesized < Treetop::Runtime::SyntaxNode
    def to_i
      additive.to_i
    end
  end

  class Number < Treetop::Runtime::SyntaxNode
    def to_i
      text_value.to_i
    end
  end
end

Treetop.load 'calc.tt'

parser = ArithmeticParser.new

puts parser.parse(ARGV.shift).to_i


実行。

$ ruby calc.rb "2*(3+4)"
14


つづく。