Anonymous user
Parsing/RPN to infix conversion: Difference between revisions
→{{header|Python}}: Replaced old example with one that properly takes associativity into account.
No edit summary |
(→{{header|Python}}: Replaced old example with one that properly takes associativity into account.) |
||
Line 757:
=={{header|Python}}==
<lang python>
"""
>>> # EXAMPLE USAGE
>>> result = rpn_to_infix('3 4 2 * 1 5 - 2 3 ^ ^ / +', VERBOSE=True)
TOKEN STACK
3 ['3']
4 ['3', '4']
2 ['3', '4', '2']
* ['3', Node('4','*','2')]
1 ['3', Node('4','*','2'), '1']
5 ['3', Node('4','*','2'), '1', '5']
- ['3', Node('4','*','2'), Node('1','-','5')]
2 ['3', Node('4','*','2'), Node('1','-','5'), '2']
3 ['3', Node('4','*','2'), Node('1','-','5'), '2', '3']
^ ['3', Node('4','*','2'), Node('1','-','5'), Node('2','^','3')]
^ ['3', Node('4','*','2'), Node(Node('1','-','5'),'^',Node('2','^','3'))]
/ ['3', Node(Node('4','*','2'),'/',Node(Node('1','-','5'),'^',Node('2','^','3')))]
+ [Node('3','+',Node(Node('4','*','2'),'/',Node(Node('1','-','5'),'^',Node('2','^','3'))))]
>>> result
'3 + 4 * 2 / (1 - 5) ^ 2 ^ 3'
"""
prec_dict = {'^':4, '*':3, '/':3, '+':2, '-':2}
assoc_dict = {'^':1, '*':0, '/':0, '+':0, '-':0}
class Node:
def __init__(self,y,op,x):
global prec_dict,assoc_dict
self.precedence = prec_dict[op]
self.assocright = assoc_dict[op]
self.op = op
if not self.assocright and self >= x and \
isinstance(x, Node) and not isinstance(y, Node):
self.x = x.x
self.y = Node(y, x.op, x.y)
else:
self.x,self.y = x,y
def __str__(self):
showypar = self.y < self or (self.y == self and self.assocright)
showxpar = self.x < self or (self.x == self and not self.assocright)
str_y = (str(self.y), '(%s)'%str(self.y))[showypar]
str_x = (str(self.x), '(%s)'%str(self.x))[showxpar]
return ' '.join([str_y, self.op, str_x])
def __repr__(self):
"""
>>> repr(Node('3','+','4')) == repr(eval(repr(Node('3','+','4'))))
True
"""
return 'Node(%s,%s,%s)'%(repr(self.y), repr(self.op), repr(self.x))
def __cmp__(self, other):
"""
>>> Node('3','+','4') < Node('6','*','7')
True
>>> Node('3','+','4') == Node('6','-','7')
True
>>> Node('3','+','4') == '-'
True
>>> Node('3','^','4') < '1'
True
"""
if isinstance(other, Node):
return cmp(self.precedence, other.precedence)
return cmp(self.precedence, prec_dict.get(other,9))
def
"""
>>> rpn_to_infix('5 4 +')
'5 + 4'
>>> rpn_to_infix('5 4 3 2 ^ ^ ^')
'5 ^ 4 ^ 3 ^ 2'
>>> rpn_to_infix('5 6 ^ 7 ^')
'(5 ^ 6) ^ 7'
>>> rpn_to_infix('4 3 2 + +')
'4 + 3 + 2'
>>> rpn_to_infix('5 4 3 2 + + +')
'5 + 4 + 3 + 2'
>>> rpn_to_infix('3 4 5 * -')
'3 - 4 * 5'
>>> rpn_to_infix('3 4 5 - *')
'(3 - 4) * 5'
>>> rpn_to_infix('4 2 * 1 5 - +')
'4 * 2 + (1 - 5)'
>>> rpn_to_infix('4 2 * 1 5 - 2 ^ /')
'4 * 2 / (1 - 5) ^ 2'
>>> rpn_to_infix('3 4 2 * 1 5 - 2 3 ^ ^ / +')
'3 + 4 * 2 / (1 - 5) ^ 2 ^ 3'
>>> rpn_to_infix('1 2 + 3 4 + ^ 5 6 + ^')
'((1 + 2) ^ (3 + 4)) ^ (5 + 6)'
"""
global prec_dict
if VERBOSE : print('TOKEN STACK')
for token in s.split():
if token in prec_dict:
x,y=stack.pop(),stack.pop()
stack.append(Node(y,token,x))
else:
# can't use \t in order to make global docstring pass doctest
if VERBOSE : print(token+' '*6+repr(stack))
return str(stack[0])
if __name__ == "__main__":
import doctest
doctest.testmod()
</lang>
=={{header|Ruby}}==
|