G27
Self-checkedTier 1 11 min readtoc.cfg-normal-forms

Simplification, CNF and GNF

Simplifying context-free grammars (removing epsilon-productions, unit productions and useless symbols, in the right order), Chomsky normal form (every production A -> BC or A -> a) and Greibach normal form (every production A -> a followed by variables), the conversion procedure with a stage-by-stage example, derivation lengths (2n - 1 steps in CNF, n in GNF), and the CYK membership algorithm with its table.

Why it exists

Arbitrary grammars are messy: empty right sides, chains of unit productions, variables that go nowhere. For proofs and algorithms one wants a standard shape. Chomsky normal form (CNF) makes every parse tree binary, which gives the CYK membership algorithm and the pumping lemma for context-free languages. Greibach normal form (GNF) makes every production start with a terminal, so a derivation of a string of length nn takes exactly nn steps and a pushdown automaton can run without ε\varepsilon-moves. GATE asks for the conversion steps, the number of productions or steps, and CYK tables.

Prerequisites

You need grammars, derivations and parse trees (context-free grammars).

Precise definitions

A grammar is in Chomsky normal form if every production has one of the forms

A→B C(B,C variables),A→a(a a terminal),A \to B\,C \quad (B, C \text{ variables}), \qquad A \to a \quad (a \text{ a terminal}),

and, only if ε∈L\varepsilon \in L, the single production S→εS \to \varepsilon with SS not occurring on any right side. A grammar is in Greibach normal form if every production is A→a αA \to a\,\alpha with aa a terminal and α\alpha a (possibly empty) string of variables.

Theorem. Every CFL has a grammar in CNF and a grammar in GNF (apart from the empty string). The conversion below produces grammars for L(G)∖{ε}L(G) \setminus \{\varepsilon\}; if ε∈L(G)\varepsilon \in L(G) add a new start variable S0S_0 with S0→S∣εS_0 \to S \mid \varepsilon.

Terms:

  • a variable is nullable if A⇒∗εA \Rightarrow^* \varepsilon;
  • a unit production is A→BA \to B with BB a variable;
  • a variable is generating if it derives some terminal string, and reachable if it occurs in a sentential form derivable from SS; a variable that is not both is useless.

How it works

Simplification steps

  1. Eliminate ε\varepsilon-productions. Find the nullable variables (iterate: AA is nullable if it has a production whose right side consists only of nullable variables). For every production, add all variants obtained by deleting any subset of nullable symbols from its right side, and delete all A→εA \to \varepsilon (never add an empty right side). This can create unit productions.
  2. Eliminate unit productions. For every pair (A,B)(A, B) with A⇒∗BA \Rightarrow^* B using unit productions only, give AA every non-unit production of BB; then delete all unit productions.
  3. Eliminate useless symbols, in this order: first remove variables that are not generating (and every production using them), then remove variables that are not reachable from the start symbol. The order matters: in S→AB∣aS \to AB \mid a, A→bA \to b, B→BbB \to Bb the variable BB is not generating; removing it deletes S→ABS \to AB and leaves AA unreachable. Removing unreachable symbols first finds nothing (all three are reachable) and then keeps A→bA \to b as a useless leftover (checked by program).

Other orders of steps 1 to 3 can reintroduce what an earlier step removed; the order above (epsilon, then unit, then useless) is safe.

Chomsky normal form

After steps 1 to 3 every right side has length at least 11, and length 11 only for a terminal. Then:

  1. Terminals: in every right side of length at least 22, replace each terminal aa by a new variable CaC_a and add Ca→aC_a \to a.
  2. Long right sides: replace A→B1B2⋯BkA \to B_1 B_2 \cdots B_k (k≥3k \ge 3) by A→B1D1A \to B_1 D_1, D1→B2D2D_1 \to B_2 D_2, …\ldots, Dk−2→Bk−1BkD_{k-2} \to B_{k-1} B_k with new variables DiD_i.

The table runs the whole conversion on one grammar that has an ε\varepsilon-production (A→εA \to \varepsilon), a chain of unit productions (S→C→DS \to C \to D), a non-generating variable (D→DdD \to Dd) and an unreachable variable (EE):

Conversion to Chomsky normal form, stage by stage: start

Computed by a script, not typed
stageproductionsnumber of productionsChomsky normal form?
original
after removing epsilon productions
after removing unit productions
after removing useless symbols
after replacing terminals in long right sides
after splitting long right sides (Chomsky normal form)

Step 0

The six stages of the conversion in the order epsilon, unit, useless, terminals, long right sides. The language is the same at every stage (checked up to length 10).

0 / 6
computed by script: the machine is simulated or the sets are constructed by scripts/toc_lib.py, one step at a time. python3 scripts/gen-toc3-traces.py

Each stage was checked to generate the same language (without ε\varepsilon) on all strings up to length 1010.

Facts about CNF.

  • The parse tree of a string of length nn is binary: nn leaves, n−1n - 1 internal nodes with two children and nn internal nodes with one leaf child. Every derivation has exactly 2n−12n - 1 steps (n−1n - 1 of the form A→BCA \to BC and nn of the form A→aA \to a).
  • Example: for aabbaabb the grammar S→AC∣ABS \to AC \mid AB, C→SBC \to SB, A→aA \to a, B→bB \to b needs 2⋅4−1=72 \cdot 4 - 1 = 7 steps.

Greibach normal form

Start from a CNF grammar. Number the variables A1,…,AmA_1, \ldots, A_m. For i=1,…,mi = 1, \ldots, m: (a) substitute, in Ai→AjγA_i \to A_j \gamma with j<ij < i, every production of AjA_j; (b) if AiA_i is now left recursive (Ai→AiγA_i \to A_i \gamma), remove the left recursion with a new variable ZiZ_i (as in LL(1) preparation). At the end every production of AiA_i starts with a terminal or with AjA_j, j>ij > i; substitute backwards from AmA_m down to A1A_1 so that every right side starts with a terminal, then do the same for the new variables ZiZ_i. The tail of each right side consists of variables because the starting grammar had terminals only in A→aA \to a.

Example: S→Sa∣bS \to S a \mid b (generates ba∗b a^*) becomes S→b∣bBS \to b \mid b B, B→a∣aBB \to a \mid a B. Every derivation of a string of length nn has exactly nn steps, because every step produces one terminal at the front (checked on the examples and on random grammars).

The GNF of a big grammar can be much larger than the grammar (for the expression grammar the result has dozens of productions); the exam asks it only for tiny grammars.

The CYK algorithm

CYK decides whether w=w1⋯wn∈L(G)w = w_1 \cdots w_n \in L(G) for a grammar in CNF. Let T[i,ℓ]T[i, \ell] be the set of variables that derive the substring of length ℓ\ell that starts at position ii.

  • Length 11: A∈TA \in T iff A→wiA \to w_i is a production.
  • Length ℓ≥2\ell \ge 2: A∈T[i,ℓ]A \in T[i, \ell] iff there is a production A→BCA \to B C and a split kk (so 1≤k<ℓ1 \le k < \ell) with B∈T[i,k]B \in T[i, k] and C∈T[i+k,ℓ−k]C \in T[i + k, \ell - k].
  • w∈Lw \in L iff S∈T[1,n]S \in T[1, n].

The table has n(n+1)/2n(n + 1)/2 cells, each needs up to n−1n - 1 splits and each split looks at all productions: time O(n3∣G∣)O(n^3 |G|) (textbook statement; the cell and split counts are n(n+1)/2n(n + 1)/2 and (n−1)n(n+1)/6(n - 1)n(n + 1)/6, checked for n=7n = 7).

For S→AC∣ABS \to AC \mid AB, C→SBC \to SB, A→aA \to a, B→bB \to b (the language anbna^n b^n, n≥1n \ge 1):

CYK algorithm on aabb: start

Computed by a script, not typed
  1. 1S → A C
  2. 2S → A B
  3. 3C → S B
  4. 4A → a
  5. 5B → b
start \ lengthlength 1length 2length 3length 4
start 1 (a)
start 2 (a)
start 3 (b)
start 4 (b)

Step 0

CYK table for the string aabb and the grammar in Chomsky normal form. The cell (start i, length l) will hold the variables that derive the substring of length l starting at position i. Cells of length 1 come from A → a and B → b; a longer cell is filled by trying every split into two shorter pieces.

0 / 11
computed by script: the machine is simulated or the sets are constructed by scripts/toc_lib.py, one step at a time. python3 scripts/gen-toc3-traces.py

The top cell contains SS: aabbaabb is generated. With one more bb the top cell does not contain SS:

CYK algorithm on aabbb: start

Computed by a script, not typed
  1. 1S → A C
  2. 2S → A B
  3. 3C → S B
  4. 4A → a
  5. 5B → b
start \ lengthlength 1length 2length 3length 4length 5
start 1 (a)
start 2 (a)
start 3 (b)
start 4 (b)
start 5 (b)

Step 0

CYK table for the string aabbb and the grammar in Chomsky normal form. The cell (start i, length l) will hold the variables that derive the substring of length l starting at position i. Cells of length 1 come from A → a and B → b; a longer cell is filled by trying every split into two shorter pieces.

0 / 16
computed by script: the machine is simulated or the sets are constructed by scripts/toc_lib.py, one step at a time. python3 scripts/gen-toc3-traces.py

Worked examples

EX 1Nullable variables

Easy

S→AB∣aBS \to AB \mid aB, A→aA∣εA \to aA \mid \varepsilon, B→bB∣εB \to bB \mid \varepsilon. AA and BB are nullable (they have ε\varepsilon productions), so S→ABS \to AB is nullable too: SS is nullable, and ε∈L\varepsilon \in L.

EX 2Eliminate epsilon productions

Easy

For the grammar above the result is S→AB∣A∣B∣aB∣aS \to AB \mid A \mid B \mid aB \mid a, A→aA∣aA \to aA \mid a, B→bB∣bB \to bB \mid b (the productions A→εA \to \varepsilon, B→εB \to \varepsilon are gone; S→ABS \to AB gave the copies AA, BB and, with both deleted, nothing). The new grammar generates L∖{ε}L \setminus \{\varepsilon\}; to keep ε\varepsilon add T→S∣εT \to S \mid \varepsilon with a new start variable TT.

EX 3Complete conversion to CNF

Medium

Continue: remove units (S→AS \to A, S→BS \to B): S→AB∣aB∣a∣aA∣bB∣bS \to AB \mid aB \mid a \mid aA \mid bB \mid b. No useless symbols. Replace terminals in right sides of length 22: a→Ca \to C, b→Db \to D (C→aC \to a, D→bD \to b): S→AB∣CB∣a∣CA∣DB∣bS \to AB \mid CB \mid a \mid CA \mid DB \mid b, A→CA∣aA \to CA \mid a, B→DB∣bB \to DB \mid b, C→aC \to a, D→bD \to b. All right sides now have length at most 22, so no splitting is needed: this is in CNF with 1212 productions (the original grammar had 66: removing ε\varepsilon and units made it larger).

EX 4CYK by hand

Medium

Grammar S→AC∣ABS \to AC \mid AB, C→SBC \to SB, A→aA \to a, B→bB \to b, string aabbaabb. Length 11: a,a→{A}a, a \to \{A\}, b,b→{B}b, b \to \{B\}. Length 22: aaaa: nothing (AAAA is not a right side); abab: S→ABS \to AB gives SS; bbbb: nothing. Length 33: aabaab = a∣aba \mid ab: AA and SS give ASA S, no production; aa∣baa \mid b: empty; nothing. abbabb = a∣bba \mid bb: empty; ab∣bab \mid b: S,BS, B give C→SBC \to SB: {C}\{C\}. Length 44: aabbaabb = a∣abba \mid abb: A,CA, C give S→ACS \to AC: SS. So S∈TS \in T: accepted. The program's table agrees cell by cell.

EX 5Typical questions

GATE level

(a) "A CNF grammar generates a string of length nn; how many derivation steps?" 2n−12n - 1. (b) "Number of steps in GNF?" nn. (c) "Which normal form has every production A→BCA \to BC or A→aA \to a?" Chomsky. (d) "Maximum number of CYK cells for a string of length 88?" 8⋅9/2=368 \cdot 9 / 2 = 36. (e) "Is every CFL generated by a CNF grammar?" Yes except that ε\varepsilon needs the special production S→εS \to \varepsilon. (f) "Order of simplification?" epsilon, units, useless (non-generating before unreachable). (g) "Is the simplified grammar always smaller?" No: removing ε\varepsilon-productions and units can increase the number of productions (above: 66 to 1212).

Cheat box

Cheat box

  • Simplify in this order: remove ε\varepsilon-productions, then unit productions, then useless symbols (non-generating first, then unreachable).
  • CNF: A→BCA \to BC or A→aA \to a (and S→εS \to \varepsilon if needed): parse trees binary, derivation of ww has 2∣w∣−12|w| - 1 steps.
  • GNF: A→aαA \to a\alpha with α\alpha variables: derivation of ww has ∣w∣|w| steps.
  • CYK: O(n3∣G∣)O(n^3 |G|), n(n+1)/2n(n + 1)/2 cells, S∈T[1,n]S \in T[1, n] means accepted.
  • Normal forms generate L∖{ε}L \setminus \{\varepsilon\}; add S0→S∣εS_0 \to S \mid \varepsilon for ε\varepsilon.

Traps and GATE patterns

Connections

CNF is the basis of the pumping lemma for CFLs (pumping lemma for CFLs); GNF gives PDAs without ε\varepsilon-moves (PDA and CFG); the left-recursion removal used for GNF is the same as in LL(1) parsing (grammar transformations in compilers).

PYQs

1 previous year question from your book. I re-solved each one myself (1 by running or simulating, 0 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2024 · Set 1 · NAT · 2 marksQ9 · page 226 of the book
Let G = (V, Σ, S, P) be a context-free grammar in
Chomsky Normal Form with Σ = {a, b, c} and V
containing 10 variable symbols including the start
symbol S. The string w = a30b30c 30 is derivable from S.
The number of steps (application of rules) in the
derivation S →* w is _________

Self-check

Question 1

A grammar in CNF generates a string of length 99. How many derivation steps does it take?

Show answer

2⋅9−1=172 \cdot 9 - 1 = 17.

Question 2

Which variables are nullable in S→ABS \to AB, A→ε∣aA \to \varepsilon \mid a, B→A∣bB \to A \mid b?

Show answer

AA (directly), BB (through B→AB \to A), and SS (since AA and BB are nullable).

Question 3

How many cells does CYK fill for a string of length 66?

Show answer

6⋅7/2=216 \cdot 7 / 2 = 21.

Question 4

Put S→aSb∣abS \to aSb \mid ab into CNF.

Show answer

S→AC∣ABS \to AC \mid AB, C→SBC \to SB, A→aA \to a, B→bB \to b.

Revision card

One-screen revision

  • Order: ε\varepsilon, units, useless (non-generating first), then terminals and splitting.
  • CNF A→BC∣aA \to BC \mid a: 2n−12n - 1 steps. GNF A→aαA \to a\alpha: nn steps.
  • CYK: fill by length; SS in the top cell; O(n3)O(n^3).
  • ε\varepsilon handled by S0→S∣εS_0 \to S \mid \varepsilon.

References

  • ·Sipser, Introduction to the Theory of Computation (3rd edition), Section 2.1 (Chomsky normal form, Theorem 2.9)
  • ·Hopcroft, Motwani, Ullman, Introduction to Automata Theory, Languages, and Computation (3rd edition), Section 7.1 (normal forms), Section 7.4.4 (the CYK algorithm)

Verification

scripts/enum-checks/toc_cfg.py: on 300 random grammars with epsilon productions, unit productions and useless symbols every stage of the conversion (epsilon, unit, useless, terminals, binarisation) generates the same language minus the empty string on all strings up to length 8; the result is in Chomsky normal form and every derivation of a string of length n takes exactly 2n - 1 steps (dynamic programming over spans, strings up to length 7); the CYK cell for every substring equals the set of variables that derive it (checked against the languages of the single variables); Greibach conversion (217 of the random grammars were small enough to test) gives productions starting with a terminal followed by variables, the same language, and derivations of exactly n steps; the worked grammars were recomputed; the order of removing useless symbols was shown to matter on S -> AB | a, A -> b, B -> Bb. Running times of the algorithms are textbook statements, quoted. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (state counts, derivations, parse-tree and move counts, decomposition counts); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never