Вы находитесь на странице: 1из 26

Shift-Reduce Parsers

There are two main categories of shift-reduce


parsers

1. Operator-Precedence Parser
simple, but only a small class of grammars.
CFG
LR
LALR

2. LR-Parsers SLR
covers wide range of grammars.
SLR simple LR parser
LR most general LR parser
LALR intermediate LR parser (lookhead LR parser)
SLR, LR and LALR work same, only their parsing tables are
different.
1
What happens with ambiguous grammars
Consider:
EE+E | E*E|
| ( E ) | id
Derive id+id*id
By two different Rightmost derivations

2
Example
STACK INPUT Remark EE+E
$ id + id * id$ Shift | E*E
$ id + id * id$ Reduce by E id
$E + id * id$
|(E)
$E+ id * id$ Shift | id
$ E + id * id$ Shift
$E+E Reduce by E id
Both reduce by E E + E, and
Shift can be performed:
Shift/reduce conflict

3
Operator-Precedence Parsing
problems encountered so far in shift/reduce parsing:
IDENTIFY a handle.
resolve conflicts (if they occur).
operator grammars: a class of grammars where handle
identification and conflict resolution is easy.

Operator Grammars: no production right side is


or has two adjacent non-terminals.
E E - E | E + E | E * E | E / E | E ^ E | - E | ( E ) | id
note: this is typically ambiguous grammar.
Ex:
EAB EEOE EE+E |
Aa Eid E*E |
Bb O+|*|/ E/E | id

not operator grammar not operator grammar operator grammar


Precedence Relations
In operator-precedence parsing, we define three
disjoint precedence relations between certain pairs
of terminals.
a <. b b has higher precedence than a
a = b b has same precedence as a
a .> b b has lower precedence than a

The determination of correct precedence relations


between terminals are based on the traditional
notions of associativity and precedence of
operators.
Using Operator -Precedence Relations

E E+E | E-E | E*E | E/E | E^E | (E) | -E | id

id + * $
The partial operator-precedence
id .> .> .>
table for this grammar
+ <. .> <. .>

* <. .> .> .>

$ <. <. <.

Then the input string id+id*id with the precedence


relations inserted will be:
$ <. id .> + <. id .> * <. id .> $
To Find The Handles
1. Scan the string from left end until the first .> is encountered.
2. Then scan backwards (to the left) over any = until a <. is
encountered.
3. The handle contains everything to left of the first .> and to
the right of the <. is encountered.

$ <. id .> + <. id .> * <. id .> $ E id $ id + id * id $


$ + <. id .> * <. id .> $ E id $ E + id * id $
$ + * <. id .> $ E id $ E + E * id $
$ +*$
$ <. + <. * .> $ E E*E $ E + E * .E $
$ <. + .> $ id + * $ E E+E $E+E$
$$ id .> .> .> $E$

+ <. .> <. .>


* <. .> .> .>
$ <. <. <.
Operator-Precedence Parsing Algorithm --
Example
stack input action
$ id+id*id$ $ <. id shift
$id +id*id$ id .> + reduce E id
$ +id*id$ shift
$+ id*id$ shift
$+id *id$ id .> * reduce E id
$+ *id$ shift
$+* id$ shift
$+*id $ id .> $ reduce E id
$+* $ * .> $ reduce E E*E
$+ $ + .> $ reduce E E+E
$ $ accept
id + * $
id .> .> .>

+ <. .> <. .>

* <. .> .> .>

$ <. <. <.


Example
STACK INPUT Remark
$ id + id * id$
$ <. id + * ( ) id $
$ <. id + id * id$
$E + id * id$ id >. + + .> <. <. .> <. .>
$ E <. + id * id$ $ <. +
* .> .> <. .> <. .>
$ E <. + <. id * id$ + <. id
* id$ id .> * ( <. <. <. .=. <.
$ E <. + E
id$ + <. *
$ E <. + E <. * ) .> .> .> .>
$ * <. id
$ E <. + E <. * <. id id .> $ id
$ .> .> .> .>
$ E <. + E <. * E * .> $
$ $
$ E <. + E + .> $ <. <. <. <. .=.
$
$E $ accept Parse Table

1-2 E E + T | T
3-4 T T * F | F
5-6 T ( E ) | id

9
Using Operator-Precedence Relations
The intention of the precedence relations is to find
the handle of a right-sentential form,
<. with marking the left end,
= appearing in the interior of the handle, and
.> marking the right hand.

In our input string $a1a2...an$, we insert the


precedence relation between the pairs of terminals
(the precedence relation holds between the
terminals in that pair).
Operator-Precedence Parsing
1. If a .=. b, then shift b into the parse stack
2. If a <. b, then shift <. And then shift b into the
parse stack
3. If a .> b, then find the top most <. relation of the
parse stack; the string between this relation (with
the non-terminal underneath, if there exists) and the
top of the parse stack is the handle (the handle
should match with the RHS of at least one
grammar rule); replace the handle with a typical
non-terminal

11
Operator-Precedence Relations from
Associativity and Precedence
1. If operator 1 has higher precedence than operator 2, make 1 > 2 and
2 < 1 . For example, if * has higher precedence than +, make * > +
and + < *. These relations ensure that, in an expression of the form
E+E*E+E, the central E*E is the handle that will be reduced first.

2. If 1 and 2 are operators of equal precedence (they may in fact be the


same operator), then make 1 > 2 and 2 > 1 if the operators are left-
associative, or make 1 < 2 and 2 < 1 if they are right-associative.

For example, if + and are left-associative, then make + > +, + > -, -


> - and - > +. If is right associative, then make < . These
relations ensure that E-E+E will have handle E-E selected and EEE
will have the last EE selected.
Operator-Precedence Relations from
Associativity and Precedence
3. Make < id, id > , < (, ( < , ) > , > ), > $, and $ < for all
operators . Also, let

( = ) $ < ( $ < id
( < ( id > $ ) > $
( < id id > ) ) > )
These rules ensure that both id and (E) will be reduced to E. Also, $ serves
as both the left and right endmarker, causing handles to be found between
$s wherever possible.

13
How to Create Operator-Precedence
Relations
We use associativity and precedence relations among operators.

1. If operator 1 has higher precedence than operator 2,


1 .> 2 and 2 <. 1
2. If operator 1 and operator 2 have equal precedence,
they are left-associative 1 .> 2 and 2 .> 1
they are right-associative 1 <. 2 and 2 <. 1
3. For all operators , <. id, id .> , <. (, (<. , .> ), ) .> , .> $, and
$ <.

4. Also, let
(=) $ <. ( id .> ) ) .> $
( <. ( $ <. id id .> $ ) .> )
( <. id
Any entry left blank indicates that two symbol should not
occur consecutively in a handle
Operator-Precedence Parsing Algorithm
The input string is w$, the initial stack is $ and a table holds
precedence relations between certain terminals
Algorithm:
set p to point to the first symbol of w$ ;
repeat forever
if ( $ is on top of the stack and p points to $ ) then return
else {
let a be the topmost terminal symbol on the stack and let b be the symbol
pointed to by p;
if ( a <. b or a = b ) then { /* SHIFT */
push b onto the stack;
advance p to the next input symbol;
}
else if ( a .> b ) then /* REDUCE */
repeat pop stack
until ( the top of stack terminal is related by <. to the terminal most
recently popped );
else error();
}
How to Create Operator-Precedence
Relations
Given an operator grammar the operator-precedence
relations can be determined from the first operator and last
operator

(i) For each non-terminal symbol construct a FIRSTOP list which includes the
first terminal symbol in each right-hand-side of a production for that
terminal, and also the first symbol if it is a non-terminal.
For example, if there is a production
X a .. | Bc ..
include `a', `B' and `c' in the FIRSTOP list of `X'.

(ii) Construct a LASTOP list for each non-terminal symbol which includes
the last terminal symbol in each right-hand-side of a production for that
terminal, and also the last symbol if it is a non-terminal. For example, if
there is a production
Y .. U | .. vW
include `u', `v' and `W' in the LASTOP list of `Y'.

17
(iii) Compute the FIRSTOP+ and LASTOP+ lists
using the closure algorithm
If A is in FIRSTOP(S), then replace A by FIRSTOP(A) in FIRSTOP(A).
If A is in LASTOP(S), then replace A by LASTOP(A) in LASTOP(S).

Remove all the non-terminals from the table entries

18
(iv) Produce a matrix of operator-precedence relations from the productions
of the grammar, the FIRSTOP+ and LASTOP+ lists.

(v)

19
Whenever a terminal 'a' precedes a non-terminal 'B',
then a <. b , where 'b' is in FIRSTOP+(B).
Whenever a terminal 'b' follows a non-terminal 'A',
then b .> a , where 'a' is in LASTOP+(A).
If there is a right side of a production of the
form 'aBc' or 'ac' , a =. c.
If there is a FIRSTOP+ and LASTOP+ conflict, then
do FIRSTOP+ first, then do LASTOP+.

20
Example

21
22
Precedence Functions
Compilers using operator precedence parsers do
not need to store the table of precedence relations.
The table can be encoded by two precedence
functions f and g that map terminal symbols to
integers.
For symbols a and b.
f(a) < g(b) whenever a <. b
f(a) = g(b) whenever a = b
f(a) > g(b) whenever a .> b
Constructing precedence functions

Input: An operator precedence matrix.


Output: Precedence functions representing the input matrix, or
an indication that none exist.
Method:
1. Create symbols fa and gb for each a that is a terminal or $.
2. Partition the created symbols into as many groups as possible, in
such a way that if a =. b, then fa and gb are in the same group.
3. Create a directed graph whose nodes are the groups found in (2).
For any a and b, if a <.b , place an edge from the group of gb to the
group of fa. Of a .> b, place an edge from the group of fa to that of
gb.
4. If the graph constructed in (3) has a cycle, then no precedence
functions exist. If there are no cycle, let f(a) be the length of the
longest path beginning at the group of fa; let g(a) be the length of the
longest path beginning at the group of ga.
Example
+ * Id $
f 2 4 4 0
gid fid
g 1 3 5 0
Create a directed graph whose
nodes are the groups found in
step 2. For any a and b, if a
f* g* <.b , place an edge from the
group of gb to the group of fa.
if a .> b, place an edge from
the group of fa to that of gb.
g+ f+ id + * $
id .> .> .>

+ <. .> <. .>

* <. .> .> .>


f$ g$ $ <. <. <.
The path is represented as, for example, there is a path from gid to f* to g* to f+ to g+ to f$ = 5, the precedence function g representing id is 5.
Disadvantages of Operator Precedence
Parsing
Disadvantages:
It cannot handle the unary minus (the lexical
analyzer should handle the unary minus).
Small class of grammars.
Difficult to decide which language is recognized
by the grammar.

Advantages:
simple
powerful enough for expressions in programming
languages

Вам также может понравиться