Académique Documents
Professionnel Documents
Culture Documents
B
y
x y
Example
Consider the grammar
1 <goal> ::= a <A> <B> e
2 <A> ::= <A> b c
3 | b
4 <B> ::= d Prod'n Sentential Handle*
and the input string abbcde. Form
-- abbcde 3,2
Why is (3,3) not a 3 a<A>bcde 2,4
handle for a<A>bcde?
2 a<A>de 4,3
4 a<A><B>e 1,4
1 <goal>
• The trick appears to be scanning the input and finding valid right-
sentential forms.
* (rule, position of right end of handle in input string).
Handles
We are trying to find a substring of the current right-sentential
form where:
matches some production A ::=
– reducing to A is one step in the reverse of a rightmost derivation.
Such a string is called a handle.
Formally,
– a handle of a right-sentential form is a production A ::= and a position
in where may be found.
Convention: position specifies the right end of the handle.
Proof:
Follows from the fact that all i are right-sentential
forms.
Corollary
The right end of a handle is to the right of the previously
reduced variable.
Shift-reduce parsing
One scheme to implement a handle-pruning, bottom-up parser
is called a shift-reduce parser.
Shift-reduce parsers use a stack and an input buffer
1. Initialize stack with $
2. Repeat until the top of the stack is the goal symbol and
the input token is eof
a) find the handle
if we don't have a handle on top of the stack, shift an input
symbol onto the stack
b) prune the handle
if we have a handle (A ::= , k) on top of the stack, reduce
i) pop | | symbols off the stack
ii) push A onto the stack
Shift-reduce parsing
Conceptual view of bottom-up parsing algorithms
(assumes a restricted class of unambiguous grammars):
?
STACK X_1 … X_m
stack
Table-
Source Intermediate
code scanner driven representation
parser
Action &
goto
tables
An LR(1) parser for either ALGOL or PASCAL has several thousand states, while an SLR(1) or LALR(1) parser for
the same language may have several hundred states
SLR(1) parsing
• Viable prefix of a right-sentential form:
– contains both terminals and nonterminals
– can be recognized with a DFA
Note: An "augmented grammar" is one where the start symbol appears only on the lhs
of productions. For the rest of LR parsing, we will assume the grammar is augmented
with a production S’ ::= S
LR(0) items
An LR(0) item is a string [], where
is a production from G with a at some position in the rhs
– The indicates how much of an item we have seen at a given state in the parsing
process.
– [A ::= XYZ] indicates that the parser is looking for a string that can be derived
from XYZ
– [A ::= XY Z] indicates that the parser has seen a string derived from XY and is
looking for one derivable from Z
• Thus, if the parser has viable prefix on its stack, the input should reduce to
B (or for some other item [B ::= ] in the closure).
To compute closure(I):
function closure(I)
repeat
new_item false
for each item [A ::= B] I, each production B ::= G
if [B ::= ] I then
add [B ::= ] to I
new_item true
endif
until (new_item = false)
return I
Goto(I,X)
• Let I be a set of LR(0) items and X be a grammar symbol.
• Then, GOTO(I,X) is the closure of the set of all items [A ::= X ]
such that [A ::= X] I
• If I is the set of valid items for some viable prefix , then goto(I,X) is the set
of valid items for the viable prefix X.
• goto(I,X) represents state after recognizing X in state I.
To compute goto(I,X) :
function goto(I, X)
J set of items [A ::= X ] such that [A ::=
X] I
J’ closure(J)
return J’
Collection of sets of LR(0) items
We start the construction of the collection of sets of LR(0) items with the item
[S’ ::= S], where
S’ is the start symbol of the augmented grammar G’
S is the start symbol of G
To compute the collection of sets of LR(0) items
procedure items(G’)
S0 closure({[S’ ::= S]})
Items {S0 }
ToDo {S0 }
while ToDo not empty do
remove Si from ToDo
for each grammar symbol X do
Snew goto(Si,X)
if Snew is a new state then
Items Items {Snew}
ToDo ToDo {Snew}
endif
endfor
endwhile
return Items
LR(0) machines
LR(0) DFA
• states - canonical sets of LR(0) items
• edges - goto transitions
• recognizes all viable prefixes
• no lookahead
Reducing a handle (rhs of production) to a
nonterminal can be viewed as:
1. returning to the state at beginning of the handle
2. making a transition on a nonterminal from this state
ACTION table
• for each [state, lookahead] pair
– have we reached end of handle?
– if not, shift
– if at end of handle, reduce
– may also accept or error
– use lookahead to guide decision
GOTO table
• for each [state, nonterminal] pair
– pick state to go to after reduction
The Algorithm
1. Construct the collection of sets of LR(0) items for G’.
2. State i of the parser is constructed from Ii.
a) if [A ::= a] Ii and goto(Ii, a) = Ij, then set ACTION[i, a]
to "shift j". (a must be a terminal)
b) if [A ::= ] Ii , then set ACTION[i, a] to "reduce A ::= "
for all a in FOLLOW(A).
c) if [S’ ::= S ] Ii , then set ACTION[i, eof] to "accept".
3. If goto(Ii,A) = Ij, then set GOTO[i, A] to j.
4. All other entries in ACTION and GOTO are set to
"error"
5. The initial state of the parser is the state constructed
from the set containing the item [S’ ::= S]
SLR(1) parser example
The Grammar
1 E ::= T+E
2 |T
3 T ::= id
S1 : [S0 ::= E ]
S2 : [ E ::= T + E ],
[ E ::= T ]
S3 : [ T ::= id ]
S4 : [ E ::= T + E ],
[ E ::= T + E ],
[ E ::= T ],
[ T ::= id ]
S5 : [ E ::= T + E ]
Example GOTO function
Start
S0 closure ( {[ S ::= E ]} )
Iteration 1
goto(S0, E) = S1
goto(S0, T) = S2
goto(S0, id) = S3
Iteration 2
goto(S2, +) = S4
Iteration 3
goto(S4, id) = S3
goto(S4, E) = S5
goto(S4, T) = S2
The DFA
S’ E•
S’ ::= • E
E ::= • T + E
E 1
E ::= • T
T ::= • id
T + E
E T+E •
0 2 4 5
T E ::= T + • E
E ::= T • + E
id E ::= T • E ::= • T + E
E ::= • T
T ::= • id
T id •
3
id
Building the SLR(1) Table: Shift Entries
ACTION
Enter a shift n (where n id + eof
is the state to go to) for S0 shift 3
each transition on a S1
S2 shift 4
terminal symbol S3
S4 shift 3
S5
S’ E•
S’ ::= • E
E ::= • T + E
E 1
E ::= • T
T ::= • id
T + E
E T+E •
0 2 4 5
T E ::= T + • E
E ::= T • + E
id E ::= T • E ::= • T + E
E ::= • T
T ::= • id
T id •
3
id
Building the SLR(1) Table: Reduce Entries
A reduce should occur ACTION
in any state containing id + eof
S0 shif t 3
an item with a • at the S1
end of a production… S2 shif t 4
S3
S4 shif t 3
S5
S’ E•
S’ ::= • E
E ::= • T + E
E 1 …but in which columns?
E ::= • T
T ::= • id
T + E
E T+E •
0 2 4 5
T E ::= T + • E
E ::= T • + E
id E ::= T • E ::= • T + E
E ::= • T
T ::= • id
T id •
3
id
The SLR(1) Solution
FOLLOW(S’) = { eof } E
T
FOLLOW(E) = { eof }
FOLLOW(T) = { +, eof }
T
id + id eof
Lookahead
Reduce Entries
ACTION
A reduce is entered in the
id + eof
column for every terminal in S0 shif t 3
FOLLOW(X), where X is the S1 reduce S’ ::= E
non-terminal on the left side S2 shif t 4 reduce E ::= T
of the production S3 reduce T ::= id reduce T ::= id
S4 shif t 3
S5 reduce E ::= T+E
S’ E•
S’ ::= • E
E ::= • T + E
E 1
E ::= • T
T ::= • id
T + E
E T+E •
0 2 4 5
T E ::= T + • E
E ::= T • + E
id E ::= T • E ::= • T + E
E ::= • T
FOLLOW(S’) = { eof }
T ::= • id FOLLOW(E) = { eof }
T id •
3 FOLLOW(T) = { +, eof }
id
GOTO
E 1
Example T + E
In state 5, reduce by E::=T+E : 0 2 4 5
1. Pop T+E (return to state 0)
id T
2. Push E, go to state 1
3
id
GOTO Table
goto(S0, E) = S1 E 1
goto(S0, T) = S2 T + E
goto(S0, id) = S3 0 2 4 5
T
goto(S2, +) = S4
goto(S4, id) = S3 id 3 id
goto(S4, E) = S5
goto(S4, T) = S2
ACTION GOTO
id + eof E T
S0 shif t 3 - - 1 2
S1 - - reduce S’ ::= E - -
S2 - shif t 4 reduce E ::= T - -
S3 - reduce T ::= id reduce T ::= id - -
S4 shif t 3 - - 5 2
S5 - - reduce E ::= T+E - -
Final Step
• Notice that to reduce by S’ ::= E amounts to
finishing building the tree for the input
string
• So, this entry is changed to “accept” in the
table
ACTION GOTO
id + eof E T
S0 shif t 3 - - 1 2
S1 - - accept - -
S2 - shif t 4 reduce 2 - -
S3 - reduce 3 reduce 3 - -
S4 shif t 3 - - 5 2
S5 - - reduce 1 - -
Final ACTION and GOTO tables
ACTION GOTO
id + eof E T
S0 shift 3 - - 1 2
S1 - - accept - -
S2 - shift 4 reduce 2 - -
S3 - reduce 3 reduce 3 - -
S4 shift 3 - - 5 2
S5 - - reduce 1 - -
ACTION GOTO
a b c d eof S A
S0 - - - Shift 2 - 1 -
S1 - - - accept - -
S2 - - Shift 3 - - - 4
S3 Shift 5 R 3 - - - -
S4 shift 6 - - - - -
S5 - - - - R2 - -
S6 - - - - R2
Added because S3
This grammar can be parsed with
contains [A ::= c ] and
an SLR(1) parser
b is in FOLLOW(A)
Example : A non-SLR(1) grammar
0. S’ ::= S New production adds
1. S ::= dca | dAb | Aa “a” to FOLLOW(A)
2. A ::= c
LR(0) items
START = S0 : {[S’ ::= S], [S ::= dca], [S ::= dAb],
[S ::= Aa], [A ::= c]}
GOTO(S0,S) = S1 : {[S’ ::= S ] }
GOTO(S0,d) = S2 : {[S ::= d ca], [S ::= d Ab], [A ::= c] }
GOTO(S2,c) = S3 : {[S ::= dc a], [A ::= c ]}
GOTO(S2,A) = S4 : {[S ::= dA b]}
GOTO(S3,a) = S5 : {[S ::= dca ] }
GOTO(S4,b) = S6 : {[S ::= dAb]}
GOTO(S0,A) = S7 : {[S ::= A a]}
GOTO(S7,a) = S8 : {[S ::= Aa ]}
GOTO(S0,c) = S9 : {[A ::= c ]}
SLR(1) parse table
ACTION GOTO
a b c d eof S A
S0 - - Shift 9 Shift 2 - 1 -
S1 - - - - accept - -
S2 - - Shift 3 - - - 4
S3 Shift 5 R 3 - - - - -
R3
S4 shif t 6 - - - - -
S5 - - - - R2 - -
S6 - - - - R2
S7 Shift 8
Shift-reduce conflict!
S8
The point
For [A ::= , a] and [B ::= , b], we can decide
between reducing to A or B by looking at limited
right context!
Canonical LR(1) items
1. S’ ::= S 4. L ::= * R
2. S ::= L = R 5. L ::= id
3. S ::= R 6. R ::= L
Canonical LR(1) collection
I0 : { [S’ ::= S, eof], [S ::= L = R, eof],[S ::= R, eof], [L ::= * R, {=, eof}], [L ::= id,
{=, eof}], [R ::= L, eof] }
I1 : { [S0 ::= S , eof] }
I2 : { [S ::= L = R, eof], [R ::= L , eof] } FOLLOW(S’) = { eof }
I3 : { [S ::= R , eof] } FOLLOW(S) = { eof }
I4 : { [L ::= * R, {=, eof}], [R ::= L, {=, eof}], FOLLOW(L) = { =, eof }
[L ::= * R, {=, eof}], [L ::= id, {=, eof}] }
FOLLOW(R) = { =, eof }
I5 : { [L ::= id , {=, eof}] }
I6 : { [S ::= L = R, eof], [R ::= L, eof],
[L ::= * R, eof], [L ::= id, eof] }
I7 : { [L ::= * R , {=, eof}] }
I8 : { [R ::= L , {=, eof]} }
I9 : { [S ::= L = R , eof] }
I10 : { [R ::= L , eof] }
I11 : { [L ::= * R, eof], [R ::= L, eof],
[L ::= * R, eof], [L ::= id, eof] }
I12 : { [L ::= id , eof] } [S ::= L = R] indicates ACTION[2, =] = "shift"
I13 : { [L ::= * R , eof] }
[R ::= L ] indicates ACTION[2, eof] = "reduce"
No conflict! This grammar is LR(1)
An LR Parsing Engine
7 E (S , E)
What are the shift-reduce parse actions for the program:
a := 7;
b := c + (d := 5 + 6, d)
sn Shift into state n; rk Reduce by rule k;
gn Goto state n; a Accept;
Error;
Example:
id := E