Introduction
A predictive parser must decide which production to apply by looking only at the next input token. A bottom-up SLR parser must decide whether to reduce by looking at the same token. Both decisions are made with two families of sets computed from the grammar alone: FIRST, the terminals that can begin a string derived from a symbol, and FOLLOW, the terminals that can appear immediately after a nonterminal in some sentential form.
Computing these sets correctly is mechanical, but every step has a trap: in FIRST, the end marker in FOLLOW, chains of nullable symbols, and the difference between "can begin" and "can follow". This note gives the definitions, the fixed-point algorithms, and fully worked grammars.
Prerequisites
- Grammar Transformations for Parsing: the notation for grammars, and the left-recursion-free expression grammar used below.
Core concepts
End-marker convention used in all Compiler Design notes. The input is followed by the end marker , a terminal that occurs nowhere else. may appear in FIRST sets but never in FOLLOW sets; may appear in FOLLOW sets but never in FIRST sets of a grammar symbol.
| Set | Definition |
|---|---|
| All terminals with for some , plus if | |
| All terminals with for some , plus if can be the last symbol of a sentential form | |
| Nullable | is nullable if , that is, |
FIRST is defined for any string of grammar symbols; FOLLOW only for nonterminals.
Algorithms
Nullable symbols first
NULLABLE(G)
N <- {A : A -> eps is a production}
repeat
for each production A -> Y1 ... Yk with every Yi in N (no terminal in the body)
add A to N
until N does not changeA body that contains a terminal is never nullable. Computing the nullable set first makes the FIRST and FOLLOW passes easier to do by hand, because "is nullable?" is then a lookup.
FIRST of a single symbol
FIRST-SETS(G)
for each terminal a: FIRST(a) <- {a}
for each nonterminal A: FIRST(A) <- {}
repeat
for each production A -> Y1 Y2 ... Yk
add FIRST-OF-STRING(Y1 Y2 ... Yk) to FIRST(A)
until no set changes
return FIRST
FIRST-OF-STRING(Y1 Y2 ... Yk)
result <- {}
for i <- 1 to k
add FIRST(Yi) - {eps} to result
if eps not in FIRST(Yi) then return result
add eps to result (every Yi is nullable, or k = 0)
return resultThe rule in words: take FIRST of the first symbol without ; if that symbol is nullable, also take FIRST of the next one; continue while symbols are nullable; add only if all of them are nullable. A production puts into .
FOLLOW
FOLLOW-SETS(G, S)
FOLLOW(S) <- {$}; every other FOLLOW(A) <- {}
repeat
for each production A -> alpha B beta, for each nonterminal occurrence B
add FIRST-OF-STRING(beta) - {eps} to FOLLOW(B)
if eps in FIRST-OF-STRING(beta) (beta nullable or empty)
add FOLLOW(A) to FOLLOW(B)
until no set changesBoth algorithms are fixed-point iterations: sets only grow and are bounded by the number of terminals, so they terminate. With nonterminals, terminals and total production length , a FIRST pass costs set work. A FOLLOW pass also has that bound if suffix FIRST/nullable sets are cached or computed in a linear right-to-left suffix pass; a literal implementation rescanning every suffix costs per pass and at most passes are needed (each pass but the last adds at least one element), a polynomial bound; small grammars settle in two or three passes.
Direction of the FOLLOW rule. When is nullable, FOLLOW of the head flows into FOLLOW of the body symbol , never the other way. In , whatever follows can follow , because ends whatever derives.
Worked examples
The expression grammar
E -> T E'
E' -> + T E' | eps
T -> F T'
T' -> * F T' | eps
F -> ( E ) | idFIRST. begins with ( or id. and is not nullable, so ; likewise .
FOLLOW. Start with . From , ) is in . From , FOLLOW(E) flows into FOLLOW(E'), and goes into FOLLOW(T); since is nullable, FOLLOW(E) also flows into FOLLOW(T). Similarly at the next level, * and FOLLOW(T) go into FOLLOW(F).
| Nonterminal | FIRST | FOLLOW |
|---|---|---|
(, id | ), | |
+, | ), | |
(, id | +, ), | |
*, | +, ), | |
(, id | *, +, ), |
Check the pattern: FOLLOW grows as one moves down the precedence levels, because a lower-level nonterminal can be followed by every operator of the levels above it.
Nullable chains
S -> A B c | B d
A -> a A | eps
B -> b | eps- , .
- : from ; nullable, so from ; nullable, so . Result , and no because is not nullable.
- , so .
- . (and adds FOLLOW(A) to itself, nothing new). .
Both alternatives of can begin with , so this grammar is not LL(1): on input b the parser cannot choose between and .
A conflict that appears only through FOLLOW
S -> X Y Z
X -> x | eps
Y -> y X | eps
Z -> z | X| Nonterminal | FIRST | FOLLOW |
|---|---|---|
x, y, z, | ||
x, | x, y, z, | |
y, | x, z, | |
x, z, |
How x enters FOLLOW(X): there are two independent routes.
- Directly from . What follows there is . is nullable, so goes into FOLLOW(X).
xis in FIRST(Z) because of . - Through . ends this body, so FOLLOW(Y) flows into FOLLOW(X), and FOLLOW(Y) contains FIRST(Z) minus epsilon, which contains
x.
Either route alone puts x into FOLLOW(X). Now and both apply on lookahead x, an LL(1) conflict that no pair of FIRST sets reveals. is nullable (all three symbols are), so , and enters FOLLOW(X) three ways: from itself (since is nullable), through , and through .
FOLLOW sets that feed each other
P -> S d S
S -> a B | eps
B -> b S | c| Nonterminal | FIRST | FOLLOW |
|---|---|---|
a, d | ||
a, | d, | |
b, c | d, |
- contains
dbecause the first is nullable; it does not contain becausedis a terminal. - In the first gets
dand the last gets . - sends FOLLOW(S) into FOLLOW(B), and sends FOLLOW(B) back into FOLLOW(S). Mutual inclusion forces ; the iteration still stops, because sets only grow.
- The number of passes depends on the order of productions. Processing gives the final sets in one pass and a second pass confirms. Processing needs three passes: FOLLOW(S) is filled in pass 1 (from ), FOLLOW(B) only in pass 2 (from ), and pass 3 confirms. The result is the same.
- The grammar is LL(1): 's alternatives are chosen by
aversus , and 's bybversusc.
FIRST and FOLLOW of a left-recursive grammar
The sets are defined for any grammar, including the left-recursive expression grammar used for LR parsing:
E -> E + T | T
T -> T * F | F
F -> ( E ) | id. , . Here + follows itself (from ), unlike the left-factored grammar above, where + follows but not . The left-recursive grammar cannot be used for LL(1) parsing (see the note Grammar Transformations for Parsing), but these FOLLOW sets are exactly what an SLR(1) table needs.
Small facts worth memorising
- : , .
- , , : , . Equal FOLLOW sets matter for SLR parsing; see the note LR(0) and SLR(1) Parsing.
Important properties and observations
- if and only if is nullable. is never in a FOLLOW set; is never in a FIRST set of a grammar symbol.
- always, and whenever can end a sentential form (it appears last in a body whose head has in FOLLOW, possibly followed by nullable symbols).
- FOLLOW sets depend on the whole grammar, FIRST sets only on the productions reachable from the symbol. Adding a production anywhere can enlarge FOLLOW sets elsewhere.
- A nonterminal on the right of its own body. In , the rule "add FOLLOW(A) to FOLLOW(A)" is harmless. In , FIRST() minus epsilon goes into FOLLOW(A); when is nullable, the usual FOLLOW(head) contribution also applies.
- FIRST of a string stops at the first terminal. In , nothing from can appear and cannot appear.
- Mutual inclusion gives equal sets. If and , the two sets are equal.
- Use of the sets. LL(1) table: FIRST of each body, and FOLLOW of the head for nullable bodies. SLR(1) table: FOLLOW of the head decides where to reduce. Operator-precedence and LR(1) parsing use other information.
Common misconceptions.
- "FIRST() is FIRST() FIRST()." Only when is nullable, and then without 's .
- "FOLLOW() in is FIRST()." Without , and plus FOLLOW() when is nullable.
- "If is a production, goes into FOLLOW()." Never; it goes into FIRST().
- "A terminal enters FOLLOW() only from the symbol right after ." It also comes from symbols further right when the ones in between are nullable, as
xenters FOLLOW(X) from FIRST(Z) across the nullable . - "FOLLOW sets that include each other make the algorithm loop forever." The sets are bounded by the terminals and only grow, so the passes stop.
GATE examination perspective
- Compute FIRST and FOLLOW for a given grammar. Work in passes until nothing changes; most errors come from stopping after one pass when a FOLLOW set feeds another FOLLOW set.
- Option elimination. Any option with in a FOLLOW set or in a FIRST set is wrong.
- Hidden flows through nullable symbols. As in the example, a terminal can enter FOLLOW through two or three links of nullable symbols.
- LL(1) decision. Two alternatives with overlapping FIRST sets, or a nullable alternative whose head's FOLLOW overlaps another alternative's FIRST, make a conflict. See the note Top-Down Parsing and LL(1).
- SLR reductions. "On which lookaheads does state reduce by ?" The answer is .
- Left-recursive grammars. FIRST and FOLLOW can be asked of directly; compute them without removing the recursion.
- Every occurrence counts. A nonterminal that occurs twice in one body ( in ) collects from both occurrences.
Summary
Sources
- A. V. Aho, M. S. Lam, R. Sethi, J. D. Ullman, Compilers: Principles, Techniques, and Tools, 2nd ed., Pearson Addison-Wesley, 2007: Section 4.4.2 (FIRST and FOLLOW), Section 4.4.3 (LL(1) grammars), Section 4.6.4 (constructing SLR-parsing tables).