Parser Generation. Bottom-Up Parsing. Constructing LR Parser. LR Parsing. Construct parse tree bottom-up --- from leaves to the root

Similar documents
Bottom-Up Parsing. Parser Generation. LR Parsing. Constructing LR Parser

Context-free grammars

Compiler Construction: Parsing

PART 3 - SYNTAX ANALYSIS. F. Wotawa TU Graz) Compiler Construction Summer term / 309

Bottom-up parsing. Bottom-Up Parsing. Recall. Goal: For a grammar G, withstartsymbols, any string α such that S α is called a sentential form


LR Parsing Techniques

3. Syntax Analysis. Andrea Polini. Formal Languages and Compilers Master in Computer Science University of Camerino

A left-sentential form is a sentential form that occurs in the leftmost derivation of some sentence.

Section A. A grammar that produces more than one parse tree for some sentences is said to be ambiguous.

Principles of Programming Languages

Bottom up parsing. The sentential forms happen to be a right most derivation in the reverse order. S a A B e a A d e. a A d e a A B e S.

CA Compiler Construction

Formal Languages and Compilers Lecture VII Part 4: Syntactic A

MIT Parse Table Construction. Martin Rinard Laboratory for Computer Science Massachusetts Institute of Technology

Types of parsing. CMSC 430 Lecture 4, Page 1

Let us construct the LR(1) items for the grammar given below to construct the LALR parsing table.

Parsing. Roadmap. > Context-free grammars > Derivations and precedence > Top-down parsing > Left-recursion > Look-ahead > Table-driven parsing

S Y N T A X A N A L Y S I S LR

Syntax Analysis. Martin Sulzmann. Martin Sulzmann Syntax Analysis 1 / 38

LR Parsing, Part 2. Constructing Parse Tables. An NFA Recognizing Viable Prefixes. Computing the Closure. GOTO Function and DFA States

MODULE 14 SLR PARSER LR(0) ITEMS

Concepts Introduced in Chapter 4

Parsing Wrapup. Roadmap (Where are we?) Last lecture Shift-reduce parser LR(1) parsing. This lecture LR(1) parsing

Bottom-Up Parsing. Lecture 11-12

Formal Languages and Compilers Lecture VII Part 3: Syntactic A

Table-driven using an explicit stack (no recursion!). Stack can be viewed as containing both terminals and non-terminals.

CSCI312 Principles of Programming Languages

LR Parsing Techniques

Parsing. Handle, viable prefix, items, closures, goto s LR(k): SLR(1), LR(1), LALR(1)

UNIT-III BOTTOM-UP PARSING

Syntactic Analysis. Top-Down Parsing

Syntax Analysis: Context-free Grammars, Pushdown Automata and Parsing Part - 4. Y.N. Srikant

3. Parsing. Oscar Nierstrasz

Compiler Construction 2016/2017 Syntax Analysis

Bottom-Up Parsing. Lecture 11-12

Parsing III. CS434 Lecture 8 Spring 2005 Department of Computer Science University of Alabama Joel Jones

Parsing III. (Top-down parsing: recursive descent & LL(1) )

In One Slide. Outline. LR Parsing. Table Construction

Compilerconstructie. najaar Rudy van Vliet kamer 140 Snellius, tel rvvliet(at)liacs(dot)nl. college 3, vrijdag 22 september 2017

LR Parsing LALR Parser Generators

CSE P 501 Compilers. LR Parsing Hal Perkins Spring UW CSE P 501 Spring 2018 D-1

Parsing #1. Leonidas Fegaras. CSE 5317/4305 L3: Parsing #1 1

CS1622. Today. A Recursive Descent Parser. Preliminaries. Lecture 9 Parsing (4)

Sometimes an ambiguous grammar can be rewritten to eliminate the ambiguity.

Lecture 7: Deterministic Bottom-Up Parsing

shift-reduce parsing

Compilers. Bottom-up Parsing. (original slides by Sam

Review: Shift-Reduce Parsing. Bottom-up parsing uses two actions: Bottom-Up Parsing II. Shift ABC xyz ABCx yz. Lecture 8. Reduce Cbxy ijk CbA ijk

Lecture 8: Deterministic Bottom-Up Parsing

Syntax Analysis. Amitabha Sanyal. ( as) Department of Computer Science and Engineering, Indian Institute of Technology, Bombay

Compiler Design 1. Bottom-UP Parsing. Goutam Biswas. Lect 6

Monday, September 13, Parsers

Chapter 4: LR Parsing

LR Parsing LALR Parser Generators

Chapter 3. Parsing #1

LR Parsers. Aditi Raste, CCOEW

Bottom-Up Parsing II (Different types of Shift-Reduce Conflicts) Lecture 10. Prof. Aiken (Modified by Professor Vijay Ganesh.

Parsing Part II (Top-down parsing, left-recursion removal)

Conflicts in LR Parsing and More LR Parsing Types

Bottom-Up Parsing II. Lecture 8

Principle of Compilers Lecture IV Part 4: Syntactic Analysis. Alessandro Artale

Acknowledgements. The slides for this lecture are a modified versions of the offering by Prof. Sanjeev K Aggarwal

Top-Down Parsing and Intro to Bottom-Up Parsing. Lecture 7

Chapter 4. Lexical and Syntax Analysis

Introduction to Parsing. Comp 412

The Parsing Problem (cont d) Recursive-Descent Parsing. Recursive-Descent Parsing (cont d) ICOM 4036 Programming Languages. The Complexity of Parsing

LR(0) Parsing Summary. LR(0) Parsing Table. LR(0) Limitations. A Non-LR(0) Grammar. LR(0) Parsing Table CS412/CS413

4. Lexical and Syntax Analysis

Wednesday, August 31, Parsers

Bottom Up Parsing. Shift and Reduce. Sentential Form. Handle. Parse Tree. Bottom Up Parsing 9/26/2012. Also known as Shift-Reduce parsing

Wednesday, September 9, 15. Parsers

Parsers. What is a parser. Languages. Agenda. Terminology. Languages. A parser has two jobs:

4. Lexical and Syntax Analysis

Syntax Analysis Part I

CS 406/534 Compiler Construction Parsing Part I


Parsers. Xiaokang Qiu Purdue University. August 31, 2018 ECE 468

CS 2210 Sample Midterm. 1. Determine if each of the following claims is true (T) or false (F).

Note that for recursive descent to work, if A ::= B1 B2 is a grammar rule we need First k (B1) disjoint from First k (B2).

VIVA QUESTIONS WITH ANSWERS

Top-Down Parsing and Intro to Bottom-Up Parsing. Lecture 7

Syntax Analyzer --- Parser

SLR parsers. LR(0) items

Compilers. Yannis Smaragdakis, U. Athens (original slides by Sam

Chapter 4. Lexical and Syntax Analysis. Topics. Compilation. Language Implementation. Issues in Lexical and Syntax Analysis.

LALR Parsing. What Yacc and most compilers employ.

CSE 401 Compilers. LR Parsing Hal Perkins Autumn /10/ Hal Perkins & UW CSE D-1

The analysis part breaks up the source program into constituent pieces and creates an intermediate representation of the source program.

UNIT III & IV. Bottom up parsing

LR Parsing. Table Construction

Bottom-Up Parsing LR Parsing

Syntax Analysis. Prof. James L. Frankel Harvard University. Version of 6:43 PM 6-Feb-2018 Copyright 2018, 2015 James L. Frankel. All rights reserved.

How do LL(1) Parsers Build Syntax Trees?

CS 314 Principles of Programming Languages

Simple LR (SLR) LR(0) Drawbacks LR(1) SLR Parse. LR(1) Start State and Reduce. LR(1) Items 10/3/2012

CS2210: Compiler Construction Syntax Analysis Syntax Analysis

CSC 4181 Compiler Construction. Parsing. Outline. Introduction

Parsing Techniques. CS152. Chris Pollett. Sep. 24, 2008.

Syntax Analysis Check syntax and construct abstract syntax tree

Transcription:

Parser Generation Main Problem: given a grammar G, how to build a top-down parser or a bottom-up parser for it? parser : a program that, given a sentence, reconstructs a derivation for that sentence ---- if done sucessfully, it recognize the sentence all parsers read their input left-to-right, but construct parse tree differently. bottom-up parsers --- construct the tree from leaves to root shift-reduce, LR, LR, LLR, operator precedence top-down parsers --- construct the tree from root to leaves recursive descent, predictive parsing, LL(1) Bottom-Up Parsing Construct parse tree bottom-up --- from leaves to the root Bottom-up parsing always constructs right-most derivation Important parsing algorithms: shift-reduce, LR parsing LR parser components: input, stack (strings of grammar symbols and states), driver routine, parsing tables. stack s m X m.. s 1 X 1 s 0 input: a 1 a 2 a 3 a 4... a n $ LR Parsing parsing output Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 1 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 2 of 28 LR Parsing sequence of new state symbols s 0, s 1, s 2,..., s m ----- each state sumarize the information contained in the stack below it. Parsing configurations: (stack, remaining input) written as (s 0 X 1 s 1 X 2 s 2...X m s m, a i a i+1 a i+2...a n $) next move is determined by s m and a i Parsing tables: CTION[s,a] and GOTO[s,X] Table CTION[s,a] --- s : state, a : terminal its entries (1) shift s k (2) reduce -> β (3) accept (4) error Table G GOTO[s,X] --- s : state, X : non-terminal its entries are states Constructing LR Parser How to construct the parsing table CTION and GOTO? basic idea: first construct DF to recognize handles, then use DF to construct the parsing tables! different parsing table yield different LR parsers LR(1), LR(1), or LLR(1) augmented grammar for context-free grammar G = G(T,N,P,) is defined as G = G (T, N { }, P { -> }, ) ------ adding nonterminal and the production ->, and is the new start symbol. When -> is reduced, parser accepts. LR(0) item for productions of a context-free grammar G ----- is a production with dot at some position in the r.h.s. For -> XYZ, its items are ->.XYZ -> X.YZ -> XY.Z -> XYZ. For -> ε, its items are just ->. Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 3 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 4 of 28

LR(0) items and LR(0) DF Informally, item -> X.YZ means a string derivable from X has been seen, and one from YZ is expected. LR(0) items are used as state names for LR(0) DF or LR(0) NF that recognizes viable prefixes. Viable prefixes of a CFG are prefixes of right-sentential forms with no symbols to right of the handle; we can always add terminals on right to form a right-sentential form. Two way to construct the LR(0) DF: 1. first construct LR(0) NF and then convert it to a DF! 2. construct the LR(0) DF directly! From LR(0) DF to the Parsing Table -------- transition table for the DF is the GOTO table; the states of DF are states of the parser. Example: LR(0) Items CFG Grammar: E -> E + T T T -> T * F F ugmented Grammar: E -> E E -> E + T T T -> T * F F LR(0) terms: E ->. E T ->. T * F F -> ( E. ) E -> E. T -> T. * F F -> ( E ). E ->. E + T T -> T *. F F ->. id E -> E. + T T -> T * F. F -> id. E -> E +. T T ->. F E -> E + T. T -> F. E ->. T F ->. ( E ) E -> T. F -> (. E ) Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 5 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 6 of 28 From LR(0) NF to LR(0) DF Construct LR(0) NF with all LR(0) items of G as states, connect states by moving the dot; final states are those with dots at the end. 1. for each item -> α.x β Convert NF to DF using subset construction algorithm. The states of the resulting LR(0) DF --- C = {I 1,I 2,..., I n } are called canonical LR(0) collection for grammar G Disadvantage: the NF is often huge, and converting from NF to DF is tedious and time-consuming. ->α.xβ X ->αx.β 2. for each pair -> α.b β, B ->.γ ε (expect to see a string derivable from γ ) ->α.bβ B ->.γ Building LR(0) DF Directly Instead of building DF from NF, we can build the LR(0) DF directly. Given a set of LR(0) items I, CLOURE(I) is defined as for each item -> α.bβ in I and each production B -> γ add B ->.γ to I, if it s not in I until I does not change GOTO(I,X) is defined as CLOURE(all items -> αx.β for each -> α.xβ in I) Canonical LR(0) collection is computed by the following procedure: I 0 = CLOURE({ ->.}) and C = {I 0 } for each I C and grammar symbol X T = GOTO(I,X); if T and T C then C = C { T}; until C does not change Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 7 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 8 of 28

Resulting LR(0) DF: C is the set of states; GOTO is the transition table Constructing LR(1) Parsing Table From the LR(0) DF, we can construct the parsing table ----- LR(1) parsing table. The parser based on LR(1) parsing table is called LR(1) parser. The LR(1) grammars are those whose LR(1) parsing table does not contain any conflicts. lgorithm --- use C = {I 0,...,I n }, GOTO, FOLLOW: 1. If -> a.aβ is in I i and GOTO(I i,a) = I j where a is a terminal, set CTION[i,a] to shift j. 2. If -> α. is in I i, set CTION[i,a] to reduce -> α for all terminal a in FOLLOW(). 3. If ->. is in I i, set CTION[ i,$] to accept 4. If GOTO(I i,) = I j, set GOTO[i,] = j 5. set all other entries to error 6. set initial state to be I i with ->. Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 9 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 10 of 28 Limitation of LR(1) Parser Unfortunately, many unambiguous grammars are not LR(1) gammars -> L = R R L -> *R id R -> L Canonical LR(0) collection --- L means l-value R means r-value * means contents of I0 : ->. I3: -> R. I6: -> L=.R ->.L=R R ->.L ->.R I4: L -> *.R L ->.*R L ->.*R R ->.L L ->.id L ->.id L ->.*R R ->.L L ->.id I7: L -> *R. I1 : ->. I5: L -> id. I8: R -> L. I2 : -> L.=R I9: -> L=R. R -> L. FOLLOW(R) = {=,...} state 2 has a shift/reduce conflict on = : shift 6 or reduce R - LR(1) Parsing Conflict arises because LR(0) states do not encode enough left context - -- in the previous example, reduction R -> L is wrong upon input = because R =... never appears in right-sentential form. olution: split LR(0) states by adding terminals to states, for example, [ -> α.,a] results in reduction only if next symbol is a. n LR(1) term is in the form of [ -> α.β,a] where -> αβ is a production and a is a terminal or $ To build LR(1) parsing table --- we first build LR(1) DF --- then construct the parsing table using the same LR(1) algorithm except 2. only if [ -> α.,a] is in I i, then set CTION[i,a] to reduce -> α To way to build LR(1) DF ---- from NF -> DF or build DF directly Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 11 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 12 of 28

Building LR(1) DF Construct LR(1) NF with all LR(1) items of G as states, connect states by moving the dot; then convert the NF to DF. 1. for each item [ -> α.x β,a] 2. for each pair [ -> α.bβ,a] B ->.γ and b in FIRT( β a ). ->α.bβ, a Construct the LR(1) DF directly (see the Dragon book) Given a set of LR(1) items I, ->α.xβ, a ->αx.β, a CLOURE(I) is now defined as for each item [ -> α.bβ, a] in I and each production B -> γ and each terminal b in FIRT(βa) add [B ->.γ, a] to I, if it s not in I until I does not change X ε B ->.γ, b Constructing LR(1) Parser Canonical LR(1) collection is computed by the following procedure: I 0 = CLOURE([ ->., $]) and C = {I 0 } for each I C and grammar symbol X T = GOTO(I,X); if T and T C then C = C { T}; until C does not change Resulting LR(1) DF: C is the set of states; GOTO is the transition table From the LR(1) DF, we can construct the parsing table ----- LR(1) parsing table. The parser based on LR(1) parsing table is called LR(1) parser. The LR(1) grammars are those whose LR(1) parsing table does not contain any conflicts (no duplicate entries). Example: -> -> C C C -> c C d Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 13 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 14 of 28 LLR(1) Parsing Bad News: LR(1) parsing tables are too big; for PCL, LR tables has about 100 states, LR table has about 1000 states. LLR (Lookhead-LR) parsing tables have same number of states as LR, but use lookahead for reductions. The LLR(1) DF can be constructed from the LR(1) DF. LLR(1) states can be constructed from LR(1) states by merging states with same core, or same LR(0) items, and union their lookahead sets. Merging I8: C -> cc., c/d I9: C -> cc., $ into a new state I89: C -> cc., c/d/$ Merging I3: C -> c.c, c/d I6: C -> c.c, $ C ->.cc, c/d C ->.cc, $ C ->.d, c/d C ->.d, $ into a new state I36: C -> c.c, c/d/$ C ->.cc, c/d/$ C ->.d, c/d/$i LLR(1) Parsing (cont d) From the LLR(1) DF, we can construct the parsing table ----- LLR(1) parsing table. The parser based on LLR(1) parsing table is called LLR(1) parser. The LLR(1) grammars are those whose LLR(1) parsing table does not contain any conflicts (no duplicate entries). LLR(1) DF and LLR(1) parsing table can be constructed without creating LR(1) DF --- see Dragon book for detailed algorithm. LLR parser makes same number of moves as LR parser on correct input. On incorrect input, LLR parser may make erroneous reductions, but will signal error before shifting input, i.e., merging states makes reduce determination less accurate, but has no effect on shift actions. Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 15 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 16 of 28

ummary: LR Parser Relation of three LR parsers: LR(1) > LLR(1) > LR(1) Most programming language constructs are LLR(1). The LR(1) is unnecessary in practice, but the LR(1) is not enough. YCC is an LLR(1) Parser Generator. When parsing ambiguious grammars using LR parsers, the parsing table will contain multiple entries. We can specify the precedence and associativity for terminals and productions to resolve the conflicts. YCC uses this trick. Other Issues in parser implementation: 1. compact representation of parsing table 2. error recovery and diagnosis. Top-Down Parsing tarting from the start symbol and guessing which production to use next step. It often uses next input token to guide guessing. example: c c matches -> c d -> ab a input symbols: cad we are looking ahead only one at a time! d c a try to decide which rule of to use here? b d c backtrack! decide to use 1st alternative of a d guessed wrong, backtrack and try another one! Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 17 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 18 of 28 Top-Down Parsing (cont d) Typical implementation is to write a recursive procedure for each non-terminal (according to the r.h.s. of each grammar rule) Grammar: advance sets c to next input token err reports error message Recursive Descent Parsing The previously referred top-down parsing method is often called recursive descent parsing! Main challenges: E -> T E E -> + T E ε T -> F T T -> * F T ε F -> id ( E ) fun e() = (t(); eprime()) and eprime() = if (c = + ) then (advance(); t(); eprime()) and t() = (f(); tprime()) and tprime() = if (c = * ) then (advance(); f(); tprime()) and f() = (if (c = id) then advance() else if (c = ( ) then (advance(); e(); if (c= ) ) then advance() else err()) else err() 1. back-tracking is messy, difficult and inefficient (solution: use input lookahead to help make the right choice) 2. more alternatives --- even if we use one lookahead input char, there are still > 1 rules to choose --- -> ab a (solution: rewrite the grammar by left-factoring) 3. left-recursion might cause infinite loop what is the procedure for E -> E + E? (solution: rewrite the grammar by eliminating left-recursions) 4. error handling --- errors detected far away from actual source. Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 19 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 20 of 28

lgorithm: Recursive Descent Parsing lgorithm (using 1-symbol lookahead in the input) 1. Given a set of grammar rules for a non-terminal -> α 1 α 2... α n we choose proper alternative by looking at first symbol it derives ---- the next input symbol decides which α i we use 2. for -> ε, it is taken when none of the others are selected lgorithm: constructing a recursive descent parser for grammar G 1. transform grammer G to G by removing left-recursions and do the left-factoring. 2. write a (recursive) procedure for each non-terminal in G Left Recursion Elimination Elimination of Left Recursion (useful for top-down parsing only) replace productions of the form -> α β with -> β -> α ε (yields different parse trees but same language) α β α α β α α α ε example: E -> E + T T T -> T * F F become E -> T E E -> + T E ε T -> F T T -> * F T ε Important: read ppel pp 51-53 for details Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 21 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 22 of 28 Left Factoring ome grammars are unsuitable for recursive descent, even if there is no left recursion dangling-else stmt -> if expr then stmt if expr then stmt else stmt... input symbol if does not uniquely determine alternative. Left Factoring --- factor out the common prefixes (see HU pp 178) change the production -> x y x z to -> x -> y z thus stmt -> if expr then stmt -> else stmt ε Predictive Parsing Predictive parsing is just table-driven recursive descent; it contains: parsing stack --- contains terminals and non-terminals parsing table : a 2-dimensional table M[X,a] where X is nonterminal, a is terminal, and table entries are grammar productions or error indicators. algorithm $ is end-of-file, is start symbol push($); push(); while top <> $ do ( a <- the input char if top is a terminal or $ then (if top == a then pop(); advance() else err()) else if M[top,a] is X->Y 1 Y 2...Y k then (pop(); push(y k );...; push(y 1 )) else err() ) input: X... Y Z $ stack a 1 a 2 a 3 a 4... a n $ Predictive Parser Parsing Table M output Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 23 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 24 of 28

Constructing Predictive Parser The key is to build the parse table M[,a] for each production -> α do for each a FIRT(α) do add -> α to M[,a] if ε FIRT(α) then for each b FOLLOW() do add -> α to M[,b] rest of M is error FIRT(α) is a set of terminals (plus ε) that begin strings derived from α, where α is any string of non-terminals and terminals. FOLLOW() is a set of terminals that can follow in a sentential form, where is any non-terminal First & Follow To compute FIRT(X) for any grammar symbol X: FIRT(X) = {X}, if X is a terminal; FIRT(X) = FIRT(X) {a}, if X -> aα ; FIRT(X) = FIRT(X) {ε}, if X -> ε; and FIRT(X) = FIRT(X) FIRT(Y 1 Y 2...Y k ), if X -> Y 1 Y 2...Y k. until nothing new is added to any FIRT FIRT(Y 1 Y 2...Y k ) = FIRT(Y 1 )-{ε} FIRT(Y 2 )-{ε} if ε FIRT(Y 1 ) FIRT(Y 3 )-{ε} if ε FIRT(Y 1 Y 2 )... FIRT(Y k )-{ε} if ε FIRT(Y 1...Y k-1 ) {ε} if all FIRT(Y i ) (i=1,...,k) contain ε Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 25 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 26 of 28 First & Follow (cont d) To compute FOLLOW(X) for any non-terminal X: FOLLOW() = FOLLOW() {$}, if is start symbol; FOLLOW(B) = FOLLOW(B) (FIRT(β) - {ε}), if -> α B β and β ε FOLLOW(B) = FOLLOW(B) FOLLOW() if -> α B or -> α B β and ε FIRT(β) Example: reason FOLLOW(E) = {$}, E is start symbol = {$ )}, F -> ( E ) FOLLOW(E )= FOLLOW(E) E -> T E = {$ )}, (Read ppel pp 47-53 for detailed examples) ummary: LL(1) Grammars grammar is LL(1) if parsing table M[,a] has no duplicate entries, which is equivalent to specifying that for each production 1. ll FIRT(α i ) are disjoint. -> α 1 α 2... α n 2. t most one α i can derive ε ; in that case, FOLLOW() must be disjoint from FIRT(α 1 ) FIRT(α 2 )... FIRT(α n ) Left-recursion and ambiguity grammar lead to multiple entries in the parsing table. (try the dangling-else example) The main difficulty in using (top-down) predicative parsing is in rewriting a grammar into an LL(1) grammar. There is no general rule on how to resolve multiple entries in the parsing table. Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 27 of 28 Copyright 1994-2005 Zhong hao, Yale University Parser Generation: Page 28 of 28