Unit IV: Syntax Directed Translation
Unit IV: Syntax Directed Translation
Question 1: What are Syntax Directed Translations (SDTs)? What are its types?
Explain with a suitable example.
1. Syntax-Directed Definition
A syntax-directed definition is a generalization of a context-free grammar in which each
grammar symbol has associated with set of attributes, divided into two types called the
synthesized and inherited attributes of that grammar symbol.
An attribute represent a string, a number, a type, a memory location, or whatever. The
value of an attribute at a parse-tree node is defined by a semantic rule associated with the
production used at that node.
The value of a synthesized attribute at a node 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.
Semantic rules set up dependencies between attributes that will be represented by a
graph. Dependency graph can derive an evaluation order for the semantic rules. Evaluation of the
semantic rules defines the values of the attributes at the nodes in the parse tree for the input
string.
A parse tree showing the values of attributes at each node is called an annotated parse
tree. The process of computing the attribute values at the nodes is called annotating or decorating
the parse tree.
Question 2: What is the Syntax Directed Definition (SDD) for the simple desk
calculator, write and explain. What would be the parse tree for 1 * 2 + 3n?
b) Synthesized Attributes
The value of a synthesized attribute at a node is computed from the values of attributes at
the children of that node in the parse tree. A syntax-directed definition that uses synthesized
attributes is said to be an S-attributed definition.
A parse tree for an S-attributed definition can always be annotated by evaluating the
semantic rules for the attributes at each node bottom up, from the leaves to the root. The value of
a synthesized attribute at a node is computed from the values of attributes at the children of that
node in the parse tree;
Example 2: Construct parse tree, syntax tree and annotated parse tree for the input siring is
1*2+3n;
Solution:
E
E + T
T F
+
T * F digit
* 3 (3)
F digit
1 2 (2)
digit
(1)
(a) Syntax Tree (b) Parse Tree
Compiler Design 179
Unit – IV
The given expression 1*2+3 is followed by a newline character (n), the program prints
the value 5. Figure shows parse tree, syntax tree and annotated parse tree for the input 1*2+3n.
The output printed at the root of the tree is the value of E.val at the first child of the root.
L .val = 5
Value obtained from
child to parent n
E.val = 5
E.val = 2 T.val = 3
+
F.val = 3
T.val = 2
digit.lexval = 1
Figure: Annotated parse tree for 1*2+3n.
For the computation of attributes, we start from the leftmost and bottommost node. The
rule F digit is used in order to reduce digit to F. The semantic action that takes place here is
F.val := digit.lexval. The value of digit is obtained from lexical analyzer becomes the value of F.
Hence F.val = 1.
Since T is the parent node of F and semantic action suggests that T.val = F.val. We can
get the T.val = 1.Thus the computation of S-attributes is done from children. Then consider
T T1 * F production; the corresponding semantic action is
T.val := T1.val F.val
Hence T.val := T1.val F.val = 1 2 = 2.
Similarly, the combination of E1.val + T.val becomes the E node.
E.val := E1.val + T.val = 2 + 3
E.val := 5
Here we get the E.val from left child of E and T.val from right child of E. Finally we acquire the
value of E as 5.Then the production L En is applied to reduce E.val = 5 and n = ;
The semantic action associated with L En suggests us to print the result E.val. Hence
the output will be 5.
180 Compiler Design
Unit – IV
Question 3: What should be the SDD with inherited attribute for the grammar:
D TL T int | real L L, id | id
show the dependency graph for "real id, id, id".
Question 4: Consider the following grammar:
D TL T int | real L L, id | id
Construct a syntax directed scheme with inherited attribute L. Show parse tree for
input string "int x, y, z".
c) Inherited Attribute
The value of inherited attribute at a node in a parse tree is defined using the attribute
values at the parent or siblings. Inherited attributes are convenient for expressing the dependence
of a programming language construct on the context in which it appears.
For example, we can use an inherited attribute to keep track of whether an identifier
appears on the left or right side of an assignment in order to decide whether the address or the
value of the identifier is needed.
Example 3: For the following grammar, annotate the parse tree for the computation of inherited
attributes for the given string: real id1, id2, id3;
D→TL
T → int | real
L → L1 , id | id
For the string real id1, id2, id3 we have to distribute the data type real to all the identifiers id1, id2
and id3; such that id1 becomes real, id2 becomes real and id3 becomes real. Following steps are to
be followed,
1. Construct the syntax directed definition using semantic action.
2. Annotate the parse tree with inherited attributes by processing in top down fashion.
The syntax directed definition for the above given grammar is
Production Semantic Rules
D→TL L.in := T.type
T → int T. type := integer
T → real T.type := real
L → L1 , id Ll.in := L.in
addType(id. entry, L.in)
L → id addType(id. entry, L.in)
Table: Syntax directed definition with inherited attribute L.in.
Compiler Design 181
Unit – IV
A declaration generated by the nonterminal D in the syntax-directed definition in table
consists of the keyword int or real, followed by a list of identifiers. The nonterminal has a
synthesized attribute type, whose value is determined by the keyword in the declaration.
The semantic rule L.in := T.type, associated with production D → TL, sets inherited
attribute L.in to the type in the declaration. The rules then pass this type down the parse tree using
the inherited attribute L.in.
Rules associated with the productions for L call procedure addtype to add the type of
each identifier to its entry in the symbol table (pointed to by attribute entry). Nonterminal D
represents a declaration, which, from production 1, consists of a type T followed by a list L of
identifiers. T has one attribute, T.type, which is the type in the declaration D. Nonterminal L also
has one attribute, which we call in to emphasize that it is an inherited attribute.
The purpose of L.in is to pass the declared type down the list of identifiers, so that it can
be added to the appropriate symbol-table entries.
Productions 2 and 3 evaluate the synthesized attribute T.type, giving the appropriate
value, integer or real. This type is passed to the attribute L.in in the rule for production 1.
Production 4 passes L.in down the parse tree. That is, the value Ll.in is computed at a
parse-tree node by copying the value of L.in from the parent of that node; the parent
corresponds to the head of the production.
Productions 4 and 5 also have a rule in which a function addType is called with two
arguments:
id.entry, a lexical value that points to a symbol-table object, and
L.in, the type being assigned to every identifier on the list.
Figure shows an annotated parse tree for the sentence real id1, id2, id3.
D
Value obtained from
child to parent
Question 5: Let synthesize attribute 'val' gives the value of binary number generated
by 'S' in the following grammar. (For example on input 100.101, S.Val = 4.625)
S L.L | L L LB | B B0|1
Give the synthesized attributes to determine S.Val.
Solution:
We will use attributes val for synthesize value, frac for fractional binary value of string,
int for integer binary value of string and len for the current position of bit in the binary string.
For example in the string 100.101, in the fractional part i.e. .101, for the first digit after
dot i.e. 1, L.len = 0 + 1 = 1, for the second digit 0, L.len = 1 + 1 = 2 and for the third digit 1,
L.len = 1 + 2 = 3. (100.101 = 22 + 01 + 00 + 2-1 + 0-2 + 2-3 = 4 + 0 + 0 + 0.5 + 0 + 0.125 = 4.625.)
Following table shows the syntax-directed definition:
Production Semantic Rules
SL.L S.val := L.int + L.frac
SL S.val := L.int
L LB L.int := L.int * 2 + B.val;
L.len := L.len + 1;
L.frac := L.frac + B.val * (1.0/2.0) L.len
184 Compiler Design
Unit – IV
LB L.int := B.val;
L.len := 1;
L.frac := B.val * (1.0/2.0) L.len
B0 B.val := 0
B1 B.val := 1
Table: Syntax-directed definition ( represents exponent operation)
For example, for the input string w = 100.101, the annotated parse tree will be,
f S.val = 4.625
Calculations are b e
given below
L.int = 4 + L.frac = 0.625
a d
B.val = 1 B.val = 1
0 0
1 1
Figure: Annotated Parse Tree
The values in the tree are calculated as:
a. L.int := L.int * 2 + B.val = 1 * 2 + 0 = 2
b. L.int := L.int * 2 + B.val = 2 * 2 + 0 = 4
c. L.frac := B.val * (1.0/2.0) L.len = 1 * (1.0/2.0) 1 = 0.5
d. L.frac := L.frac + B.val * (1.0/2.0) L.len = 0.5 + 0 * (1.0/2.0) 2 = 0.5 + 0 = 0.5
e. L.frac := L.frac + B.val * (1.0/2.0) L.len = 0.5 + 1 * (1.0/2.0) 3 = 0.5 + 0.125 = 0.625
f. S.val := L.int + L.frac = 4 + 0.625 = 4.625 (From (b) and (e))
a) Dependency Graph
A dependency graph shows the flow of information among the attribute instances in a
particular parse tree; an edge from one attribute instance to another means that the value of the first
is needed to compute the second. Edges express constraints implied by the semantic rules.
If an attribute 'y' is evaluated after the evolution of 'z' then we say that y is dependent on z
this dependency can be shown by parse tree with some other relation known as dependency graph.
Dependency graph exist in both synthesized and inherit attribute. Before constructing a
dependency graph for a parse tree, we put each semantic rule into the form b := f (c1, c2, . . . , ck)
by introducing a dummy synthesized attribute b for each semantic rule that consists of a
procedure call. The graph has a node for each attribute and an edge to the node for b from the
node for c if attribute b depends on attribute c.
Example 5: Design the dependency graph for the following grammar
E E1 + E2
E E1 * E2
Solution:
The semantic rules for the above grammar are as given below:
Production Semantic Rules
E E1 + E2 E.val := E1.val + E2.val
E E1 * E2 E.val := E1.val * E2.val
Table: Syntax-directed definition
The dependency graph is shown in following Figure.
Eval
Eval + Eval
E1val * E2val
Figure: Dependency Graph
The synthesized attributes can be represented by • val. Hence the synthesized attributes
are given by E.val, E1.val and E2.val. The dependencies among the nodes are given by solid
arrows. The arrows from E1 and E2 show that value of E depends upon E1 and E2.
186 Compiler Design
Unit – IV
Example 6:
Suppose A.a := f(X.x, Y.y) is a semantic rule for the production A → XY. This rule defines
a synthesized attribute A.a that depends on the attributes X.x and Y.y. If this production is used in
the parse tree, then there will be three nodes A.a, X.x, and Y.y in the dependency graph with an
edge to A.a from X.x since A.a depends on X.x, and an edge to A.a from Y.y since A.a also
depends on Y.y.
If the production A → XY has the semantic rule X.i := g(A.a, Y.y) associated with it, then
there will be an edge to X.i from A.a and also an edge to X.i from Y.y, since X.i depends on both
A.a and Y.y.
Example 7:
An example of a complete dependency graph is shown in Fig. The nodes of the
dependency graph, represented by the numbers 1 through 9, correspond to the attributes in the
annotated parse tree in Fig (page no. 184)
Question 7: Consider the following grammar. Show the parse tree and dependency
graph for the input string real x, y, z:
D TL
T int | real
L L, id | id.
Solution:
A dependency graph for the input string real idl, id2, id3 is shown in Figure.
L
From sibling
T.type L.in
L
L.in , id2
From sibling
id1
Figure: Dependency graph for a declaration real id1, id2, id3
The dependencies among the nodes can be shown be solid arrows. In the dependency
graph how the values can be inherited from the parent or sibling nodes are shown. Hence the
name for the attributes is inherited attributes.
b) Evaluation Order
The topological sort of the dependency graph decides the evaluation order in a parse tree.
In deciding evaluation order the semantic rules in the syntax directed definitions are used. Thus
the translation is specified by syntax directed definitions.
T.type L.in=real 2
6 L.in=real , id2 5
7 id1
c) S-Attributed Definitions
Given an SDD, it is diffcult to tell whether there exist any parse trees whose dependency
graphs have cycles. In practice, translations can be implemented using classes of SDD's that
guarantee an evaluation order, since they do not permit dependency graphs with cycles. Also, the
classes can be implemented efficiently in connection with top-down or bottom-up parsing. The
first class is defined as follows:
An SDD is S-attributed if every attribute is synthesized.
d) L-Attributed Definitions
The second type of SDD's is called L-attributed definitions. In this type, between the
attributes associated with a production body, dependency-graph edges can go from left to right,
but not from right to left (hence "L-attributed"). In short, each attribute must be either
1. Synthesized, or
2. Inherited, but with the rules limited as follows. Suppose that there is a production A →
X1X2 • • Xn, and that there is an inherited attribute Xi.a computed by a rule associated with
this production. Then the rule may use only:
a) Inherited attributes associated with the head A.
b) Either inherited or synthesized attributes associated with the occurrences of symbols
X1X2 • • Xi - 1 located to the left of Xi.
190 Compiler Design
Unit – IV
c) Inherited or synthesized attributes associated with this occurrence of Xi itself, but only
in such a way that there are no cycles in a dependency graph formed by the attributes of
this Xi.
Example 9:
The SDD in table is L-attributed.
Production Semantic Rules
T→FT' T'.inh := F.val
T.val := T'.syn
T ' → * F T1' T1'.inh := T1'.inh × F.val
T'.syn := T1'.syn
T'→ T'.syn := T'.inh
F → digit F.val := digit.lexval
Table: Syntax-directed definition
To see why, consider the semantic rules for inherited attributes
Production Semantic Rules
T→FT' T'.inh := F.val
T ' → * F T1' T1'.inh := T1'.inh × F.val
T'.synT'.inh
The first of these rules defines the inherited attribute := T '.syn
using only F.val, and F appears to the
left of T ' in the production body. The second rule defines T1'.inh using the inherited attribute
T '.inh associated with the head, and F.val, where F appears to the left of T1' in the production
body.
In each of these cases, the rules use information "from above or from the left," as
required by the class. The remaining attributes are synthesized. Hence, the SDD is L-attributed.
Example 10:
Any SDD containing the following production and rules cannot be L-attributed:
Production Semantic Rules
A→BC A.s := B.b
B.i := f (C.c, A.s)
The first rule, A.s := B.b, is a legitimate rule in either an S-attributed or L-attributed SDD. It
defines a synthesized attribute A.s in terms of an attribute at a child (that is, a symbol within the
production body).
The second rule defines an inherited attribute B.i, so the entire SDD cannot be S-attributed. Also,
the rule is legal, the SDD cannot be L-attributed, because the attribute C.c is used to define B.i,
Question 8: Write and explain the syntax directed definition (SDD) for constructing a
syntax tree for an expression? Show the syntax tree for “a – 4 + c”
Question 9: Consider the following grammar:
E E1 + T | E1 – T | T T (E) | id | num
where id and num are terminal symbols
i) Obtain syntax directed definition for constructing syntax-tree for the above
grammar.
ii) Obtain suitable translation scheme for definition in part (i) above.
iii) Show the steps for construction of syntax-tree for expression 'x - 5 + y '.
– id c
to entry for c
id a num 4
Question 10: How the translator for an S-attributed definition can be implemented with
the help of LR parser generator? (Synthesized attribute on the parser stack). Show the
implementation of a desk calculator with LR parser.
Question 11: Consider the following grammar:
LE E E1 + T | T T T1 * F | F F (E) | digit
where digit is terminal symbol.
i) Obtain Syntax Directed Definition for the above grammar.
ii) Give the implementation of above grammar using an LR parser.
iii) Show the moves made by the translator of part (ii) on input 5 + 3*4.
B B.b
top
C C.c
Question 12: Eliminate left Recursive from this grammar and develop Syntax-Directed
translation scheme for 9 – 5 + 2 grammar is:
EE+T|E–T|T
T (E) | id | num
5. Top-down Translation
In top-down translation, L-attributed definitions will be implemented during predictive parsing.
Example 16: Give translation scheme and show the annotated parse tree with the value of the
attribute E.val at root for 9 – 5 + 2 for the following grammar
EE+T|E–T|T
T (E) | num
Solution:
Compiler Design 201
Unit – IV
The translation scheme for the left recursive grammar is given below.
Production Semantic Action
E → El + T { E.val := E1.val + T.val }
E → El – T { T.val := Tl.val – F.val }
E→T { E.val := T.val }
T→(E) { T.val := E.val }
T → num { T.val := num.val }
Table: Translation scheme with left-recursive grammar.
Now remove the left recursion and rewrite the translation scheme for right recursive grammar as:
Production Semantic Action
E→T { R.i := T.val }
R { E.val := R.s }
R → +T { R1.i := R.i + T.val }
R1 { R.s := R1.s }
E → –T { R1.i := R.i - T.val }
R1 { R.s := R1.s }
R→ε { R.s := R.i }
T→ (
E { T.val := E.val }
)
T → num { T.val := num.val }
Figure: Transformed translation scheme with right-recursive grammar.
The annotated parse tree is shown in Figure.
E
T.val = 9 R.i = 9
– R.i = 4
T.val = 5
num.val = 9
+ T.val = 2 R.i = 6
num.val = 5
num.val = 2
X R.i = f(X.x)
A.a = g(f(X.x), Y1.y) Y2
A.a = f(X.x) Y1
X
Figure: Eliminating left recursion from a postfix SDT (Two different ways for the input "XYY")
In addition, R has a synthesized attribute R.s, not shown in Figure. This attribute is first
computed when R ends its generation of Y symbols, as signaled by the use of production R .
R.s is then copied up the tree, so it can become the value of A.a for the entire expression
XYY ….Y. The case where A generates XYY is shown in Figure, and we see that the value of A.a
at the root of Figure (a) has two uses of g.
Thus R.i is at the bottom of the tree as shown in Figure (b), and the value of R.s gets
copied up into that tree. To accomplish this translation, we use the following syntax directed
definition:
Production Semantic Action
AX {R.i = f(X.x)}
R {A.a = R.s}
RY {R1.i = g(R.i, Y.y)}
R1 {R.s = R1.s}
R {R.s = R.i}
The inherited attribute R.i is evaluated immediately before a use of R in the body, while the
synthesized attributes A.a and R.s are evaluated at the ends of productions. Thus, whatever values
are needed to compute these attributes will be available from what has been computed to the left.