Last active
December 18, 2020 23:03
-
-
Save nitely/497540eb017ed8a75aecb6a4e609c9a2 to your computer and use it in GitHub Desktop.
Python shunting-yard algorithm
This file contains 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
# LICENSE: MIT | |
import collections | |
RIGHT, LEFT = range(2) | |
Op = collections.namedtuple('Op', [ | |
'precedence', | |
'associativity']) | |
OPS = { | |
'^': Op(precedence=4, associativity=RIGHT), | |
'*': Op(precedence=3, associativity=LEFT), | |
'/': Op(precedence=3, associativity=LEFT), | |
'+': Op(precedence=2, associativity=LEFT), | |
'-': Op(precedence=2, associativity=LEFT)} | |
def has_precedence(a, b): | |
return ((OPS[b].associativity == RIGHT and | |
OPS[a].precedence > OPS[b].precedence) or | |
(OPS[b].associativity == LEFT and | |
OPS[a].precedence >= OPS[b].precedence)) | |
def _pop_greater_than(ops, op): | |
out = [] | |
while True: | |
if not ops: | |
break | |
if ops[-1] not in OPS: | |
break | |
if not has_precedence(ops[-1], op): | |
break | |
out.append(ops.pop()) | |
return out | |
def _pop_until_group_start(ops): | |
out = [] | |
while True: | |
op = ops.pop() | |
if op == '(': | |
break | |
out.append(op) | |
return out | |
def rpn(expression): | |
""" | |
An implementation of the Shunting-yard algorithm\ | |
for producing Reverse Polish notation out of\ | |
an expression specified in infix notation | |
""" | |
output = [] | |
operators = [] | |
for char in expression: | |
if char == '(': | |
operators.append(char) | |
continue | |
if char == ')': | |
output.extend(_pop_until_group_start(operators)) | |
continue | |
if char in OPS: | |
output.extend(_pop_greater_than(operators, char)) | |
operators.append(char) | |
continue | |
if char.isdigit(): | |
output.append(char) | |
output.extend(reversed(operators)) | |
return ''.join(output) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment