grammar Arithmetic rule assign s variable s '=' expr { def value variable.value = expr.value end } / expr end rule expr s term seq:( s add_op s term )* s { def value seq.elements.inject(term.value) { |sum, el| el.add_op.operate(sum, el.term.value) } end } end rule term factor s mul_op s term { # Right-associative! def value mul_op.operate(factor.value, term.value) end } / factor end rule factor variable / number / '(' expr ')' { def value expr.value end } end rule variable [a-zA-Z_] [a-zA-Z0-9]* { def value @@variables[text_value] end def value=(v) (@@variables ||= {})[text_value] = v end def variables @@variables end } end rule number ([1-9] [0-9]* / '0') { def value; text_value.to_i; end } end rule add_op '+' { def operate(a, b); a+b; end } / '-' { def operate(a, b); a-b; end } end rule mul_op '*' { def operate(a, b); a*b; end } / '/' { def operate(a, b); a/b; end } / '%' { def operate(a, b); a%b; end } end rule s [ \t\n\r]* end end