Content
- Overview
- Predictive Grammars & Parsers
- LL(1)
- Recursive Descent
- First() & Follow()
- First+()
- First & Follow Sets Calculation
- Table-Driven Parsing
Overview
- Lookahead
- Backtracking: excessive is grammar complex
Predictive Grammars & Parsers
LL(1)
- Scanned from left to right (L)
- Leftmost derivation (L)
- 1 symbol lookahead (1)
- No left recursions (not the other way round)
- No left factors (not the other way round)
Recursive Descent
A predictive parser based on LL(1). Another is table-driven parser.
Using recursive function, top-down starting from root.
A -> aAb | c
# each non-terminal has a routine
ParseA() {
if (nextSym() == 'a') {
ParseA();
if (nextSym() == 'b') OK else ERROR;
} else if (nextSym() == 'c') OK;
else ERROR;
}
Must be no left recursion.
# left recursion:
P -> E
E -> E + T | E - T | T
T -> T * S | T / S | S
S -> F ^ S | F
F -> ( E ) | char
# transform to EBNF:
P -> E
E -> T {(+|-)T}
T -> S {(*|/)S}
S -> F^S | F # left factor!
F -> ( E ) | char
Must also get rid of left factors.
First() & Follow()
First(u) is the set of terminals that starts the sequences of symbols derivable from u.Follow(A) is the set of terminals that immediately follows A.
A -> u1 | u2 | ..., if First(ui) are disjoint, then a RD routine can be easily written. Since A may be ε, Follow(A) is needed.
void ParseA() {
switch (lookahead)
{
case First(u1):
/* code to recognize u1 */
return;
...
case Follow(A):
// predict production A -> ε if A is nullable
/* usually do nothing here */
default:
...
}
}
First+()
If A -> α and A -> β, then need to make sure First(α) ∩ First(β) = ∅. But if α can be ε, then also Follow(α) ∩ First(β) = ∅.
First+(α) = First(α) ∪ Follow(α) if ε ∈ First(α)
= First(α) otherwise
A grammar is LL(1) if A -> α and A -> β implies:
First+(α) ∩ First+(β) = ∅
First & Follow Sets Calculation
First(u):
u = X1X2...Xn- If
X1is terminal, add X1 and finish - Else, add
First(X1) - ε- If
X1is nullable, addFirst(X2) - ε, and keep going- If
X2...XNare nullable, addε
- If
- Else, finish
- If
- If
Follow()
- Add
$toFollow(S) - For
A -> uBv, addFirst(v) - εtoFollow(B)- If
vis nullable, addFollow(A)toFollow(B)
- If
- For
A -> uB, addFollow(A)toFollow(B)
- Add
Table-Driven Parsing

- For
A -> u, do 2. & 3. - For each terminal
ainFirst(u), addA -> utoM[A,a] - If
Anullable, then for each terminalbinFollow(A), addA -> utoM[A,b] - Undefined entries are errors