CS305 -- Formal Language Theory
Use arrow keys or buttons to navigate. ~21 slides.
A Pushdown Automaton takes everything an NFA can do and adds a stack -- an infinite, last-in-first-out memory.
The stack lets the PDA "remember" unbounded amounts of information, but only in LIFO order. This is exactly the extra power needed to match things like nested parentheses and anbn.
A DFA has finite memory -- just its current state. It cannot count beyond a fixed bound.
Consider the language L = { anbn | n ≥ 0 }:
Solution: Give the machine a stack! Push each a, then pop one for each b. Accept if stack is empty.
Think of a spring-loaded cafeteria tray dispenser. You can only see and grab the top tray. You push trays on and pop them off. You never reach into the middle. That's exactly how a PDA's stack works.
A PDA has three components: an input tape (read left-to-right), a finite control (current state), and a stack (unbounded LIFO memory).
A PDA is a 7-tuple:
| Symbol | Meaning |
|---|---|
| Q | Finite set of states |
| Σ | Input alphabet |
| Γ | Stack alphabet |
| δ | Transition function |
| q0 | Start state (q0 ∈ Q) |
| Z0 | Initial stack symbol (Z0 ∈ Γ) |
| F | Set of accept (final) states |
The range is a set of (state, string) pairs -- this makes PDAs nondeterministic. The PDA can "choose" among multiple possible moves. It accepts if any choice sequence leads to acceptance.
Σ is the input alphabet (e.g., {a, b}). Γ is the stack alphabet (e.g., {a, b, $}). They can overlap, but Γ often has extra symbols like the bottom marker $.
Each transition is written as:
Read this as:
The string Y is pushed so that its leftmost symbol ends up on top of the stack. If Y = ABC, then A is on top, B below it, C at the bottom of the pushed portion.
Every transition pops the stack top and pushes a replacement string. We encode push, pop, and no-change using this single mechanism.
a read: push an a onto the stackb read: pop one a from the stackThe stack counts the a's. Each b cancels one a by popping. If counts match, the stack returns to just $, and we accept.
The empty string ε is in this language (n=0). We must accept it! That's why q0 transitions directly to accept on seeing $.
Try it yourself! Enter a string of a's and b's and step through the PDA execution.
There are two equivalent ways a PDA can accept a string.
This is the more common definition in textbooks. The accept states F determine acceptance.
Here, F is ignored (or F = Q). The PDA accepts purely by emptying its stack after reading all input.
These two acceptance modes are equivalent in power. Any language accepted by a PDA using final states can also be accepted by some (different) PDA using empty stack, and vice versa. We can mechanically convert between the two.
The new bottom marker Z0' is essential! Without it, the original PDA might empty its stack prematurely (not at a final state), and the conversion would accept strings it shouldn't.
Language: { w ∈ {(, )}* | w has properly nested, balanced parentheses }
()) but stack has only $ -- reject (unmatched close)Note: We can use a single state q0! The transitions for ( and ) just loop on q0.
Even-length palindromes! The string's second half is the reverse of the first.
Consider 01 10: the first half is 01, the second half 10 is 01 reversed.
But how does the PDA know where the middle is?
The PDA guesses the midpoint! At every position, it nondeterministically branches into two choices:
It accepts if any guess leads to acceptance. The "correct" guess (at the true midpoint) will succeed.
Imagine cloning yourself at every step. One clone keeps pushing, the other switches to matching. Most clones die. The one who guessed right survives.
For finite automata, deterministic = nondeterministic in power.
A deterministic PDA has at most one move at each step. Formally: for every (state, input, stack_top), there is at most one transition, and if there's an ε-transition, there are no other transitions for that (state, stack_top).
The language { wwR | w ∈ {0,1}* } is context-free but NOT deterministic context-free. No DPDA can recognize it -- the "guess the middle" trick requires nondeterminism.
Languages recognized by DPDAs are called Deterministic CFLs. They are important in practice because most programming languages are designed to be deterministic CFLs (so parsers are efficient).
| Language | DPDA? | PDA? |
|---|---|---|
| anbn | Yes | Yes |
| wwR | No | Yes |
| wcwR (with center marker) | Yes | Yes |
Given any CFG G, we can build a PDA M such that L(M) = L(G). This uses a top-down parsing strategy.
The PDA has essentially one working state (qloop) that does all the work.
The stack holds the "prediction" of what the rest of the input should look like. Variables get expanded (replaced by rule right-hand sides). Terminals get matched and consumed. This is a leftmost derivation simulation.
This generates { anbn | n ≥ 0 }.
The harder direction: given a PDA, build an equivalent CFG. This proves every PDA language is context-free.
Create a variable Apq for every pair of states (p, q). This variable generates exactly the strings that take the PDA:
This construction can produce a huge number of rules (|Q|3 rules just from Rule 2). Many rules may be useless (generating no terminal strings), but the grammar is correct.
The start variable is Aq0,qf for accept states qf. The grammar works because every computation that starts with an empty stack and ends with an empty stack can be decomposed into paired push/pop segments.
This is one of the fundamental theorems of formal language theory. It says that the generative model (grammars deriving strings) and the recognition model (automata accepting strings) agree perfectly for context-free languages.
Think of CFGs as blueprints (how to build strings) and PDAs as inspectors (how to verify strings). The theorem says: anything one can build, the other can check -- and vice versa. They're two views of the same reality.
| Language | PDA? | Why Not |
|---|---|---|
| { anbncn } | No | Can't count 3 things |
| { ww } (copy) | No | Can't match forward |
| { anbncndn } | No | Same reason |
{ aibjck | i| No | Two independent counts | |
A stack is LIFO (last-in, first-out). It naturally handles reversal (palindromes, nesting) but cannot handle copying or three-way matching. These require a Turing machine's tape.
Use the Pumping Lemma for CFLs to formally prove a language is not context-free (and hence no PDA can recognize it).
| Language | Regular? | CFL? |
|---|---|---|
| a*b* | Yes | Yes |
| anbn | No | Yes |
| balanced parens | No | Yes |
| wwR | No | Yes (nondet) |
| wcwR | No | Yes (det) |
| anbncn | No | No |
| ww (copy) | No | No |
DPDA < PDA (unlike DFA = NFA). Some CFLs fundamentally require nondeterminism. Example: wwR (even palindromes) needs nondeterministic "guess the middle."
DFA = person with a notecard (finite notes).
PDA = person with a stack of plates (LIFO memory).
TM = person with a scroll (random-access memory).
3 random questions from a pool of 6. Pick the correct answer!