Syntax-Directed Translation
Technique used to build semantic information for large structures, based
on its syntax.
In a compiler, Syntax-Directed Translation is used for
Constructing Abstract Syntax Tree
Type checking
Intermediate code generation
Compilers Attribute Grammars CSE 304/504 1 / 21
The Essence of Syntax-Directed Translation
The semantics (i.e., meaning) of the various constructs in the language is
viewed as attributes of the corresponding grammar symbols.
Example:
sequence of characters 495
→ grammar symbol TOK INT
→ meaning ≡ integer 495
→ is an attribute of TOK INT (yylval.int val).
Attributes are associated with Terminal as well as Nonterminal symbols.
Compilers Attribute Grammars CSE 304/504 2 / 21
An Example of Syntax-Directed Translation
E −→ E * E
E −→ E + E
E −→ id
E −→ E1 * E2 {E .val := E1 .val ∗ E2 .val}
E −→ E1 + E2 {E .val := E1 .val + E2 .val}
E −→ int {E .val := int.val}
Compilers Attribute Grammars CSE 304/504 3 / 21
Another Example of Syntax-Directed Translation
Decl −→ Type VarList
Type −→ integer
Type −→ float
VarList −→ id , VarList
VarList −→ id
Decl −→ Type VarList {VarList.type := Type.type}
Type −→ integer {Type.type := int}
Type −→ float {Type.type := float}
VarList −→ id , VarList 1 {VarList 1 .type := VarList.type;
id.type := VarList.type}
VarList −→ id {id.type := VarList.type}
Compilers Attribute Grammars CSE 304/504 4 / 21
Attributes
Synthesized: Attribute of LHS symbol of a grammar rule, whose
value depends on attributes of RHS symbols of the grammar rule.
Value flows from child to parent in the parse tree.
Example: val in Expression grammar
Inherited: Attribute of an RHS symbol of a grammar rule, whose
value depends on attributes of the LHS symbol and the other RHS
symbols of the grammar rule.
Value flows into a node in the parse tree from parents and/or siblings.
Example: type of VarList in declaration grammar
Compilers Attribute Grammars CSE 304/504 5 / 21
Syntax-Directed Definition
Actions associated with each production in a grammar.
For a production A −→ X Y , actions may be of the form:
A.attr := f (X .attr 0 , Y .attr 00 ) for synthesized attributes
Y .attr := f (A.attr 0 , X .attr 00 ) for inherited attributes
If the function f does not have side effects, syntax directed definitions is
also called as attribute grammars.
Compilers Attribute Grammars CSE 304/504 6 / 21
Attributes and Definitions
S-Attributed Definitions: Where all attributes are synthesized.
L-Attributed Definitions: Where all inherited attributes are such
that their values depend only on
inherited attributes of the parent, and
attributes of left siblings
Compilers Attribute Grammars CSE 304/504 7 / 21
Synthesized Attributes: An Example
E −→ E * E
E −→ E + E
E −→ int
E −→ E1 * E2 {E .val := E1 .val ∗ E2 .val}
E −→ E1 + E2 {E .val := E1 .val + E2 .val}
E −→ int {E .val := int.val}
Compilers Attribute Grammars CSE 304/504 8 / 21
Information Flow for “Expression” Example
11 E
6 E + 5 E
3 E * 2 E 5 int
3 int 2 int
3 * 2 + 5
Compilers Attribute Grammars CSE 304/504 9 / 21
Another Example of Syntax-Directed Translation
Decl −→ Type VarList
Type −→ integer
Type −→ float
VarList −→ id , VarList
VarList −→ id
Decl −→ Type VarList {VarList.type := Type.type}
Type −→ integer {Type.type := int}
Type −→ float {Type.type := float}
VarList −→ id , VarList 1 {VarList 1 .type := VarList.type;
id.type := VarList.type}
VarList −→ id {id.type := VarList.type}
Compilers Attribute Grammars CSE 304/504 10 / 21
Information Flow for “Type” Example
int Decl
int Type int VarList
int integer int id , VarList int
id int
integer x , y
Compilers Attribute Grammars CSE 304/504 11 / 21
Syntax-Directed Definitions with yacc/Bison
E −→ E1 * E2 {E .val := E1 .val ∗ E2 .val}
E −→ E1 + E2 {E .val := E1 .val + E2 .val}
E −→ int {E .val := int.val}
E : E MULT E {$$.val = $1.val ∗ $3.val}
E : E PLUS E {$$.val = $1.val + $3.val}
E : INT {$$.val = $1.val}
Compilers Attribute Grammars CSE 304/504 12 / 21
Synthesized Attributes and Bottom-up Parsing
Keep track of attributes of symbols while parsing.
Shift-reduce parsing: Keep a stack of attributes corresponding to
stack of symbols.
Compute attributes of LHS symbol while performing reduction (i.e.,
while pushing the symbol on symbol stack)
Compilers Attribute Grammars CSE 304/504 13 / 21
Synthesized Attributes & Shift-reduce parsing
E −→ E +E
E −→ E *E
E −→ int
Stack Input Stream Attributes
$ 3 * 2 + 5$ $
$ int * 2 + 5$ $3
$ E * 2 + 5$ $3
$ E * 2 + 5$ $3⊥
$ E * int + 5$ $3⊥2
$ E + 5$ $6
$ E + 5$ $6⊥
$ E + int $ $6⊥5
$ E +E $ $$6⊥5
$ E $ $ 11
Compilers Attribute Grammars CSE 304/504 14 / 21
Inherited Attributes
Ss −→ S ; Ss
Ss −→
B −→ { Ss }
S −→ B
S −→ other
Ss −→ S ; Ss 1 {S.block = Ss.block;
Ss 1 .block = Ss.block; }
Ss −→
B −→ { Ss } {Ss.block = child(B.block); }
S −→ B {B.block = S.block; }
S −→ other {other.block = S.block; }
Compilers Attribute Grammars CSE 304/504 15 / 21
Top-down Parsing
parse Ss() {
/* production 1 */
parse S();
parse Ss();
return;
/* production 2 */
return;
}
parse B() {
consume(OPEN BRACE);
parse Ss();
consume(CLOSE BRACE);
}
Compilers Attribute Grammars CSE 304/504 16 / 21
Inherited Attributes and Top-down Parsing
parse Ss(block) {
/* production 1 */
parse S(block);
parse Ss(block);
return;
/* production 2 */
return;
}
parse B(block) {
consume(OPEN BRACE);
parse Ss(child(block));
consume(CLOSE BRACE);
}
Compilers Attribute Grammars CSE 304/504 17 / 21
Attributes and Top-down Parsing
Inherited: analogous to function arguments
Synthesized: analogous to return values
L-attributed definitions mean that argument to a parsing function is
argument of the calling function, or
return value/argument of a previously called function
Compilers Attribute Grammars CSE 304/504 18 / 21
Attributes and Bottom-up Parsing
Synthesized: stored along with symbols on stack
Inherited: ???
Compilers Attribute Grammars CSE 304/504 19 / 21
Inherited Attributes and Bottom-up Parsing
Inherited attributes depend on the context in which a symbol is used.
For inherited attributes, we cannot assign an value to a node’s attributes
unless the parent’s attributes are known.
When building parse trees bottom-up, parent of a node is not known when
the node is created!
Solution:
Ensure that all attributes are inherited only from left
siblings.
Use “global” variables to capture inherited values,
and introduce “marker” nonterminals to manipulate the
global variables.
Compilers Attribute Grammars CSE 304/504 20 / 21
Inherited Attributes & Bottom-up parsing
Ss −→ S ; Ss
Ss −→
B −→ { Ss }
S −→ B
S −→ other
B −→ { M1 Ss M2 }
M1 −→ { current block++;}
M2 −→ { current block−−;}
M1 and M2 are marker non-terminals.
Compilers Attribute Grammars CSE 304/504 21 / 21