Created
June 9, 2012 03:14
-
-
Save mono0x/2899223 to your computer and use it in GitHub Desktop.
Calc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| class Expression | |
| attr_reader :value | |
| def initialize(tokens) | |
| left = Term.new(tokens) | |
| @value = left.value | |
| until tokens.empty? | |
| op = tokens.first | |
| break unless op == '+' || op == '-' | |
| tokens.shift | |
| right = Term.new(tokens) | |
| case op | |
| when '+' | |
| @value += right.value | |
| when '-' | |
| @value -= right.value | |
| end | |
| end | |
| end | |
| end | |
| class Term | |
| attr_reader :value | |
| def initialize(tokens) | |
| left = Factor.new(tokens) | |
| @value = left.value | |
| until tokens.empty? | |
| op = tokens.first | |
| break unless op == '*' || op == '/' | |
| tokens.shift | |
| right = Factor.new(tokens) | |
| case op | |
| when '*' | |
| @value *= right.value | |
| when '/' | |
| @value /= right.value | |
| end | |
| end | |
| end | |
| end | |
| class Factor | |
| attr_reader :value | |
| def initialize(tokens) | |
| case token = tokens.shift | |
| when '(' | |
| expr = Expression.new(tokens) | |
| raise 'invalid symbol' unless tokens.shift == ')' | |
| @value = expr.value | |
| when '+' | |
| @value = Expression.new(tokens).value | |
| when '-' | |
| @value = -Expression.new(tokens).value | |
| when Numeric | |
| @value = token | |
| else | |
| raise 'invalid token' | |
| end | |
| end | |
| end | |
| def tokenize(input) | |
| result = [] | |
| chars = input.each_char.to_a | |
| until chars.empty? | |
| case char = chars.shift | |
| when '+', '-', '*', '/', '(', ')' | |
| result << char | |
| when /[1-9]/ | |
| n = [ char ] | |
| while chars.first =~ /[0-9]/ | |
| n << chars.shift | |
| end | |
| result << Integer(n.join) | |
| else | |
| raise 'invalid token' | |
| end | |
| end | |
| result | |
| end | |
| def calc(input) | |
| Expression.new(tokenize(input)).value | |
| end | |
| p calc('19+23') | |
| p calc('19+23-4') | |
| p calc('1+2*4') | |
| p calc('(1+2)*4') | |
| p calc('(4/2+2*3)*4') | |
| p calc('(4/2+2*3)*4+') rescue p 'exception' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment