Skip to content

Instantly share code, notes, and snippets.

@gmittal
Created December 14, 2018 00:17
Show Gist options
  • Save gmittal/254b2d5f7584315cbc2dd6200ea3d2ae to your computer and use it in GitHub Desktop.
Save gmittal/254b2d5f7584315cbc2dd6200ea3d2ae to your computer and use it in GitHub Desktop.
Basic infix interpreter in Python.
from operator import add, mul, sub, floordiv
import re
OPERATORS = {'*': mul, '+': add, '-': sub, '/': floordiv}
def parse(text, left=r'[(]', right=r'[)]', sep=r','):
""" *** Based on https://stackoverflow.com/a/17141899/190597 (falsetru) ***
>>> parse('1+2')
['1', '+', '2']
>>> parse('(1+2)*(3-4)')
[['1', '+', '2'], '*', ['3', '-', '4']]
>>> parse('1000*(2+1)')
['1000', '*', ['2', '+', '1']]
"""
pat = r'({}|{}|{})'.format(left, right, sep)
tokens = re.split(pat, text)
stack = [[]]
for x in tokens:
if not x or re.match(sep, x): continue
if re.match(left, x):
stack[-1].append([])
stack.append(stack[-1][-1])
elif re.match(right, x):
stack.pop()
if not stack:
raise ValueError('error: opening bracket is missing')
else:
stack[-1].append(x)
if len(stack) > 1:
print(stack)
raise ValueError('error: closing bracket is missing')
separate = lambda e: re.findall('[+-/*//()]|\d+', e)
def process(e):
if not e:
return []
elif isinstance(e[0], list):
return [process(e[0])] + process(e[1:])
else:
return separate(e[0]) + process(e[1:])
return process(stack.pop())
def evaluate(expr):
"""
>>> evaluate(['2', '+', '2'])
4
>>> evaluate([['1', '/', '2'], '*', '3'])
0
"""
if isinstance(expr, str):
return int(expr)
elif len(expr) == 1:
return evaluate(expr[0])
else:
op = expr[1]
first = evaluate(expr[0])
second = evaluate(expr[2])
return OPERATORS[op](first, second)
def infix(expr):
"""
>>> infix('1+2')
3
>>> infix('(1)+(2*3)')
7
>>> infix('1')
1
>>> infix('(1*2)-(3*(4+(3/3)))')
-13
>>> infix('(1000/2)*(4*((0-1)*(3-12)))')
18000
"""
return evaluate(parse(expr))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment