-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathprefix_calc.py
61 lines (51 loc) · 1.66 KB
/
prefix_calc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
""" Prefix calculator. Takes a space-delimited string like '* ( / 10 5 ) ( + ( - 5 2 ) ( * 1 3 ) )'
and parses it, builds an AST, and reduces the AST to a number by running specified operators. """
__author__ = "Caleb Madrigal"
__date__ = "2015-03-04"
def calc(node):
if node == ():
return
(op, a, b) = node[0], node[1], node[2]
if type(a) == tuple:
a = calc(a)
if type(b) == tuple:
b = calc(b)
if op == '+':
return a + b
elif op == '-':
return a - b
elif op == '*':
return a * b
elif op == '/':
return a / b
def build_ast(token_list):
if not token_list:
return (), ()
token, *rest = token_list
if token == '(':
internal, remainder = build_ast(rest)
internal2, remainder2 = build_ast(remainder)
return (internal,) + internal2, remainder2
elif token == ')':
return (), rest
elif token in ['+', '-', '*', '/']:
internal, remainder = build_ast(rest)
return (token,) + internal, remainder
else: # Token is number
internal, remainder = build_ast(rest)
return (float(token),) + internal, remainder
def parse(calc_str):
return calc_str.split()
if __name__ == '__main__':
calc_str = '+ ( * 2 2 ) ( - ( + 3 2 ) 4 )'
parsed = parse(calc_str)
ast, _ = build_ast(parsed)
print("Original: '{}'".format(calc_str))
print("Parsed:", parsed)
print("AST:", ast)
print("Result:", calc(ast))
calc_str2 = '* ( / 10 5 ) ( + ( - 5 2 ) ( * 1 3 ) )'
ast, _ = build_ast(parse(calc_str2))
print("\nOriginal: '{}'".format(calc_str2))
print("AST:", ast)
print("Result:", calc(ast))