0% found this document useful (0 votes)
20 views20 pages

Lecture#16, Chapter 04 (Part II)

1) Left factoring is a process used to make grammars LL(1) and suitable for predictive parsing by replacing productions with common prefixes. 2) Predictive parsing involves eliminating left recursion, left factoring the grammar, computing FIRST and FOLLOW sets, and using these to construct a predictive parsing table. 3) The FIRST set of a nonterminal contains the possible first terminals that could begin strings derived from that nonterminal. The FOLLOW set contains terminals that could follow the nonterminal.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views20 pages

Lecture#16, Chapter 04 (Part II)

1) Left factoring is a process used to make grammars LL(1) and suitable for predictive parsing by replacing productions with common prefixes. 2) Predictive parsing involves eliminating left recursion, left factoring the grammar, computing FIRST and FOLLOW sets, and using these to construct a predictive parsing table. 3) The FIRST set of a nonterminal contains the possible first terminals that could begin strings derived from that nonterminal. The FOLLOW set contains terminals that could follow the nonterminal.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

1

Syntax Analysis
Part I
Chapter 4
2

Left Factoring
• When a nonterminal has two or more productions
whose right-hand sides start with the same
grammar symbols, the grammar is not LL(1) and
cannot be used for predictive parsing
• Replace productions
A   1 |  2 | … |  n | 
with
A   AR | 
AR  1 | 2 | … | n
3

Predictive Parsing
• Eliminate left recursion from grammar
• Left factor the grammar
• Compute FIRST and FOLLOW
• Two variants:
– Recursive (recursive calls)
– Non-recursive (table-driven)
• Wait for definition of LL(1)
4

Computing First(X) : All Grammar Symbols


Informally, suppose we want to compute
First(X1 X2 … Xn ) = First (X1) “+”
First(X2) if  is in First(X1) “+”
First(X3) if  is in First(X2) “+”

First(Xn) if  is in First(Xn-1)

Note 1: Only add  to First(X1 X2 … Xn) if 


is in First(Xi) for all i
Note 2: For First(X1), if X1 Z1 Z2 … Zm ,
then we need to compute First(Z1 Z2 … Zm) !
5

Computing First(X) : All Grammar Symbols


1. If X is a terminal, First(X) = {X}
2. If X  is a production rule, add  to First(X)
3. If X is a non-terminal, and X Y1Y2…Yk is a production rule
Place First(Y1) in First(X)
*
if Y1 , Place First(Y2) in First(X)
if Y2 
* , Place First(Y3) in First(X)

* ,
if Yk-1  Place First(Yk) in First(X)
NOTE: As soon as Yi 
*  , Stop.

Repeat above steps until no more elements are added to any First(
) set.
Checking “Yj *  ?” essentially amounts to checking whether 
belongs to First(Yj)
6

Computing FIRST (Revisited)


• FIRST() = the set of terminals that begin all strings
derived from 

FIRST(a) = {a} if a  T
FIRST() = {}
FIRST(A) = A FIRST() for A  P
FIRST(X1X2…Xk) =
if for all j = 1, …, i-1 :   FIRST(Xj) then
add non- in FIRST(Xi) to FIRST(X1X2…Xk)
if for all j = 1, …, k :   FIRST(Xj) then
add  to FIRST(X1X2…Xk)
7

Example 3: Computing First


Given the production rules:
i E t SS’ = If E then S S’ = If E then S Else S
S’ = Else S

S  i E t SS’ | a
S’  eS | 
E b

Verify that
First(S) = { i, a }
First(S’) = { e,  }
First(E) = { b }
8

Example 4
Computing First for: E  TE’
E’  + TE’ | 
T  FT’
T’  * FT’ | 
F  ( E ) | id
9

Example 4 Computing First


Computing First for: E  TE’
E’  + TE’ | 
T  FT’
T’  * FT’ | 
F  ( E ) | id
First(TE’)
First(T) “+” First(E’)
First(E) * 
Not First(E’) since T 
First(T)

First(F) “+” First(T’) First(F) Not First(T’) since F 


* 

First((E)) “+” First(id) “(“ and “id”

Overall: First(E) = { ( , id } = First(F)


First(E’) = { + ,  } First(T’) = { * ,  }
First(T)  First(F) = { ( , id }
10

Computing Follow(A) : All Non-Terminals


1. Place $ in Follow(S), where S is the start symbol and $ signals end
of input

2. If there is a production A B, then everything in First() is in


Follow(B) except for .

3. If A B is a production, or A B and  *  (First()


contains  ), then everything in Follow(A) is in Follow(B)

Whatever followed A must follow B, since nothing follows B


from the production rule.

We’ll calculate Follow for two grammars.


11

More Formal Way of Computing


FOLLOW
• FOLLOW(A) = the set of terminals that can
immediately follow nonterminal A

FOLLOW(A) =
for all (B   A )  P do
add FIRST()\{} to FOLLOW(A)
for all (B   A )  P and   FIRST() do
add FOLLOW(B) to FOLLOW(A)
for all (B   A)  P do
add FOLLOW(B) to FOLLOW(A)
if A is the start symbol S then
add $ to FOLLOW(A)
12

Computing Follow : Example 5


Recall: S  i E t SS’ | a First(S) = { i, a }
S’  eS |  First(S’) = { e,  }
E b First(E) = { b }

Follow(S) – Contains $, since S is start symbol


Since S  i E t SS’ , put in First(S’) – not 
Since S’ 
* , Put in Follow(S)

Since S’  eS, put in Follow(S’) So…. Follow(S) = { e, $ }

Follow(S’) = Follow(S) HOW?

Follow(E) = { t }
13

Example 6
Compute Follow for: E  TE’
E’  + TE’ | 
T  FT’
T’  * FT’ | 
F  ( E ) | id
14

Example 6: First and Follows


Already Computed
Compute Follow for: E  TE’
E’  + TE’ | 
T  FT’
T’  * FT’ | 
F  ( E ) | id

First Follow
E ( id E $)
E’ + E’ $)
T ( id T +$)
T’ * T’ +$)
F ( id F +*$)
15

Constructing Parsing Table


Algorithm:
1. Repeat Steps 2 & 3 for each rule A
2. Terminal a in First(): Add A to M[A, a ]
3. a)  in First(): Add A  to M[A, b ] for all
terminals b in Follow(A).
b)  in First() and $ in Follow(A): Add A  to M[A, $ ]
4. All undefined entries are errors.
16

Constructing a Predictive Parsing


Table: More Formal Way
for each production A   do
for each a  FIRST() do
add A   to M[A,a]
enddo
if   FIRST() then
for each b  FOLLOW(A) do
add A   to M[A,b]
enddo
endif
enddo
Mark each undefined entry in M error
17

Constructing Parsing Table – Example 7

S  i E t SS’ | a First(S) = { i, a } Follow(S) = { e, $ }


S’  eS |  First(S’) = { e,  } Follow(S’) = { e, $ }
E b First(E) = { b } Follow(E) = { t }
18
Constructing Parsing Table – Example 7
S  i E t SS’ | a First(S) = { i, a } Follow(S) = { e, $ }
S’  eS |  First(S’) = { e,  } Follow(S’) = { e, $ }
E b First(E) = { b } Follow(E) = { t }
S  i E t SS’ Sa Eb
First(i E t SS’)={i} First(a) = {a} First(b) = {b}

S’  eS S
First(eS) = {e} First() = {} Follow(S’) = { e, $ }

Non- INPUT SYMBOL


terminal a b e i t $
S S a S iEtSS’
S’ S’ 
S’ eS S’ 
E E b
19

Constructing Parsing Table – Example 8


E  TE’ First(E,F,T) = { (, id } Follow(E,E’) = { ), $}
E’  + TE’ | 
T  FT’ First(E’) = { +,  } Follow(F) = { *, +, ), $ }
T’  * FT’ |  First(T’) = { *,  } Follow(T,T’) = { +, ) , $}
F  ( E ) | id

Expression Example: E  TE’ : First(TE’) = First(T) = { (, id }


M[E, ( ] : E  TE’
by rule 2
M[E, id ] : E  TE’
(by rule 2) E’  +TE’ : First(+TE’) = + : M[E’, +] : E’  +TE’
(by rule 3) E’   :  in First( ) T’   :  in First( )
M[E’, )] : E’   (3.1) M[T’, +] : T’   (3.1)
M[E’, $] : E’   (3.2) M[T’, )] : T’   (3.1)
(Due to Follow(E’) M[T’, $] : T’   (3.2)
20

Example 8
E  TE’
E’  + TE’ | 
T  FT’ Our well-worn example !
T’  * FT’ | 
F  ( E ) | id

First(E,F,T) = { (, id } Follow(E,E’) = { ), $}
First(E’) = { +,  } Follow(F) = { *, +, ), $ }
Table M First(T’) = { *,  } Follow(T,T’) = { +, ) , $}

Non- INPUT SYMBOL


terminal
id + * ( ) $
E ETE’ ETE’
E’ E’+TE’ E’ E’
T TFT’ TFT’
T’ T’ T’*FT’ T’ T’
F Fid F(E)

You might also like