Compilation PhasesSource code Scanner Parser Semantic analyzer Intermediate code generation Intermediate code Optimized code back end... One-pass CompilerBKIT code Scanner √ Parser... Mu
Trang 1Syntax-Directed Translation
Dr Nguyen Hua PhungFalcuty of CSE – HCMUT
2007
Trang 3Compilation Phases
Source code Scanner
Parser
Semantic analyzer
Intermediate code generation
Intermediate code
Optimized code back end
Trang 4• A pass consists of reading an input file
and writing an output file
• A pass may include many phases
• One-pass or multi-pass compilation
– internal form
– information dependence
Trang 5One-pass Compiler
BKIT code
Scanner √ Parser
Trang 6Multi-pass Compiler
BKIT code
Scanner √ Parser
Trang 7Semantic Analyzer
• enforce semantic requirements:
– is an identifier a scalar, array, struct or a method ?
– is an identifier declared before used?
Trang 9Syntax-directed Definition
• Each grammar symbol associates with it a set of attributes
• Each grammar production associates with
it a set of semantics rules which evaluate
the symbols in the production
Trang 114 F.val = 8
T.val = 8 E.val = 8
4 F.val = 5
4 F.val = 5
T→ F {T.val = F.val}
E→ T {E.val = T.val}
Trang 14Example 2
E → E1 + T E.node = new BinExp(E1.node,+, T.node)
E → T E.node = T.node
T → T1 * F T.node = new BinExp(T1.node,*, F.node)
T → F T.node = F.node
F → ( E ) F.node = E.node
F → digit F.node = new LitExp(digit.lexeme)
F → id F.node = new VarExp(id.lexeme)
Trang 15BinExp LitExp(8)
Trang 18Synthesized Attribute
• An attribute of a grammar symbol in LHS is synthesized
if its value is computed from the values of the attributes
of the grammar symbols in RHS
• A syntax-directed definition that consists of only
synthesized attributes is called a S-attributed definition
4 F.val = 8
T.val = 8 E.val = 8
Trang 19Inherited Attribute
• An attribute of a grammar symbol in RHS is inherited if its value is computed from the values of the attributes of the grammar symbols in LHS and/or RHS
E’
T +
T’ F
Trang 20E → T E’ E’.in = T.val; E.val = E’.val
E’ → + T E’1 E’1.in = E’.in add T.val; E.val = E’1.val
T → F T’ T’.in = F.val; T.val = T’.val
T’ → * F T’1 T’1.in = T’.in mul F.val; T’.val = T’1.val
F → digit F.val = IntVal(digit.lexeme)
Trang 21E.val = E’.val = 17 E
T
E’
T +
E ’.in =E’.in add T.val = 17
Trang 22L-attributed Definitions
– the attributes of X1,X2,…Xj-1
– the inherited attributes of A
Trang 23E → T E’ E’.in = T.val ; E.val = E’.val
E’ → + T E’1 E’1.in = E’.in add T.va l; E.val = E’1.val
T → F T’ T’.in = F.val ; T.val = T’.val
T’ → * F T’1 T’1.in = T’.in mul F.val ; T’.val = T’1.val
Trang 26E → T {E’.in = T.val} E’ {E.val = E’.val}
E’ → + T {E’1.in = E’.in add T.val} E’1 {E’.val = E’1.val}
E’ → ∈ {E’.val = E’.in}
T → F {T’.in = F.val} T’ {T.val = T’.val}
T’ → * F {T’1.in = T’.in mul F.val} T’1 {T’.val = T’1.val}
T’ → ∈ {T’.val = T’.in}
F → ( E ) {F.val = E.val}
F → digit {F.val = IntVal (digit.lexeme)}
Trang 27Top-down Translation
• Read Algorithm 5.2 page 306
Trang 28Imperative Approach
• Create a function for each nonterminal
• Semantics actions are inserted into
corresponding places in the function
Trang 29L → E $ { print (E.val)}
E → T {E’.in = T.val} E’ {E.val = E’.val}
E’ → + T {E’1.in = E’.in add T.val} E’1 {E’.val = E’1.val}
E’ → ∈ {E’.val = E’.in}
T → F {T’.in = F.val} T’ {T.val = T’.val}
T’ → * F {T’1.in = T’.in mul F.val} T’1 {T’.val = T’1.val}
T’ → ∈ {T’.val = T’.in}
F → ( E ) {F.val = E.val}
F → digit {F.val = IntVal (digit.lexeme)}
Trang 31Example (cont’d)
Select(E → TE’) = {(,digit}
• E → T { E’.in = T.val} E’ {E.val = E’.val}
Trang 32Example (cont’d)
E’ → + T {E’1.in = E’.in add T.val} E’1 {E’.val = E’1.val}
E’ → ∈ {E’.val = E’.in}
int parseE’( int E’in ) {
int Tval, E1’in, E1’val, E’val;
switch (lookahead) {
case ‘+’ : match(‘+’);
Tval = parseT();
E1’in = E’in + Tval;
E1’val = parseE’( E1’in );
E’val = E1’val;
return E’val;
case ‘)’: case EOF: E’val = E’in; return E’val;
default: error(“waiting for +, ) and EOF”);
}
}
Trang 33Implicit Parser Tree
• No real parser tree generated
• A nonterminal node is actually a call to the corresponding function
• A terminal node is actually a call to the
Trang 34Object-oriented Approach
• A class is created for each nonterminal
• A method parse is created for each class
• For each terminal in a right hand side of a production, a call to match
• For each nonterminal in a right hand side
of a production, the corresponding object
is created and its method parse is called
Trang 35class E { void parse() {
switch (lookahead) { case ‘(‘: case ‘digit’:
Trang 36}
Trang 37Example (cont’d)
Object E
Trang 38Explicit Parser Tree
• The OO approach really creates a parser tree
• Each instance of a class represents an
instance of a nonterminal in the parser
tree
• Attributes can be attached to nodes easily
• Semantics actions can be evaluated when parsing or later
Trang 39L → E $ { print (E.val)}
E → T {E’.in = T.val} E’ {E.val = E’.val}
E’ → + T {E’1.in = E’.in add T.val} E’1 {E’.val = E’1.val}
E’ → ∈ {E’.val = E’.in}
T → F {T’.in = F.val} T’ {T.val = T’.val}
T’ → * F {T’1.in = T’.in mul F.val} T’1 {T’.val = T’1.val}
T’ → ∈ {T’.val = T’.in}
F → ( E ) {F.val = E.val}
F → digit {F.val = IntVal (digit.lexeme)}
Trang 40Example (cont’d)
• Attributes:
class L { }
class E { int val; }
class E’ { int in,val; }
class T { int val; }
class T’ {int in, val; }
class F {int val; }
E’.in, T’.in
E.val, E’.val, T.val, T’.val, F.val
Trang 42Example (cont’d)
E’ → + T {E’1.in = E’.in add T.val} E’1 {E’.val = E’1.val}
E’ → ∈ {E’.val = E’.in}
class E’ {
int in, val;
void parse() {
switch (lookahead) { case ‘+’ : match(‘+’);
( T t = new T()).parse();
E’ e1’ = new E’();
e1’.in = this.in + t.val;
Trang 43Abstract Syntax Tree (AST)
• Phrases
• AST
• How to make an AST?
Trang 44An binary-expression-phrase has 2 subphrases: 2 expressions.
An if-phrase has 3 subphrases: 1 expression and 2 statements
A while-phrase has 2 subphrases: 1 expression and 1 statement
Trang 458 + 5 * 4
E T
E’
T +
Trang 46• More natural than a parser tree:
– Some extra nonterminals used to solve
ambiguity become unnecessary
– Delimiters are removed
– Keywords become implicit
• Be able to traverse in any order
• Used widely in type checker, code
optimization, code generation
Trang 49F → num {F.node = new LitExp(num.Lexeme)}
F → id {F.node = new VarExp(id.Lexeme)}
F → ( E ) {F.node = E.node}
Trang 50BinExp VarExp(a)
F.node=new LitExp(num)
Trang 51Hand-on Exercise
• Write the translation scheme to generate
an AST for the following grammar:
Trang 52Directed Acyclic Graph (DAG)
• Like a syntax tree
• a node may have more than one parent
a + a * (b – c) + (b – c) * d
b a
Trang 54Bottom-up Evaluation for S-attributed Definitions
• The values of the synthesized attributes
associated with the grammar symbols are kept on the stack
• When a reduction is made, the
synthesized attributes of the LHS are
computed from the attributes of the RHS
on the stack
Trang 56Removing Embedding Actions
Trang 57Bottom-up Evaluation for L-attributed Definitions
Trang 58Stack Val
Trang 59D → T {L.in = T.type } L
T → int {T.type = int}
T → float {T.type = float}
Trang 60Example (con’t)
D → T L