Theory of ComputationUnit 37 min read
Pushdown Automata & Context-Free Languages: CFGs, PDAs, Parsing & Proofs
Unit 3 of Theory of Computation covers Pushdown Automata (PDAs) and Context-Free Grammars (CFGs), their formal definitions, conversion methods, parsing techniques, and proof methods for non-context-free languages. Learn how to design PDAs, simplify CFGs, and apply the Pumping Lemma to prove language properties.
TAKEAWAYS:
- Understand the stack-based memory of PDAs and how it enables parsing nested structures (e.g., parentheses, brackets).
- Master CFG simplification (removing useless symbols, unit productions, and chaining) to standardize grammars for analysis.
- Design PDAs for languages like
{aⁿbⁿ}or{w wᵣ | w ∈ Σ*}using epsilon transitions and stack operations. - Apply the Pumping Lemma for CFGs to prove languages are not context-free (e.g.,
{aⁿbⁿcⁿ}). - Compare top-down vs. bottom-up parsing (e.g., recursive descent vs. LR parsers) and their real-world use in compilers.
- Recognize ambiguity in CFGs and its impact on parsing efficiency (e.g., arithmetic expressions).
1. Context-Free Grammars (CFGs): Formal Definition and Structure
A Context-Free Grammar (CFG) is a 4-tuple , where:
- : Non-terminal symbols (e.g., ).
- : Terminal symbols (e.g., ).
- : Production rules (e.g., ).
- : Start symbol.
Key Components Visualized
classDiagram
class CFG {
+V: Non-terminals
+Σ: Terminals
+R: Productions
+S: Start symbol
}
CFG --> "1" Production : contains
Production --> "0..*" Symbol : expands to
Symbol <|-- NonTerminal
Symbol <|-- TerminalExample CFG for
S → aSb | ab
- Derivation: (for ).
Simplifying CFGs
Goal: Remove useless symbols (non-generating or unreachable) and unit productions (e.g., ). Steps:
- Remove unreachable non-terminals: Delete symbols not derivable from .
- Remove non-generating symbols: Delete symbols that cannot derive any terminal string.
- Remove unit productions: Replace with productions of .
Example: Original CFG:
S → Aa | Bb
A → aA | ε
B → bB | ε
Simplified CFG (after removing and unit productions):
S → aA | b
A → aA | ε
2. Pushdown Automata (PDAs): The Stack-Based Machine
A PDA extends a DFA with a stack to recognize context-free languages (CFLs). Formal Definition: , where:
- : Stack alphabet.
- : Transition function (push/pop).
- : Start stack symbol.
- : Accepting states.
PDA Block Diagram
Example PDA for
States: . Stack Alphabet: . Transitions:
- Push for each : .
- Pop for each : .
- Accept if stack is empty: .
Trace for aab:
| Step | Stack | Input | Action |
|---|---|---|---|
| 1 | aab | Push : | |
| 2 | ab | Push : | |
| 3 | b | Pop : | |
| 4 | Pop : | ||
| 5 | Pop : | ||
| 6 | Accept |
3. Epsilon Transitions in PDAs
Definition: Transitions without consuming input (). Purpose:
- Simplify PDA design (e.g., handle nested structures like
aⁿbᵐcⁿ). - Enable non-determinism (guessing stack operations).
Example PDA for :
- Push for each .
- Use -transitions to switch to -mode.
- Pop for each .
stateDiagram-v2
[*] --> q0 : read a
q0 --> q0 : push A, read a
q0 --> q1 : ε
q1 --> q1 : pop A, read b
q1 --> q2 : ε
q2 --> q2 : pop A, read c
q2 --> q_accept : ε, stack empty4. Parsing Techniques: Top-Down vs. Bottom-Up
| Method | Approach | Example Algorithms | Use Case |
|---|---|---|---|
| Top-Down | Start from start symbol. | Recursive Descent, LL(1) | Simple grammars (e.g., arithmetic). |
| Bottom-Up | Build parse tree upward. | LR(0), SLR, LALR | Complex grammars (e.g., programming languages). |
Real-World Example: Compilers (e.g., GCC, Clang)
- Front-end parsers use LR parsers (bottom-up) to validate code syntax.
- Ambiguous grammars (e.g.,
if-elsestatements) require disambiguation rules.
5. Proving Languages Are Not Context-Free
Tool: Pumping Lemma for CFGs. Statement: For any CFG , there exists a pumping length such that for any string with , can be divided into where:
- ,
- ,
- for all .
Example: Prove is not CFL
Proof:
- Assume is CFL. Let be the pumping length.
- Take . Divide into :
- , , (where ).
- Pump : . This is not in unless .
- Contradiction: No valid pumping exists. Thus, is not CFL.
6. Ambiguity in CFGs
Definition: A CFG is ambiguous if a string has multiple leftmost derivations. Example: Grammar for arithmetic expressions:
E → E + E | E * E | (E) | id
- String
id + id * idhas 5 parse trees.
Real-World Impact:
- Compilers must resolve ambiguity (e.g., operator precedence).
- Pathao’s ride-sharing app uses CFGs to parse user queries (e.g., "Go to Thamel via Ring Road") but avoids ambiguity with disambiguation rules.
## In the Real World
Khalti’s Transaction Validation
- Uses PDAs to parse nested JSON/XML requests (e.g.,
{"user": {"payment": {"amount": 1000}}}). - The stack ensures balanced tags (like
aⁿbⁿbut for<?xml>...</xml>).
- Uses PDAs to parse nested JSON/XML requests (e.g.,
Daraz’s Order Processing Queue
- CFGs model order states:
Order → Placed → Shipped → Delivered. - Ambiguity is avoided by strict production rules (e.g.,
Shipped → Deliveredonly afterPaymentConfirmed).
- CFGs model order states:
Ncell’s USSD Menu Parser
- Top-down parsing handles nested menus:
Main → Balance → *123# → Check → *123*1# → Display - PDAs validate input sequences (e.g., reject
*123*2#if2is invalid).
- Top-down parsing handles nested menus:
## Exam Tip
For CFG Simplification:
- Always remove unit productions first, then useless symbols.
- Mark steps clearly (e.g., "After Step 2, is non-generating").
For PDA Design:
- Label transitions with stack operations (e.g., "Push ").
- Test edge cases: Empty string, single symbol, and maximum stack depth.
For Pumping Lemma Proofs:
- Pick the "worst-case" string (e.g., ).
- Show why pumping fails (e.g., unbalanced counts).
Ambiguity Questions:
- Draw parse trees for the given string to prove ambiguity.
- Suggest fixes (e.g., add precedence rules).
Visual Summary:
mindmap
root((Pushdown Automata & CFGs))
CFG
Definition
Simplification
Ambiguity
PDA
Stack Operations
Epsilon Transitions
Design Steps
Parsing
Top-Down
Bottom-Up
Proofs
Pumping Lemma
Non-CFL ExamplesBased on the PU BE Computer (PU) syllabus for Theory of Computation, unit 3.
Discussion
Loading…