Visual walkthrough — Equivalence of CFGs and PDAs
Step 1 — What a stack actually is (from zero)
WHAT. We draw a stack as a vertical column. The bottom plate went on first; the top plate is where all the action happens.
WHY this object and not a list or array? Because a stack answers exactly one question — "what is the single most recent unfinished thing I owe?" — and forgets everything below it until that top is cleared. That "one unfinished thing at a time, deepest last" behaviour is precisely how nested things (boxes in boxes, brackets in brackets) close.
PICTURE. The left column shows a push; the right column shows a pop. Watch the top move.
Recall Why "top only"?
Why can a stack read only its top plate? ::: Because that top plate is the innermost unfinished job; you cannot finish an outer job until the inner one closes — same as brackets.
Step 2 — A derivation is already a stack (the key sighting)
WHAT. We expand and draw the nesting as brackets.
WHY. This is the whole theorem in embryo. The reason a machine with one stack can imitate a grammar is that the grammar's own recursion is a bracket structure, and brackets are what a stack tracks. Nothing deeper is going on than this matching of shapes.
PICTURE. Each expansion opens a new bracket pair a[ ]b; the deepest bracket is the one we resolve first — exactly the top of a stack.
- = terminals (real output characters).
- = "empty string", the base case where the innermost produces nothing.
- The brace nesting = the stack depth at that moment.
Step 3 — Turning the grammar into a one-state PDA
WHAT. Two move-types, straight from the grammar:
WHY one state? The grammar has no "control state" — every scrap of progress lives in the sentential form (the half-finished string). We store that whole sentential form on the stack, so the machine needs no memory in its state at all. One state suffices.
WHY does expansion read ? Applying a grammar rule produces no input character; it only rearranges what we still owe. Reading a real symbol happens only in the second move, when a promised terminal meets the actual input.
PICTURE. Top of stack decides which move is even legal: a variable on top → only expansion; a terminal on top → only matching.
Step 4 — Run it on (the film strip)
WHAT. We trace the PDA move-by-move on the string . Stack top is drawn at the left.
WHY show every row? Because acceptance is a path, and we must witness that the guesses (which rule to expand) can be made so the stack empties exactly as the input ends.
PICTURE. Each frame = the stack after one move; the arrow labels which move fired.
| Step | Move (why) | Unread input | Stack (top-left) |
|---|---|---|---|
| 0 | start | ||
| 1 | expand | ||
| 2 | match | ||
| 3 | expand | ||
| 4 | match | ||
| 5 | expand | ||
| 6 | match | ||
| 7 | match | (empty) → accept |
Step 5 is the guess: nondeterminism tries here, and this guess is the one that works.
Step 5 — The invariant that proves it (one picture)
WHAT. Read the read-part and the stack-part as one string; that concatenation is always something can derive so far.
WHY it clinches Direction 1. When input is exhausted and the stack is empty, both sides say "" — the whole input was genuinely derived. Conversely any derivation gives an accepting run. So .
PICTURE. A dotted seam splits "already read" (left, teal) from "still on stack" (right, orange); glue them and you get the sentential form (plum) above.
Step 6 — The reverse direction: reading a run as brackets
WHAT. We first normalise the PDA so every move either pushes exactly one symbol or pops exactly one. Then a balanced run looks like a bracket string, and each variable expands like a bracket.
WHY this definition? A push that waits and is later popped is literally a matching bracket pair. A grammar variable expanding to "open · middle · close" is the same shape. Matching the shapes gives the grammar for free.
PICTURE. Stack height plotted over time (a "mountain profile"). = one full mountain returning to the baseline.
Step 7 — The two rules, and why they are ALL the cases
WHAT. Term-by-term on the match rule :
- = the input read when the machine pushes symbol , moving .
- = the input read when the machine pops that same , moving .
- = whatever happened above while it sat on the stack — a balanced sub-run from to .
WHY exactly two working shapes? Look at the first symbol pushed in a balanced run. There are only two fates for it:
- It is popped only at the very end → one outer bracket wraps everything → match rule.
- It is popped strictly before the end → the stack touches baseline mid-run at some state → the run splits into two balanced halves → split rule.
No third possibility exists, so the rules generate exactly .
PICTURE. Two mountain profiles side by side: left = one big arch (match), right = two arches meeting the baseline (split).
For our example PDA (state pushes per ; pops per into ; pops per staying in ), the match rule gives and — literally again. The two constructions are inverse in spirit.
The one-picture summary
WHAT. One figure that stacks all four viewpoints of the SAME string : the parse tree, the bracket nesting, the PDA stack film, and the balanced mountain profile. Read any column — they are the same object.
Compare with Leftmost Derivations and Parse Trees and Chomsky Normal Form (the normal form that makes the balanced-run argument clean). The one-stack limit is what keeps us inside Closure Properties of CFLs and short of Turing Machines — two stacks would jump the fence.
Recall Feynman: tell it to a friend in plain words
A grammar is a recipe for nesting boxes: to make a box you may put a smaller box inside and then close the lid, and the innermost box must be finished before any outer lid closes. A stack machine is a kid holding a pile of plates: every time the recipe opens a box the kid puts a plate down; every time a real letter is matched the kid takes the matching plate off. Because you must always deal with the top plate first — the innermost box first — the pile of plates and the nested boxes rise and fall in perfect step. Reading the run forward, the plate you set down first is the plate you lift last: one opening bracket, one closing bracket, with a smaller balanced run sitting on top of it. That single fact — "first plate down is last plate up" — is why one stack equals grammar recursion, and why two stacks would be too much and turn the kid into a full computer.
Recall Active recall — cover the answers
- What single shape do a derivation and a stack share? ::: nesting / matched brackets.
- In CFG→PDA, when is input read? ::: only on the match move (a terminal on top meets the input); expansion is an -move.
- What does "balanced run" mean for ? ::: same start and end stack height, never dipping below the start.
- Why exactly two rule schemas in PDA→CFG? ::: the first pushed symbol is popped either at the very end (match) or earlier (split); no third case.
- Why does the equivalence fail with two stacks? ::: two stacks simulate a Turing machine, escaping the context-free class.