Chapter 4
Chapter 4
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.
8
Annotated Parse Tree
9
Annotating a Parse Tree With
Depth-First Traversals
10
Example: Synthesized Attributed grammar that calculate the
value of expression
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
digit.lexval=5 digit.lexval=3
14
Quiz: Synthesized Attributed grammar that
calculate the value of expression
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
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
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
digit.lexval=5 digit.lexval=3
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
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
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=“”
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.
33
S-Attributed Definitions
• A syntax-directed definition that uses synthesized
attributes exclusively is called an S-attributed
definition (or S-attributed grammar)
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.
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
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
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
48
Exercises…
49