Syntax Directed Translation SDT
Syntax Directed Translation SDT
• Symbols E,
E T,
T and F are associated with a synthesized attribute val.
val
• The token digit has a synthesized attribute lexval (it is assumed that it is
evaluated by the lexical analyzer).
E.val=17 return
E.val=5 + T.val=12
digit.lexval=5 digit.lexval=3
E.val=17
E.val=5 T.val=12
digit.lexval=5 digit.lexval=3
• Symbols E,E T,
T and F are associated with synthesized attributes loc and
code.
• The token id has a synthesized attribute name (it is assumed that it is
evaluated by the lexical analyzer).
• It is assumed that || is the string concatenation operator.
D L.in=real
id id.entry=p
stack parallel-stack
top → Z Z.z
Y Y.y
X X.x Î top → A A.a
. . . .
CS308 Compiler Theory 15
Bottom-Up Eval. of S-Attributed 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
A all
ll other
h shifts,
hif we do d not put anything
hi into
i val-stack
l k because
b
other terminals do not have attributes (but we increment the
stack pointer for val
val-stack).
stack).
.. .. .
L→ Er r T
E T →T *F
E→
E→
..
E+T
T
I2: L →E r
E →E +T
+ I8: E →E+ T
T → T*F .. (
F 4
5
T→
T→
F→..
T*F
F
(E)
T I3: E →T ..
T →T *F
T→ F
F → (E)
F→ d
( ) .. d
6
F→ d
F I4: T →F . *
.
. I9: T →T* F
..
F
I12: T →T*F .
..
( I5: F → ( E) F → (E)
(
E→ E+T E
F→ d 5
..
E→ T d
6
T→
T→
F→..
T*F
F
(E)
T
3
I10: F →(E )
E →E
E +T
.. +
) I13: F →(E) .
F→ d F
4 8
d I6: F →d . (
d
5
6
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”);
}
• Every S-attributed
S attributed definition is L-attributed,
L attributed the restrictions only apply
to the inherited attributes (not to synthesized attributes).
• Ex:
E A → { ... } X { ... } Y { ... }
S
Semantic
ti Actions
A ti
CS308 Compiler Theory 25
Translation Schemes
• When designing a translation scheme, some restrictions should be
observed
b d to ensure that
h an attribute
ib valuel is
i available
il bl when
h a semantic i
action refers to that attribute.
• These
Th restrictions
t i ti (motivated
( ti t d by b L-attributed
L tt ib t d definitions)
d fi iti ) ensure that
th t
a semantic action does not refer to an attribute that has not yet
computed.
computed
• In translation schemes, we use semantic action terminology instead of
semantic rule terminology gy used in syntax-directed
y definitions.
• The position of the semantic action on the right side indicates when that
semantic action will be evaluated.
⇓
E → E1 + T { E.val = E1.val + T.val } Î the production of the corresponding
translation scheme
E→TR
R → + T { print(“+”) } R1
R→ε
T → id { print(id.name) }
a+b+c Î ab+c+
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.
CS308 Compiler Theory 29
Inherited Attributes in Translation Schemes
• If a translation scheme has to contain both synthesized and inherited
attrib tes wee have
attributes, ha e to observe
obser e the following
follo ing rules:
r les:
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
L attributed syntax-directed
syntax directed definition
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).
CS308 Compiler Theory 30
Top-Down Translation
• We will look at the implementation of L-attributed definitions during
predictive
di i parsing.i
• Instead of the syntax-directed translations, we will work with
t
translation
l ti schemes.
h
• We will see how to evaluate inherited attributes (in L-attributed
definitions) during recursive predictive parsing.
parsing
• We will also look at what happens to attributes during the left-recursion
elimination in the left
left-recursive
recursive grammars
grammars.
• 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
i actions
i
CS308 Compiler Theory 34
Eliminating Left Recursion (cont.)
inherited attribute synthesized attribute
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
g { F.val = digit.lexval
g }
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
y = R.in }
A Y A.a=g(f(X.x),Y.y)
parse tree of non-left-recursive grammar
X X.x=f(X.x) A
X R.in=f(X.x) R A.a=g(f(X.x,Y.y)
Y R1.in=g(f(X.x),Y.y) R1 R.syn=g(f(X.x),Y.y)
ε R1.syn=g(f(X.x),Y.y)
⇓ remove embedding
b ddi semantic
i actions
i
E→TR
R → + T M R1
R→ε
T → id { print(id.name) }
M → ε { print(
print(“+”)
+ )}
CS308 Compiler Theory 45
Translation with Inherited Attributes
• Let us assume that every non-terminal A has an inherited attribute A.i, and every
symbol X has a synthesized attribute X.s
X s in our grammar.
grammar
• For every production rule A→ X1 X2 ... Xn ,
– introduce new marker non-terminals M1,M2,...,Mn and
– replace this production rule with A→ M1 X1 M2 X2 ... Mn Xn
– the synthesized attribute of Xi will be not changed.
– the inherited attribute of Xi will be copied into the synthesized attribute of Mi by the new semantic
action added at the end of the new pproduction rule Mi→ε.
– Now, the inherited attribute of Xi can be found in the synthesized attribute of Mi (which is immediately
available in the stack.
S → M1 A { s[ntop]=k(s[top-1],s[top]) }
M1→ ε { s[ntop]=1 }
A → M2 B M3 C { s[ntop]=h(s[top-4],s[top-3],s[top-2],s[top-1],s[top]) }
M2→ ε { s[ntop]=f(s[top]) }
M3→ ε { s[ntop]=g(s[top-2],s[top-1],s[top])}
B→b { s[ntop]=m(s[top-1],s[top]) }
C→c { s[ntop]=n(s[top-1]
s[ntop] n(s[top-1],s[top])
s[top]) }
B.i=f(1) C.i=g(1,f(1),m(..))
B C
B
B.s=m(f(1),b.s)
(f(1) b ) C
C.s=n(g(..),c.s)
( ( ) )
b c
S → M1 L
L → M2 L1 1 Î But since L → ε will be reduced first by the bottom-up
L → ε { print(s[top]) } parser, the translator cannot know the number of 1s.
M1 → ε { s[ntop]=0 }
M2 → ε { s[ntop]=s[top]+1 }
L→Lb L→MLb
L→a Î L→a NOT
O LR-grammar
M→ε
.
S’ → L,, $
L → . M L b, $
L → . a,, $
M → .,a Î shift/reduce conflict