4
4
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
5
5
"""
6
6
7
+ from typing import Literal
8
+
7
9
from .balanced_parentheses import balanced_parentheses
8
10
from .stack import Stack
9
11
12
+ PRECEDENCES : dict [str , int ] = {
13
+ "+" : 1 ,
14
+ "-" : 1 ,
15
+ "*" : 2 ,
16
+ "/" : 2 ,
17
+ "^" : 3 ,
18
+ }
19
+ ASSOCIATIVITIES : dict [str , Literal ["LR" , "RL" ]] = {
20
+ "+" : "LR" ,
21
+ "-" : "LR" ,
22
+ "*" : "LR" ,
23
+ "/" : "LR" ,
24
+ "^" : "RL" ,
25
+ }
26
+
10
27
11
28
def precedence (char : str ) -> int :
12
29
"""
13
30
Return integer value representing an operator's precedence, or
14
31
order of operation.
15
32
https://en.wikipedia.org/wiki/Order_of_operations
16
33
"""
17
- return {"+" : 1 , "-" : 1 , "*" : 2 , "/" : 2 , "^" : 3 }.get (char , - 1 )
34
+ return PRECEDENCES .get (char , - 1 )
35
+
36
+
37
+ def associativity (char : str ) -> Literal ["LR" , "RL" ]:
38
+ """
39
+ Return the associativity of the operator `char`.
40
+ https://en.wikipedia.org/wiki/Operator_associativity
41
+ """
42
+ return ASSOCIATIVITIES [char ]
18
43
19
44
20
45
def infix_to_postfix (expression_str : str ) -> str :
@@ -35,6 +60,8 @@ def infix_to_postfix(expression_str: str) -> str:
35
60
'a b c * + d e * f + g * +'
36
61
>>> infix_to_postfix("x^y/(5*z)+2")
37
62
'x y ^ 5 z * / 2 +'
63
+ >>> infix_to_postfix("2^3^2")
64
+ '2 3 2 ^ ^'
38
65
"""
39
66
if not balanced_parentheses (expression_str ):
40
67
raise ValueError ("Mismatched parentheses" )
@@ -50,9 +77,26 @@ def infix_to_postfix(expression_str: str) -> str:
50
77
postfix .append (stack .pop ())
51
78
stack .pop ()
52
79
else :
53
- while not stack .is_empty () and precedence (char ) <= precedence (stack .peek ()):
80
+ while True :
81
+ if stack .is_empty ():
82
+ stack .push (char )
83
+ break
84
+
85
+ char_precedence = precedence (char )
86
+ tos_precedence = precedence (stack .peek ())
87
+
88
+ if char_precedence > tos_precedence :
89
+ stack .push (char )
90
+ break
91
+ if char_precedence < tos_precedence :
92
+ postfix .append (stack .pop ())
93
+ continue
94
+ # Precedences are equal
95
+ if associativity (char ) == "RL" :
96
+ stack .push (char )
97
+ break
54
98
postfix .append (stack .pop ())
55
- stack . push ( char )
99
+
56
100
while not stack .is_empty ():
57
101
postfix .append (stack .pop ())
58
102
return " " .join (postfix )
0 commit comments