Skip to content
Part IA Michaelmas, Lent Term

Compiling Regular Expressions to NFA

Overview

We construct an NFA-ε\varepsilon for each regular expression by induction on the structure of the regex.

Each construction maintains the invariant that:

  • The NFA has exactly one start state (no incoming ε\varepsilon-transitions)
  • The NFA has exactly one accepting state (no outgoing ε\varepsilon-transitions)

This modular approach enables clean composition.

Base Cases

Epsilon: ε\varepsilon

NFA with one state that is both start and accepting.

NFA for epsilon

q\xrightarrow{\quad} \textcircled{\scriptstyle q}

L(Mε)={ε}L(M_\varepsilon) = \{\varepsilon\}

Empty: \emptyset

NFA with one state, start but not accepting.

NFA for empty set

q\xrightarrow{\quad} q

L(M)=L(M_\emptyset) = \emptyset

Symbol: aa

NFA with two states with a single aa-labelled transition.

NFA for symbol a

q0aq1\xrightarrow{\quad} q_0 \xrightarrow{a} \textcircled{\scriptstyle q_1}

L(Ma)={a}L(M_a) = \{a\}

Union: R1R2R_1 | R_2

Construction

  1. Create new start state qsq_s
  2. Create new accepting state qfq_f
  3. Add ε\varepsilon-transitions:
    • qsεstart(M1)q_s \xrightarrow{\varepsilon} \text{start}(M_1)
    • qsεstart(M2)q_s \xrightarrow{\varepsilon} \text{start}(M_2)
    • accept(M1)εqf\text{accept}(M_1) \xrightarrow{\varepsilon} q_f
    • accept(M2)εqf\text{accept}(M_2) \xrightarrow{\varepsilon} q_f

NFA construction for union

Properties

  • Number of states: M1+M2+2|M_1| + |M_2| + 2
  • Linear in regex size

Concatenation: R1R2R_1 R_2

Construction

  1. Add ε\varepsilon-transition from accept(M1)\text{accept}(M_1) to start(M2)\text{start}(M_2)
  2. Start state: start(M1)\text{start}(M_1)
  3. Accepting state: accept(M2)\text{accept}(M_2)

NFA construction for concatenation

Properties

  • Number of states: M1+M2|M_1| + |M_2|
  • No new states added

Kleene Star: RR^*

Construction

  1. Create new start/accepting state q0q_0
  2. Add ε\varepsilon-transition q0εstart(M)q_0 \xrightarrow{\varepsilon} \text{start}(M)
  3. Add ε\varepsilon-transition from accept(M)\text{accept}(M) to start(M)\text{start}(M) (loop)
  4. Add ε\varepsilon-transition from accept(M)\text{accept}(M) to q0q_0
  5. q0q_0 is the new accepting state

NFA construction for Kleene star

Alternative Construction

Some presentations use:

  • q0q_0 is start, εstart(M)\varepsilon \to \text{start}(M)
  • Accepting states include accept(M)\text{accept}(M) and a new state
  • Loop back from accept(M)\text{accept}(M) to start(M)\text{start}(M)

Properties

  • Number of states: M+1|M| + 1
  • Accepts ε\varepsilon and any concatenation of strings from L(M)L(M)

Size Analysis

Number of States

For regex RR of size nn (number of symbols and operators):

MR=O(n)|M_R| = O(n)

The Thompson construction builds NFAs with at most 2n2n states.

Comparison to DFA

The equivalent DFA may have up to 2MR2^{|M_R|} states.

The exponential blowup is unavoidable in the worst case.

Correctness

Theorem

For any regex RR, the construction produces NFA-ε\varepsilon MRM_R with L(MR)=L(R)L(M_R) = L(R).

Proof

By structural induction on RR.

Base cases: Direct verification for ε\varepsilon, \emptyset, and symbols.

Union: wL(MR1R2)w \in L(M_{R_1|R_2}) iff there is a path through M1M_1 or M2M_2. This happens iff wL(M1)w \in L(M_1) or wL(M2)w \in L(M_2), iff wL(R1)L(R2)=L(R1R2)w \in L(R_1) \cup L(R_2) = L(R_1 | R_2).

Concatenation: wL(MR1R2)w \in L(M_{R_1 R_2}) iff we can split w=uvw = uv with path through M1M_1 on uu then through M2M_2 on vv. This happens iff uL(R1)u \in L(R_1) and vL(R2)v \in L(R_2), iff wL(R1)L(R2)w \in L(R_1) \cdot L(R_2).

Star: Similar analysis using the fact that the construction accepts ε\varepsilon and any concatenation of strings from L(M)L(M).


Summary

  • Thompson’s construction: linear-size NFA for any regex
  • Union: new start with ε\varepsilon-edges to both branches
  • Concatenation: ε\varepsilon-edge from accept of first to start of second
  • Star: new start/accept with loop back
  • Total states: O(R)O(|R|) where R|R| is regex size