Constructing an NPDA for a Given CFG
To construct an NPDA from a context-free grammar (CFG), we use the standard correspondence: each CFG production is implemented as a nondeterministic stack rewrite step. Concretely, when the automaton sees a nonterminal on top of the stack, it can replace by the right-hand side of any production by pushing onto the stack (in reverse order). Simultaneously, terminals are matched by consuming input symbols when the same terminal appears on top of the stack.
This course section applies that construction to the specific grammar:
where denotes a (fixed) terminal string that must be read in the input. (If instead is meant to be a single terminal, the construction specializes by using that one symbol as the read sequence.)
Key terms
- CFG
- Production
- Stack symbol
- Epsilon transition
- Start symbol
NFA/NPDA basics: converting CFGs to pushdown automata (conceptual)
Grammar-to-NPDA construction pattern
The “recipe” for a CFG to an NPDA is:
- Use stack to simulate the derivation.
- Start with stack containing the start symbol (and typically a bottom marker).
- For each production add an -move that replaces by on the stack.
- For each terminal add a move that consumes input when is on the stack top.
- Accept by empty stack or by entering a final state after input is consumed (both are standard variants).
Why this works (intuitively)
A leftmost derivation in the CFG corresponds to a sequence of rewrites of the leftmost nonterminal. In the NPDA simulation, “rewriting” is done whenever a nonterminal is on top of the stack, and “reading” is done when a terminal is on top of the stack.
Note: “push reversed” means if then we push so that becomes the new top (to be expanded/consumed next).
type="tip" title="Pro Tip: Treat terminals as stack symbols too" content="In this construction, terminals in the RHS are pushed to the stack as well; then separate transitions pop them while consuming matching input characters."
type="warning" title="Important: Clarify what means" content="The grammar uses on multiple RHSs. The NPDA must read exactly that same fixed terminal string each time it appears in a chosen derivation; if is actually a single terminal symbol, you should replace each occurrence of the string by that one symbol."
Step-by-step construction of an NPDA for the given grammar
- 1Step 1
Let with a start state , stack alphabet containing nonterminals , terminals from , and a bottom marker . Acceptance by empty stack (or a final state) is fine; we will use empty stack.
- 2Step 2
Use an -move from that pushes onto the stack above .
- 3Step 3
For every production , add a transition of the form: when is on top of stack, replace it by the string (push its symbols in reverse order).
- 4Step 4
For each terminal in that appears as a symbol on the stack, add a move that reads from input and pops from the stack.
- 5Step 5
If multiple productions apply to the same nonterminal (e.g., has two), the NPDA will have multiple alternative -moves for that same stack top.
- 6Step 6
Accept when the input is fully consumed and the stack has no non-bottom symbols left (empty stack above ). Concretely: when stack top is and no input remains, transition to accept state or halt with acceptance.
NPDA definition (formal transitions)
We must implement these productions:
Assumptions about alphabets
Let contain at least symbols appearing inside . Terminals in are treated as literal input symbols the NPDA will consume in order.
Define the stack alphabet:
(Practically, already includes those terminals.)
States
Let (single working state + accept).
Start move
On initialization, push above the bottom marker:
(Interpretation: replace top by .)
-transitions for the grammar’s nonterminals
We now add transitions that replace a stack-top nonterminal by the RHS string.
For
- For :
- If top is , replace by the sequence . So the NPDA push is: push RHS symbols in reverse order:
- push , then , then , then the symbols of in reverse, and keep them so that the leftmost symbol of is consumed first.
- For similarly: replace by .
For
- For replace by .
- For replace by .
For
- For replace by .
- For replace by .
To avoid ambiguity about the internal symbols of , we represent as a concrete terminal string:
Then a push for means pushing so that ends up on top.
Transitions written schematically
For clarity, we show the replacement rule in stack form.
-productions
- If stack top is , push :
- If stack top is , push :
-productions
- :
- :
-productions
- :
because RHS is ; reversed push order puts first to be matched by input.
- :
Terminal matching transitions (consume input when terminal is on top)
For each terminal symbol (including and all from ):
- If the stack top is , consume and pop it:
Concretely, for the symbol :
And similarly for each in :
Acceptance transition
Use acceptance by empty stack above bottom marker:
- If no input remains and top is , move to accept:
Alternatively, you can define .
Production-to-transition mapping summary
How each CFG production is realized in the NPDA
Common pitfalls and how to avoid them
Knowledge Check
In the standard CFG-to-NPDA construction, what does the NPDA do when a nonterminal X is on top of the stack?
Explore Related Topics
Convert a Context-Free Grammar to GNF (Worked Example)
Ambiguity in the Grammar \(S \rightarrow ABA,\; A \rightarrow aA \mid \epsilon,\; B \rightarrow bB \mid \epsilon\)
The grammar (S\rightarrow ABA,;A\rightarrow aA\mid\epsilon,;B\rightarrow bB\mid\epsilon) is ambiguous because the two (A) nonterminals can distribute the same (a)-string in multiple ways, especially when (B) derives (\epsilon).
- It generates the language (L(S)={a^i b^j a^k\mid i,j,k\ge0}=a^*b^a^).
- The shortest string (a) has two distinct left‑most derivations (or parse trees), proving ambiguity.
- Every string (a^n) with (n\ge1) can be split between the two (A) symbols in (n+1) ways, yielding multiple parse trees.
- The ambiguity stems from both (A) producing (a^*) and (B) being able to vanish via (\epsilon).
- An equivalent unambiguous grammar can be constructed, showing the ambiguity is a property of this grammar, not necessarily of the language.
Eliminating Left Recursion/Left Factoring and Testing Suitability for Top-Down Parsing