Title: Predictive Parsing
1Predictive Parsing
2Top Down Parsing Methods
- Simplest method is a full-backup recursive
descent parse - Write recursive recognizers (subroutines) for
each grammar rule - If rules succeeds perform some action (I.e.,
build a tree node, emit code, etc.) - If rule fails, return failure. Caller may try
another choice or fail - On failure it backs up which might have problem
if it needs to return a lexical symbol to the
input stream
3Problems
- Also remember left recursion problem
- Need to backtrack , suppose that you could always
tell what production applied by looking at one
(or more) tokens of lookahead called predictive
parsing - Factoring
4Summary of Recursive Descent
- Simple and general parsing strategy usually
coupled with simple handcrafted lexer - Left-recursion must be eliminated first
- but that can be done automatically
- Unpopular because of backtracking
- Thought to be too inefficient
- In practice, backtracking is eliminated by
restricting the grammar
5Elimination of Immediate Left Recursion
- A -gt A a1 A a2 A am b1 b2
bn - ________________________________________
- -gt b1 A b2 A bn A
- -gt a1 A a2 A amA e
Doesnt solve S-gt Sa (See ASU Chapter 4 for
general algorithm w/o cycle no e)
6Predictive Parsers
- 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
- L means left-to-right scan of input
- L means leftmost derivation
- k means predict based on k tokens of lookahead
- In practice, LL(1) is used
7Summary of Recursive Descent
- Simple and general parsing strategy
- Left-recursion must be eliminated first
- but that can be done automatically
- Unpopular because of backtracking
- Thought to be too inefficient
- In practice, backtracking is eliminated by
restricting the grammar
8Predictive Parsers
- 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
- L means left-to-right scan of input
- L means leftmost derivation
- k means predict based on k tokens of lookahead
- In practice, LL(1) is used
9LL(1) Languages
- In recursive-descent, for each non-terminal and
input token there may be a choice of production - LL(1) means that for each non-terminal and token
there is only one production - Can be specified via 2D tables
- One dimension for current non-terminal to expand
- One dimension for next token
- A table entry contains one production
10Predictive Parsing and Left Factoring
- Recall the grammar
- E ? T E T
- 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
- A grammar must be left-factored before use for
predictive parsing
11Left-Factoring Example
- Recall the grammar
- E ? T E T
- T ? int int T ( E )
- Factor out common prefixes of productions
- E ? T X
- X ? E ?
- T ? ( E ) int Y
- Y ? T ?
12LL(1) Parsing Table Example
- Left-factored grammar
- E ? T X X ? E ?
- T ? ( E ) int Y Y ? T ?
- The LL(1) parsing table
int ( )
E T X T X
X E ? ?
T int Y ( E )
Y T ? ? ?
13LL(1) Parsing Table Example (Cont.)
- Consider the E, int entry
- When current non-terminal is E and next input is
int, use production E ? T X - This production can generate an int in the first
place - Consider the Y, entry
- When current non-terminal is Y and current token
is , get rid of Y - Y can be followed by only in a derivation in
which Y ? ?
14LL(1) Parsing Tables. Errors
- Blank entries indicate error situations
- Consider the E, entry
- There is no way to derive a string starting with
from non-terminal E
15Using Parsing Tables
- Method similar to recursive descent, except
- For each non-terminal S
- We look at the next token a
- And chose the production shown at S,a
- We use a stack to keep track of pending
non-terminals - We reject when we encounter an error state
- We accept when we encounter end-of-input
16LL(1) Parsing Algorithm
- initialize stack ltS gt and next
- repeat
- case stack of
- ltX, restgt if TX,next Y1Yn
- then stack ? ltY1 Yn
restgt - else error ()
- ltt, restgt if t next
- then stack ? ltrestgt
- else error ()
- until stack lt gt
17LL(1) Parsing Example
- Stack Input
Action - E int int
T X - T X int int
int Y - int Y X int int
terminal - Y X int
T - T X int
terminal - T X int
int Y - int Y X int
terminal - Y X
? - X
? -
ACCEPT
18Constructing Parsing Tables
- LL(1) languages are those defined by a parsing
table for the LL(1) algorithm - No table entry can be multiply defined
- We want to generate parsing tables from CFG
19Constructing Parsing Tables (Cont.)
- If A ? ?, where in the line of A we place ? ?
- In the column of t where t can start a string
derived from ? - ? ? t ?
- We say that t ? First(?)
- In the column of t if ? is ? and t can follow an
A - S ? ? A t ?
- We say t ? Follow(A)
20Computing First Sets
- Definition First(X) t X ? t? ? ? X
? ? - Algorithm sketch (see book for details)
- for all terminals t do First(t) ? t
- for each production X ? ? do First(X) ? ?
- if X ? A1 An ? and ? ? First(Ai), 1 ? i ? n
do - add First(?) to First(X)
- for each X ? A1 An s.t. ? ? First(Ai), 1 ? i ?
n do - add ? to First(X)
- repeat steps 4 5 until no First set can be grown
21First Sets. Example
- Recall the grammar
- E ? T X X ? E
? - T ? ( E ) int Y Y ? T
? - First sets
- First( ( ) ( First( T )
int, ( - First( ) ) ) First( E )
int, ( - First( int) int First( X )
, ? - First( ) First( Y )
, ? - First( )
22Computing Follow Sets
- Definition
- Follow(X) t S ? ? X t ?
- Intuition
- If S is the start symbol then ? Follow(S)
- If X ? A B then First(B) ? Follow(A) and
- Follow(X) ?
Follow(B) - Also if B ? ? then Follow(X) ? Follow(A)
23Computing Follow Sets (Cont.)
- Algorithm sketch
- Follow(S) ?
- For each production A ? ? X ?
- add First(?) - ? to Follow(X)
- For each A ? ? X ? where ? ? First(?)
- add Follow(A) to Follow(X)
- repeat step(s) ___ until no Follow set grows
24Follow Sets. Example
- Recall the grammar
- E ? T X X ? E
? - T ? ( E ) int Y Y ? T
? - Follow sets
- Follow( ) int, ( Follow( )
int, ( - Follow( ( ) int, ( Follow( E )
), - Follow( X ) , ) Follow( T ) ,
) , - Follow( ) ) , ) , Follow( Y )
, ) , - Follow( int) , , ) ,
25Constructing 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
- TA, t ?
- If ? ? First(?), for each t ? Follow(A) do
- TA, t ?
- If ? ? First(?) and ? Follow(A) do
- TA, ?
-
26Notes on LL(1) Parsing Tables
- If any entry is multiply defined then G is not
LL(1) - If G is ambiguous
- If G is left recursive
- If G is not left-factored
- And in other cases as well
- Most programming language grammars are not LL(1)
- There are tools that build LL(1) tables
27References
- Compilers Principles, Techniques and Tools, Aho,
Sethi, Ullman Chapters 2/3 - http//www.cs.columbia.edu/lerner/CS4115
- http//www.cs.wisc.edu/bodik/cs536/lectures.html