Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
41 views

Compilers Lecture 7

The document discusses predictive parsing and LL(1) grammars. Predictive parsing uses a parsing table to predict which production to use based on the next 1-2 tokens. This allows parsing left-to-right without backtracking. The document provides examples of left-factoring a grammar to make it LL(1) and constructing the LL(1) parsing table using the grammar's first and follow sets.

Uploaded by

Fatma Sakr
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views

Compilers Lecture 7

The document discusses predictive parsing and LL(1) grammars. Predictive parsing uses a parsing table to predict which production to use based on the next 1-2 tokens. This allows parsing left-to-right without backtracking. The document provides examples of left-factoring a grammar to make it LL(1) and constructing the LL(1) parsing table using the grammar's first and follow sets.

Uploaded by

Fatma Sakr
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 21

Compilers Design

Top-down Parsing (part 2)

1
Predictive Parsing
Like recursive-descent but parser can “predict” which
production to use
By looking at the next few tokens
No backtracking
Predictive parsers accept LL(k) grammars
LL(k): L(left to right)L(leftmost derivation) (k)
k is the number of look ahead and usually is 1
Predictive Parsing
In recursive descent,
At each step, many choices of production to use
Backtracking used to undo bad choices
In LL(1),
At each step, only one choice of production
Left factoring
Recall the grammar
E →T |T + E
T → int | int * T | ( E )
Hard to predict because
For T two productions start with int
For E it is not clear how to predict
We need to left-factor the grammar
Left factoring
Recall the grammar
E → T |T + E
T → int | int * T | ( E )
we can rewrite as
E → T X
X → + E | ε
T → int Y | (E)
Y → * T | ε
The LL(1) parsing table
E → T X
X → + E | ε
T → int Y | (E)
Y → * T | ε
The LL(1) parsing table
Consider the [E, int] entry
“When current non-terminal is E and next input is int,
use production E → T X”
The LL(1) parsing table
Consider the [Y,+] entry
“When current non-terminal is Y and current token is
+, get rid of Y”
Y can be followed by + only if Y → ε
The LL(1) parsing table
Consider the [E,*] entry
“There is no way to derive a string starting with * from
non-terminal E”. An error must be raised.
Predictive parsing
Method similar to recursive descent, except
 For the leftmost non-terminal S
 We look at the next input token a
 And choose the production shown at [S,a]
A stack records frontier of parse tree
 Non-terminals that have yet to be expanded
 Terminals that have yet to matched against the input
 Top of stack = leftmost pending terminal or non-terminal
Reject on reaching error state
Accept on end of input & empty stack
Predictive parsing algorithm
initialize stack = <S $> and next
repeat
case stack of
<X, rest> : if T[X,*next] = Y1…Yn
then stack → <Y1… Yn rest>;
else error ();
<t, rest> : if t == *next ++
then stack → <rest>;
else error ();
until stack == < >
Example
Stack Input Action
E$ int * int $ TX
TX$ int * int $ int Y
int Y X $ int * int $ terminal
YX$ * int $ *T
*TX$ * int $ terminal
TX$ int $ int Y
int Y X $ int $ terminal
YX$ $ ε
X$ $ ε
$ $ ACCEPT
First and follow sets
Consider non-terminal A, production A → α, & token t
T[A,t] = α in two cases:
If α→* t β
 α can derive a t in the first position
 We say that t є First(α)
If A → α and α→* ε and S →* β A tδ
 Useful if stack has A, input is t, and A cannot derive t
 In this case only option is to get rid of A (by deriving ε)
Can work only if t can follow A in at least one derivation
 We say t є Follow(A)
First sets
Definition
First(X) = { t | X →* tα} U {ε| X →* ε}
Algorithm sketch:
1. First(t) = { t } t is a terminal
2. ε є First(X)
 if X →ε
 if X → A1 … An and ε є First(Ai) for 1 <= i <= n

3. First(α) ⊆ First(X) if X → A1 … An α
 and ε є First(Ai) for 1 <= i <= n
Example
E → T X
X → + E | ε
T → int Y | (E)
Y → * T | ε
First(+) = {+} First(E) = First(T)
First(() = {(} First(T) = {(,int}
First()) = {)} First(X) = {+, ε}
First(*) = {*} First(Y) = {*, ε}
First(int) = {int}
Follow Sets
Definition:
Follow(X) = { t | S → * β X t δ }
Intuition
If X → A B then First(B) ⊆ Follow(A) and
Follow(X) ⊆ Follow(B)
 If B →* ε then Follow(X) ⊆ Follow(A)
If S is the start symbol then $ є Follow(S)
Follow Sets
Algorithm sketch:
1. $ є Follow(S)
2. First(β) - {ε} ⊆ Follow(X)
 For each production A → X β
3. Follow(A) ⊆ Follow(X)
 For each production A → α X β where ε є First(β)
Example
E → T X
X → + E | ε
 T → int Y | (E)
Y → * T | ε
Follow(X) = Follow(E) Follow(E) = {$,)}
Follow(E) = Follow(X) Follow(X) = {$,)}
Follow(E) = Follow(T) Follow(T) = {+,$,)}
Follow(Y) = Follow(T) Follow(Y) = {+,$,)}
Follow(T) = Follow(Y) Follow(‘(‘) = {(,int}
Follow(‘)’) = {+,$,)}
Follow(‘+) = {(,int}
Follow(‘*’) = {(,int}
Follow(int) = {*,+,$,)}
LL(1) Parsing Tables
Construct a parsing table T for CFG G
For each production A →α in G do:
For each terminal t є First(α) do
 T[A, t] = α
If ε є First(α), for each t є Follow(A) do
 T[A, t] = α

If ε є First(α) and $ є Follow(A) do


 T[A, $] = α
The LL(1) parsing table
E → T X
X → + E | ε
T → int Y | (E)
Y → * T | ε
Questions?

21

You might also like