Chapter 3 - Context-Free Languages

Updated 4 Oct 2026

Table of Contents

  1. Context Free Grammars (CFG)
  2. Regular Languages are Context-free
  3. Parse Trees
  4. Pushdown Automata
  5. Algorithmic Properties

1. Context Free Grammars (CFG)

Definition

A context-free grammar GG is a quadruple (V,Σ,R,S)(V, \Sigma, R, S) where:

  • VV is an alphabet (set of all symbols)
  • Σ\Sigma (the set of terminals) is a subset of VV
    • Terminal symbols are the actual characters in the language (e.g., a,b,x,+,∗a, b, x, +, *)
  • RR (the set of rules) is a finite subset of (V−Σ)×V∗(V - \Sigma) \times V^*
    • Rules define how non-terminals can be replaced
  • SS (the start symbol) is an element of V−ΣV - \Sigma
    • This is where all derivations begin

Key Components:

  • Non-terminals: Elements of V−ΣV - \Sigma (phrase types, variables)
    • These are symbols that can be further expanded
  • Terminals: Elements of Σ\Sigma (actual symbols in strings)

Analogy: Think of a CFG like a recipe. Non-terminals are instructions like "add filling," while terminals are actual ingredients like "sugar" and "flour." The start symbol is "make cake," and rules tell you how to break down each instruction into smaller steps or actual ingredients.

Grammar Rules and Derivations

Notation:

  • We write A→Gu\boxed{A \xrightarrow{G} u} for any rule (A,u)∈R(A, u) \in R
    • This means: "A generates u" or "A can be replaced by u"

Derivation:

  • For any strings ω,β∈V∗\omega, \beta \in V^*, we write ω⇒Gβ\boxed{\omega \underset{G}{\Rightarrow} \beta} if and only if:
    • There is a rule A→GuA \xrightarrow{G} u in RR
    • ω=xAy\omega = xAy (string with AA somewhere in it)
    • β=xuy\beta = xuy (same string but AA replaced with uu)

This means you can derive β\beta from ω\omega by replacing one non-terminal with its production rule.

Multi-step Derivation:

  • A sequence ω0⇒Gω1⇒G...⇒Gωn\omega_0 \underset{G}{\Rightarrow} \omega_1 \underset{G}{\Rightarrow} ... \underset{G}{\Rightarrow} \omega_n where n≥0n \geq 0 is called a derivation of ωn\omega_n from ω0\omega_0
  • We write ω⇒G∗β\boxed{\omega \underset{G}{\Rightarrow}^* \beta} if there exists a derivation for β\beta from ω\omega
    • The asterisk * means "zero or more steps"

Language Generated by G:
L(G)={ω∈Σ∗∣S⇒G∗ω}\boxed{L(G) = \{\omega \in \Sigma^* \mid S \underset{G}{\Rightarrow}^* \omega\}}

  • This is the set of all strings of terminal symbols that can be derived from the start symbol SS

Exam Tip: When showing derivations, work step-by-step and replace only ONE non-terminal at a time. Make sure your final result contains only terminal symbols.

Example: Grammar for Arithmetic Expressions

Consider grammar G=(V,Σ,R,E)G = (V, \Sigma, R, E) where:

Terminals: Σ={x,+,∗,(,)}\Sigma = \{x, +, *, (, )\}
Variables: V=Σ∪{T,E,F}V = \Sigma \cup \{T, E, F\}
Start Symbol: EE (Expression)

Rules RR:

E → E + T    (Expression can be Expression plus Term)
E → T        (Expression can be just a Term)
T → T * F    (Term can be Term times Factor)
T → F        (Term can be just a Factor)
F → (E)      (Factor can be parenthesized Expression)
F → x        (Factor can be variable x)

Real-world use: This grammar structure is used in compilers to parse mathematical expressions in programming languages. The hierarchy (Expression → Term → Factor) enforces operator precedence: multiplication before addition.


Derivation Examples

Example 1: Derive (x)(x)

E⇒T(using E→T)⇒F(using T→F)⇒(E)(using F→(E))⇒(T)(using E→T)⇒(F)(using T→F)⇒(x)(using F→x)\begin{align} E &\Rightarrow T && \text{(using } E \to T\text{)} \\ &\Rightarrow F && \text{(using } T \to F\text{)} \\ &\Rightarrow (E) && \text{(using } F \to (E)\text{)} \\ &\Rightarrow (T) && \text{(using } E \to T\text{)} \\ &\Rightarrow (F) && \text{(using } T \to F\text{)} \\ &\Rightarrow (x) && \text{(using } F \to x\text{)} \end{align}

Example 2: Derive (x+x)∗x(x + x) * x

E⇒T(R2)⇒T∗F(R3)⇒F∗F(R4)⇒(E)∗F(R5)⇒(E+T)∗F(R1)⇒(T+T)∗F(R2)⇒(F+T)∗F(R4)⇒(x+T)∗F(R6)⇒(x+F)∗F(R4)⇒(x+x)∗F(R6)⇒(x+x)∗x(R6)\begin{align} E &\Rightarrow T && \text{(R2)} \\ &\Rightarrow T * F && \text{(R3)} \\ &\Rightarrow F * F && \text{(R4)} \\ &\Rightarrow (E) * F && \text{(R5)} \\ &\Rightarrow (E + T) * F && \text{(R1)} \\ &\Rightarrow (T + T) * F && \text{(R2)} \\ &\Rightarrow (F + T) * F && \text{(R4)} \\ &\Rightarrow (x + T) * F && \text{(R6)} \\ &\Rightarrow (x + F) * F && \text{(R4)} \\ &\Rightarrow (x + x) * F && \text{(R6)} \\ &\Rightarrow (x + x) * x && \text{(R6)} \end{align}

Exam Strategy: Label which rule you're using at each step. This makes it easy for graders to follow your work and gives you partial credit even if you make a mistake later.


2. Regular Languages are Context-free

Theorem

Any regular language is context-free\boxed{\text{Any regular language is context-free}}

Relationship: RL⊆CFL\text{RL} \subseteq \text{CFL} (Regular Languages are a subset of Context-Free Languages)

This means CFGs are more powerful than regular expressions and finite automata. They can describe all regular languages PLUS more complex languages.

Proof (Converting FSA to CFG)

Given:

  • A regular language LL accepted by a deterministic finite automaton M=(K,Σ,δ,s,F)M = (K, \Sigma, \delta, s, F)

Construct:

  • A grammar G=(V,Σ,R,S)G = (V, \Sigma, R, S) as follows:

Construction:

  1. V=K∪ΣV = K \cup \Sigma (variables are the states plus terminals)
  2. Start symbol SS = initial state of the DFA
  3. Rules RR consist of:
    • P→aQ\boxed{P \to aQ} where δ(P,a)=Q\delta(P, a) = Q
      • For each transition from state PP to state QQ on symbol aa
    • P→ε\boxed{P \to \varepsilon} for P∈FP \in F
      • For each accepting state PP

Example Conversion:

FSA Transition:     Grammar Rule:
[P] --a--> [Q]  →   P → aQ
[P] is accepting →   P → ε

Intuition: Each state becomes a non-terminal. Each transition becomes a rule that "consumes" a symbol and moves to the next state. Accepting states have rules that allow the derivation to terminate.

Proof Sketch:
By induction, we can show:

(S,a1...an)⊢M(Q1,a2...an)⊢M⋯⊢M(Qn,ε)(S, a_1...a_n) \vdash_M (Q_1, a_2...a_n) \vdash_M \cdots \vdash_M (Q_n, \varepsilon)

if and only if

S⇒∗a1Q1⇒∗...⇒∗a1...anQnS \Rightarrow^* a_1Q_1 \Rightarrow^* ... \Rightarrow^* a_1...a_nQ_n

Therefore, for any string ω∈Σ∗\omega \in \Sigma^*:

  • ω∈L\omega \in L
  • ⟺ (S,ω)⊢M∗(P,ε)(S, \omega) \vdash_M^* (P, \varepsilon) and P∈FP \in F
  • ⟺ S⇒∗ωPS \Rightarrow^* \omega P and P→εP \to \varepsilon in RR
  • ⟺ S⇒∗ωS \Rightarrow^* \omega

Example CFGs for Non-Regular Languages

Example 1: L={anbn∣n≥0}L = \{a^nb^n \mid n \geq 0\}

This language is NOT regular (it requires counting/memory), but it IS context-free.

Grammar:

S → ab
S → aSb
S → ε

Derivation for aabbaabb:

S⇒aSb⇒aabbS \Rightarrow aSb \Rightarrow aabb

Real-world application: This pattern appears in matching opening and closing brackets in code: (), ((())), etc.

Example 2: L={anbncn∣n≥0}L = \{a^nb^nc^n \mid n \geq 0\}

This language is NOT context-free (requires counting two independent counters simultaneously).


3. Parse Trees (Derivation Trees)

Definition

A parse tree (or derivation tree) is a graphical representation of a derivation.

Structure:

  • Root: The start symbol or a non-terminal
  • Internal nodes: Non-terminal symbols
  • Leaves: Terminal symbols or ε\varepsilon
  • Yield: The string formed by reading leaves from left to right

Construction Rules for Parse Trees

Let G=(V,Σ,R,S)G = (V, \Sigma, R, S)

Rule 1: Terminal Symbols

For each a∈Σa \in \Sigma, the tree:

  a

is a parse tree with:

  • Root: aa
  • Only leaf: aa
  • Yield: aa

Rule 2: Epsilon Rules

If A→εA \to \varepsilon is a rule in GG, then:

  A
  |
  ε

is a parse tree with:

  • Root: AA
  • Only leaf: ε\varepsilon
  • Yield: ε\varepsilon

Rule 3: Multiple Children

If T1,T2,...,TnT_1, T_2, ..., T_n are parse trees (where n≥1n \geq 1) with:

  • Roots: A1,...,AnA_1, ..., A_n
  • Yields: y1,...,yny_1, ..., y_n

And A→A1...AnA \to A_1...A_n is a rule in RR, then:

      A
     /|\
    / | \
   A₁ A₂ Aₙ
   |  |  |
  T₁ T₂ Tₙ

is a parse tree with:

  • Root: AA
  • Leaves: All leaves of T1,...,TnT_1, ..., T_n
  • Yield: y1...yny_1...y_n

Parse Tree Examples

Example 1: Parse tree for (x)(x)

        E
        |
        T
        |
        F
       /|\
      ( E )
        |
        T
        |
        F
        |
        x

Yield: (x)(x)

Example 2: Grammar for {anbn}\{a^nb^n\}

Grammar:

S → ab
S → aSb

Parse tree for aaabbbaaabbb:

       S
      /|\
     a S b
      /|\
     a S b
      /|\
     a S b
       |
       ε

Yield: aaabbbaaabbb

Exam Tip: Always verify your parse tree by reading the leaves from left to right - this should give you your target string.


Key Lemma

Theorem: Let G=(V,Σ,R,S)G = (V, \Sigma, R, S) be a context-free grammar, A∈V−ΣA \in V - \Sigma, and ω∈Σ∗\omega \in \Sigma^*.

The following statements are logically equivalent:

  1. A⇒G∗ω\boxed{A \underset{G}{\Rightarrow}^* \omega}
  2. There exists a parse tree with root AA and yield ω\omega

This means: Derivations and parse trees are two ways of representing the same thing. A derivation is the "process" and a parse tree is the "structure."


4. Left-most and Right-most Derivations

Left-most Derivation

Definition: We write x⇒Lyx \underset{L}{\Rightarrow} y if the non-terminal symbol being replaced is the leftmost non-terminal in the string.

  • x=ωAβx = \omega A\beta
  • y=ωuβy = \omega u\beta
  • where ω∈Σ∗\omega \in \Sigma^*, β∈V∗\beta \in V^*, and A→uA \to u is a rule in RR

Form: x1⇒Lx2⇒L...⇒Lxnx_1 \underset{L}{\Rightarrow} x_2 \underset{L}{\Rightarrow} ... \underset{L}{\Rightarrow} x_n

Example: E⇒L...⇒L(x+x)∗xE \underset{L}{\Rightarrow} ... \underset{L}{\Rightarrow} (x+x)*x

E⇒LT⇒LT∗F⇒LF∗F⇒L(E)∗F⇒L(E+T)∗F⇒L(T+T)∗F⇒L(F+T)∗F⇒L(x+T)∗F⇒L(x+F)∗F⇒L(x+x)∗F⇒L(x+x)∗x\begin{align} E &\underset{L}{\Rightarrow} T \\ &\underset{L}{\Rightarrow} T * F \\ &\underset{L}{\Rightarrow} F * F \\ &\underset{L}{\Rightarrow} (E) * F \\ &\underset{L}{\Rightarrow} (E+T) * F \\ &\underset{L}{\Rightarrow} (T+T) * F \\ &\underset{L}{\Rightarrow} (F+T) * F \\ &\underset{L}{\Rightarrow} (x+T) * F \\ &\underset{L}{\Rightarrow} (x+F) * F \\ &\underset{L}{\Rightarrow} (x+x) * F \\ &\underset{L}{\Rightarrow} (x+x) * x \end{align}

Right-most Derivation

Definition: We write x⇒Ryx \underset{R}{\Rightarrow} y if the non-terminal symbol being replaced is the rightmost non-terminal in the string.

  • x=ωAβx = \omega A\beta
  • y=ωuβy = \omega u\beta
  • where β∈Σ∗\beta \in \Sigma^*, ω∈V∗\omega \in V^*, and A→uA \to u is a rule in RR

Form: x1⇒Rx2⇒R...⇒Rxnx_1 \underset{R}{\Rightarrow} x_2 \underset{R}{\Rightarrow} ... \underset{R}{\Rightarrow} x_n

Example: E⇒R...⇒R(x+x)∗xE \underset{R}{\Rightarrow} ... \underset{R}{\Rightarrow} (x+x)*x

Key Insight: The ORDER of applying derivation rules doesn't matter for the final result, but it creates a different "path" through the derivation. Left-most and right-most are standard conventions used by parsers.


Equivalence Theorem

Theorem: Let G=(V,Σ,R,S)G = (V, \Sigma, R, S) be a context-free grammar, A∈V−ΣA \in V - \Sigma, and ω∈Σ∗\omega \in \Sigma^*.

The following statements are equivalent:

  1. A⇒G∗ω\boxed{A \underset{G}{\Rightarrow}^* \omega} (some derivation exists)
  2. There is a parse tree with root AA and yield ω\omega
  3. A⇒L∗ω\boxed{A \underset{L}{\Rightarrow}^* \omega} (left-most derivation exists)
  4. A⇒R∗ω\boxed{A \underset{R}{\Rightarrow}^* \omega} (right-most derivation exists)

Meaning: No matter which order you apply the rules (left-most, right-most, or random), you'll get the same parse tree and same final string. The derivation path differs, but the result is the same.

Exam Application: You can choose whichever derivation order is easiest for you! Left-most is often more intuitive.


5. Ambiguity

Ambiguous vs Unambiguous Grammars

Let Σ={x,+,∗,(,)}\Sigma = \{x, +, *, (, )\}. Consider two grammars for the same language:

Grammar G₁ (Unambiguous)

V₁ = Σ ∪ {T, F, E}
R₁ = {
    E → E + T
    E → T
    T → T * F
    T → F
    F → (E)
    F → x
}

Property: For each string ω∈L(G1)\omega \in L(G_1), there is exactly one parse tree that yields ω\omega.

Parse tree for x+x∗xx + x * x:

        E
       /|\
      E + T
      |  /|\
      T T * F
      | |   |
      F F   x
      | |
      x x

This correctly shows that multiplication happens before addition.


Grammar G₂ (Ambiguous)

V₂ = Σ ∪ {E}
R₂ = {
    E → E + E
    E → E * E
    E → (E)
    E → x
}

Property: There are distinct parse trees yielding the same string.

Two different parse trees for x+x∗xx + x * x:

Tree 1 (multiplication first):

      E
     /|\
    E + E
    |  /|\
    x E * E
      |   |
      x   x

Tree 2 (addition first):

      E
     /|\
    E * E
   /|\  |
  E + E x
  |   |
  x   x

Problem: Ambiguity means the grammar doesn't uniquely determine how to parse an expression, leading to potential misinterpretation of meaning.


Definition of Ambiguity

A grammar GG is ambiguous if:
∃ω∈L(G) such that ω has more than one parse tree\boxed{\exists \omega \in L(G) \text{ such that } \omega \text{ has more than one parse tree}}

A grammar is unambiguous if:
∀ω∈L(G),ω has exactly one parse tree\boxed{\forall \omega \in L(G), \omega \text{ has exactly one parse tree}}

Real-world Impact: Programming language compilers need unambiguous grammars. Otherwise, the same code could be interpreted different ways, leading to bugs and security vulnerabilities.


Spotting Ambiguity

How to identify ambiguous grammars:

  1. Look for recursive rules on both sides:
    • E→E+EE \to E + E (both left and right are the same non-terminal)
    • This creates multiple ways to group operations
  2. Missing operator precedence rules:
    • When all operators are at the same level in the grammar
    • Example: E→E+E∣E∗EE \to E + E \mid E * E treats ++ and ∗* equally
  3. No associativity specification:
    • E→E+EE \to E + E doesn't specify left or right associativity
    • Can parse x+x+xx + x + x as (x+x)+x(x+x)+x or x+(x+x)x+(x+x)

Common culprits:

E → E + E       // Ambiguous (left or right associative?)
E → E * E       // Ambiguous (same issue)
E → (E)
E → x

How to fix:

E → E + T       // Unambiguous (forces left associativity for +)
E → T
T → T * F       // Unambiguous (forces left associativity for *)
T → F
F → (E)
F → x

The hierarchy E→T→FE \to T \to F enforces precedence: ∗* binds tighter than ++.

Exam Tip: If asked "What makes this grammar ambiguous?", look for rules like A→A∘AA \to A \circ A where the same non-terminal appears on both sides of an operator.


Summary & Key Takeaways

Context-Free Grammars

  • Definition: G=(V,Σ,R,S)G = (V, \Sigma, R, S)
    • More powerful than regular expressions
    • Can handle nested structures (balanced parentheses, etc.)

Key Relationships

  • Regular Languages ⊂ Context-Free Languages ⊂ All Languages
  • Any FSA can be converted to an equivalent CFG
  • Not all CFLs are regular (e.g., {anbn}\{a^nb^n\})

Derivations & Parse Trees

  • Derivation: Step-by-step application of rules
  • Parse Tree: Graphical representation of structure
  • Equivalence: Any derivation corresponds to exactly one parse tree (if unambiguous)

Left-most vs Right-most

  • Different paths to the same result
  • Useful for parser implementation
  • Don't affect final yield or parse tree structure

Ambiguity

  • Critical for compilers: Need unambiguous grammars
  • Detection: Look for symmetric recursion (E→E∘EE \to E \circ E)
  • Resolution: Introduce hierarchy and enforce precedence

Exam Tips Summary

  1. For derivations: Work step-by-step, label rules used
  2. For parse trees: Verify yield by reading leaves left-to-right
  3. For ambiguity questions: Look for recursive rules and lack of precedence
  4. For conversions: FSA → CFG is straightforward (states become non-terminals)
  5. Time management: Start with simpler derivations, come back to complex ones

Real-World Applications

Compilers & Programming Languages

  • Parsing source code syntax
  • Enforcing operator precedence
  • Checking balanced brackets, parentheses

Natural Language Processing

  • Parsing sentence structure
  • Grammar checking
  • Machine translation

Data Formats

  • XML/HTML parsing
  • JSON validation
  • Configuration file parsing

Protocol Design

  • Network protocol specification
  • API definition languages
  • Communication format standards

Additional Practice Problems

Problem 1

Design a CFG for L={aibjck∣i=j or j=k}L = \{a^ib^jc^k \mid i = j \text{ or } j = k\}

Problem 2

Prove that L={anbncn∣n≥0}L = \{a^nb^nc^n \mid n \geq 0\} is NOT context-free (requires Pumping Lemma for CFLs)

Problem 3

Convert the following NFA to a CFG:

  • States: {q0,q1}\{q_0, q_1\}
  • Initial: q0q_0
  • Accepting: {q1}\{q_1\}
  • Transitions: δ(q0,a)=q1\delta(q_0, a) = q_1, δ(q1,b)=q1\delta(q_1, b) = q_1

Problem 4

Show that the following grammar is ambiguous and provide an unambiguous equivalent:

S → aSb | SS | ε