You are on page 1of 21

LL(1) Parsing

Programming Language Principles Lecture 4

Prepared by

Manuel E. Bermdez, Ph.D.


Associate Professor University of Florida

Example
Build the LL(1) parse table for the following grammar. SL E T P S begin SL end {begin} id := E; {id} SL S {begin,id} * S {begin,id} E+T {(, id} * T {(, id} P*T {(, id} * P {(, id} (E) {(} * - not LL(1) id {id}

Example (contd)
Lemma: Left recursion always produces a non-LL(1) grammar (e.g., SL, E above) Proof: Consider A A

First () or Follow (A) First () Follow (A)

Problems with our Grammar


1. SL is left recursive. 2. E is left recursive.

3. T P * T P

both begin with the same sequence of symbols (P).

Solution to Problem 3
Change: T P * T P to: TPX X*T { (, id } { (, id } { (, id } {*} { +, ; , ) } Disjoint!

Follow(X) Follow(T) Follow(E) = { +, ;, ) }

due to T P X due to E E+T , E T due to E E+T, S id := E ; and P (E)

Solution to Problem 3 (contd)


In general, change A 1 2 ... n to A X X 1 ... n Hopefully all the s begin with different symbols

Solution to Problems 1 and 2


We want (((( T + T) + T) + T)) Instead, (T) (+T) (+T) (+T) Change: EE+T T E TY Y +TY { (, id } { (, id } { (, id } {+} { ;,)}
No longer contains +, because we eliminated the production E E + T

To:

Follow(Y) Follow(E) ={;,)}

Solution to Problems 1 and 2 (contd)


In general, Change: A A1 ... An A 1 X ... m X A 1 ... m X 1 X ... n X

to:

Solution to Problems 1 and 2 (contd)


In our example, Change: SL SL S S SL S Z ZSZ { begin, id } { begin, id } { begin, id } { begin, id } { end }

To:

Modified Grammar
S SL Z E Y T X P begin SL end id := E ; S Z S Z T Y + T Y P X * T (E) id {begin} {id} {begin,id} {begin,id} {end} (,id} {+} {;,)} {(,id} {*} {;,+,)} {(} {id}

Disjoint.
Grammar is LL(1)

Recursive Descent Parsing


Top-down parsing strategy, suitable for LL(1) grammars. One procedure per nonterminal. Contents of stack embedded in recursive call sequence. Each procedure commits to one production, based on the next input symbol, and the select sets. Good technique for hand-written parsers.

For our Modified, LL(1) Grammar


S; {S begin SL end id := E; } case Next_Token of T_begin : Read(T_begin); SL; Read (T_end); T_id : Read(T_id); Read (T_:=); E; Read (T_;); otherwise Error; end end; proc
Read (T_X) verifies that the upcoming token is X, and consumes it.

Next_Token is the upcoming token.

For our Modified, LL(1) Grammar (contd)


proc SL; {SL SZ} S; Technically, should have insisted Z; that Next Token be either T_begin or T_id, but S will do end; that anyway. Checking early would aid error recovery. proc E; {E TY} T; Y; // Ditto for T_( and T_id. end;

For our Modified, LL(1) Grammar (contd)


proc Z;{Z SZ } case Next Token of T_begin, T_id: S;Z; T_end: ; otherwise Error; end end;

For our Modified, LL(1) Grammar (contd)


proc Y; {Y +TY Could have used a } case statement if Next Token = T_+ then Read (T_+) T; Y; end; proc T; {T PX} P; Could have checked for T_( and T_id. X end;

For our Modified, LL(1) Grammar (contd)


proc X;{X *T } if Next Token = T_* then Read (T_*); T; end;

For our Modified, LL(1) Grammar (contd)


proc P; {P (E) id } case Next Token of T_(: Read (T_(); E; Read (T_)); T_id: Read (T_id); otherwise Error; end end;

LL(1) Parsing
Programming Language Principles Lecture 4

Prepared by

Manuel E. Bermdez, Ph.D.


Associate Professor University of Florida

You might also like