CD Notes
How finite automata (DFA and NFA) are used in lexical analysis to implement pattern matching for token recognition in compilers.
Introduction
Finite automata are the computational model underlying lexical analysis. Every regular expression (used to define token patterns) can be converted into a finite automaton that recognizes exactly the same set of strings. The lexical analyzer is essentially a collection of finite automata running in parallel, each trying to match a different token pattern.
Types of Finite Automata
Nondeterministic Finite Automaton (NFA)
An NFA is defined as a 5-tuple: N = (Q, Σ, δ, q₀, F) where:
- Q = finite set of states
- Σ = input alphabet
- δ = transition function: Q × (Σ ∪ {ε}) → P(Q)
- q₀ = start state
- F = set of accepting (final) states
NFAs can have:
- Multiple transitions on the same input from a state
- ε-transitions (transitions without consuming input)
Deterministic Finite Automaton (DFA)
A DFA is defined as a 5-tuple: D = (Q, Σ, δ, q₀, F) where:
- δ = transition function: Q × Σ → Q (exactly one transition per input)
- No ε-transitions allowed
- Exactly one next state for each state-input pair
NFA for Token Recognition
Thompson's Construction
Every regular expression can be converted to an NFA using Thompson's construction:
Base cases:
Concatenation (rs):
Alternation (r|s):
**Kleene Closure (r*):**
Example: NFA for (a|b)*abb
| ε ┌─a─ | 3 ─ε─┐ ε |
| ─ | 0 ─ε─→ 1 ──┤ ├──→ 2 ─ε─→ 1 (loop back) |
| └─b─ | 4 ─ε─┘ │ |
| 5 ─a─ | 6 ─b─→ 7 ─b─→ ((8)) |
Subset Construction: NFA to DFA
The subset construction algorithm converts an NFA to an equivalent DFA:
Algorithm
Example: Converting (a|b)*abb NFA to DFA
| From A on 'a' | move(A,a) = {3,6} |
| From A on 'b' | move(A,b) = {4} |
| From B on 'a': | State B |
| From B on 'b': | {1,2,3,4,5,7} = State D |
| From C on 'a': | State B |
| From C on 'b': | State C |
| From D on 'a': | State B |
| From D on 'b': | {1,2,3,4,5,8} = State E (accepting!) |
| From E on 'a': | State B |
| From E on 'b': | State C |
Resulting DFA:
DFA Minimization
Minimize the DFA by merging equivalent states:
Hopcroft's Algorithm
Implementation in Lexical Analyzer
Table-Driven DFA
Multiple Pattern Matching
In practice, the lexical analyzer combines multiple token patterns into a single DFA:
| ε | [NFA for identifiers] → accept(ID) |
| ε | [NFA for numbers] → accept(NUM) |
| ε | [NFA for operators] → accept(OP) |
| ε | [NFA for keywords] → accept(KW) |
Then convert to a single DFA where each accepting state knows which token it represents.
Comparison: NFA vs DFA for Lexical Analysis
| Aspect | NFA | DFA |
|---|---|---|
| Construction | Easier from regex | Requires subset construction |
| Size | O(n) states for regex of length n | Can be O(2^n) states (worst case) |
| Matching speed | Slower (multiple paths) | O(1) per character (single path) |
| Implementation | Simulation needed | Direct table lookup |
| Used in practice | Intermediate step | Final implementation |
Interview Questions
- Why are finite automata used in lexical analysis?
Because every regular expression (which defines token patterns) has an equivalent finite automaton. DFAs provide O(1) per-character matching speed, making them ideal for efficient token recognition in compilers.
- What is the difference between NFA and DFA in the context of lexical analysis?
An NFA can have multiple transitions on the same input and ε-transitions, making it easier to construct from regex but harder to simulate. A DFA has exactly one transition per input, enabling direct O(1) lookups but potentially exponential state count.
- Explain Thompson's construction.
Thompson's construction converts a regular expression to an NFA by building small NFAs for base cases (single characters, ε) and combining them using rules for concatenation, alternation, and Kleene closure. Each operation adds at most 2 new states.
- What is the subset construction algorithm?
It converts an NFA to a DFA where each DFA state represents a set of NFA states. Starting from ε-closure of the start state, it computes transitions by finding ε-closures of move sets. DFA accepting states are those containing any NFA accepting state.
- How does a lexical analyzer handle multiple token patterns simultaneously?
All token patterns are combined into a single NFA (with ε-transitions from a new start state to each pattern's NFA), then converted to one DFA. Each accepting state records which token pattern it matches. The longest match and priority rules resolve conflicts.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Finite Automata in Lexical Analysis.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, lexical, analysis, finite, automata
Related Compiler Design Topics