CSE443 Compilers
- Dr. Carl Alphonce
CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis - - PowerPoint PPT Presentation
CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall Phases of a Syntactic compiler structure Figure 1.6, page 5 of text FIRST(X) if X T then FIRST(X) = { X } if X N and X -> Y 1 Y 2 Y k P for k
Figure 1.6, page 5 of text
if X ∈ T then FIRST(X) = { X } if X ∈ N and X -> Y1 Y2 … Yk ∈ P for k≥1, then add a ∈ T to FIRST(X) if ∃i s.t. a ∈ FIRST(Yi) and 𝜁 ∈ FIRST(Yj) ∀ j < i (i.e. Y1 Y2 … Yk ⇒* 𝜁 ) if 𝜁 ∈ FIRST(Yj) ∀ j < k add 𝜁 to FIRST(X)
FIRST SETS
FIRST(F) = { ( , id } F -> ( E ) here's where the parenthesis comes from F -> id here's where id comes from FIRST(T) = FIRST(F) = { ( , id } T -> F T' (T' not relevant since 𝜁 not in FIRST(F)) FIRST(E) = FIRST(T) = FIRST(F) = { ( , id } E -> T E' (E' not relevant since 𝜁 not in FIRST(T)) FIRST(E') = { + , 𝜁 } E' -> + T E' here's where + comes from E' -> 𝜁 here's where 𝜁 comes from FIRST(T') = { * , 𝜁 } T' -> * F T' here's where * comes from T' -> 𝜁 here's where 𝜁 comes from
For each production A -> 𝛽 of G: For each terminal a ∈ FIRST(𝛽), add A -> 𝛽 to M[A,a] If 𝜁 ∈ FIRST(𝛽), then for each terminal b in FOLLOW(A), add A - > 𝛽 to M[A,b] If 𝜁 ∈ FIRST(𝛽) and $ ∈ FOLLOW(A), add A -> 𝛽 to M[A,$]
if X ∈ T then FIRST(X) = { X } if X ∈ N and X -> Y1 Y2 … Yk ∈ P for k≥1, then add a ∈ T to FIRST(X) if ∃i s.t. a ∈ FIRST(Yi) and 𝜁 ∈ FIRST(Yj) ∀ j < i (i.e. Y1 Y2 … Yk ⇒* 𝜁 ) if 𝜁 ∈ FIRST(Yj) ∀ j < k add 𝜁 to FIRST(X) E -> T E' E' -> + T E' | 𝜁 T -> F T' T' -> * F T' | 𝜁 F -> ( E ) | id
For each production A -> 𝛽 of G: For each terminal a ∈ FIRST(𝛽), add A -> 𝛽 to M[A,a] If 𝜁 ∈ FIRST(𝛽), then for each terminal b in FOLLOW(A), add A - > 𝛽 to M[A,b] If 𝜁 ∈ FIRST(𝛽) and $ ∈ FOLLOW(A), add A -> 𝛽 to M[A,$]
1. Place $ in FOLLOW(S), where S is the start symbol ($ is an end marker) 2. if A -> 𝛽B𝛾 ∈ P, then FIRST(𝛾) - {𝜁} is in FOLLOW(B)
then everything in FOLLOW(A) is in FOLLOW(B)
FOLLOW SETS
FOLLOW(E) = { ) , $ } E is our start symbol, so by rule 1 we add $ to FOLLOW(E). E appears in right hand side (RHS) of one production: F -> ( E ) By rule 2, we add ) to FOLLOW(E) since ) follows E in this production. FOLLOW(E') = FOLLOW(E) = { ) , $ } E' appears in RHS of two productions: E -> T E' and E' -> + T E' By rule 3, we add everything from FOLLOW(E) = { ) , $ } to FOLLOW(E'). FOLLOW(T) = { + , ) , $ } T appears in RHS of two productions: E -> T E' and E' -> + T E' By rule 2, we add everything from FIRST(E') = { + , 𝜁 } - { 𝜁 } = { + } to FOLLOW(T). By rule 3, since 𝜁 ∈ FIRST(E'), add everything from FOLLOW(E) = FOLLOW(E') ={ ) , $ } to FOLLOW(T). FOLLOW(T') = FOLLOW(T) = { + , ) , $ } T' appears in RHS of two productions: T -> F T' and T' -> * F T' By rule 3, we add everything from FOLLOW(T) = { + , ) , $ } to FOLLOW(T'). FOLLOW(F) = { + , * , ) , $ } F appears in RHS of two productions: T -> F T' and T' -> * F T' By rule 2, we add everything from FIRST(T') = { * , 𝜁 } - { 𝜁 } = { * } to FOLLOW(F). By rule 3, since 𝜁 ∈ FIRST(T'), add everything from FOLLOW(T) = FOLLOW(T') ={ + , ) , $ } to FOLLOW(F).
E -> T E' E' -> + T E' | 𝜁 T -> F T' T' -> * F T' | 𝜁 F -> ( E ) | id
INPUT: Grammar G = (N,T,P,S) OUTPUT: Parsing table M For each production A -> 𝛽 of G:
M[A,a]
FOLLOW(A), add A -> 𝛽 to M[A,b]
M[A,$]
NON TERMINALS
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
For each production A -> 𝛽 of G: For each terminal a ∈ FIRST(𝛽), add A -> 𝛽 to M[A,a] If 𝜁 ∈ FIRST(𝛽), then for each terminal b in FOLLOW(A), add A -> 𝛽 to M[A,b] If 𝜁 ∈ FIRST(𝛽) and $ ∈ FOLLOW(A), add A -> 𝛽 to M[A,$]
FIRST(E) = FIRST(T) = FIRST(F) = { ( , id } FIRST(E') = { + , 𝜁 } FIRST(T') = { * , 𝜁 } FOLLOW(E') = FOLLOW(E) = { ) , $ } FOLLOW(T') = FOLLOW(T) = { + , ) , $ } FOLLOW(F) = { + , * , ) , $ } E -> T E' E' -> + T E' | 𝜁 T -> F T' T' -> * F T' | 𝜁 F -> ( E ) | id
INPUT: A string 𝜕 and a parsing table M for a grammar G=(N,T,P,S). OUTPUT: If 𝜕∈𝓜(G), a leftmost derivation of 𝜕, error otherwise
$ S $ 𝜕
stack input
parser M
Let a be the first symbol of 𝜕 Let X be the top stack symbol while (X ≠ $) { if (X == a) { pop the stack, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop the stack push Yk … Y2 Y1 onto the stack } Let X be the top stack symbol } Accept if a == X == $
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E'
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T'
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E'
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T'
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T'
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> 𝜁
if (X == a) { pop, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E'
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T' T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> 𝜁 id + id * id $ $ Since both a and X are $, accept
while (X ≠ $) { if (X == a) { pop the stack, advance a in 𝜕 } else if (X is a terminal) { error } else if (M[X,a] is blank) { error } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop the stack push Yk … Y2 Y1 onto the stack } Let X be the top stack symbol } Accept if a == X == $
INPUT (a) STACK (X) OUTPUT id + id * id $ E $ E -> T E' id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> + T E' id + id * id $ + T E' $ id + id * id $ T E' $ T -> F T' id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> * F T' id + id * id $ * F T' E' $ id + id * id $ F T' E' $ F -> id id + id * id $ id T' E' $ id + id * id $ T' E' $ T' -> 𝜁 id + id * id $ E' $ E' -> 𝜁 id + id * id $ $ Since both a and X are $, accept
Skip input symbols until a synchronizing token appears. 1. synch(A) includes FOLLOW(A) 2. … <expr> ; FOLLOW(<expr>) is {';'}, but if ';' is missing, then include all keyword-beginning statement starts in synch(A) 3. add contents of FIRST(A) to synch(A)
5. if terminal a on the stack cannot be matched, pop it and issue a message "'a ' was inserted". (Synch is set to all other tokens.)
NON TERMINALS
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' T -> F T'
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
synch is added to each blank M[X,a] when a ∈ FOLLOW(X) FOLLOW(E) = FOLLOW(E') = { ) , $ }
NON TERMINALS
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id F -> ( E )
synch is added to each blank M[X,a] when a ∈ FOLLOW(X) FOLLOW(T) = FOLLOW(T') = { + , ) , $ }
NON TERMINALS
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
synch is added to each blank M[X,a] when a ∈ FOLLOW(X) FOLLOW(F) = { + , * , ) , $ }
NON TERMINALS
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
synch is added to each blank M[X,a] when a ∈ FOLLOW(X) FOLLOW(E) = FOLLOW(E') = { ) , $ } FOLLOW(T) = FOLLOW(T') = { + , ) , $ } FOLLOW(F) = { + , * , ) , $ }
Algorithm 4.34 (modified w/ error handling)
Let a be the first symbol of 𝜕 Let X be the top stack symbol while (X ≠ $) { if (x == a) { pop the stack, advance a in 𝜕 } else if (X is a terminal) { pop stack } else if (M[X,a] is blank) { advance a in 𝜕 } else if (M[X,a] is synch) { pop stack } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop the stack push Yk … Y2 Y1 onto the stack } Let X be the top stack symbol } Accept if a == X == $
INPUT (a) STACK (X) OUTPUT + id * + id $ E $ ???
if (x == a) { pop, advance a in 𝜕 } else if (X is a terminal) { pop } else if (M[X,a] is blank) { advance a in 𝜕 } else if (M[X,a] is synch) { pop } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
INPUT (a) STACK (X) OUTPUT + id * + id $ E $ error, skip + Since there were errors, do not accept.
if (x == a) { pop, advance a in 𝜕 } else if (X is a terminal) { pop } else if (M[X,a] is blank) { advance a in 𝜕 } else if (M[X,a] is synch) { pop } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
INPUT (a) STACK (X) OUTPUT + id * + id $ E $ error, skip + + id * + id $ E $ E -> T E' + id * + id $ T E' $ T -> F T' + id * + id $ F T' E' $ F -> id + id * + id $ id T' E' $ + id * + id $ T' E' $ T' -> * F T' + id * + id $ * F T' E' $ + id * + id $ F T' E' $ ??? Since there were errors, do not accept.
if (x == a) { pop, advance a in 𝜕 } else if (X is a terminal) { pop } else if (M[X,a] is blank) { advance a in 𝜕 } else if (M[X,a] is synch) { pop } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
INPUT (a) STACK (X) OUTPUT + id * + id $ E $ error, skip + + id * + id $ E $ E -> T E' + id * + id $ T E' $ T -> F T' + id * + id $ F T' E' $ F -> id + id * + id $ id T' E' $ + id * + id $ T' E' $ T' -> * F T' + id * + id $ * F T' E' $ + id * + id $ F T' E' $
error, M[F ,+] = synch, pop F
Since there were errors, do not accept.
if (x == a) { pop, advance a in 𝜕 } else if (X is a terminal) { pop } else if (M[X,a] is blank) { advance a in 𝜕 } else if (M[X,a] is synch) { pop } else if (M[X,a] is X -> Y1 Y2 … Yk) {
pop push Yk … Y2 Y1 } Let X be the top stack symbol
id + * ( ) $ E
E -> T E' E -> T E' synch synch
E'
E' -> + T E' E' -> 𝜁 E' -> 𝜁
T
T -> F T' synch T -> F T' synch synch
T'
T' -> 𝜁 T' -> * F T T' -> 𝜁 T' -> 𝜁
F
F -> id synch synch F -> ( E ) synch synch
INPUT (a) STACK (X) OUTPUT + id * + id $ E $ error, skip + + id * + id $ E $ E -> T E' + id * + id $ T E' $ T -> F T' + id * + id $ F T' E' $ F -> id + id * + id $ id T' E' $ + id * + id $ T' E' $ T' -> * F T' + id * + id $ * F T' E' $ + id * + id $ F T' E' $
error, M[F ,+] = synch, pop F
+ id * + id $ T' E' $ T' -> 𝜁 + id * + id $ E' $ E' -> + T E' + id * + id $ + T E' $ + id * + id $ T E' $ T -> F T' + id * + id $ F T' E' $ F -> id + id * + id $ id T' E' $ + id * + id $ T' E' $ T' -> 𝜁 + id * + id $ E' $ E' -> 𝜁 + id * + id $ $ Since there were errors, do not accept.
Examples will use this grammar: E -> E + T E -> T T -> T * F T -> F F -> ( E ) F -> id This is the left-recursive grammar we could not use directly with our top-down predictive parser
"Informally, a 'handle' is a substring that matches the body of a production and whose reduction represents one step along the reverse
Formally, if S ⇒*rm 𝛽A𝜕 ⇒*rm 𝛽𝛾𝜕, then the production A -> 𝛾 in the position following 𝛽 is a handle of 𝛽𝛾𝜕
" A handle A -> 𝛾 in the parse tree for 𝛽𝛾𝜕" Fig 4.27 [p. 236]
" Alternatively, a handle of a right- sentential form 𝛿 is a production A -> 𝛾 and a position of 𝛿 where the string 𝛾 may be found, such that replacing 𝛾 at that position by A produces the previous right-sentential form in a rightmost derivation of 𝛿."
Rightmost derivation Production E ⇒ T E -> T ⇒ T * F T -> T * F ⇒ T * id F -> id ⇒ F * id T -> F ⇒ id * id F -> id
E.g. T * id has handle id (or more formally F -> id is a handle after T *) Table is reverse of that on previous slide (!)
Right sentential form Handle Reducing production id * id id F -> id F * id F T -> F T * id id F -> id T * F T * F T -> T * F T T E -> T E