
# simple calc parser

class Calcp

  prechigh
    nonassoc UMINUS
    left '*' '/'
    left '+' '-'
  preclow

rule

  target: exp
        | /* none */ { result = 0 }
        ;

  exp: exp '+' exp { result += val[2] }
     | exp '-' exp { result -= val[2] }
     | exp '*' exp { result *= val[2] }
     | exp '/' exp { result /= val[2] }
     | '(' exp ')' { result = val[1] }
     | '-' NUMBER  = UMINUS { result = -val[1] }
     | NUMBER
     ;

end


---- header ----

# calc.rb : generated by racc

---- inner ----
  
  def parse( str )
    @q = []

    while str.size > 0 do
      case str
      when /\A\s+/o
      when /\A\d+/o
        @q.push [:NUMBER, $&.to_i]
      when /\A.|\n/o
        s = $&
        @q.push [s, s]
      end
      str = $'
    end
    @q.push [false, '$end']

    do_parse
  end

  def next_token
    @q.shift
  end


---- footer ----

parser = Calcp.new
count = 0
scnt  = 0

puts
puts 'type "Q" to quit.'
puts

while true do
  puts
  print '? '
  str = gets.chop!
  break if /q/i === str

  begin
    val = parser.parse( str )
    print '= ', val, "\n"
  rescue ParseError
    puts $!
  rescue
    puts 'unexpected error ?!'
    raise
  end

end
