0% found this document useful (0 votes)
34 views27 pages

Unit 3 - Sessions 7 (B) - 8

The document discusses operator precedence parsing. It covers topics like operator precedence relations, how to use precedence relations to parse strings, and methods to construct an operator precedence parsing table using associativity and precedence rules. It provides examples of parsing the expression "id + id * id" using a stack implementation and constructing a precedence table for arithmetic expressions.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views27 pages

Unit 3 - Sessions 7 (B) - 8

The document discusses operator precedence parsing. It covers topics like operator precedence relations, how to use precedence relations to parse strings, and methods to construct an operator precedence parsing table using associativity and precedence rules. It provides examples of parsing the expression "id + id * id" using a stack implementation and constructing a precedence table for arithmetic expressions.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 27

18CSC304J

COMPILER DESIGN

UNIT 3
SESSION 7 & 8
Topics that will be covered in this Session

• Operator Precedence Parser


• Computation of LEADING
• Computation of TRAILING
• Problems related to LEADING and TRAILING
Operator Precedence Parser
Operator Grammar
• Operator Precedence Parsing can be applied only for a small but important class of grammars
called Operator Grammars
• Operator Grammars have the following properties
• No production on the right side is ε
• Should not have 2 adjacent non terminals
• Example 1
E → E+E | E-E | E*E | E/E | E↑E | (E) | -E | id
• Example 2
S→(L)|a
L→L,S|S
• Example for a grammar which is not an operator grammar
E → EAE | (E) | -E | id
A→+|-|*|/|↑
Operator Precedence Parsing – Advantages & Disadvantages

• Advantage
• Simplicity
• Powerful enough for expressions in programming languages
• Disadvantage
• It is hard to handle tokens like the minus sign, which has two different precedences (unary
minus and binary minus)
• We cannot be sure that the parser accepts exactly the desired language
• Only a small class of grammars can be parsed using operator-precedence techniques
Precedence Relations
• There are 3 disjoint precedence relations between certain pairs of terminals

a <. b b has higher precedence than a [ a “yields precedence to “b]


a =· b b has same precedence as a
a .> b b has lower precedence than a [ a “takes precedence over “b]

• These precedence relations guide the selection of handles


• There are two methods for determining the precedence relations:
1. Based on associativity and precedence of operators
2. Mechanical Method : Using LEADING and TRAILING
How to use Operator Precedence Relations for Parsing a string
• Consider the grammar • Steps to parse the string by finding handles
E → E+E | E*E | id 1. Scan the string from left end until the first .>
is encountered.
• The operator precedence relations are
2. Then scan backwards (to the left) over any =·
defined in the table given below: until a <. is encountered.
3. The handle contains everything to left of the
id + * $ first .> and to the right of the <. is
encountered.
id >
.
>
.
>
.

+ <. >
.
<. >
.
$ <. id .> + <. id .> * <. id .> $ E  id $ id + id * id $
* < .
>
.
>
.
>
.
$ <. + <. id .> * <. id .> $ E  id $ E + id * id $
$ <. <. <. $ <. + <. * <. id .> $ E  id $ E + E * id $
• Parse the string $ <. + <. * .> $ E  E*E $ E + E * .E $
id + id * id $ <. + .> $ E  E+E $E+E$
• The given string with the precedence $$ $E$
relations inserted is
$ <. id .> + <. id .> * <. id .> $
Stack Implementation of Operator Precedence Parsing /
Algorithm:- Operator Precedence Parsing

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();
}
Example – Stack Implementation of Operator Precedence Parsing
• Consider the grammar
E → E+E | E*E | id
• The operator precedence relations are Stack Input Action
defined in the table given below: $ id + id * id $ $ <. id shift
$ id + id * id $ id .> + reduce by E  id (Pop)
id + * $
$ + id * id $ $ <. + shift
id >
.
>
.
>
.
$+ id * id $ + <. id shift
+ < .
>
.
< .
>
.
$ + id * id $ id .> * reduce by E  id (Pop)
* < .
>
.
>
.
>
.
$+ * id $ + <. * shift
$ <. <. <. $ +* id $ * <. id shift

• Parse the string $ + * id $ id .> $ reduce by E  id (Pop)


$+ * $ * .> $ reduce by E  E*E (Pop)
id + id * id
$+ $ + .> $ reduce by E  E+E (Pop)
$ $ Accept
Constructing Operator Precedence Parsing Table – Method 1
Using Associativity and Precedence Relations

For a language of arithmetic expressions, operator-precedence relations can be created by using the
associativity and precedence rules as follows:
1. If operator O1 has higher precedence than operator O2,
 O1 .> O2 and O2 <. O1
2. If operator O1 and operator O2 have equal precedence,
and if they are left-associative  O1 .> O2 and O2 .> O1
if they are right-associative  O1 <. O2 and O2 <. O1
3. For all operators O,
O <. id, id .> O, O <. (, (<. O, O .> ), ) .> O, O .> $, and $ <. O
4. Also, let
(=·) $ <. ( id .> ) ) .> $
( <. ( $ <. id id .> $ ) .> )
( <. id
Example – Table Construction

Consider the grammar + - * / ^ id ( ) $


E → E+E | E-E | E*E | E/E | E↑E | (E) | id + .
> .
> <. <. <. <. <. .
> .
>
Assume
- .
> .
> <. <. <. <. <. .
> .
>
• ↑ is of highest precedence and right-
associative * .
> .
> .
> .
> <. <. <. .
> .
>
• * and / are of next highest precedence and / .
> .
> .
> .
> <. <. <. .
> .
>
left associative ^ .
> .
> .
> .
> <. <. <. .
> .
>
• + and – are of lowest precedence and left
associative
id .
> .
> .
> .
> .
> .
> .
>
( <. <. <. <. <. <. <. =·
Construct operator precedence parsing table ) .
> .
> .
> .
> .
> .
> .
>
for the given grammar
$ <. <. <. <. <. <. <.
Parsing a string using the table Stack Input Action
$ id * ( id ↑ id ) – id / id $ Shift
Consider the grammar $ id * ( id ↑ id ) – id / id $ Reduce
$ * ( id ↑ id ) – id / id $ Shift
E → E+E | E-E | E*E | E/E | E↑E | (E) | id
$* ( id ↑ id ) – id / id $ Shift
Parse the string $*( id ↑ id ) – id / id $ Shift
id * ( id ↑ id ) – id / id $ * ( id ↑ id ) – id / id $ Reduce
$*( ↑ id ) – id / id $ Shift
+ - * / ^ id ( ) $ $*(↑ id ) – id / id $ Shift

+ .
> .
> <. <. <. <. <. .
> .
> $ * ( ↑ id ) – id / id $ Reduce
$*(↑ ) – id / id $ Reduce
- .
> .
> <. <. <. <. <. .
> .
> $*( ) – id / id $ Shift

* .
> .
> .
> .
> <. <. <. .
> .
> $*()
$*(
– id / id $
– id / id $
Reduce
( =. ) Pop ( also
/ .
> .
> .
> .
> <. <. <. .
> .
> $* – id / id $ Reduce
$ – id / id $ Shift
^ .
> .
> .
> .
> <. <. <. .
> .
> $- id / id $ Shift

id .
> .
> .
> .
> .
> .
> .
> $ - id / id $ Reduce
$ - / id $ Shift
( <. <. <. <. <. < .
<. =· $-/ id $ Shift

) .
> .
> .
> .
> .
> .
> .
> $ - / id $ Reduce
$-/ $ Reduce
$ <. <. <. <. <. < .
<.
$- $ Reduce
$ $ Accept
Handling Unary Operators
• Consider a unary operator such as logical negation, which is not also a binary operator
• Suppose ! is a unary prefix operator, then
• Make θ <. ! for any operator θ
• If ! has higher precedence than θ, make ! .> θ
• If ! has lower precedence than θ make ! <. θ
• The rule for unary postfix operators is analogous
Operators that act as both unary and binary
• In case of operators like minus sign – that is both unary and binary, the best approach is to use
the lexical analyzer to distinguish between unary minus and binary minus by returning
different tokens
• The lexical analyser cannot use lookahead to distinguish the two
• It must remember the previous token
• For example, a minus sign is unary if the previous token was an operator, a left parenthesis, a
comma or an assignment symbol
Precedence Functions

• Compilers using operator-precedence parsers need not store the table of precedence
relations
• In most cases, the table can be encoded by two precedence functions f and g that map
terminal symbols to integers.
• We attempt to select f and g so that, for symbols a and b,
Algorithm for computing Precedence Functions
Input : An operator precedence matrix
Output : Precedence functions f(a) and g(a) representing the input matrix or an indication that
none exist
Method
1. Create symbols and for each a that a terminal or $
2. Partition the created symbols into as many groups as possible, in such a way that
i. If , then and are in the same group
ii. If and then and are in the same group
3. Create a directed graph whose nodes are the groups found in step 2
1. If a<. b, place an edge from and
2. If a.> b, place an edge from and
4. If the graph constructed has a cycle, then no precedence functions exist. If there are no
cycles, let f(a) be the length of the longest path beginning at . Let g(a) be the length of the
longest path from
Example for computing Precedence Functions
Consider the following operator precedence Step 3
matrix

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

Compute the operator precedence functions


Solution Step 4
Step 1
Create symbols fid , f+ , f* , f$ , gid , g+ , g* , g$
Step 2
There is no =. relationships. So each symbol
is in a group by itself
Example – Parsing String using precedence functions

• Consider the grammar


E → E+E | E*E | id Stack Input Action
• The operator precedence functions are $ id + id * id $ f($) < g(id) shift
given below: $ id + id * id $ f(id) > g(+) reduce by E  id (Pop)
$ + id * id $ f($) < g(+) shift
$+ id * id $ f(+) < g(id) shift
$ + id * id $ f(id) > g(*) reduce by E  id (Pop)
$+ * id $ f(+) < g(*) shift
$ +* id $ f(*) < g(id) shift

• Parse the string $ + * id $ f(id) > g($) reduce by E  id (Pop)


id + id * id $+ * $ f(*) > g($) reduce by E  E*E (Pop)
$+ $ f(+) > g($) reduce by E  E+E (Pop)
$ $ Accept
Error Recovery in Operator Precedence Parsing
Error Cases

There are two points in the parsing process at which an operator-precedence parser can discover
syntactic errors

1. If no precedence relation holds between the terminal on top of the stack and the current
input

2. If a handle has been found, but there is no production with this handle as a right side

Error Recovery

3. Each empty entry is filled with a pointer to an error routine

4. Decides the popped handle “looks like” which right hand side and tries to recover from
that situation
COMPUTATION OF
LEADING & TRAILING
Constructing Operator Precedence Parsing Table – Method 2
Mechanical way by computing LEADING and TRAILING

Steps Involved
• Ensure that the grammar is an operator grammar
• Compute the function LEADING()
• Compute the function TRAILING
• Construct the Operator Precedence Parsing Table from the functions LEADING and TRAILING
• Compute precedence functions
• Parse the given input string using the table
LEADING and TRAILING

LEADING(A)
• LEADING(A) for a non-terminal A is the set of terminals a such that a is the leftmost terminal in
some string derived from A
• Rule 1 :
• Rule 2 : If there is a production of the form , then add everything in LEADING(B) to LEADING(A)

TRAILING(A)
• TRAILING(A) for a non-terminal A is the set of terminals a that can be the rightmost in a some
string derived from A
• Rule 1 :
• Rule 2 : If there is a production of the form , then add everything in TRAILING(B) to TRAILING(A)
Computation of LEADING and TRAILING – Examples
Example 1 Example 2
Compute LEADING and TRAILING for the Compute LEADING and TRAILING for the
non-terminals in the grammar given below: non-terminals in the grammar given below:
S→(L)|a S→iEtSeS|iEtS|a
L→L,S|S E→b

LEADING(S) = { ( , a } LEADING(S) = { i , a }
LEADING(L) = { , , LEADING(S) } LEADING(E) = { b }
={,,(,a}
TRAILING(S) = { e , t , a }
TRAILING(S) = { ) , a } TRAILING(E) = { b }
TRAILING(L) = { , , TRAILING(S) }
={,,),a}
Computation of LEADING and TRAILING – Examples
Example 3
Compute LEADING and TRAILING for the non-terminals in the grammar given below:
S → L = R| R
L → * R | id
R→L

LEADING(S) = { = , LEADING(L),
TRAILING(S) = { = , TRAILING(R) }
LEADING(R) }
= { = , * , id }
= { = , * , id }
TRAILING(L) = { * , id }
LEADING(L) = { * , id }
TRAILING(R) = { TRAILING(L) }
LEADING(R) = { LEADING(L) }
= { * , id }
= { * , id }
Computation of LEADING and TRAILING – Examples
Example 4
Compute LEADING and TRAILING for the non-terminals in the grammar given below:
→ or |
→ and r |
→ not | ( ) | true | false
The terminals in the grammar are given in bold

LEADING() = { or , LEADING() } TRAILING() = { or , TRAILING() }


= { or , and, not , ( , true , false } = { or , and, not , ) , true , false }
LEADING() = { and , LEADING() } TRAILING() = { and , TRAILING() }
= { and , not , ( , true , false = { and , not , ) , true , false
LEADING() = { not , ( , true , false } TRAILING() = { not , ) , true , false }
Constructing Operator Precedence Parsing Table
By computing LEADING and TRAILING
Steps Involved
1. Find LEADING and TRAILING for all the non terminals
2. For terminals a and b, we say a=.b if there is a rightside of the form aβbγ where β is either
empty or a single non-terminal
3. We say a<.b if there is a rightside of the form aAβ and b is in LEADING(A)
4. We say a.>b if there is a rightside of the form Abβ and a is in TRAILING(A)
5. $<.b whenever b is in LEADING(S) where S is the start symbol of the grammar
6. a.>$ whenever a is in TRAILING(S) where S is the start symbol of the grammar
Stack Input Action
Example 1
$ ((a,a),a)$ Shift
Construct operator precedence parsing table for the
$( (a,a),a)$ Shift
grammar given below and parse the string ( (a , a) , a )
$(( a,a),a)$ Shift
S→(L)|a
$((a ,a),a)$ Pop
L→L,S|S
$(( ,a),a)$ Shift
$((, a),a)$ Shift
Find LEADING and TRAILING
$((,a ),a)$ Pop
LEADING(S) = { ( , a }
$((, ),a)$ Pop
LEADING(L) = { , , LEADING(S) }
$(( ),a)$ Shift
={,,(,a}
$(() ,a)$ ) > , Pop
TRAILING(S) = { ) , a }
$(( ,a)$ ( = ) Pop (stack top & most
TRAILING(L) = { , , TRAILING(S) } recently popped)
={,,),a} $( ,a)$ Shift
a ( ) , $ $(, a)$ Shift
a .
> .
> .
> $(,a )$ Pop

( <. <. =. <. $(, )$ Pop

) .
> .
> .
> $( )$ Pop
$() $ Pop
, <. <. .
> .
>
$( $ ( = ) Pop (stack top & most
$ <. <. recently popped)
$ $ Accept
Example 2 Stack Input Action
Construct operator precedence parsing table for the $ * id = id $ Shift
grammar given below and parse the strings *id=id and
$* id = id $ Shift
id*id=id
S → L = R| R $ * id = id $ Pop
L → * R | id $* = id $ Pop
R→L $ = id $ Shift
$= id $ Shift
Find LEADING and TRAILING $ = id $ Pop
LEADING(S) = { = , * , id } $= $ Pop
LEADING(L) = { * , id } $ $ Accept
LEADING(R) = { * , id }

= * id $
= <. <. .
> Stack Input Action
* .
> <. <. .
> $ id * id = id $ Shift
id .
> .
>
$ id * id = id $ Error
$ <. < .
< .

You might also like