Infix ↔ Postfix Notation Converter: Tools, Algorithms, and Examples
Understanding and converting between infix and postfix (also called Reverse Polish Notation, RPN) is essential for compilers, interpreters, calculators, and many algorithmic tasks. This article explains the notations, shows key algorithms (shunting-yard and stack-based conversion), provides example code, discusses practical tools, and gives examples and test cases.
What are infix and postfix?
- Infix: Operators placed between operands (e.g., A + B). Common in human-readable math.
- Postfix (RPN): Operators placed after operands (e.g., A B +). Evaluated left-to-right with a stack, no need for parentheses.
Why convert?
- Postfix simplifies evaluation because operator precedence and parentheses are encoded in order, enabling simple stack-based evaluation.
- Converts enable expression evaluation in constrained environments (embedded systems, calculators) and simplify compiler backends.
Algorithms
1) Infix → Postfix: Shunting‑Yard (Dijkstra)
Overview: Read tokens left to right, use an operator stack to reorder operators according to precedence and associativity, and output operands immediately.
Pseudocode (concise):
Code
output = [] ops = empty stack for each token t:if t is operand: append t to output else if t is operator o1:while ops not empty and top is operator o2 and (precedence(o2) > precedence(o1) or (precedence(o2) == precedence(o1) and o1 is left-assoc)): pop ops -> append to output push o1 onto opselse if t is ‘(’:
push '(' onto opselse if t is ‘)’:
while top of ops != '(': pop ops -> append to output pop '('while ops not empty: pop -> append to output return output as space-separated string
Notes:
- Define precedence (e.g., ^ highest, then *,/, then +,-).
- Associativity: ^ is typically right-associative, others left-associative.
- Support unary operators (like unary minus) by tokenizing and treating unary minus as separate with higher precedence.
2) Postfix → Infix
Overview: Use a stack of expression strings. For each operand push it. For each operator pop required operands, combine with parentheses based on precedence to preserve original evaluation order, then push combined string.
Pseudocode:
Code
stack = empty for token in postfix: if token is operand: push token else if token is binary operator op:right = pop stack left = pop stack left = maybe_parenthesize(left, op) right= maybe_parenthesize(right, op, right_side=True) push "(" + left + " " + op + " " + right + ")"return pop stack
Key: maybeparenthesize compares inner expression root operator precedence and associativity to decide if parentheses are needed to preserve evaluation order.
3) Evaluate Postfix (for testing)
Simple stack-based numeric evaluation:
Code
stack = [] for token in postfix: if operand: push numeric value else: b = pop; a = pop; push apply(op, a, b) return popExample implementation (Python — concise)
Code
# Infix to Postfix (shunting-yard), tokenized by whitespace or simple scanner precedence = {‘+’:1, ‘-’:1, ‘*’:2, ‘/’:2, ‘^’:3} right_assoc = {‘^’}def infix_to_postfix(tokens):
out, ops = [], [] for t in tokens: if t.isalnum() or is_number(t): out.append(t) elif t == '(': ops.append(t) elif t == ')': while ops and ops[-1] != '(': out.append(ops.pop()) ops.pop() else: # operator while ops and ops[-1] != '(' and ( precedence.get(ops[-1],0) > precedence.get(t,0) or (precedence.get(ops[-1],0) == precedence.get(t,0) and t not in right_assoc) ): out.append(ops.pop()) ops.append(t) while ops: out.append(ops.pop()) return outdef is_number(s):
try: float(s); return True except: return FalseFor postfix→infix, maintain pairs (expr_string, root_op_prec) to decide parentheses.
Tools & Libraries
- Command-line/calculator tools:
- Unix bc and dc: dc uses RPN.
- HP calculators (RPN models) accept postfix directly.
- Programming libraries:
- Many language standard examples exist (Python snippets, JavaScript libraries) — shunting‑yard is widely implemented.
- Parser generators (ANTLR) can produce ASTs; converting AST ↔ postfix/infix is straightforward.
- Online converters:
- Numerous online infix↔postfix converters and visualizers (search for “infix to postfix converter” or “shunting yard visualizer”).
Examples & Test Cases
- Simple:
- Infix: A + B * C
- Postfix: A B C * +
- Parentheses:
- Infix: (A + B) * C
- Postfix: A B + C *
- Right-associative:
- Infix: A ^ B ^ C
- Postfix: A B C ^ ^ (since ^ is right-assoc)
- Unary minus:
- Infix: -A + B (tokenize unary minus as u-)
- Postfix: A u- B + (or 0 A – B + if you handle unary via zero)
- Numeric evaluation test:
- Infix: (3 + 4) * 5 – 6 / 2
- Postfix: 3 4 + 5 * 6 2 / –
- Evaluation: ((3+4)*5) – (⁄2) = 35 – 3 = 32
Practical tips
- Tokenization matters: handle multi-digit numbers, decimals, variable names, and unary operators explicitly.
- Preserve associativity rules when converting back to infix to avoid unnecessary parentheses.
- For production parsers, build an AST; convert between notations via traversal rather than string manipulation.
- Add support for function calls (e.g., sin, max) by treating them like operators with argument count.
Quick reference table
| Task | Recommended approach |
|---|---|
| Infix → Postfix | Shunting‑yard algorithm |
| Postfix → Infix | Stack of subexpressions with precedence-aware parenthesis |
| Evaluate Postfix | Stack-based numeric evaluation |
| Handle unary ops | Tokenize unary forms or rewrite (0 – x) |
| Complex grammars | Build AST with a parser generator (ANTLR, Bison) |
Conclusion
Converting between infix and postfix is robustly solved with the shunting‑yard and stack-based methods. For simple expressions use the shunting‑yard and stack evaluation; for complex languages prefer building an AST and emitting desired notation. Test conversions with varied precedence, associativity, parentheses, and unary operators to ensure correctness.
Leave a Reply