0% found this document useful (0 votes)
165 views9 pages

Compiler Construction Insights

This document discusses semantic analysis and intermediate code generation in compiler construction. It addresses: 1. The task of semantic analysis is to check static semantics and generate an internal representation of the program. Static semantics include variable definitions, type checking operands, and parameter matching. 2. An internal form is generated to translate source code, as generating optimal code cannot be done in one pass. 3. Different formalisms are used in compiler phases due to their strengths - regular expressions for lexical analysis, context-free grammars for syntax analysis, and syntax-directed translation for semantics and code generation.

Uploaded by

Mohamed Selmani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
165 views9 pages

Compiler Construction Insights

This document discusses semantic analysis and intermediate code generation in compiler construction. It addresses: 1. The task of semantic analysis is to check static semantics and generate an internal representation of the program. Static semantics include variable definitions, type checking operands, and parameter matching. 2. An internal form is generated to translate source code, as generating optimal code cannot be done in one pass. 3. Different formalisms are used in compiler phases due to their strengths - regular expressions for lexical analysis, context-free grammars for syntax analysis, and syntax-directed translation for semantics and code generation.

Uploaded by

Mohamed Selmani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

TDDD55 Compilers and Interpreters

Semantic Analysis and Intermediate


TDDB44 Compiler Construction Code Generation
source program
sequence of chars:
’IF sum=5 THEN..’
Lexical
analysis
sequence of tokens:
’IF’ ’sum’ ’=’ ’5’
Syntactic
analysis
Semantic Analysis and parse tree, derivation tree
Semantic
Intermediate Code Generation Table
management
analysis and
Intermediate
Error
Management
code gen
internal form,
intermediate code
Code
optimization

internal form
Code
generation

Peter Fritzson, Christoph Kessler, object program


IDA, Linköpings universitet, 2011
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.2 TDDD55/TDDB44 Compiler Construction, 2011

Semantic Analysis and Intermediate Methods/Formalisms in Compiler


Representations Phases?
 The task of this phase is to check the "static semantics“ and
generate the internal form of the program.  Which methods / formalisms are used in the various
phases during the analysis?
1. Lexical analysis: RE (regular expressions)
 Static semantics
2. Syntax analysis: CFG (context-free grammar)
 Check that variables are defined, operands of a given
operator
t are compatible,
tibl th
the number
b off parameters
t 3 Semantic analysis and intermediate code generation:
3.
matches the declaration etc. (syntax-directed translation)
 Formalism for static semantics?
 Internal form
 Generation of good code cannot be achieved in a single
pass – therefore the source code is first translated to an
internal form.
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.3 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.4 TDDD55/TDDB44 Compiler Construction, 2011

Why not the Same Formalism Use of Context Free Grammars vs


Everywhere? Regular Expressions?
Why not use the same formalism (formal notation) during  Follow-up questions:
the whole analysis?  Why are lexical and syntax analysis divided into two
 REs are too weak for describing the language’s syntax and different phases?
semantics.  Why not use a CFG instead of REs in lexical descriptions
 Both lexical features and syntax of a language can be of a language?
described using a CFG.
CFG Everything that can be described  Answers:
A
using REs can also be described using a CFG.
 Simple design is important in compilers. Separating lexical
 A CFG can not describe context-dependent (static semantics) and syntax analysis simplifies the work and keeps the
features of a language. Thus there is a need for a stronger phases simple.
method of semantic analysis and the intermediate code
 You build a simple machine using REs (i.e. a scanner),
generation phase.
which would otherwise be much more complicated if built
using a CFG.
Syntax-directed translation is commonly used in this phase.
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.5 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.6 TDDD55/TDDB44 Compiler Construction, 2011

1
Syntax-Directed Translation in
Semantics Phase Goal: Intermediate Code Generation
The first method we present for the semantics phase is syntax-  Another representation of the source code is generated, a so-
directed translation. called intermediate code representation
Goal 1: Semantic analysis:  Generation of intermediate code has, among others, the
 a) Check the program to find semantic errors, e.g. type errors, following advantages:
undefined variables, different number of actual and formal The internal form is:
parameters in a procedure, ....
+ machine-independent
hi i d d t
 b) Gather information for the code generation phase, e.g.
var a: real; + not profiled for a certain language
b: integer
+ suitable for optimization
begin
a:= b; + can be used for interpreting
...
generates code for the transformation:
a := IntToReal(b); // Note: IntToReal is a function for changing
integers to a floating-point value.
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.7 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.8 TDDD55/TDDB44 Compiler Construction, 2011

Examples of Internal/Intermediate forms Postfix Notation


 Internal forms Postfix notation
(Also called reverse Polish notation) Examples and comparison:
 Infix notation
 Postfix notation (reverse Polish notation, RPN) Infix Postfix
 Abstract syntax trees, AST  Operators come after the operands. a+b ab+
 Three-address code  No parentheses or priority ordering a+b*c abc*+
required. (a + b) * c ab+c*
 Quadruples a + (-b - 3 * c) ab@3c*-+
 Ti l
Triples  Stack
St k machine,
hi compare with
ith an HP
calculator. Here @ denotes
 Infix notation unary minus
 Operands have the same ordering as in
 Example: infix notation.
a := b + c * (d + e)  Operators come in evaluation order.
 Operands are between the operators (binary operators).  Suitable for expressions without
Suitable notation for humans but not for machines because conditions (e.g. if ....)
of priorities, associativities, parentheses.

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.9 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.10 TDDD55/TDDB44 Compiler Construction, 2011

Evaluation of Postfix Notation Example Evaluation of Postfix Notation


 Given an arithmetic expression in reverse Polish (Postfix) notation it is  Example: evaluate the postfix expression below.
easy to evaluate directly from left to right.
 Often used in interpreters. ab@3c*-+
 We need a stack for storing intermediate results.
Given that a = 34, b = 4, c = 5
 If numeric value:
corresponding infix notation: a + (-b - 3 * c)
 Push the value onto the stack.
Step Stack Input
 If identifier: 1 -| ab@3c*-+ |-
 Push the value of the identifier (r-value) onto the stack. 2 -|34 b@3c*-+ |-
3 -|34 4 @3c*-+ |-
 If binary operator: 4 -|34 -4 3c*-+ |-
 Pop the two uppermost elements , apply the operator to them and push 5 -|34 -4 3 c*-+ |-
the result. 6 -|34 -4 3 5 *-+ |-
7 -|34 -4 15 -+ |-
 If unary operator: 8 -|34 -19 + |-
 Apply the operator directly to the top of the stack. 9 -|15 |-

 When the expression is completed, the result is on the top of the stack.
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.11 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.12 TDDD55/TDDB44 Compiler Construction, 2011

2
Extending Polish/Postfix Notation Extending Polish/Postfix Notation
Assignment Statement Conditional Statement
 Assignment  We need to introduce the unconditional jump, JUMP, and the
conditional jump, JEQZ, Jump if EQual to Zero, and also we
 := binary operator,
need to specify the jump location, LABEL.
 lowest priority for infix form,
L1 LABEL (or L1: )
 uses the l-value for its first operand <label> JUMP
 Example: <value> <label> JEQZ
Q
(value = 0 ⇒ false, otherwise ⇒ true)
x := 10 + k * 30
⇓ Example 1:
IF <expr> THEN <statement1> ELSE <statement2>
x 10 k 30 * + := gives us

<expr> L1 JEQZ <statement1> L2 JUMP L1: <statement2> L2:


where L1: stands for L1 LABEL

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.13 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.14 TDDD55/TDDB44 Compiler Construction, 2011

Example 2, Postfix Notation for If-then-


Else Statements
if a+b then
if c-d then
x := 10
else y := 20 Small Postfix Notation Exercise
else z := 30;

gives
i us

a b + L1 JEQZ
c d - L2 JEQZ
x 10 := L3 JUMP
L2: y 20 := L4 JUMP
L1: z 30 := L3: L4:

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.15 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.16 TDDD55/TDDB44 Compiler Construction, 2011

Representing While
Suitable Data Structure for Postfix Code Abstract Syntax Trees (AST)
 ASTs are a reduced variant of parse trees. A parse tree
while <expr> do <stat>
contains redundant information, see the figure below.
gives us
 Example: Parse tree for
L2: <expr> L1 JEQZ <stat> L2 JUMP L1: a := b * c + d Abstract syntax tree for
a := b * c + d :
<assign>

Exercise
<id> := <expr>
:=
Translate the repeat
p and for statements to p
postfix notation.

a <expr> + <term> a +
Suitable data structure for postfix code <term> <factor>
* d
An array where label corresponds to index.
<term> * <factor> <id>
Array Elements: b c
<factor>
 Operand – pointer to the symbol table. <id> d

 Operator – a numeric code, for example, which does not collide with <id>
c
the symbol table index.
b
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.17 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.18 TDDD55/TDDB44 Compiler Construction, 2011

3
Properties of Abstract Syntax Trees Three-address Code and Quadruples

 Advantages and disadvantages of abstract syntax trees Three-address code Z := x op y


 op: = +, -, *, /, :=, JEQZ, JUMP, [ ]=, =[ ] ↑ ↑ ↑
+ Good to perform optimization on addr1 addr2 addr3
Quadruples
+ Easy to traverse  Form:
+ Easy to evaluate, i.e. suitable for interpreting Example: Assignment statement Quadruples:
A := B * C + D
+ unparsing (prettyprinting) possible via inorder traversal op arg1 arg2 res
 gives us the quadruples
+ postorder traversing gives us postfix notation!
T1 := B * C
− Far from machine code T2 := T1 + D op arg1 arg2 res
A := T2 * B C T1
+ T1 D T2
 T1, T2 are temporary variables.
:= T2 A
 The contents of the table are references
to the symbol table.

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.19 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.20 TDDD55/TDDB44 Compiler Construction, 2011

Control Structures Using Quadruples Procedure call Quad- op arg1 arg2 res
no
 Example:  Example:f(a1, a2, ..., an) 1 param a1
Quad-no op arg1 arg2 res
if a = b 2 param a2
1 = a b T1
then x := x + 1 ... ... ...
2 JEQZ T1 (6) †
else y := 20; n := an
3 + x 1 T2  Example: READ(X)
4 := T2 x n+1 call f n

5 JUMP (7) † Quad- op arg1 arg2 res


6 := 20 y no
7 1 param X
Quad- op arg1 arg2 res
2 call READ 1 no
1 * A B T1
† The jump address was filled in later as we can not know in 2 + X 5 T2
advance the jump address during generation of the quadruple  Example: WRITE(A*B, X+5) 3 param T1
in a phase. We reach the addresses either during a later pass 4 param T2
or by using syntax-directed translation and filling in when 5 call WRITE 2
these are known. This is called backpatching.
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.21 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.22 TDDD55/TDDB44 Compiler Construction, 2011

Quadruples vs triples
Array-reference Triples (also called two-address code)
A[I] := B Quad- op arg1 arg2 res Triples Form:
no  Example: A := B * C + D
[ ]= is called l-value,
1 []= A I T1
specifies the address to  No temporary name!
2 := B T1
an element. In l-value Quadruples:
context we obtain − Temporary variables take up space in the symbol table.
storage adress from the + Good control over temporary
p y variables.
value of T1. + Easier to optimise and move code around.
Quad- op arg1 arg2 res
Triples:
B := A[I] no
1 =[] A I T2 − Know nothing about temporary variables.

=[ ] is called r-value, 2 := T2 B + Take up less space.


specifies the value of − optimization by moving code around is difficult; in this case indirect
an element triples are used.

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.23 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.24 TDDD55/TDDB44 Compiler Construction, 2011

4
Methods for Syntax-Directed Translation
1. Attribute Grammars 2. Syntax Directed Translation Scheme

There are two main methods: Describe the translation process using:
1. Attribute grammars,’attributed translation grammars’ a) a CFG
 Describe the translation process using b) a number of semantic operations
 a) CFG e.g. a rule: A → XYZ {semantic operation}

 b) a number of attributes that are attached to terminal and  Semantic operations are performed:
nonterminal symbols, and  when reduction occurs (bottom-up), or
 c) a number of semantic rules that are attached to the rules  during expansion (top-down).
in the grammar which calculate the value of the attribute.
 This method is a more procedural form of the previous one
(contains implementation details), which explicitly show the
evaluation order of semantic rules.

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.25 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.26 TDDD55/TDDB44 Compiler Construction, 2011

Example 1: Translation Schema for Example 2: Translation Schema


Semantic Analysis Intermediate Code Generation
 Intuition: Attach semantic actions to syntactic rules to perform
semantic analysis and intermediate code generation.
Translation of infix notation Productions Semantic operations
 Part of CFG, variable declarations of a language with non-nested blocks.
to postfix notation in a
 The text in {} stands for a description of the semantic analysis for bottom-up environment. 1 E → E1 + T {print(’+’)}
book-keeping of information on symbols in the symbol table. 2 | T . . .
3 T → T1 * F {print(’*’)}
Translation of the input string: 4 | F . . .
<decls>
decls → ...
<decl> → var <name-list> : <type-id> a+b*d 5 F → ( E ) . . .
{Attach the type of <type-id> to all id in <name-list>} 6 | id {print(id)}
<name-list> → <name-list> , <name> becomes in postfix:
{Check that name in <name-list> is not duplicated, and
a b d * +
check that name has not been declared previously}
<name-list> → <name>
{Check that name has not been declared previously}
<type-id>→ "ident" See the parse tree on the
{Check in the symbol table for "ident", return its index coming page:
if it is already there, otherwise error: unknown type.}
<name>→ "ident"
{Update the symbol table to contain an entry for this "ident"}

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.27 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.28 TDDD55/TDDB44 Compiler Construction, 2011

Translation Schema Intermediate Code E


x specifies temporal order

Parse Tree of 8 r1
of the reductions

Generation, Implementation in LR Case


Translation to
The parser routine: The semantic routine:
Postfix Code E + T
void parser(); void semantic(int ruleNo); 3 r2 r3
7
{ {
Translation of the T
while not done { switch ruleNo {
input string:
switch action { case 1: print(’+’); 2 r4
a+b*d T * F
case shift: case 3: print(’*’);
... case 6: print(id); F 5 r4 6 r6
to postfix:
case reduce: }; 1 r6
a b d * +
semantic(ruleNo); }; F id

... id 4 r6 d
}/* switch */; Productions Semantic operations Productions Semantic operations
a
}/* while */; 1 E → E1 + T {print(’+’)} 1 E → E1 + T {print(’+’)} id
2 | T . . .
}/* parser */; 2 | T . . . 3 T → T1 * F {print(’*’)} b
3 T → T1 * F {print(’*’)} 4 | F . . .
4 | F . . . 5 F → ( E ) . . .
5 F → ( E ) . . . 6 | id {print(id)}
6 | id {print(id)}
a b d * +

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.29 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.30 TDDD55/TDDB44 Compiler Construction, 2011

5
TDDD55 Compilers and Interpreters
TDDB44 Compiler Construction
Generating Quadruples
op opnd1 res

1. S  Var := E { GEN( ASGN, E.adr, 0, Var.adr ); }


Syntax-directed translation 2. E  E1 + T { temp = gen_tempvar();
of assignment statements and GEN( ADD, E1.adr, T.adr, temp );
E.adr = temp; }
arithmetic expressions 3. | T { E.adr = T.adr; }
into quadruples 4. T  T1 * F { temp = gen_tempvar();
GEN( MUL, T1.adr, F.adr, temp );
T.adr = temp; }
5. | F { T.adr = F.adr; }
using a bottom-up approach
6. F  ( E ) { F.adr = E.adr; }
7. | id { F.adr = lookup( id.name ); }
8. Var  id { Var.adr = lookup( id.name ); }

Peter Fritzson, Christoph Kessler,


IDA, Linköpings universitet, 2011
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.32 TDDD55/TDDB44 Compiler Construction, 2011

Generating Quadruples for Control Structures


Generating Quadruples for A := B * C + D Example: IF-THEN-ELSE
S
 S  if E then S1 else S2

Var A.adr Index Quadruple Table


:= E T2.adr
 Jump to S2 if E is false/zero
in: Quadruples for ....
 After S1 jump to after S2 .... temp := E
id E1 T1.adr + T D.adr
A p: <JEQZ, temp, q+1, 0>

T T1.adr F D.adr  Problem: jump target Quadruples for ...


quadruple indices q+1, r are ... statement S1
unknown q: <JUMP, r, 0, 0>
T1 B.adr F C.adr
* id when the jumps are generated
q+1: (L1:) Quadruples for ...
D
 Solution: factorise the ... statement S2
F B.adr grammar, store jump index in
( MUL, B.adr, C.adr, T1.adr ) id r: (L2:) ...
C attribute quad
( ADD, E1.adr, T.adr, T2.adr )
( ASGN, E1.adr, 0, Var.adr ) id
B
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.33 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.34 TDDD55/TDDB44 Compiler Construction, 2011

Generate Quadruples for if-then-else (2) Generate quadruples for if-then-else (3)
3. <ifclause> ::= if E then
 Factorised grammar:
{ <ifclause>.quad = currentquad + 1;
1. <ifstmt> ::= <truepart> S2
// save address p of jump over S1 for later in <ifclause>.quad
2. <truepart> ::= <ifclause> S1 else GEN ( JEQZ, E.addr, 0, 0 );
// jump to S2. Target q+1 not known yet.
3. <ifclause> ::= if E then
}
2 <truepart> ::= <ifclause>
2. f S1 else
{ <truepart>.quad = currentquad + 1;
// save address q of jump over S2 for later
Attributes: GEN ( JUMP, 0, 0, 0 );
addr = address to the symbol table entry for result of E // jump over S2. Target r not known yet.
QUADRUPLE[ <ifclause>.quad ][ 2 ] = currentquad + 1;
quad = quadruple number // backpatch JEQZ target to q+1
}
3. <ifstmt> ::= <truepart> S2
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.35 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.36 TDDD55/TDDB44 Compiler Construction, 2011

6
Generate WHILE <E> DO <S>
Generate Quadruples for if-then-else (4) in: quadruples for Temp := <E>
Quadruples p: JEQZ Temp q+1 Jump over <S> if <E> false
quadruples for <S>
3. <ifclause> ::= if E then for a while q: JUMP in Jump to the loop-predicate
… q+1: ...
statement The grammar factorises on:
2. <truepart> ::= <ifclause> S1 else 1. <while-stat> ::= <while-clause> <S>
2. <while-clause>::= <while> <E> DO
{ <truepart>.quad = currentquad + 1; 3. <while> ::= WHILE
// save address q of jump over S2 for later An extra attribute, NXTQ, must be introduced here. It has
GEN ( JUMP, 0, 0, 0 ); the same meaning as QUAD in the previous example.
// jump
j over S2. Target
T t r nott known
k yet.
t 3 {<while>
3. {<while>.QUAD QUAD ::= NEXTQUAD}
Rule to find start of <E>
QUADRUPLE[ <ifclause>.quad ][ 2 ] = currentquad + 1; 2. {<while-clause>.QUAD := <while>.QUAD;
// backpatch JEQZ target to q+1 Move along start of <E>
} <while-clause>.NXTQ := NEXTQUAD;
Save the address to the next quadruple.
1. <ifstmt> ::= <truepart> S2 GEN(JEQF, <E>.ADDR, 0, 0)
Jump position not yet known! }
1. {GEN(JUMP, <while-clause>.QUAD,0,0);
{ QUADRUPLE[ <truepart>.quad ][ 1 ] = currentquad + 1; Loop, i.e. jump to beginning <E>
// backpatch JUMP target to (r-1)+1 QUADR[<while-clause>.NXTQ,3]:=NEXTQUAD
} Similarly: while statement, repeat statement …
(backpatch) Position at the end of <S> }
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.37 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.38 TDDD55/TDDB44 Compiler Construction, 2011

TDDD55 Compilers and Interpreters


TDDB44 Compiler Construction

Small Quadruple Generation Exercise Attribute Grammars

Peter Fritzson, Christoph Kessler,


IDA, Linköpings universitet, 2011
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.39 TDDD55/TDDB44 Compiler Construction, 2011

Attribute Grammar Example 1


Attribute Grammar Semantic Analysis – Type Inference
Extended context-free grammar (CFG):  Given: Attribute Grammar, Parse tree for string i+3*r
 Attribute(s) (value fields) for each nonterminal
 Compute: Type for each subexpression (nonterminal)
 Semantic rule(s) for each production
 equational computation on attributes E type = Realtype
 executed at reduce (LR parsing) or expand (LL parsing)

 Inherited Attributes E1 type = Inttype op E2 type = Realtype


Synthesized +
 Information propagated from left to right in a production attribute: type
and downwards in a parse tree
id type = Inttype E1 op E2 type =
 E.g., type in declarations, addresses of variables Grammar Semantic
type = Realtype
rules: rules: i name = i *
 Synthesized Attributes Inttype
E  num { E.type = Inttype; }
 Information propagated from right to left in a production num id
and upwards in a parse tree E  num . num { E.type = Realtype; }
3 type = Inttype r type =
 E.g., value of expressions, type of expressions, transl. to internal form E  id { E.type = lookup(id.name).type; } Realtype
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.41 TDDD55/TDDB44 Compiler Construction, 2011 E  E op E
P. Fritzson,1C. Kessler, { E.type = ... (see next page)
2 IDA, Linköpings universitet. 8.42 } TDDD55/TDDB44 Compiler Construction, 2011

7
(cont.) (cont.)
 Attribute grammar for syntax-directed type checking  Attribute grammar extended for assignment statement
with implicit type conversion from integer to Real

... ...
E  num { E.type = Inttype; } E  E1 op E2 { E.type = ... }
E  num . num { E.type = Realtype; } ...

E  id { E.type
Et = lookup(id.name).type;
l k (id )t } S  V := E { if (V.type
(V type == E E.type)
type)
... // generate code directly according to type
E  E1 op E2 { E.type = (E1.type == Inttype && E2.type == Inttype)? Inttype : else
( E1.type == Inttype && E2.type == Realtype if (V.type == Inttype && E.type == Realtype)
|| E1.type == Realtype && E2.type == Inttype error(”Type error”);
|| E1.type == Realtype && E2.type == Realtype ) ? else
Realtype : if (V.type == Realtype && E.type == Inttype)
error(”Type error”), Notype; } // Code generation / evaluation with type conversion:
E.value = ... ;
type is a synthesised attribute: V.value = ConvertIntToReal( E.value );
information flows right-to-left, bottom-up }
}
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.43 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.44 TDDD55/TDDB44 Compiler Construction, 2011

Attribute Grammar Example 2: Attribute grammar example 3:


Intermediate Code Generation Calculator (an interpreter of expressions)
 Given: Attribute grammar G  Semantic rules calculate the value of an arithmetic expression
 Translate expressions in the language over G(E) to intermediate code in without generating any intermediate code
postfix notation
 Semantic rules execute at grammar rule reductions (LR)
 For example: 2+3-5 is translated to: 23+5- or 235-+ depending on parse
tree  Synthesised attribute N.val for each nonterminal N
 The attribute code is attached to all nonterminals in the grammar { display( E.val ); }
SE=
 A semantic rule attached to each g
grammar rule { E.val
E val = E1.val
val + T
T.val
val ); }
E  E1 + T
| T { E.val = T.val; }
E  E1 + E2 { E.code = concat( E1.code, E2.code, ”+” ); }
T  T1 * F { T.val = T1.val * F.val ); }
| E1 – T { E.code = concat( E1.code, T.code, ”-” ); }
| F { T.val = F.val; }
| T { E.code = T.code; }
F(E) { F.val = E.val; }
T  ’0’ { T.code = ”0”; }
| ’1’ { T.code = ”1”; } | num { F.val = num.val; }
... ...
| ’9’ { T.code = ”9”; }
value of integer-constant token num
as computed by the scanner
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.45 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.46 TDDD55/TDDB44 Compiler Construction, 2011

(cont.)
S display(37)
 Calculator input:
25 + 4 * 3 =
E 37 =

Small Attribute Grammar Exercise


E1 25 + T 12

SE= { display( E.val ); }


T 25 T 4 * F 3
E  E1 + T { E.val = E1.val + T.val); }
| T { E.val = T.val; }
T  T1 * F { T.val = T1.val * F.val ); } F 25 num
F 4
3
| F { T.val = F.val; }
F(E) { F.val = E.val; }
num num
| num { F.val = num.val; } 25 4
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.47 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.48 TDDD55/TDDB44 Compiler Construction, 2011

8
LR Implementation of Attribute Grammars LR Implementation of Attribute Grammars
 In an LR parser:  In an LR parser (comment to picture on the previous slide)
 Semantic stack in parallel with the parse stack  A semantic action: E.val = E1.val +T.val
(common stack pointer) translated to
 Each entry can store all attributes of a nonterminal a statement: val[stkp-2] = val[stkp-2]+val[stkp]

 When performing a reduction [ A  1 2 ...  k . ]  Comments:


 stkp denotes the stack pointer,
pointer val the attribute value (an array)
 calculate all attributes attr by
 its value in the semantic action is the value before the reduction
A.attr = f ( 1.attr, ..., k.attr )  Af the call, the LR parser will reduce stkp by the length of the right
Parse stack: Semantic stack: hand side of grammar rule (here: 3)
stack
pointer T T.val = 12  It then puts E on the parse stack (because we reduced with
E = E1+T) with the result that the stack pointer increases a step and
+ we get the reduced configuration in the previous slide.
Reduce stack
E1 E1.val = 25 pointer E E.val = 37
E  E1 + T
... ... ... ...
P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.49 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.50 TDDD55/TDDB44 Compiler Construction, 2011

LR Implementation of Attribute Grammars Implementation of Attribute Grammars


Generated semantic routine: Grammar:  In a Recursive Descent Parser:
semantic(ruleno)
{ switch ruleno 1. S  E =  Recall: One procedure for each nonterminal
case 1: display(val[stkp-1]); 2. E  E1 + T  Interpretation:
case 2: val [stkp-2] = val [stkp-2] + val[stkp];
3. | T
case 3: ;  Add a formal parameter for each attribute
case 4: val[stkp-2] = val[stkp-2] * val[stkp]; 4. T  T1 * F
case 5: ;
– implicit
p semantic stack ((i.e., by
ypparameters stored
5
5. | F
case 6: val[stkp-2] = val[stkp-1]; on the normal program execution stack)
6. F  ( E )
case 7: val[stkp] = num.val;
– parameters for synthesized attributes to be passed
} 7. | num
by reference, so values can be returned
 stkp specifies the stack pointer before reducing  Code generation:
 The stack grows with higher addresses  Write the translated code to a memory buffer or file
 reduce pops with stkp := stkp – lengthRightHandSide(rule) or return a pointer to generated code block to caller

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.51 TDDD55/TDDB44 Compiler Construction, 2011 P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.52 TDDD55/TDDB44 Compiler Construction, 2011

Example: Calculator for Recursive Descent


LL(1) grammar for calculator (EBNF style):

SE= { display( E.val ); }


E  T1 { E.val = T1.val; }
{+ T2 } { E.val = T1.val + T2.val; }
void E ( int *E_val )
T  F1 { T.val = F1.val; }
{
{{* F2} { T.val
T val = F1.val
val + F2.val;
val; } int T1_val,
T1 val T2_val;
T2 val;
F(E) { F.val = E.val; } T ( &T1_val );
*E_val = T1_val;
| num { F.val = num.val; } while (token == ’+’) {
scan();
T ( &T2_val );
*E_val = T1_val +T2_val );
}
}

P. Fritzson, C. Kessler, IDA, Linköpings universitet. 8.53 TDDD55/TDDB44 Compiler Construction, 2011

You might also like