Skip to content

Instantly share code, notes, and snippets.

@komamitsu
Created February 11, 2012 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komamitsu/1799588 to your computer and use it in GitHub Desktop.
Save komamitsu/1799588 to your computer and use it in GitHub Desktop.
simple calc (LL parser)
require 'strscan'
require 'test/unit'
class Calc
def run(str)
@scanner = StringScanner.new(str)
expr
end
def scan(re)
@scanner.skip /\s+/
result = @scanner.scan re
result.nil? ? false : result
end
private
def fact
if scan /\(/
x = expr
raise unless (scan /\)/)
x
else
(scan /\d+/).to_i
end
end
def expr
x = term
while (op = scan /[+-]/)
m = x.method(op)
x = m.call(term)
end
x
end
def term
x = fact
while (op = scan /[*\/]/)
m = x.method(op)
x = m.call(fact)
end
x
end
end
include Test::Unit::Assertions
calc = Calc.new
assert_equal(5, calc.run('2 + 3'))
assert_equal(7, calc.run('1 + 2 * 3'))
assert_equal(10, calc.run('5*(3-1)'))
expr = '10/ 2 + (2 - 3)*(4 +5- 6) * ( 101 -1 )'
assert_equal((eval expr), calc.run(expr))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment