7.3 Grammar Simplification & Normal Forms: Chomsky (CNF) & Greibach (GNF)
💡 Core Intuition: The Standardized Modular Assembly Line
In manufacturing, if every car model were assembled using screws, bolts, and hinges of completely arbitrary lengths and shapes, automated assembly robots would be impossible to build. Every tool would require a custom gripper.
To solve this, industrial manufacturing relies on strict geometric standardization: every fastener must be one of two standard shapes: a binary bracket or an atomic pin.
In formal language theory, an unconstrained Context-Free Grammar is similarly messy:
- Some rules might generate nothing at all (useless dead-ends).
- Some rules might loop infinitely between variables without making progress ().
- Some rules might erase symbols into thin air ().
- Other rules might have 15 variables and terminals jumbled together ().
To enable high-speed algorithmic parsing, we subject the grammar to two mathematical standardization processes:
- Grammar Simplification: Purge all dead-ends, null erasures, and redundant daisy-chained aliases.
- Normal Forms: Transform every remaining production rule into one of two canonical shapes:
- Chomsky Normal Form (CNF): Every rule is strictly binary () or atomic ().
- Greibach Normal Form (GNF): Every rule consumes exactly one terminal token upfront ().
🍳 The Everyday Analogy: Cleaning & Organizing the Kitchen
Imagine an apprentice chef following a messy recipe binder:
- Useless Steps: "Step 4: Go to the roof and check the weather." This step has zero connection to cooking the soup. We delete it.
- Redundant Renaming (Unit Rules): "Step 7: Pour the broth into Container B. Step 8: Pour Container B into Container C." Why use two bowls? Just pour directly into Container C!
- Empty Work (Null Productions): "Step 12: Add 0 grams of invisible salt." Doing nothing just clutters the instructions.
Once you eliminate useless detours, empty steps, and redundant transfers, you can standardize every cooking step into a fixed 2-ingredient mix. That is Chomsky Normal Form.
💻 Bridging to Computer Science
In compiler engineering and computational biology, parsing an arbitrary CFG string of length via naive brute-force backtracking takes exponential time .
However, when a grammar is transformed into Chomsky Normal Form (CNF):
- Every parse tree becomes a strictly binary tree.
- Deriving a string of length requires exactly derivation steps.
- The Cocke-Younger-Kasami (CYK) Algorithm can parse any string in deterministic polynomial time:
When a grammar is transformed into Greibach Normal Form (GNF):
- Every derivation step produces exactly one terminal symbol.
- Deriving a string of length takes exactly steps.
- GNF maps directly to real-time Pushdown Automata (PDA) transitions, where reading one input token pops a variable and pushes replacement symbols onto the stack without stalling.
📑Table of Contents
- 🧹 The 3-Phase Grammar Simplification Pipeline
- 💨 Phase 1: Elimination of ε-Productions
- 🔗 Phase 2: Elimination of Unit Productions
- 🗑️ Phase 3: Elimination of Useless Symbols
- 🏛️ Chomsky Normal Form (CNF)
- 📐 Mathematical Invariants of Chomsky Normal Form
- ⚡ Greibach Normal Form (GNF)
- 🏭 Real-World Production Context: The CYK Algorithm & Bioinformatics
- 📐 Numerical Applications & Worked Examples
- 🎯 Exam & Interview Pitfall Check
🧹 The 3-Phase Grammar Simplification Pipeline
Before converting a CFG into any normal form, we must clean the grammar of all redundant and non-productive rules. This is achieved via a strict 3-phase elimination pipeline:
The 3-Phase Grammar Simplification Pipeline
The mathematically mandatory sequence for cleaning context-free grammars
Eliminate Epsilon Productions
Find all nullable variables (A ⇒* ε) and expand combinations without ε.
Eliminate Unit Productions
Remove single-variable aliases (A → B) by substituting B's productions directly into A.
Eliminate Useless Symbols
Prune non-generating variables first, then prune unreachable symbols from start symbol S.
The ordering of the simplification pipeline is ABSOLUTE and MANDATORY:
- -Productions FIRST
- Unit Productions SECOND
- Useless Symbols LAST
Why? Eliminating -productions can introduce new unit productions (e.g. with yields ). Eliminating unit productions can expose newly dead, non-generating, or unreachable symbols. Running useless symbol elimination last guarantees that the final simplified grammar contains zero dead or unreachable elements!
💨 Phase 1: Elimination of ε-Productions
A production of the form is called an -production (or null production). If the language does not contain the empty string , all -productions can be removed without changing the language.
Step 1: Identify Nullable Variables
A variable is nullable if .
- Base Case: Any variable with a direct production is nullable.
- Inductive Step: If there is a production where every is already determined to be nullable, then is also nullable.
- Repeat until no new nullable variables are discovered.
Step 2: Replace Productions
For each production :
- Form all possible productions by substituting for every subset of nullable variables in .
- If has occurrences of nullable variables, this produces up to new productions.
- Do not include the production .
Example:
Let .
- Nullable set: .
- From :
- Keep both:
- Remove :
- Remove :
- Remove both: (omit , or add if ).
- New productions: .
🔗 Phase 2: Elimination of Unit Productions
A production of the form where both is called a unit production. Unit productions merely rename non-terminals without generating terminal symbols.
Step 1: Compute the Unit Pairs
For each variable , find the set of all variables such that using only unit productions:
- By reflexivity, for every variable .
- If and , then (transitive closure).
Step 2: Construct the New Production Set
For each variable :
- For every :
- If is a non-unit production in the original grammar, add to the new grammar.
- Discard all unit productions .
Example:
Let .
- Non-unit productions: , , .
- Result:
🗑️ Phase 3: Elimination of Useless Symbols
A symbol is useful if there exists a derivation:
This requires two distinct conditions:
- Generating: must be able to derive a string of pure terminals: .
- Reachable: must be reachable from the start symbol: .
You MUST eliminate non-generating symbols first, and eliminate unreachable symbols second. If you reverse this order, eliminating a non-generating symbol may cause previously reachable symbols to become unreachable, leaving dead symbols in your grammar!
The Two Conditions of Useful Symbols
Why a symbol must satisfy both generation and reachability to survive in a minimal CFG
Generating Symbols
- •A symbol X is generating if X ⇒* w for some string of pure terminals w ∈ T*.
- •Algorithm: Mark all terminals as generating. Inductively mark variable A if A → α where all symbols in α are already generating.
- •Prune all non-generating variables and any production referencing them.
Reachable Symbols
- •A symbol X is reachable if S ⇒* α X β for some strings α, β ∈ (V ∪ T)*.
- •Algorithm: Mark start symbol S as reachable. Inductively mark all symbols appearing on the RHS of productions of reachable variables.
- •Prune all symbols and productions that were never reached from S.
🏛️ Chomsky Normal Form (CNF)
A Context-Free Grammar is in Chomsky Normal Form (CNF) if every production rule has one of two canonical forms:
The 2 Canonical Production Shapes of CNF
Strictly binary variable branching or solitary terminal production
Binary Variable Rule
A → BC- The RHS consists of EXACTLY TWO non-terminals: B, C ∈ V.
- Zero terminals permitted on the RHS of this rule.
- Creates a strictly binary bifurcation in the derivation parse tree.
Solitary Terminal Rule
A → a- The RHS consists of EXACTLY ONE terminal symbol: a ∈ T.
- Zero variables permitted on the RHS of this rule.
- Forms an atomic leaf node in the derivation parse tree.
(Note: If , the rule is permitted, provided does not appear on the RHS of any production).
Algorithmic Conversion from CFG to CNF
Given a simplified CFG with no -productions, unit productions, or useless symbols:
Step 1: Replace Terminals in Composite Rules
For every production whose RHS has length containing terminals:
- For each terminal , introduce a new variable and add the rule .
- In all composite productions, replace terminal with .
- Example: becomes , with and .
Step 2: Break Long Variable Chains into Binary Pairs
For every production whose RHS contains non-terminals:
Introduce new auxiliary variables and replace the production with the cascading binary sequence:
Now, every single production in the grammar is strictly of the form or !
📐 Mathematical Invariants of Chomsky Normal Form
The strictly binary nature of CNF yields two fundamental mathematical theorems:
Derivation Step Invariant (2n - 1)
Theorem: In any Chomsky Normal Form grammar, deriving a non-empty string of length requires exactly derivation steps.
Mathematical Proof:
- Let the target string have length .
- To produce a string of terminal symbols, we must eventually apply the rule exactly times (one for each terminal).
- In a CNF grammar, the number of non-terminals increases by only when a binary rule is applied.
- Starting from the single start symbol , to reach a sentential form containing non-terminals requires applying binary rules exactly times.
- Total derivation steps:
| String Length () | Binary Expansions () | Terminal Replacements () | Total Derivation Steps () |
|---|---|---|---|
| step | |||
| steps | |||
| steps | |||
| steps | |||
| steps |
Parse Tree Height & String Length Bounds
Let be the height (longest path length from root to leaf) of a parse tree in a CNF grammar:
- Because every internal node has at most 2 children, a tree of height can have at most leaves.
- For a string of length , the height must satisfy:
- Furthermore, in the worst-case degenerate (skewed) tree:
This property forms the mathematical bedrock of the Pumping Lemma for Context-Free Languages, proving that any sufficiently long string must repeat a variable along a deep path in the tree.
⚡ Greibach Normal Form (GNF)
A Context-Free Grammar is in Greibach Normal Form (GNF) if every production rule has the form:
Every production begins with strictly ONE terminal symbol, followed by zero or more non-terminals.
Chomsky Normal Form vs Greibach Normal Form
Comparing the two dominant canonical representations of context-free languages
Chomsky Normal Form (CNF)
- •Rule format: A → BC or A → a.
- •Parse tree is a strictly binary tree.
- •Derivation of string of length n requires exactly 2n - 1 steps.
- •Optimal for Cocke-Younger-Kasami (CYK) dynamic programming parsing.
Greibach Normal Form (GNF)
- •Rule format: A → a α (a ∈ T, α ∈ V*).
- •Every step consumes exactly one terminal token from the input.
- •Derivation of string of length n requires exactly n steps.
- •Direct 1-to-1 correspondence with Pushdown Automaton (PDA) stack operations.
PDA Equivalence with GNF
In Greibach Normal Form, each production corresponds directly to a Pushdown Automaton transition:
- When non-terminal is on top of the stack, reading terminal from the input pops and pushes the string onto the stack:
Because every rule consumes a terminal, a PDA built from a GNF grammar never executes an -transition, preventing infinite stack loops!
🏭 Real-World Production Context: The CYK Algorithm & Bioinformatics
Why do computer scientists spend so much effort converting grammars into Chomsky Normal Form? The primary production reason is the Cocke-Younger-Kasami (CYK) Algorithm.
The CYK Dynamic Programming Parsing Pipeline
How Chomsky Normal Form enables deterministic polynomial-time chart parsing
Target String (w)
Length n string: w = w₁ w₂ ... wₙ.
Terminal Cell Fill (Substring Len 1)
For each position i, find all variables A such that A → w_i ∈ P.
Binary Substring Combinations
For substring length l = 2..n, split at k: check if A → B C where B ∈ Table(i, k) and C ∈ Table(i+k, l-k).
Acceptance Check: S ∈ Table(1, n)
If start symbol S is in the top cell, output YES in O(n³ · |P|) time.
Industrial Applications of CNF & CYK Parsing
- Computational Biology (RNA Secondary Structure Prediction): RNA folding forms complex hairpin loops, bulges, and stems that are modeled as Context-Free Grammars. Algorithms like ViennaRNA and Infernal convert RNA stochastic CFGs into Chomsky Normal Form and use CYK dynamic programming to compute the minimum free energy structure of viral genomes (such as SARS-CoV-2).
- Natural Language Processing (Statistical Parsers): Early statistical NLP engines (such as the Stanford Parser) converted Penn Treebank grammars into CNF to run probabilistic CYK parsing, calculating the most likely grammatical parse tree for spoken English queries.
- Formal Verification of Network Protocols: Security tools convert packet layout grammar definitions into CNF to verify whether a packet capture stream matches a valid protocol specification without suffering combinatorial explosions.
📐 Numerical Applications & Worked Examples
Problem 1: Complete 3-Phase Grammar Simplification
Problem Statement:
Simplify the following CFG by systematically executing the 3-phase pipeline:
Step-by-Step Solution:
Phase 1: Eliminate ε-Productions
- Find nullable variables:
- is nullable.
- Can become nullable? . Since does not derive , is NOT nullable.
- Nullable set: .
- Replace rules containing :
- : Removing yields .
- : Unchanged.
- Discard .
- Result of Phase 1:
Phase 2: Eliminate Unit Productions
- Compute Unit sets for each variable:
- Non-unit productions available:
- From :
- From :
- From :
- From :
- Expand rules:
Phase 3: Eliminate Useless Symbols
- Generating Symbols:
- Terminals are generating.
- is generating.
- is generating.
- is generating.
- is generating.
- is generating.
- is generating.
- All variables are generating!
- Reachable Symbols from :
- is reachable.
- From :
- Symbols and terminals are directly reachable!
- What about and ?
- Neither nor appears on the RHS of any production originating from , or !
- Therefore, and are UNREACHABLE.
- Prune and :
This is the minimal, fully simplified grammar.
Problem 2: Algorithmic Conversion to Chomsky Normal Form (CNF)
Problem Statement:
Convert the following simplified grammar into Chomsky Normal Form:
Step-by-Step Solution:
Step 1: Replace Terminals in Composite Rules
Introduce auxiliary variables for terminals and :
Substitute and into all rules with length :
Step 2: Binarize Long Variable Chains
Binarizing (length 4): Introduce auxiliary variables and :
Binarizing (length 3): Introduce auxiliary variable :
Binarizing (length 3): Introduce auxiliary variable :
Step 3: Final Chomsky Normal Form Grammar
Every production is strictly of the form or . The grammar is in Chomsky Normal Form.
Problem 3: Derivation Step Invariant Verification
Problem Statement:
Using the CNF grammar obtained in Problem 2, verify the derivation step invariant for the terminal string (length ).
Step-by-Step Solution:
Step 1: Calculate Theoretical Bound
For :
Step 2: Trace the Leftmost Derivation
Step 3: Verification
Counting the individual derivation steps:
- Step 1: (Binary expansion 1)
- Step 2: (Terminal replacement 1)
- Step 3: (Binary expansion 2)
- Step 4: (Terminal replacement 2)
- Step 5: (Binary expansion 3)
- Step 6: (Terminal replacement 3)
- Step 7: (Terminal replacement 4)
Total steps = .
This confirms the invariant .
🎯 Exam & Interview Pitfall Check
- Why can't Chomsky Normal Form derive the empty string without an explicit exception?
Because every CNF rule either replaces a variable with two variables () or with a terminal (). Neither rule reduces the length of the string! Thus, starting from , the shortest string derivable is of length 1. To generate , formal theory permits adding , provided does not appear on the RHS of any production. - If a grammar has no -productions and no unit productions, does converting to CNF increase the language accepted?
No. The transformation to CNF is an exact language-preserving homomorphism. . - Why does Greibach Normal Form require eliminating left recursion ()?
In GNF, every rule must begin with a terminal (). If a production has left recursion (), it begins with a non-terminal , which directly violates the GNF definition. Converting to GNF requires eliminating immediate and indirect left recursion using auxiliary variables.
- Trap: Executing Useless Symbol Elimination Before Epsilon Elimination:
Never run useless symbol elimination first! Removing -productions or unit productions frequently makes previously useful symbols useless. Always execute Phase 3 (Useless Symbols) last. - Trap: Confusing Non-Generating with Unreachable Symbols:
A non-generating symbol is a variable that enters an infinite recursion without ever producing pure terminals (e.g. with no base case). An unreachable symbol is a valid rule that is simply disconnected from (e.g. where is never mentioned in any rule reachable from ). - Trap: Forgetting That CYK Parsing Requires CNF:
Students often attempt to run the CYK dynamic programming table on an arbitrary grammar. The CYK split step strictly relies on the binary decomposition . Without CNF, CYK cannot partition substrings into binary pairs!