Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 53

CHAPTER FOUR

Syntax-Directed Translation

1
Outline
• Introduction
• Syntax-Directed Definitions and Translation Schemes
• Syntax-Directed Definitions
• Annotated Parse Tree
• Annotating a Parse Tree With Depth-First Traversals
• Dependency Graph
• Evaluation order
• S-Attributed Definitions
• Bottom-Up Evaluation of S-Attributed Definitions
• Top-Down Evaluation of S-Attributed Definitions
• L-Attributed Definitions
• Translation Schemes
2
Introduction
• Grammar symbols are associated with attributes to
associate information with the programming language
constructs that they represent.
• Values of these attributes are evaluated by the semantic
rules associated with the production rules.

• Evaluation of these semantic rules:


– may generate intermediate codes
– may put information into the symbol table
– may perform type checking
– may issue error messages
– may perform some other activities
– in fact, they may perform almost any activities.
3
Syntax-Directed Definitions and Translation
Schemes
• When we associate semantic rules with productions, we use two
notations:
– Syntax-Directed Definitions
– Translation Schemes
• Syntax-Directed Definitions:
– give high-level specifications for translations
– hide many implementation details such as order of evaluation of
semantic actions.
– We associate a production rule with a set of semantic actions, and we do
not say when they will be evaluated.
• Translation Schemes:
– indicate the order of evaluation of semantic actions associated with a
production rule.
– In other words, translation schemes give more information about
implementation details. 4
Syntax-Directed Definitions
• A syntax-directed definition is a generalization of a
context-free grammar in which:
– Each grammar symbol is associated with a set of attributes.
– This set of attributes for a grammar symbol is partitioned into
two subsets called synthesized and inherited attributes of that
grammar symbol.
– Each production rule is associated with a set of semantic rules.
• An attribute can represent anything we choose:
– a string, a number, a type, a memory location, intermediate
program representation etc...
– The value of a synthesized attribute is computed from the values
of attributes at the children of that node in the parse tree.
– The value of an inherited attribute is computed from the values
of attributes at the siblings and parent of that node in the parse
tree.
5
Syntax-Directed Definitions…
• Semantic rules set up dependencies between attributes which
can be represented by a dependency graph.
• This dependency graph determines the evaluation order of
these semantic rules.
• Evaluation of a semantic rule defines the value of an
attribute.
• But a semantic rule may also have some side effects such as
printing a value.
• A depth-first traversal algorithm traverses the parse tree
thereby executing semantic rules to assign attribute values.
• After the traversal is complete the attributes contain the
translated form of the input.
6
Syntax-Directed Definition…
• In a syntax-directed definition, each production A → α is
associated with a set of semantic rules of the form:
b=f(c 1,c 2,…,c )n where f is a function,
and b can be one of the followings:
ꢀ b is a synthesized attribute of A and c ,c ,…,c 1 2 aren
attributes of the grammar symbols in the production
( A → α ). For A ꢁ C A.b = C.c
OR
ꢀ b is an inherited attribute one of the grammar symbols in
α (on the right side of the production),
and c 1,c ,…,c
2 nare attributes of the grammar symbols in the
production ( A → α ). For A ꢁC C.c = A.b
7
Attribute Grammar
• So, a semantic rule b=f(c ,c ,…,c
1 2 ) nindicates that the
attribute b depends on attributes c ,c ,…,c
1 2. n

• In a syntax-directed definition, a semantic rule:


– may just evaluate a value of an attribute or
– it may have some side effects such as printing values.

• An attribute grammar is a syntax-directed definition in which


the functions in the semantic rules cannot have side effects
(they can only evaluate values of attributes).

8
Annotated Parse Tree

• A parse tree showing the values of attributes at


each node is called an annotated parse tree.
• The process of computing the attributes values at
the nodes is called annotating (or decorating) of
the parse tree.
• Of course, the order of these computations
depends on the dependency graph induced by
the semantic rules.

9
Annotating a Parse Tree With
Depth-First Traversals

procedure visit(n : node);


Begin
for each child m of n, from left to right do
visit(m);
evaluate semantic rules at node n
end

10
Example: Synthesized Attributed grammar that calculate the
value of expression

Production Semantic Rules


L→En print(E.val)
E → E1 + T E.val = E1.val + T.val
E→T E.val = T.val
T → T1 * F T.val = T1.val * F.val
T→F T.val = F.val
F→(E) F.val = E.val
F → digit F.val = digit.lexval

ꢂ It specifies a simple calculator that reads an input line


containing an arithmetic expression involving:
ꢂ digits, parenthesis, the operator + and *, followed by a new line
character n, and
ꢂ prints the value of expression. 11
Example: Synthesized Attributed grammar that
calculate the value of expression
Production Semantic Rules
L→En print(E.val)
E → E1 + T E.val = E1.val + T.val
E→T E.val = T.val
T → T1 * F T.val = T1.val * F.val
T→F T.val = F.val
F→(E) F.val = E.val
F → digit F.val = digit.lexval

• Symbols E, T, and F are associated with a synthesized


attribute val.
• The token digit has a synthesized attribute lexval
(it is assumed that it is evaluated by the lexical analyzer).
12
Depth-First Traversals: Example
Input: 9+5+2n
L print (16)

E.val=16

E.val=14 T.val=2

E.val=9 F.val=2
T.val=5
Note: all attributes
T.val=9 in this example
F.val=5
are of synthesized
F.val=9 attributes

9 + 5 + 2 n 13
Annotated Parse Tree: Example
Input: 5+3*4 L (print 17)

E.val=17 n

E.val=5 + T.val=12

T.val=5 T.val=3 * F.val=4

F.val=5 F.val=3 digit.lexval=4

digit.lexval=5 digit.lexval=3

14
Quiz: Synthesized Attributed grammar that
calculate the value of expression

ꢂGiven the expression 5+3*4 followed by new line, the


program prints 17.
ꢂ Draw the decorated parse tree for input: 1*2n

ꢂ Draw the annotated parse tree for input: 5*3+4n

ꢂ Draw the annotated parse tree for input: 5*(3+4)n

15
Exercises : Synthesized Attributed grammar
that calculate the value of expression
• By making use of SDD of slide 11: give annotated parse
trees for the following expressions:

a) (3+4) * (5+6)n
b) 7*5*9*(4+5)n
c) (9+8*(7+6)+5)*4n

16
Syntax-Directed Definition: Exercises
Production Semantic Rules
N → L1.L2 N.v = L1.v + L2.v / (2L2.l)
L1 → L2 B L1.v = 2 * L2.v + B.v
L1.l = L2.l + 1
L→B L.v = B.v
L1.l = 1
B→0 B.v = 0
B→1 B.v = 1

ꢂ Draw the decorated parse tree for input:


a - 1011.01
b – 11.1
c – 1001.001
17
Dependency Graphs for Attributed Parse
Trees
• Annotated parse tree shows the values of attributes.
• Dependency graph helps us to determine how those
values can be computed.
• The attributes should be evaluated in a given order
because they depend on one another.
• The dependency of the attributes is represented by a
dependency graph.
• b(j) -----D()----> a(i) if and only if there exists a
semantic action such as a (i) := f (... b (j) ...)
• Algorithm for the construction of the dependency graph
18
Dependency graph : Algorithm

for each node n in the parse tree do


for each attribute a of the grammar symbol at n do
construct a node in the dependency graph for a
for each node n in the parse tree do
for each semantic rule b := f (c1, c2, ... ck)
associated with the production used at n do
for i:= 1 to k do
construct an edge from the node for ci to the node for b;

19
Dependency Graphs for
Attributed Parse Trees Direction of value
dependence
Synthesized A.a
attributes A.a= (X.x, Y.y)
X.x Y.y

A.a
A ꢁ XY X.x= (A.a, Y.y)
X.x Y.y

Inherited A.a
attributes
X.x Y.y Y.x= (A.a, X.x)

20
Annotated Parse Tree: Example
Input: 5+3*4 L (print 17)

E.val=17 n

E.val=5 + T.val=12

T.val=5 T.val=3 * F.val=4

F.val=5 F.val=3 digit.lexval=4

digit.lexval=5 digit.lexval=3

21
Dependency Graph
Input: 5+3*4 L (print 17)

E.val=17

E.val=5 T.val=12

T.val=5 T.val=3 F.val=4

F.val=5 F.val=3 digit.lexval=4

digit.lexval=5 digit.lexval=3

val is synthesized attribute


22
Syntax-Directed Definition: Inherited
Attributes Inherited
Production Semantic Rules
D→ TL L.inh = T.type
T → int T.type = integer
T → real T.type = real synthesized
L → L1 , id L1.inh = L.inh,
addtype(id.entry,L.inh)
L → id addtype(id.entry,L.inh)

• Symbol T is associated with a synthesized attribute


type.
• Symbol L is associated with an inherited attribute inh.
23
A Dependency Graph – Inherited Attributes
Input: real id ,id
1 ,id
2 3

T.type =real L.inh = real

L.inh = real Id .entry


3
real ,
Annotated
Parse tree
L.inh = real , Id2.entry

Id1.entry
24
A Dependency Graph – Inherited Attributes
Input: real id ,id
1 ,id
2 3

D
1-10 represents
5 L1.inh = real 6
nodes of T1.type =real 4
Dependency
graph 3
7 L .inh = real
2
real 8 Id3.entry
,
L3.inh = real Id2.entry 2
9 10 ,
Id1.entry
1
25
SDD based on a grammar suitable for top-down
parsing
Production Semantic Rules
T → FT’ T’.inh = F.val
T.val = T’.syn
T’ → *FT1’ T1’.inh = T’.inh X F.val
T’.syn = T1’.syn
T’ → ε T’.syn = T’.inh
F → digit F.val = digit.lexval

• The SDD above computes terms like 3 * 5 and 3 * 5 * 7.


• Each of the non-terminals T and F has a synthesized attribute val;
• The terminal digit has a synthesized attribute lexval.
• The non-terminal T’ has two attributes:
• an inherited attribute inh and
• a synthesized attribute syn. 26
Annotated parse tree for 3*5

T.val = 15

F.val = 3 T’.inh = 3
T’.syn = 15

T ’.inh = 15
1
digit.lexval = 3
F.val = 5 T1’.syn = 15
*

digit.lexval = 5 ε

27
Dependency graph for the annotated parse tree
of 3*5
T.val = 15 9

F.val = 3 5 T’.inh = 3
3 T’.syn = 15 8

6 T ’.inh = 15
digit.lexval = 3 4 1

* F.val = 5 T1’.syn = 15
1 7
2
Synthesized attribute digit.lexval = 5 ε
Inherited attribute
28
Dependency graph: Exercises
Production Semantic Rules
N → L1.L2 N.v = L1.v + L2.v / (2L2.l)
L1 → L2 B L1.v = 2 * L2.v + B.v
L1.l = L2.l + 1
L→B L.v = B.v
L1.l = 1
B→0 B.v = 0
B→1 B.v = 1

ꢂ Draw the decorated parse tree and


ꢂ Draw the dependency graph for input:
a - 1011.01
b – 11.1
c – 1001.001 29
Evaluation Order
• A topological sort of a directed acyclic graph (DAG) is
any ordering m , 1m , …,
2 m ofn the nodes of the graph,
such that:
if m i → m j is an edge, then m appears
i before m j

• Any topological sort of a dependency graph gives a


valid evaluation order of the semantic rules.

• Note: It is not possible to find such an order for an


acyclic graph.

30
Example Parse Tree with Topologically Sorted
Actions
Topological sort:
1. Get id1.entry D
2. Get id2.entry
3. Get id3.entry
4. T1.type=real
5 L1.in = real
T1.type =real 4
5. L1.in=T1.type 6
6. addtype(id .entry,
3
L1.in) 7 L .in = real
2 Id .entry 3
3
7. L2.in=L1.in real 8
8. addtype(id2.entry, ,
L2.in)
9. L3.in=L2.in L3.in = real Id2.entry 2
9 10 ,
10. addtype(id1.entry,
L3.in)
Id1.entry
1
31
Syntax-Directed Definition – Example
Production Semantic Rules
E → E1 + T E.loc=newtemp(), E.code = E1 .code || T.code || add E .loc,T.loc,E.loc
1
E→T E.loc = T.loc, E.code=T.code
T → T1 * F T.loc=newtemp(), T.code = T 1.code || F.code || mult T 1.loc,F.loc,T.loc
T→F T.loc = F.loc, T.code=F.code
F→(E) F.loc = E.loc, F.code=E.code
F → id F.loc = id.name, F.code=“”

• Symbols E, T, and F are associated with synthesized attributes


loc and code.
• The token id has a synthesized attribute name (it is assumed
that it is evaluated by the lexical analyzer).
• It is assumed that || is the string concatenation operator.

32
S-Attributed Definitions
• Syntax-directed definitions are used to specify syntax-directed
translations that guarantee an evaluation order.
• We would like to evaluate the semantic rules during parsing
(i.e. in a single pass, we will parse and we will also evaluate
semantic rules during the parsing).
• We will look at two sub-classes of the syntax-directed
definitions:
– S-Attributed Definitions: only synthesized attributes used
in the syntax-directed definitions.
– L-Attributed Definitions: in addition to synthesized
attributes, we may also use inherited attributes.

• These classes of SDD can be implemented efficiently in


connection with top-down and bottom-up parsing.

33
S-Attributed Definitions
• A syntax-directed definition that uses synthesized
attributes exclusively is called an S-attributed
definition (or S-attributed grammar)

• A parse tree of an S-attributed definition is annotated


with a single bottom-up traversal.
• Bottom-up parser uses depth first traversal.
• A new stack is maintained to store the values of the
attributes as in the following example.

• Yacc/Bison only support S-attributed definitions

34
Example: Attribute Grammar in Yacc

%{
#include <stdio.h>
void yyerror(char *);
%}
%token INTEGER
%%
program:
program expr '\n' { printf("%d\n", $2); }
|
;
expr:
INTEGER { $$=$1;}
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
; Synthesized
%% attribute of
parent node expr
35
Bottom-Up Evaluation of S-Attributed
Definitions
• We put the values of the synthesized attributes of the grammar symbols into
a parallel stack.
– When an entry of the parser stack holds a grammar symbol X (terminal
or non-terminal), the corresponding entry in the parallel stack will hold
the synthesized attribute(s) of the symbol X.
• We evaluate the values of the attributes during reductions.

A → XYZ A.a=f(X.x,Y.y,Z.z) where all attributes are synthesized.

stack parallel-stack
top → Z Z.z
Y Y.y
X X.x top → A A.a
. . . .
36
Bottom-Up Eval. of S-Attributed Definitions…
Production Semantic Rules
L→En print(val[top-1])
E → E1 + T val[ntop] = val[top-2] + val[top]
E→T $$ = $1 + $3; in yacc
T → T1 * F val[ntop] = val[top-2] * val[top]
T→F
F→(E) val[ntop] = val[top-1]
F → digit
• At each shift of digit, we also push digit.lexval into val-stack.
• At all other shifts, we do not put anything into val-stack
because other terminals do not have attributes (but we
increment the stack pointer for val-stack).
37
Canonical LR(0) Collection for The Grammar
.. L I: . . .
.
I : L’→ L → I : L →En I : E →E+T * 9

.. .. .
0 L → En L’ L n 7 T 11 T →T
E
..
1
E→ E+T I2: L
E →E n + I 8: E
T →E+
→ T F 4 *F

..
E→ T +T T*F (
5
T→
T→
F→..
T*F
F
(E)
T
I3 : E
T →T ..*F
.
T→ F
F → (E)
F→ d
d
6

F→ d T →F *
F I:
4
.. I : T →T* . F
I : T →T*F .
.
( I : F → ( E)
9
F → (E)F 12
(
..
5
E → E+T E id 5
E→ T d
6
T → T*F
T→ F T ..
F →(E
I10:E →E )
F →(E) .
.
F → (E) 3 )
+T +
F I :
F→ d 4 8 13
F →d (
d 5

.
I: d
6 6

38
Bottom-Up Evaluation -- Example
• At each shift of digit, we also push digit.lexval into val-stack.
stack val-stack input action semantic rule
0 5+3*4n s6 d.lexval(5) into val-stack
0d6 5 +3*4n F→d F.val=d.lexval – do nothing
0F4 5 +3*4n T→F T.val=F.val – do nothing
0T3 5 +3*4n E→T E.val=T.val – do nothing
0E2 5 +3*4n s8 push empty slot into val-stack
0E2+8 5- 3*4n s6 d.lexval(3) into val-stack
0E2+8d6 5-3 *4n F→d F.val=d.lexval – do nothing
0E2+8F4 5-3 *4n T→F T.val=F.val – do nothing
0E2+8T11 5-3 *4n s9 push empty slot into val-stack
0E2+8T11*9 5-3- 4n s6 d.lexval(4) into val-stack
0E2+8T11*9d6 5-3-4 n F→d F.val=d.lexval – do nothing
0E2+8T11*9F12 5-3-4 n T→T*F T.val=T1.val*F.val
0E2+8T11 5-12 n E→E+T E.val=E1.val*T.val
0E2 17 n s7 push empty slot into val-stack
0E2n7 17- $ L→En print(17), pop empty slot from val-stack
0L1 17 $ acc
39
Top-Down Evaluation of S-Attributed Definitions

Productions Semantic Rules


A→B print(B.n0), print(B.n1)
B → 0 B1 B.n0=B1.n0+1, B.n1=B 1.n1
B → 1 B1 B.n0=B1.n0, B.n1=B 1.n1+1
B→ε B.n0=0, B.n1=0

where B has two synthesized attributes (n0 and n1).

40
Top-Down Evaluation of S-Attributed Definitions
• In a recursive predictive parser, each non-terminal corresponds
to a procedure.

procedure A() {
call B(); A→B
}
procedure B() {
if (currtoken=0) { consume 0; call B(); } B→0B
else if (currtoken=1) { consume 1; call B(); } B→1B
else if (currtoken=$) {} // $ is end-marker B→ε
else error(“unexpected token”);
}

41
Top-Down Evaluation of S-Attributed Definitions
procedure A() {
int n0,n1; Synthesized attributes of non-terminal B
call B(&n0,&n1); are the output parameters of procedure B.
print(n0); print(n1);
} All the semantic rules can be evaluated
procedure B(int *n0, int *n1) { at the end of parsing of production rules
if (currtoken=0)
{int a,b; consume 0; call B(&a,&b); *n0=a+1; *n1=b;}
else if (currtoken=1)
{ int a,b; consume 1; call B(&a,&b); *n0=a; *n1=b+1; }
else if (currtoken=$) {*n0=0; *n1=0; } // $ is end-marker
else error(“unexpected token”);
}

42
L-Attributed Definitions
• S-Attributed Definitions can be efficiently implemented.
• We are looking for a larger (larger than S-Attributed
Definitions) subset of syntax-directed definitions which
can be efficiently evaluated.

L-Attributed Definitions

• L-Attributed Definitions can always be evaluated by the


depth first visit of the parse tree.
• This means that they can also be evaluated during the
parsing.

43
L-Attributed Definitions
• A syntax-directed definition is L-attributed if each
inherited attribute of X , where
j 1≤j≤n, on the right side
of A → X1 X2 ...X n depends only on:
1. The attributes of the symbols X ,...,X
1 toj-1the left of X in the j
production and
2. the inherited attribute of A A.a

A → X1 X2
Dependency of X .x
2
inherited attributes X1.x

44
L-Attributed Definitions
• L-attributed definitions allow for a natural order of
evaluating attributes: depth-first and left to right.
Aꢁ XY
X.i=A.i A.s=Y.s
X.i = A.i A
A.s= Y.s
Y.i= X.s
X Y.i=X.s Y

Every S-attributed definition is L-attributed, the restrictions


only apply to the inherited attributes (not to synthesized
attributes). 45
A Definition which is NOT L-Attributed
Productions Semantic Rules
A→ LM L.in=l(A.i), M.in=m(L.s), A.s=f(M.s)
A→QR R.in=r(A.in), Q.in=q(R.s), A.s=f(Q.s)

• This syntax-directed definition is not L-attributed because the


semantic rule Q.in=q(R.s) violates the restrictions of L-
attributed definitions.
• When Q.in must be evaluated before we enter to Q because it is
an inherited attribute.
• But the value of Q.in depends on R.s which will be available
after we return from R.
• So, we are not be able to evaluate the value of Q.in before we
enter to Q.
46
Example: L-attributed definition
Production Semantic Rules
T → FT’ T’.inh = F.val
T.val = T’.syn
T’ → *FT1’ T1’.inh = T’.inh X F.val
T’.syn = T1’.syn
T’ → ε T’.syn = T’.inh
F → digit F.val = digit.lexval

• The SDD above computes terms like 3 * 5 and 3 * 5 * 7.


• Each of the non-terminals T and F has a synthesized attribute val;
• The terminal digit has a synthesized attribute lexval.
• The non-terminal T’ has two attributes:
• an inherited attribute inh and
• a synthesized attribute syn. 47
Exercises
• Suppose that we have a production A → BCD. Each of the
four non-terminals A, B, C, and D have two attributes:
– s is a synthesized attribute, and
– i is an inherited attribute.
• For each of the sets of rules below, tell whether:
(i) the rules are consistent with an S-attributed definition
(ii) The rules are consistent with an L-attributed definition,
and
(iii) whether the rules are consistent with any evaluation
order at all?

48
Exercises…

1) A.s = B.i + C.c


2) A.s = B.i + C.c and D.i = A.i + B.s
3) A.s = B.s + D.s
4) A.s = D.i, B.i = A.s + C.s, C.i = B.s, and D.i = B.i + C.i

49

You might also like