SDT SDD PPT
SDT SDD PPT
1
Syntax-Directed Translation
2. Values of these attributes are evaluated by the semantic rules associated with the
production rules.
2
Syntax-Directed Translation
• Conceptually with both the syntax directed translation and translation
scheme we
– Parse the input token stream
– Build the parse tree
– Traverse the tree to evaluate the semantic rules at the parse tree nodes.
3
Syntax-Directed Definitions
1. 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.
2. The value of an attribute at a parse tree node is defined by the semantic rule
associated with a production at that node.
3. The value of a synthesized attribute at a node is computed from the values of
attributes at the children in that node of the parse tree
4. The value of an inherited attribute at a node is computed from the values of
attributes at the siblings and parent of that node of the parse tree
4
Syntax-Directed Definitions
Examples:
Synthesized attribute : E→E1+E2 { E.val =E1.val + E2.val}
Inherited attribute :A→XYZ {Y.val = 2 * A.val}
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(c1,c2,…,cn)
where f is a function and b can be one of the followings:
7
Attribute Grammar
• So, a semantic rule b=f(c1,c2,…,cn) indicates that the attribute b
depends on attributes c1,c2,…,cn.
8
Syntax-Directed Definition -- Example
10
Annotated Parse Tree -- Example
Input: 5+3*4 L
E.val=17 n
E.val=5 + T.val=12
digit.lexval=5 digit.lexval=3
11
Dependency Graph
Input: 5+3*4 L
E.val=17 n
E.val=5 + T.val=12
digit.lexval=5 digit.lexval=3
12
Syntax-Directed Definition – Inherited Attributes
13
Dependency Graph
• Directed Graph
• Shows interdependencies between attributes.
• If an attribute b at a node depends on an attribute c, then the semantic rule for b at that
node must be evaluated after the semantic rule that defines c.
• Construction:
– Put each semantic rule into the form b=f(c1,…,ck) by introducing dummy
synthesized attribute b for every semantic rule that consists of a procedure call.
– E.g.,
• LEn print(E.val)
• Becomes: dummy = print(E.val)
– 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.
14
Dependency Graph Construction
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
15
Dependency Graph Construction
• Example
• Production Semantic Rule
E→E1 + E2 E.val = E1.val + E2.val
E . val
16
Dependency Graph
D→TL L.in = T.type
T → int T.type = integer
T → real T.type = real
L → L1 , id L1.in = L.in,
addtype(id.entry,L.in)
L → id addtype(id.entry,L.in)
17
Evaluation Order
• A topological sort of a directed acyclic graph is any ordering
m1,m2…mk of the nodes of the graph such that edges go from nodes
earlier in the ordering to later nodes.
. i.e if there is an edge from mi to mj them mi appears before mj in the ordering
• Any topological sort of dependency graph gives a valid order for
evaluation of semantic rules associated with the nodes of the parse tree.
• The dependent attributes c1,c2….ck in b=f(c1,c2….ck ) must be available before f
is evaluated.
18
Evaluation Order
• a4=real;
• a5=a4;
• addtype(id3.entry,a5);
• a7=a5;
• addtype(id2.entry,a7);
• a9=a7;
• addtype(id1.entry,a5);
19
Syntax Trees
Syntax-Tree
– an intermediate representation of the compiler’s input.
– A condensed form of the parse tree.
– Syntax tree shows the syntactic structure of the program while
omitting irrelevant details.
– Operators and keywords are associated with the interior nodes.
– Chains of simple productions are collapsed.
Syntax directed translation can be based on syntax tree as well as
parse tree.
20
Syntax Tree-Examples
Expression: if B then S1 else S2
+ if - then - else
5 * B S1 S2
Statement:
3 4 • Node’s label indicates what kind
• Leaves: identifiers or constants of a statement it is
• Internal nodes: labelled with • Children of a node correspond to
operations the components of the statement
• Children: of a node are its
operands
21
Constructing Syntax Tree for Expressions
• Each node can be implemented as a record with several fields.
• Operator node: one field identifies the operator (called label of the node) and
remaining fields contain pointers to operands.
• The nodes may also contain fields to hold the values (pointers to values) of
attributes attached to the nodes.
• Functions used to create nodes of syntax tree for expressions with binary
operator are given below.
– mknode(op,left,right)
– mkleaf(id,id.entry)
– mkleaf(num,num.val)
Example: a-4+c
+
1. p1:=mkleaf(id,entrya);
2. p2:=mkleaf(num,4);
- id
3. p3:=mknode(-,p1,p2)
4. p4:=mkleaf(id,entryc);
to entry for c
5. p5:= mknode(+,p3,p4); num 4
id
23
A syntax Directed Definition for Constructing
Syntax Tree
1. It uses underlying productions of the grammar to schedule the calls of
the functions mkleaf and mknode to construct the syntax tree
2. Employment of the synthesized attribute nptr (pointer) for E and T to
keep track of the pointers returned by the function calls.
PRODUCTION SEMANTIC RULE
E E1 + T E.nptr = mknode(“+”,E1.nptr ,T.nptr)
E E1 - T E.nptr = mknode(“-”,E1.nptr ,T.nptr)
ET E.nptr = T.nptr
T (E) T.nptr = E.nptr
T id T.nptr = mkleaf(id, id.lexval)
T num T.nptr = mkleaf(num, num.val)
24
Annotated parse tree depicting construction of
syntax tree for the expression a-4+c
E.nptr
E.nptr + T.nptr
E.nptr - T.nptr id
+
T.nptr num
- id
id
Entry for c
id nu
m
Entry for a 25
S-Attributed Definitions
1. Syntax-directed definitions are used to specify syntax-directed translations.
3. 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).
27
Bottom-Up Evaluation of S-Attributed Definitions
• 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.
state val state val
top Z Z.z
Y Y.y
X X.x top A A.a
. . . .
28
Bottom-Up Evaluation of S-Attributed Definitions
Production Semantic Rules
L→En { print(val[top-1]); top=top-1;}
E → E1 + T {val[top-2] = val[top-2] + val[top]; top=top-2;}
E→T
T → T1 * F val[top-2] = {val[top-2] * val[top]; top=top-2;}
T→F
F→(E) {val[top-2] = val[top-1];top=top-2;}
F → digit
29
Bottom-Up Evaluation -- Example
• At each shift of digit, we also push digit.lexval into val-stack.
Input state val semantic rule
5+3*4n - -
+3*4n 5 5
+3*4n F 5 F → digit
+3*4n T 5 T→F
+3*4 n E 5 E→T
3*4n E+ 5-
*4 n E+3 5-3
*4n E+F 5-3 F → digit
*4n E+T 5-3 T→F
4n E+T* 5-3-
n E+T*4 5-3-4
n E+T*F 5-3-4 F → digit
n E+T 5-12 T → T1 * F
n E 17 E → E1 + T
En 17- L→En
L 17
30
L-Attributed Definitions
• When translation takes place during parsing, order of evaluation is linked to the order in which
the nodes of a parse tree are created by parsing method.
• A natural order can be obtained by applying the procedure dfvisit to the root of a parse tree.
• We call this evaluation order depth first order.
• L-attributed definition is a class of syntax directed definition whose attributes can always be
evaluated in depth first order( L stands for left since attribute information flows from left to
right).
dfvisit(node n)
{
for each child m of n, from left to right
{
evaluate inherited attributes of m
dfvisit(m)
}
evaluate synthesized attributes of n
}
31
L-Attributed Definitions
A syntax-directed definition is L-attributed if each inherited attribute of Xj,
where 1≤j≤n, on the right side of A → X1X2...Xn depends only on
1. The attributes of the symbols X1,...,Xj-1 to the left of Xj in the
production
2. The inherited attribute of A
32
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.
33
Translation Schemes
• In a syntax-directed definition, we do not say anything about the evaluation time of the
semantic rules (when the semantic rules associated with a production should be
evaluated).
• Translation schemes describe the order and timing of attribute computation.
• A translation scheme is a context-free grammar in which:
– attributes are associated with the grammar symbols and
– semantic actions enclosed between braces {} are inserted within the right sides of
productions.
Each semantic rule can only use the information computed by already executed semantic
rules.
• Ex: A → { ... } X { ... } Y { ... }
Semantic Actions
34
Translation Schemes for S-attributed Definitions
• useful notation for specifying translation during parsing.
• Can have both synthesized and inherited attributes.
• 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.
35
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+
36
A Translation Scheme Example (cont.)
T R
id {print(“a”)} + T {print(“+”)} R
id {print(“b”)} + T {print(“+”)} R
id {print(“c”)} ε
The depth first traversal of the parse tree (executing the semantic actions in that order)
will produce the postfix representation of the infix expression.
37
Inherited Attributes in Translation Schemes
• If a translation scheme has to contain both synthesized and inherited attributes, we have
to observe the following rules to ensure that the attribute value is available when an
action refers to it.
1. An inherited attribute of a symbol on the right side of a production must be
computed in a semantic action before that symbol.
2. A semantic action must not refer to a synthesized attribute of a symbol to the right
of that semantic action.
3. A synthesized attribute for the non-terminal on the left can only be computed after
all attributes it references have been computed (we normally put this semantic action at
the end of the right side of the production).
• With a L-attributed syntax-directed definition, it is always possible to construct a
corresponding translation scheme which satisfies these three conditions (This may not
be possible for a general syntax-directed translation).
38
Inherited Attributes in Translation Schemes: Example
A1 A2 {A1.in=1; A2.in=2}
39
A Translation Scheme with Inherited Attributes
D → T {L.in = T.type } L
T → int { T.type = integer }
T → real { T.type = real }
L → {L1.in = L.in } L1, id {addtype(id.entry,L.in)}
L → id {addtype(id.entry,L.in)}
• This is a translation scheme for an L-attributed definitions
40
Bottom Up evaluation of Inherited Attributes
1) Removing Embedding Semantic Actions
In bottom-up evaluation scheme, the semantic actions are evaluated during reductions.
• During the bottom-up evaluation of S-attributed definitions, we have a parallel stack to
hold synthesized attributes.
• Problem: where are we going to hold inherited attributes?
• A Solution:
– We will convert our grammar to an equivalent grammar to guarantee to the following.
– All embedded semantic actions in our translation scheme will be moved at the
end of the production rules.
– All inherited attributes will be copied into the synthesized attributes (most of the
time synthesized attributes of new non-terminals).
– Thus we will evaluate all semantic actions during reductions, and we find a
place to store an inherited attribute.
41
1 Removing Embedded Semantic Actions
42
Removing Embedded Semantic Actions
E→TR
R → + T { print(“+”) } R
R→ε
T → id { print(id.name) }
⇓
remove embedding semantic actions
E→TR
R→+TMR
R→ε
T → id { print(id.name) }
M → ε { print(“+”)}
43
2 Inheriting attributes on parser stack
44
3. Replacing Inherited by Synthesized Attributes
• Sometimes it’s possible to avoid the use of inherited attributes by
changing the grammar.
• A declaration in Pascal consists of a list of inentifiers followed by type.
a , b : integer
• A grammar for such declarations may include productions of the form
D L : T {L.s = T.s;}
T integer {T.s = integer;}
| char {T.s = char;}
L L1 , id {L.s = L1.s;}
| id
(for this grammar synthesized attribute alone will not work.)
• Modification to remove the need of inherited attributes.
D id L
L , id L | : T
T integer | char
45
Replacing Inherited by Synthesized Attributes
46
Top-Down Translation
• We will look at the implementation of L-attributed definitions during
predictive parsing.
• Instead of the syntax-directed definitions, we will work with translation
schemes.
• We will see how to evaluate inherited attributes (in L-attributed
definitions) during recursive predictive parsing.
• We will also look at what happens to attributes during the left-recursion
elimination in the left-recursive grammars.
47
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 }
48
Eliminating Left Recursion from Translation Scheme
• A translation scheme with a right-recursive grammar.
E → T {-----------}
R {-----------}
R→+
T {-----------}
R {-----------}
R→ -
T {-----------}
R {-----------}
R→
T → ( E ) { T.val = E.val }
T → num { T.val = num.val }
49
Eliminating Left Recursion from Translation Scheme
• A translation scheme with a left recursive grammar.
• When we eliminate the left recursion from the grammar (to get a
suitable grammar for the top-down parsing) we also have to change
semantic actions
50
Eliminating Left Recursion (cont.)
inherited attribute synthesized attribute
E → T { R.in=T.val } R { E.val=R.syn }
R → + T { R1.in=R.in+T.val } R1 { R.syn = R1.syn}
R → - T { R1.in=R.in-T.val } R1 { R.syn = R1.syn}
R → { R.syn = R.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 }
51