Functional List C and Data Structures Baojian Hua [email protected].
LL(k) Parsing Compiler Baojian Hua [email protected].
Click here to load reader
-
Upload
adele-sharon-davidson -
Category
Documents
-
view
241 -
download
1
Transcript of LL(k) Parsing Compiler Baojian Hua [email protected].
![Page 2: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/2.jpg)
Front End
source code
abstract syntax
tree
lexical analyzer
parser
tokens
IRsemantic analyzer
![Page 3: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/3.jpg)
Parsing
The parser translates the source program into abstract syntax trees Token sequence:
from the lexer abstract syntax trees:
compiler internal data structures for programs check (syntactic) validity of programs
Must take account the program syntax
![Page 4: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/4.jpg)
Conceptually
token sequence
abstract
syntax treeparser
language syntax
![Page 5: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/5.jpg)
Syntax: Context-free Grammar
Context-free grammars are (often) given by BNF expressions (Backus-Naur Form) read dragon-book sec 2.2
More powerful than RE in theory Good for defining language syntax
![Page 6: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/6.jpg)
Context-free Grammar (CFG)
A CFG consists of 4 components: a set of terminals (tokens): T a set of nonterminals: N a set of production rules: P
s -> t1 t2 … tn with sN, and t1, …, tn (T ∪N)
a unique start nonterminal: S
![Page 7: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/7.jpg)
Example// SLP as in Tiger book chap. 1 (simplified):
N = {S, E}T = {SEMICOLON, ID, IF, ASSIGN, …}S = S
S -> S SEMICOLON S | ID ASSIGN E | PRINT LPAREN E RPARENE -> ID | NUM | E PLUS E | E TIMES E
![Page 8: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/8.jpg)
Derivation
A derivation: Starts with the unique start nonterminal S repeatedly replacing a right-hand nonter
minal s by the body of a production rule of the nonterminal s
stop when right-hand are all terminals The final string consists of terminals o
nly and is called a sentence (program)
![Page 9: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/9.jpg)
ExampleS -> S ; S | id := E | print (E)E -> …
x := 5;print (x)
derive me
S -> … (a choice)
![Page 10: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/10.jpg)
Example
x := 5;print (x)
derive meS -> S ; S -> x := E ; S -> x := 5 ; S -> x := 5 ; print (E) -> x := 5 ; print (x)
S -> S ; S | id := E | print (E)E -> id | num | E + E | E * E
![Page 11: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/11.jpg)
Another Try to Derive the same Program
x := 5;print (x)
derive me
S -> x := E -> x := 5 -> // stuck! :-(
S -> S ; S | id := E | print (E)E -> …
![Page 12: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/12.jpg)
Derivation For same string, there may exist
many different derivations left-most derivation right-most derivation
Parsing is the problem of taking a string of terminals and figure out whether it could be derived from a CFG error-detection
![Page 13: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/13.jpg)
Parse Trees Derivation can also be represented as trees
useful to understand AST (discussed later) Idea:
each internal node is labeled with a nonterminal
each leaf node is labeled with a terminal each use of a rule in a derivation explains how t
o generate children in the parse tree from the parent
![Page 14: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/14.jpg)
ExampleS -> S ; S
| …
x := 5;print (x)
derive me
S
S ; S
x := E
5
print E
x
( )
![Page 15: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/15.jpg)
Parse Tree has Meanings:post-order traversalS -> S ; S
| …
x := 5;print (x)
derive me
S
S ; S
x := E
5
print E
x
( )
![Page 16: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/16.jpg)
Ambiguous Grammars
A grammar is ambiguous if the same sequence of tokens can give rise to two or more different parse trees
![Page 17: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/17.jpg)
ExampleE -> num | id | E + E | E * E
3+4*5
derive me
E -> E + E -> 3 + E -> 3 + E * E -> 3 + 4 * E -> 3 + 4 * 5E -> E * E -> E + E * E -> 3 + E * E -> 3 + 4 * E -> 3 + 4 * 5
![Page 18: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/18.jpg)
ExampleE -> num | id | E + E | E * E
E -> E + E -> 3 + E -> 3 + E * E -> 3 + 4 * E -> 3 + 4 * 5E -> E * E -> E + E * E -> 3 + E * E -> 3 + 4 * E -> 3 + 4 * 5
E
E + E
3 E * E
54
E
E * E
5E + E
43
![Page 19: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/19.jpg)
Ambiguous Grammars Problem: compilers make use of parse trees
to interpret the meaning of parsed programs different parse trees have different meanings eg: 4 + 5 * 6 is not (4 + 5) * 6 languages with ambiguous grammars are DISAST
ROUS; the meaning of programs isn’t well-defined! You can’t tell what your program might do!
Solution: rewrite grammar to equivalent forms
![Page 20: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/20.jpg)
Eliminating ambiguity In programming language syntax, am
biguity often arises from missing operator precedence or associativity * is of high precedence than + both + and * are left-associative Why or why not?
Rewrite grammar to take account of this
![Page 21: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/21.jpg)
ExampleE -> num | id | E + E | E * E
E -> E + T | TT -> T * F | FF -> num | id
Q: is the right grammar ambiguous? Why or why not?
![Page 22: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/22.jpg)
Parser A program to check whether a program is d
erivable from a given grammar expensive in general must be fast
to compile a 2000k lines of kernel even for small application code, speed may be a conce
rn Theorists have developed specialized kind
of grammar which may be parsed efficiently LL(k) and LR(k)
![Page 23: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/23.jpg)
Recursive Decedent Parsing
![Page 24: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/24.jpg)
Predictive parsing A.K.A: Recursive descent parsing, top-down
parsing simple to code by hand efficient can parse a large set of grammar your Tiger compiler will use this
Key idea: one (recursive) function for each nonterminal one clause for each right-hand production rule
![Page 25: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/25.jpg)
Connecting with the lexer(* step #1: represent tokens *)token = ID | IF | NUM | ASSIGN | SEMICOLON | LPAREN | RPAREN | …(* step #2: connect with lexer *)token current_token; /* external var */
void eat (token t) = if (current_token = t) current_token = Lex_nextToken (); else error (“want “, t, “but got”, current_token)
![Page 26: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/26.jpg)
stm -> stm ; stm | id := exp | print (exp)exp -> ID | NUM | exp + exp | exp * exp
(* step #1: cook a lexer, including tokens *)struct token current_token = lex ();(* step #2: build the parser *)void parse_stm () = switch (current_token) case ID => eat (ID); eat (ASSIGN); parse_exp (); case PRINT => eat (PRINT); eat (LPAREN); parse_exp (); eat (RPAREN); default =>error(“want ID, PRINT”);
void parse_exp () = switch (current_token) case ID: ??? case NUM: ??? // backtracking!!
parse_stm()parse_exp()
![Page 27: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/27.jpg)
How to handle precedence?void parse_stm_all ()
parse_stm();
while (current_token == “;”)
eat (;);
parse_stm ();
void parse_exp_plus ()
parse_exp_times();
while (current_token == “+”)
eat (+);
parse_exp_times();
stm ; stm ; stm ; stm
2+3*4+5*7
Generally: if there are n level of precedence, one may write n parsing functions.
![Page 28: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/28.jpg)
Moral The key point in predicative parsing is
to determine the production rule to use (recursive function to call) must know the “start” symbols of each rule “start” symbol must not overlap e.g.:
exp -> NUM | ID
This motivates the idea of first and follow sets
![Page 29: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/29.jpg)
First & Follow
![Page 30: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/30.jpg)
Moral
S -> w1
-> w2
-> …
-> wn
For nonterminal S, and current input token t if wk starts with t, then choose wk,
or if wk derives empty string, and the
string follow S starts with t First symbol sets of wi (1<=i<=n)
don’t overlap to avoid backtracking
![Page 31: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/31.jpg)
Nullable, First and Follow sets To use predicative parsing, we must compu
te: Nullable: nonterminals that derive empty string First(ω) : set of terminals that can begin any stri
ng derivable from ω Follow(X): set of terminals that can immediately
follow any string derivable from nonterminal X Read tiger sec 3.2
Fixpoint algorithms
![Page 32: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/32.jpg)
Nullable, First and Follow sets Which symbol X, Y and Z
can derive empty string? What terminals may the
string derived from X, Y and Z begin with?
What terminals may follow X, Y and Z?
Z -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
![Page 33: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/33.jpg)
Nullable If X can derive an empty string, iff:
base case: X ->
inductive case: X -> Y1 … Yn
Y1, …, Yn are n nonterminals and may all derive empty strings
![Page 34: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/34.jpg)
Computing Nullable/* Nullable: a set of nonterminals */Nullable <- {};while (Nullable still changes) for (each production X -> α) switch (α) case : Nullable = {X};∪ break; case Y1 … Yn: if (Y1Nullable && … && YnNullable) Nullable = {X};∪ break;
![Page 35: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/35.jpg)
Example: NullablesZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round 0 1 2
nullable {}
![Page 36: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/36.jpg)
Example: NullablesZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round 0 1 2
nullable {} {Y, X}
![Page 37: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/37.jpg)
Example: NullablesZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2
Φ {} {Y, X} {Y, X}
![Page 38: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/38.jpg)
First(X) Set of terminals that X begins with:
X => a … Rules
base case: X -> a
First (X) ∪= {a} inductive case:
X -> Y1 Y2 … Yn First (X) ∪= First(Y1) if Y1Nullable, First (X) ∪= First(Y2) if Y1,Y2 Nullable, First (X) ∪= First(Y3) …
![Page 39: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/39.jpg)
Computing First// Suppose Nullable set has been computedforeach (nonterminal X) First(X) <- {}; while (some First set still changes) for (each production X -> α) switch (α) case a: First(X) = {a};∪ break; case Y1 … Yn: First(X) = First(Y1);∪ if (Y1 \not\in Nullable) break; First(X) = First(Y2);∪ …; // Similar as above
![Page 40: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/40.jpg)
Example: FirstZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2 3
First(Z)
{}
First(Y)
{}
First(X)
{}
Nullable = {X, Y}
![Page 41: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/41.jpg)
Example: FirstZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2 3
First(Z)
{} {d}
First(Y)
{} {c}
First(X)
{} {c, a}
Nullable = {X, Y}
![Page 42: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/42.jpg)
Example: FirstZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2 3
First(Z)
{} {d} {d, c, a}
First(Y)
{} {c} {c}
First(X)
{} {c, a} {c, a}
Nullable = {X, Y}
![Page 43: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/43.jpg)
Example: FirstZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2 3
First(Z)
{} {d} {d, c, a}
{d, c, a}
First(Y)
{} {c} {c} {c}
First(X)
{} {c, a} {c, a} {c, a}
Nullable = {X, Y}
![Page 44: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/44.jpg)
Parsing with FirstZ -> d {d}
-> X Y Z {a, c, d}
Y -> c {c}
-> {}
X -> Y {c}
-> a {a}
First(Z)
{d, c, a}
First(Y)
{c}
First(X)
{c, a}Nullable = {X, Y}
Now consider this string: d
Suppose we choose the production: Z -> X Y Z
But we get stuck at:X -> Y -> aBut neither can accept d!What’s the problem?
![Page 45: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/45.jpg)
Follow(X) Set of terminals that may follow X:
S => … X a … Rules:
Base case: Follow (X) = {}
inductive case: Y -> ω1 X ω2
Follow(X) ∪= Fisrt(ω2) if ω2 is Nullable, Follow(X) ∪= Follow(Y)
![Page 46: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/46.jpg)
Computing Follow(X)foreach (nonterminal X) Follow(X) <- {};while (some Follow still changes) { for (each production Y -> ω1 X ω2 ) Follow(X) = First (∪ ω2); if (ω2 is Nullable) Follow(X) = Follow (Y);∪
![Page 47: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/47.jpg)
Example: FollowZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round 0 1 2 3
First(Z)Follow(Z)
{d, c, a}{}
First(Y)Follow(Y)
{c}{}
First(X)Follow(X)
{c, a}{}
Nullable = {X, Y}
![Page 48: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/48.jpg)
Example: FollowZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round 0 1 2 3
First(Z)Follow(Z)
{d, c, a}{}
{$}
First(Y)Follow(Y)
{c}{} {d, c,
a}
First(X)Follow(X)
{c, a}{} {d, c,
a}
Nullable = {X, Y}
![Page 49: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/49.jpg)
Example: FollowZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round 0 1 2 3
First(Z)Follow(Z)
{d, c, a}{}
{$} {$}
First(Y)Follow(Y)
{c}{} {d, c,
a}{d, c, a}
First(X)Follow(X)
{c, a}{} {d, c,
a}{d, c, a}
Nullable = {X, Y}
![Page 50: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/50.jpg)
Predicative Parsing Table
With Nullables, First(), and Follow(), we can make a parsing table P(N,T) each entry contains a set of productions
t1 t2 t3 t4 … $(EOF)
N1 ri
N2 rk
N3 rj
…
![Page 51: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/51.jpg)
Predicative Parsing Table
For each rule X -> ω for each aFirst(ω), add X -> ω to P(X, a) if X is nullable, add X -> ω to P(X, b) for ea
ch b Follow (X) all other entries are “error”
t1 t2 t3 t4 … $(EOF)
N1 r1
N2 rk
N3 ri
…
![Page 52: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/52.jpg)
Example: Predicative Parsing Table
First(X)Follow(X)
{c, a}{c, d, a}
First(Y)Follow(Y)
{c}{c, d, a}
First(Z)Follow(Z)
{d, c, a}{$}
Z -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Nullable = {X, Y}
a c d
Z Z->X Y Z Z->X Y Z Z->dZ->X Y Z
Y Y-> Y->cY->
Y->
X X->YX->a
X->Y X->Y
![Page 53: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/53.jpg)
Example: Predicative Parsing Table
First(X)Follow(X)
{c, a}{c, d, a}
First(Y)Follow(Y)
{c}{c, d, a}
First(Z)Follow(Z)
{d, c, a}{$}
Z -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Nullable = {X, Y}
a c d
Z Z->X Y Z Z->X Y Z Z->dZ->X Y Z
Y Y-> Y->cY->
Y->
X X->YX->a
X->Y X->Y
![Page 54: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/54.jpg)
LL(1) A context-free grammar is called LL(1) if it can be parsed this way: Left-to-right parsing Leftmost derivation 1 token lookahead
This means that in the predicative parsing table, there is at most one production in every entry
![Page 55: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/55.jpg)
Speeding up set Construction
All these sets (Nullable, First, Follow) can be computed simultaneously see Tiger book algorithm 3.13
Order the computation: What’s the optimal order to compute th
ese set?
![Page 56: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/56.jpg)
Example: Speeding up set Construction
Z -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Round
0 1 2 3
First(Z)
{}
First(Y)
{}
First(X)
{}
Nullable = {X, Y}
Q1: What’s reasonable order here?
Q2: How to set this order?
![Page 57: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/57.jpg)
Directed Graph ModelZ -> d
-> X Y Z
Y -> c
->
X -> Y
-> a
Nullable = {X, Y}
Q1: What’s reasonable order here?
Q2: How to set this order?
Z
X
Y{c}
{c, a}
{d, c, a}
Order: Y X Z
![Page 58: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/58.jpg)
Reverse Quasi-Topological Sort Quasi-topological sort the directed graph
Quasi: topo-sort general directed graph is impossible
also known as reverse depth-first ordering Reverse: information (here: First) flows fro
m successors backward to predecessors Refer to your favorite algorithm book
![Page 59: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/59.jpg)
Problem
LL(1) can only be used with grammars in which every production rules for a nonterminal start with different terminals
Unfortunately, many grammars don’t have this perfect property
![Page 60: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/60.jpg)
Exampleexp -> NUM -> ID -> exp + exp -> exp * exp
exp -> exp + term -> termterm -> term * factor -> factorfactor -> NUM -> ID
Q: is the right grammar LL(1)? Why or why not?
![Page 61: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/61.jpg)
Solutions
Left-recursion elimination Left-factoring Read:
tiger section 3.2
![Page 62: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/62.jpg)
Example for SLPstm -> id := exp A -> print(exp) AA -> ; stm A ->
Q1: is the right grammar LL(1)?
Q2: are these two grammars equivalent?
stm -> stm ; stm -> id := exp -> print (exp)
![Page 63: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/63.jpg)
LL(k) LL(1) can be further generalized to LL
(k): Left-to-right parsing Leftmost derivation k token lookahead
Q: table size? other problems with this approach?
![Page 64: LL(k) Parsing Compiler Baojian Hua bjhua@ustc.edu.cn.](https://reader037.fdocuments.in/reader037/viewer/2022100221/56649f445503460f94c65937/html5/thumbnails/64.jpg)
Summary Context-free grammar is a math tool for spe
cifying language syntax among others…
Writing parsers for general grammar is hard and costly LL(k) and LR(k)
LL(1) grammars can be implemented efficiently table-driven algorithms (again!)