Stacks: Push and Pop Operations
A stack-based evaluation algorithm can detect errors in a postfix expression without needing parentheses or a human reader.
Catching Mistakes Without Reading the Expression
A postfix expression places each operator after the operands it works on. Because of this placement, an expression can be evaluated from left to right using a stack, with no parentheses needed. The same structure also makes certain mistakes easy to catch. A stack-based evaluation algorithm can reject a malformed expression on its own, without a person reading it.
Two kinds of malformed input are worth studying. In the first, an operator appears with too few operands before it. In the second, operands are left over with too few operators after them. Both expressions look close to valid input, and both are caught by the same algorithm. The question this article answers is when the algorithm knows something is wrong, and which kind of error it has found at that moment.
Tracing the Stack Token by Token
The algorithm reads the expression one token at a time. Each number is pushed onto the stack. Each operator takes its operands from the top of the stack: it pops two values, combines them, and pushes the result back. The stack is the only place where values wait, so its contents at each step show whether the expression is still consistent.
Tracing the faulty expression 2 3 + *
Evaluate the postfix expression 2 3 + * with the stack algorithm and state where the error is detected.
- 1Push 2 and push 3
Both numbers are legal on their own, so each one is pushed. The stack now holds 2 and 3, with 3 on top.
- 2Read the plus operator
The plus operator pops two values, 3 and 2, adds them, and pushes 5 back. The stack now holds only 5.
- 3Read the multiplication operator
This operator also needs two values. It pops 5, which succeeds, and then tries to pop a second value from an empty stack. The + consumed both numbers, so there is no second operand left.
- 4State where the error is found
The error is an insufficient operands error. It is detected during processing, at the multiplication operator, not after the last token.
Insufficient operands error, detected while processing the final operator *.
Insufficient Operands: Caught During Processing
An insufficient operands error is detected when an operator tries to pop its second operand from an empty stack. Each operator needs two values, so before it acts, the algorithm checks that the stack can supply them. The check happens while the operator is being processed, which is why this error is found earlier than the other kind.
The diagram shows the decision that matters. For a number, the algorithm pushes it and moves on. For an operator, it checks whether the stack holds two values. If it does, the operator pops both, combines them, and pushes the result. If it does not, the algorithm stops with an insufficient operands error. In the faulty expression 2 3 + *, the operator that fails is the multiplication, because the plus has already reduced the stack to a single value.
Insufficient Operators: Caught at the End
An insufficient operators error is detected when values remain on the stack at the end of the algorithm. A valid expression reduces to exactly one value once every token has been read. If more than one value is still on the stack, there were not enough operators to combine all the operands, and the error is found only at this final checkpoint.
Consider 2 3 4 +. Every token is legal on its own: three numbers and one operator. The plus pops only the two numbers on top, 4 and 3, and pushes 7. The number 2 at the bottom is left over, so the stack ends with two values. No operator ever failed, so the algorithm cannot catch this mistake until all tokens have been read.
What do you think happens?
In the expression 2 3 4 +, does any operator fail while the tokens are being read, or is the error found only after the last token?
Reveal answer
The error is found only after the last token
The plus operator always finds two values, so it never fails. The stack still holds 2 and 7 when reading ends, and that leftover value is what reveals the error.
Mistakes When Locating Each Error
Common mistake Assuming every faulty expression fails at the last token
What it looks likeIn 2 3 + *, the error is found at the multiplication operator, which is not the last token in a sense that matters: the stack check fails there, during processing.
Why it failsInsufficient operands errors are found during processing, when an operator cannot pop its second operand.
Do this insteadCheck each operator as it is read. If it cannot pop two values, stop at that operator.
Common mistake Thinking that a stack holding several values during processing is always an error
What it looks likeAfter reading 2 and 3 in 2 3 + *, the stack holds two values, which is perfectly normal.
Why it failsOperands are supposed to wait on the stack until an operator uses them. Extra values are only a problem if they remain at the end.
Do this insteadOnly check the stack size at the end for an insufficient operators error, and check the operand count at each operator for an insufficient operands error.
Common mistake Expecting an insufficient operators error to be caught while an operator runs
What it looks likeIn 2 3 4 +, the plus operator runs without any problem.
Why it failsThe plus always finds two values, so no operator fails. The leftover 2 is only visible once reading has ended.
Do this insteadLook for an insufficient operators error after the final token, by counting the values still on the stack.
Comparing a Valid and a Faulty Trace
The same algorithm handles valid and faulty input. The only difference is what the stack looks like at the moment of the operator check or at the end of reading. The table below places the three expressions side by side. The first two come from the source, and the valid expression 2 3 + 4 * is a generated contrast example.
| Expression | Where the stack ends or fails | Error type | Checkpoint |
|---|---|---|---|
| 2 3 + 4 * (valid) | One value, 20 | None | Final stack holds exactly one value |
| 2 3 + * (faulty) | Fails at the multiplication, after popping 5 | Insufficient operands | During processing, at the operator |
| 2 3 4 + (faulty) | Two values, 2 and 7 | Insufficient operators | After the last token |
Three traces under the same stack algorithm. The valid expression ends with one value, and each faulty expression is caught at a different checkpoint.
Practice Tracing a Faulty Expression
Trace the postfix expression 1 2 + + with the stack algorithm. State which error type occurs, the token where it is detected, and the stack contents just before that token.
Hints
- After reading 1 and 2, what is on the stack, and what does the first plus do to it?
- When the second plus arrives, how many values does the stack hold?
- Decide whether the error is found during processing or only after the last token.
Summary
At a glance
- A stack-based evaluation algorithm reads a postfix expression one token at a time, pushing numbers and having each operator pop two values, combine them, and push the result.
- An insufficient operands error is detected during processing, when an operator tries to pop its second operand from an empty stack.
- An insufficient operators error is detected after the last token, when more than one value still remains on the stack.
- Trace the stack token by token to find the exact checkpoint where an error appears, and state which error type it is.