Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Chapter V: Syntax directed translation

Parsing an input to do nothing about it is useless. In fact, an input is parsed so that some code is
generated, an information is displayed, etc. These different actions are done by the semantic actions
associated to the different rules of the grammar.
To execute these actions the parsing table may or may not be constructed first. Indeed, the best solution
performance-wise is to execute the actions while producing the parse tree.
Syntax directed definitions
A syntax directed definition is a generalization of the CFG in which each grammar symbol has an
associated set of attributes (synthesized and inherited). An attribute can represent anything we choose (
a string, a number, a type, a memory location, 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.
Semantic rules calculate the values of attributes hence set-up dependencies between attributes that will
be represented by a graph. The dependency graph enables to find an evaluation order for the semantic
rules.
A parse tree showing the values of the attributes is called an annotated or decorated parse tree.

Exercice 1: example of an attributed grammar:


/* We have two attributes defined for this grammar */
Syntax rules Semantic rules
N Æ L 1. L2 N.v = L1.v + L2.v / (2 L2.l)
L1 Æ L2 B L1.v = 2 * L2.v + B.v
L1.l = L2.l + 1
LÆ B L.v = B.v
L.l = 1
B Æ0 B.v = 0
B Æ1 B.v = 1

In the above example, everything is calculated from leaves to root; all attributes are synthesized.
Thus all the attributes can be calculated in a single pass.

Exercice 2: example of another attributed grammar:


/* We have three attributes defined for this grammar */
Syntax rules Semantic rules
N Æ L1 . L2 N.v = L1.v + L2.v

1
L1.s = 0
L2.s = -L2.l
L1 Æ L2 B L1.l = L2.l + 1
L2.s = L1.s + 1
B.s = L1.s
L1.v = L2.v + B.v
L ÆB L.v = B.v
L.l = 1
B.s = L.s
B Æ0 B.v = 0
B Æ1 B.v = 1 * 2B.s
Exercise: Draw the decorated parse tree for input 1011.01

Formal definition
In a syntax directed definition, each grammar production A --> α has associated with it a set of
semantic rules of the form:
b := f (c1, c2, .... ck) where f is a function and b, c1, ... ck are attributes of A and the symbols at the
right side of the production.
We say that:
b is synthesized attribute of A if c1, c2, ...ck are attributes belonging to the grammar symbols of the
production and,
b is inherited attribute of one of the grammar symbols on the right side of the production if c1, c2, ...ck
are attributes belonging to the grammar symbols of the production and,
In either case, we say that attribute b depends on attributes c1, c2, ...........ck.

Exercice 3: Attributed grammar that calculate the value of the expression,


Note: id.value is the attribute of id that gives its value.

Syntax Rule Semantic rule


E ÆE+T E1.v := E2.v + T.v
E ÆT E.v := T.v
T ÆT*F T1.v := T2.v * F.v
T ÆF T.v := F.v
F Æ id F.v := id.value
F Æ (E) F.v := E.v

2
Exercice 4: Attributed grammar that associates to an identifier its type

Syntax Rule Semantic rule


D ÆTL L.in := T.type
T Æ real T.type := real
L Æ ident ident.type := L.in
L1 Æ L2, ident L2.h := L1.h
ident.type := L1.h
Notes:
Here, the semantic action of an ident may have the side effect of adding the type in the symbol table for
that particular identifier.

Evaluation order
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


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;

Evaluation Order
A topological sort of a directed acyclic graph is any ordering m1, m2, m3, ... mk of the nodes of the
graph such that edges go from nodes earlier in the ordering to later nodes. i.e. if mi ( mj is an edge from
mi to mj then mi appears before mj in the ordering.

Note: It is not possible to find such an order for an acyclic graph.

3
Several methods have been proposed for evaluating semantic rules:
1. Parse rule based methods: for each input, the compiler finds an evaluation order. These
methods fail only if the dependency graph for that particular parse tree has a cycle.
2. Rule based methods: the order in which the attributes associated with a production are evaluated
is predetermined at compiler-construction time. For this method, the dependency graph need not
be constructed.
3. Oblivious methods: The evaluation order is chosen without considering the semantic rules. This
restricts the class of syntax directed definition that can be used.
Some classes of non-circular attributed grammars
S-Attributed grammars
We say that an attributed grammar is S-Attributed when all of its attributes are synthesized; i.e. it
doesn't have inherited attributes. Synthesized attributes can be evaluated by a bottom-up parser as the
input is being parsed. A new stack will be maintained to store the values of the attributes as in the
following example.
Example:
E Æ E1 + E2 { E.v = E1.v + E2.v }
Val(newTop) = Val(oldTop) + Val(oldTop – 2)
$$ = $1 + $3 (in Yacc)
We assume that the synthesized attributes are evaluated just before each reduction. Before the
reduction, attributes of E is in Val(Top) and attributes of E1 and E2 are in Val (Top – 1) and Val(Top -
2) respectively. After the reduction, E is put at the top of the State stack and its attribute values are put
at the top of Val.

The semantic actions that reference the attributes of the grammar will in fact be translated by the
Compiler generator (such as Yacc) into codes that reference the value stack.

L-Attributed grammars
It is difficult to execute the tasks of the compiler just by synthesized attributes. The L-attributed (L
stands for left) class of grammar allows a limited kind of inherited attributes.

Definition: A grammar is L-Attributed if and only if for each rule X0 --> X1 X2 ... Xj ... XN, all
inherited attributes of Xj depend only on:
1. Attributes of X1, ... X j- 1
2. Inherited attributes of X0

Of course all S-attributed grammars are L-attributed.

Example:

4
A ÆLM { L.h = f1 (A.h)
M.h = f2 (L.s)
A.s = f3 (M.s) }
This production does not contradict the rules of L-attributed grammars. Therefore, the corresponding
grammar may be L-attributed if all of the other productions follow the rule of L-attributed grammars.

Example:
A ÆQR { R.h = f4 (A.h)
Q.h = f5 (R.s)
A.s = f6 (Q.s) }

The grammar containing this production is not L-Attributed since Q.h depends on R.s which
contradicts with the rule of L-attributed grammars.

You might also like