Chapter 5 - Syntax Directed Translation
Chapter 5 - Syntax Directed Translation
Instructor: Mohammed O.
Email: momoumer90@gmail.com
Samara University
Chapter Five
This Chapter Covers:
Syntax Directed Translation and definitions
Construction of syntax trees
Syntax-Directed Translation
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.
An attribute may hold almost any thing.
a string, a number, a memory location, a complex record.
SDD and Translation Schemes
When we associate semantic rules with productions, we use
two notations:
Syntax-Directed Definitions
Translation Schemes
Syntax-Directed Definitions:
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 a little bit
information about implementation details.
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.
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.
Syntax-Directed Definitions (Cont.)
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.
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.
Syntax-Directed Definition
In a syntax-directed definition, each production A→α is
associated with a set of semantic rules of the form:
b=f(c1,c2,…,cn) where f is a function,
and b can be one of the followings:
b is a synthesized attribute of A and c1,c2,…,cn are
attributes of the grammar symbols in the production
( A→α ).
OR
b is an inherited attribute one of the grammar
symbols in α (on the
right side of the production), and c1,c2,…,cn are
attributes of the grammar symbols in the production
( A→α ).
Attribute Grammar
So, a semantic rule b=f(c1,c2,…,cn) indicates that the
attribute b depends on attributes c1,c2,…,cn.
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.
*
*
Dependency Graph
Input: 5+3*4
SDD – Example2
Production Semantic Rules
E → E1 + T E.loc=newtemp(),
E.code=E1.code||T.code || add E1.loc,T.loc,E.loc
E → T E.loc = T.loc, E.code=T.code
T → T1 * F T.loc=newtemp(),T.code=T1.code
|| F.code || mult T1.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=“”
stack parallel-stack
top Z Z.z
Y Y.y
X X.x top A A.a
. . . .
Bottom-Up Eval. of S-Att Definitions (Cont.)
Production Semantic Rules
L → E return print(val[top-1])
E → E1 + T val[ntop] = val[top-2] + val[top]
E→T
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).
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*4r s6 d.lexval(5) into val-stack
0d6 5 +3*4r F→d F.val=d.lexval–do nothing
0F4 5 +3*4r T→F T.val=F.val – do nothing
0T3 5 +3*4r E→T E.val=T.val – do nothing
0E2 5 +3*4r s8 push empty slot into val-stack
0E2+8 5- 3*4r s6 d.lexval(3) into val-stack
0E2+8d6 5-3 *4r F→d F.val=d.lexval – do nothing
0E2+8F4 5-3 *4r T→F T.val=F.val – do nothing
0E2+8T11 5-3 *4r s9 push empty slot into val-stack
0E2+8T11*9 5-3- 4r s6 d.lexval(4) into val-stack
0E2+8T11*9d6 5-3-4 r F→d F.val=d.lexval – do nothing
0E2+8T11*9F12 5-3-4 r T→T*F T.val=T1.val*F.val
0E2+8T11 5-12 r E→E+T E.val=E1.val*T.val
0E2 17 r s7 push empty slot into val-stack
0E2r7 17- $ L→Er print(17), pop empty slot from val-stack
0L1 17 $ acc
Top-Down Evaluation (of S-Att Definitions)
Productions Semantic Rules
A→B print(B.n0), print(B.n1)
B → 0 B1 B.n0=B1.n0+1, B.n1=B1.n1
B → 1 B1 B.n0=B1.n0, B.n1=B1.n1+1
B→ B.n0=0, B.n1=0
Semantic Actions
Translation Schemes
When designing a translation scheme, some restrictions
should be observed to ensure that an attribute value is
available when a semantic action refers to that attribute.
These restrictions (motivated by L-attributed definitions)
ensure that a semantic action does not refer to an attribute
that has not yet computed.
In translation schemes, we use semantic action
terminology instead of semantic rule terminology used in
syntax-directed definitions.
The position of the semantic action on the right side
indicates when that semantic action will be evaluated.
Translation Schemes for S-att Definitions
If our syntax-directed definition is S-attributed, the
construction of the corresponding translation scheme will
be simple.
Each associated semantic rule in a S-attributed syntax-
directed definition will be inserted as a semantic action into
the end of the right side of the associated production.
Production Semantic Rule
E → E1 + T E.val = E1.val + T.val a production of
a syntax directed definition
E → E1 + T { E.val = E1.val + T.val } the production of
the corresponding translation scheme
A Translation Scheme Example
A simple translation scheme that converts infix expressions
to the corresponding postfix expressions.
E→TR
R → + T { print(“+”) } R1
R→
T → id { print(id.name) }
a+b+c ab+c+
E → T { A.in=T.val } A { E.val=A.syn }
A → + T { A1.in=A.in+T.val } A1 { A.syn = A1.syn}
A → - T { A1.in=A.in-T.val } A1 { A.syn = A1.syn}
A → { A.syn = A.in }
T → F { B.in=F.val } B { T.val=B.syn }
B → * F { B1.in=B.in*F.val } B1 { B.syn = B1.syn}
B → { B.syn = B.in }
F → ( E ) { F.val = E.val }
F → digit { F.val = digit.lexval }
Eliminating Left Recursion (in general)
A → A1 Y { A.a = g(A1.a,Y.y) } a left recursive grammar with
A → X { A.a=f(X.x) } synthesized attributes (a,y,x).
A → X { R.in=f(X.x) } R { A.a=R.syn }
R → Y { R1.in=g(R.in,Y.y) } R1 { R.syn = R1.syn}
R→ { R.syn = R.in }