Skip to content
{{ message }}

Instantly share code, notes, and snippets.

# berdario/calc.py

Last active Aug 29, 2015
 #! /usr/bin/env python from enum import Enum from numbers import Number from operator import add, sub, mul, truediv, mod class Operation(Enum): PLUS = (add, 6) MINUS = (sub, 6) MULT = (mul, 7) QUOT = (truediv, 7) MOD = (mod, 7) def __init__(self, fn, precedence): self.fn = fn self.precedence = precedence ops_table = {'+': 'PLUS', '-': 'MINUS', '*': 'MULT', '/': 'QUOT', '%': 'MOD'} class AST: def __init__(self, v1, op=None, v2=None): if op is None and v2 is None: self.root = v1 self.l = self.r = None self.precedence = 10 else: self.root = op self.precedence = op.precedence self.l = v1 self.r = v2 def append(self, op, v): if op.precedence > self.precedence: self.r = AST(self.r, op, AST(v)) return self else: return AST(self, op, AST(v)) def evaluate(self): if isinstance(self.root, Number): return self.root elif isinstance(self.root, Operation): return self.root.fn(self.l.evaluate(), self.r.evaluate()) else: raise Exception("sorry, this shouldn't happen, root is: %s", self.root) def __str__(self): if isinstance(self.root, Number): return str(self.root) elif isinstance(self.root, Operation): return '({} {} {})'.format(self.root, self.l, self.r) def parse(s): n, *rest = s.split() ast = AST(int(n)) while rest: op, v, *rest = rest assert op in ops_table, "%s is not a valid operation" % op ast = ast.append(Operation[ops_table[op]], int(v)) return ast if __name__ == '__main__': while True: expr = parse(input('> ')) print(expr.evaluate()) import pytest # run the tests with py.test calc.py def test_single_value(): assert parse('0').evaluate() == 0 assert parse('5').evaluate() == 5 assert parse('100000000000000000000').evaluate() == 100000000000000000000 def test_5ops(): assert parse('1 + 1').evaluate() == 2 assert parse('1 - 1').evaluate() == 0 assert parse('1 * 3').evaluate() == 3 assert parse('12 / 3').evaluate() == 4 assert parse('14 % 5').evaluate() == 4 def test_combined_exprs(): assert parse('1 + 1 + 1').evaluate() == 3 assert parse('1 - 1 - 1').evaluate() == -1 assert parse('2 * 3 - 1').evaluate() == 5 assert parse('2 - 6 / 2').evaluate() == -1 assert parse('1 + 1 - 4 * 4').evaluate() == -14
 py==1.4.23 pytest==2.6.1
to join this conversation on GitHub. Already have an account? Sign in to comment