Skip to content

Instantly share code, notes, and snippets.

@sangheestyle
Last active June 16, 2016 02:29
Show Gist options
  • Save sangheestyle/c530a5a8f3c4ceb7a67ceea7755845bb to your computer and use it in GitHub Desktop.
Save sangheestyle/c530a5a8f3c4ceb7a67ceea7755845bb to your computer and use it in GitHub Desktop.
Simple calc. Modified the original source from http://pyparsing.wikispaces.com/file/view/fourFn.py/30154950/fourFn.py
# fourFn.py
#
# Make the original fourFn.py simple to understand how it works.
#
# Original source code:
# http://pyparsing.wikispaces.com/file/view/fourFn.py/30154950/fourFn.py
import math
import operator
from pyparsing import Literal, CaselessLiteral, Word, Combine, \
Group, Optional, ZeroOrMore, Forward, nums, alphas
class SimpleCalculator(object):
"""Support only two operators.
"""
operators = {
"+" : operator.add,
"-" : operator.sub,
}
def __init__(self):
self.expr_stack = []
self.bnf = None
def _push_first(self, strg, loc, toks):
self.expr_stack.append(toks[0])
def set_bnf(self):
"""
addop :: '+' | '-'
integer :: '0'..'9'+
atom :: integer | '(' expr ')'
expr :: atom [ addop atom ]*
"""
if not self.bnf:
number = Word(nums)
plus = Literal("+")
minus = Literal("-")
lpar = Literal("(").suppress()
rpar = Literal(")").suppress()
addop = plus | minus
expr = Forward()
atom = (number).setParseAction(self._push_first) \
| (lpar + expr.suppress() + rpar)
expr << atom + \
ZeroOrMore((addop + atom).setParseAction(self._push_first))
self.bnf = expr
def parse(self, string):
self.set_bnf()
self.bnf.parseString(string)
return list(self.expr_stack)
def calc(self, string):
expr_stack = self.parse(string)
def evaluate_stack(s):
op = s.pop()
if op in self.operators.keys():
op2 = evaluate_stack(s)
op1 = evaluate_stack(s)
return self.operators[op](op1, op2)
else:
return float(op)
return evaluate_stack(expr_stack), list(self.expr_stack)
if __name__ == "__main__":
def test(s, exp_val):
sc = SimpleCalculator()
val, expr_stack = sc.calc(s)
if val == exp_val:
message = "{} = {}: {}"
else:
message = "ERROR: {} != {}: {}"
print(message.format(val, exp_val, expr_stack))
test( "9", 9 )
test( "(9)", (9) )
test( "9 + 3 + 6", 9 + 3 + 6 )
test( "(9 + 3)", (9 + 3) )
test( "9 - 12 - 6", 9 - 12 - 6 )
test( "(9 - 12) - 6", (9 - 12) - 6 )
test( "9 - (12 - 6)", 9 - (12 - 6) )
"""
Test ouput:
$ python simple_calc.py
9.0 = 9: ['9']
9.0 = 9: ['9']
18.0 = 18: ['9', '3', '+', '6', '+']
12.0 = 12: ['9', '3', '+']
-9.0 = -9: ['9', '12', '-', '6', '-']
-9.0 = -9: ['9', '12', '-', '6', '-']
3.0 = 3: ['9', '12', '6', '-', '-']
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment