Professional Documents
Culture Documents
Semantic analysis
Lexical analysis
token stream
Syntax analysis
syntax tree
Semantic analysis
syntax tree
Code generation
machine code
Code optimization
machine code
1. Syntax-directed translation
S ! aSb|aS|cSacS|✏ a 3 S2 b
Example: synthesized
Example: attribute to evaluate
synthesized attribute expressions
to evaluate expressions
Example:
LL expression synthesized attribute to evaluate expressions
grammar
Example:
grammarsynthesized attribute to evaluate
attributeexpressions
LL expression
Example: synthesized
Example: attribute
Productionsynthesized
toExample: synthesized
evaluate expressions
Semantic rulesattribute to evaluate expressions
to evaluate expres
T ! FT 0 T 0 .inh = F .val T .val = 15 F .val = 3
Production Semantic rulesLLProduction expression grammar
Example:
LL expression
T .val =synthesized
grammar num.lexval = 3 TLL expression gr
0 .inh = 3
0
rules Semanticattribute to evaluate expressions
T .syn
Semantic
Production rules 0
0 LL 0expression grammar T ! ⇤FT T .inh = T .inh ⇥ F .val 0
T
0
.val
0
T .syn = = 15
15 F FT.val
.val =
.val
0
3==515 F .val = 3
T ! FT TProduction
.inh =Semantic
F .valrules T ! FT T .inh
T
T !
LL .val
= FFT
.syn =
expression
.val T .inh = F .val
T .syn
grammar
LL
0
expression
1 0 1
0
num.lexval
num.lexval
grammar
= 5 T
0
= 3 num.lexval
T .inh1 =3=
0
Production
0 .inh =
0
1
0
0
153 T 0 .inh = 3 Se 0
.valT ! ✏ TProduction
0 0
TT
= T .syn
==
.val 15 T .val ==T3 .syn
.inhF .val rules
0 0 0
TT.val T.val0 .syn
! FTLL expression
T .inh
=Production
T
= Fgrammar
LL
T expression
! ⇤FT T grammar
= T Semantic
.syn num TF!
F ! rules
.syn
.inh =!T⇤FT
Tnum.lexval
.valFT 0
T Semantic
.inh ⇥T
= num.lexval
0
= Production
F .val
.inh
3 T 0 .inh
= 0
T .inh
1=
0T
3 ⇥
0
1 .syn
0
T Semantic
.syn1 == 15
F .val 15 0
rules T 0 .syn
F .val = 5= T
0
15 !
T .val0 = 15 F .valT =
0 0
F .valFT
0
10 =5 0
3 = 15 F .val T
0
1
0
Production TSemantic
T 0=
.syn TrulesT .inh
.synTT
=
!
T.syn F=.val
= FT T .inh
T5F.syn 0
num.lexval = F= T .inh = 15= 5 .val
.val5 num.lexval 0
T10 .inh = 15 = 3 00 0
T 0 ! ⇤FT10 TT10 .inh 0 = TT.inh 15 = 3=
0 0 0 .syn 00
=T15 .val
F .val = .val
=T!T.syn
! ⇤FT T T .inh
FT .inh T ⇥
.inh
T
= TT .syn
.val
!!
=
F
⇥=FF.val
✏1
FT
T
.val 1
0 T
0
.valT .synT
.inh
LL expression
.syn
=
!= T✏
F
num.lexval
.inh
.val
0
.val
0
grammar T = T=
.syn
num.lexval 0
= 5=TT1 .inh
0
.syn
0
T
=T=
T
T
0
.inh .val
0 0
.val
.syn 0
3num.lexval
T.val
115 0
=
==
.inh T 0
15 3 0 T1 .syn 0
1
0
0 = 15 0
T 0 .inh
F .val01 = 3 = 3 num.lexval
num.lexval
15.syn
0
0 = 3 = 3 T 0 .in
T
0
0
1
0 0
T ! ⇤FT 1T .inh .inh ⇥ F T .syn
= 3⇥TF.inh =
10 15 F .val = 5
.val = 3 T .syn = 15 F .val =
0 0 0 0
TTF0 .syn
!✏ = T T!T.syn
00 = TTF.inh
⇤FT .syn.inh
! num F .val1= num.lexval
! num Production
0
T ! ⇤FT T T
FT
0
!
F=
.val
.val
= T .inh ⇥ FT.val
FT
!
00=num.lexval
T
1 .syn
1
.inh
num.syn F
00
Semantic
= TT=.inh1
.inh
0
T
0 .syn
T.syn
T15 ⇥=F= F
!=⇤FT
.valrules
=T 15
.val
.val
num.lexval
0
0
0 1
T .inh = T .inh
.synF .val
T0 .syn
T = 5=
.syn 0
*
=T 15 num.lexval
F .val
.syn
T .val 0= 15 = 5FT =05 =
0
.val !
1
0
T103.inh ⇤FT
num.lexval
0 = 15=0 5 TT
0 .in 0
1
1 1
0 0
1
T .syn = T .syn 0 0 010 1 1 1
Tnum.lexval = 5num.lexval
TT.syn 1 .inh== 15 0 0
T0 ! ✏ T 0 .syn = T✏ 0 .inh ! ✏ = T .syn
TT .syn .synT T= T✏ .inh T105.syn 0 0 0 0
!.syn 1 T .inh
=
num.lexvalT10 .inh
== 15=3 15
T 0T.inh
0 ==
1 .syn 3 15 0
T ! T .syn = T .inhF ! num T .val
0 0 =
0 .syn 0 1
T ! ✏ T T!.syn
! num F .val = num.lexval ⇤FT= TT.inh
FT.val
.inh1F
0
=!
= num.lexval
=
T .inhnum15
⇥ FTF.val
0
0
0.val = num.lexval
1 .syn = T 150 .syn = 15 F .val = 5
0
0
0 T
0
Semantic analysis 10
Semantic analysis 10
(Dragonbook)
Semantic analysis 240
Evaluation order of SDD’s
2 2
1 1
1 8
6 7
2 5
3 4
Actions are performed from left-to-right when the rules is used for a
reduction
Interesting for example to generate code incrementally
T ! T1 ⇤ F 0 0
{print( ⇤ )} E ! T T
E E! !E T(E
+T {print(T
1 !
+ )}F T(E )
1 ⇤ F0 0
1 T .val = T
E! !FEEE .val
E1T!
F
+
F!
!
!T= Tnum
T F
T⇤T
)
F! E.val
.val
Put
{print(=grammar
digit ⇤= F!.val
F)}
E .val
Enum
1F .val
and.val += T2.14
.val
digit.lexva
{print(num.lexval)}
=Figure
T 0 0
.val of dragon
T T!!
!
T F⇤ F {print(T= !
{print(
⇤ )} F9expressions)
{print(num.lexval)}
1
)} {print(
0 0 5 )}T{print(
.val 2 )}= F
0 0 0 0 0 0
T !F F !
T ! T1 ⇤RF! T(EET )
.val
{print(
1F!! =
T5)TT1E1⇤.val
9 F
)} .val to
.val
{print( 10 0
5 )} =E
evaluate .val
TFhandout
{print(E.val
1 .val
2 )} 0 0
T .val F .v
0 0
F ! (E ) T ! F FE !
T
digit
!F (E
)numF .val (put
FF the
(see = ! the
.val
(E
Put
digit.lexval
=table
)2.14
grammar T1and
about F.valand
Figure=
.val
syntax-directed trE
2.14
!T TTF.val
F!!
!!
=
(EPut
F
FE .val
grammar .val =
and T
Figure
{print(num.lexval)}
Tgrammars
.val
to .val
)} =with
evaluate
of dragonbook
F .val
expressions)
(and
F ! num {print(num.lexval)}
F ! (E )T ! FT
F{print(
.val
num
=
9 )}
to ET
{print(
evaluate
.val F
complex !
{print(num.lexval)}
0 0
)} {print(
5expressions) 2digit0 0
F
int).val0 0
= d
9 (put
{print(
F 1! ⇤9Put
F
the
)} {print(
(see(E )
grammar
the
5.val
0 0
table
handout andF
Post-fix =
)} {print(
andT)} .val
2(see
.val
SDT
Figure
about
0 0
tree
theall
handout
1syntax-directed
as =
2.14 E
of .val
actions Fin.val
0 0
are
dragonbook the
about syntax
performe
for a (and d
treatm
F ! digit
T !FF.valPut to
digit.lexval
=grammar
evaluate
complex Tgrammars
.val =with
and Figure
expressions) (put
complex
F 2.14
.val the table
grammars with(and
int)of dragonbook
int) po
F ! digitexpressions)
to evaluate F .val digit.lexval
=SDT
Post-fix as all actions are
(putF !
the(E )(see theFhandout = Esyntax-directed
attable and
(see
Post-fix .valastree
SDT about
all
in
.val
actions
the dragobo
syntax-directed for at
are performed a treatm
the en
(Post-fix SDT as all actions are performed the theend
complex ofabout
handout
grammarsthe (put
with productions)
int)
the for a treatme
table and
tree
F ! digit
complex F .val
grammars=withdigit.lexval
int)
Semantic analysis
Semantic analysis
Semantic analysis
Semantic analysis
Analyse(N, InheritedAttributes)
if leaf(N) 1 8
return SynthesizedAttributes
6 7
Attributes = InheritedAttributes
for each child C of N, from left to right 2 5
Instead of a giant switch, one could have separate routines for each
nonterminal (as with recursive top-down parsing) and a switch on
productions having this nonterminal as LHS (see examples later)
Global variables can be used instead of parameters to pass inherited
attributes by side-e↵ects (with care)
Can be easily adapted to use syntax-directed translation schemes
(by interleaving child analysis and semantic actions)
Parsing table:
( ) $
S0 S0 ! S S0 ! S
S S ! (S)S S !✏ S !✏
1. Syntax-directed translation
epresents ansuch
containing rules assignment
as expression not an assignment statement. In C an
The abstract
railing semicolon. syntax
That is, in treein is
C (unlike usedtheassemicolon
Algol) a basis isfor most semantic
a statement
r. analyses and for intermediate code generation (or even used as an
intermediate representation)
When the grammar has been modified for parsing, the syntax tree is
(expr). Note also the hierarchical decomposition in the figure on the right.
mply syntax. a more naturalneeds
The compiler representation
semantic information, than the parse
e.g., tree(integer,
the types
g is somewhat arbitrary, but invariably if a recursive definition is involved,
) of the objects involved. This enables checking
The abstract syntax tree can be constructed using for semantic errors and inserting
SDD (see next
yntax tree withslides)
operators as interior nodes and
he syntax tree on the right corresponds to the parse
Another SDD can then be defined on the syntax tree to perform
semantic
nts an assignment expression notchecking
an assignmentor generate
statement. In C an another intermediate code (directed
semicolon. That is, in C (unlike in Algol) the semicolon is a statement
by the syntax tree and not the parse tree)
Semantic analysis 258
Generating an abstract syntax tree
For the left-recursive expression grammar:
Production Semantic rules
E ! E1 + T E .node = new Node(0 +0 , E1 .node, T .node)
E ! E1 T E .node = new Node(0 0 , E1 .node, T .node)
E !T E .node = T .node
T ! (E ) T .node = E .node
T ! id T .node = new Leaf (id, id.entry )
T ! num T .node = new Leaf (num, num.entry )
(Dragonbook)
(Dragonbook)
1. Syntax-directed translation
Static checkings:
I All checkings done at compilation time (versus dynamic checkings
done at run time)
I Allow to catch errors as soon as possible and ensure that the program
can be compiled
Two important checkings:
I Scope checking: checks that all variables and functions used within a
given scope have been correctly declared
I Type checking: ensures that an operator or function is applied to the
correct number of arguments of the correct types
These two checks are based on information stored in a symbol table
{ int x; int y;
{ int w; bool y; int z; x int
..w..; ..x..; ..y..; ..z..; y int
}
..w..; ..x..; ..y..; w int
} y bool
z int
The compiler keeps track of names and their binding using a symbol
table (also called an environment)
A symbol table must implement the following operations:
I Create an empty table
I Add a binding between a name and some information
I Look up a name and retrieve its information
I Enter a new scope
I Exit a scope (and reestablish the symbol table in its state before
entering the scope)
Identify the types of the language and the language constructs that
have types associated with them
Associate a type attribute to these constructs and semantic rules to
compute them and to check that the typing system is respected
Needs to store identifier types in the symbol table
One can use two separate tables, one for the variable names and one
for the function names
Function types is determined by the types (and number) of
arguments and return type. E.g., (int, int) ! int
Type checking can not be dissociated from scope and other
semantic checking
TypeIds ! TypeId
We will use the following source grammarTypeIds
to illustrate type, checking
! TypeId TypeIds
Exp ! num
Program ! Funs
Exp ! id
Exp ! Exp + Exp
Funs ! Fun
Exp ! Exp = Exp
Funs ! Fun Funs
Exp ! if Exp then Exp else Exp
Exp ! id ( Exps )
Fun ! TypeId ( TypeIds ) = Exp
Exp ! let id = Exp in Exp
TypeId ! int id
Exps ! Exp
TypeId ! bool id
Exps ! Exp , Exps
TypeIds ! TypeId
TypeIds ! TypeId , TypeIds Grammar 5.1: Example language for interpretation
Exp ! num
! id5 and 6 of (Mogensen, 2010) for full details)
Exp chapter
(see
Exp ! Exp + Exp
Exp ! Exp = Exp
Exp ! if Exp then Exp else Exp
Exp analysis!
Semantic id ( Exps ) 270
Implementation on the syntax tree: expressions
Type checking of expressions:
6.5. TYPE CHECKING EXPRESSIONS 137
inherited attributes
CheckExp (Exp, vtable, f table) = case Exp of
num int filled in by lexer
id t = lookup(vtable, getname(id))
if t = unbound scope checking
then error(); int
else t
Exp1 + Exp2 t1 = CheckExp (Exp1 , vtable, f table) error recovery
t2 = CheckExp (Exp2 , vtable, f table)
if t1 = int and t2 = int
then int
type checking
else error(); int
Exp1 = Exp2 t1 = CheckExp (Exp1 , vtable, f table)
synthesized attribute
t2 = CheckExp (Exp2 , vtable, f table)
if t1 = t2
Follows the implementation
then bool of slide 249 with one function per
else error(); bool
nonterminal,
if Exp1
with a switch on production rules. Could be implemented
t1 = CheckExp (Exp1 , vtable, f table)
withthen
classes/methods
Exp2 t2 = Checkor a visitor
Exp (Exp 2 , vtable,pattern.
f table)
else Exp3 t3 = CheckExp (Exp3 , vtable, f table)
if t1 = bool and t2 = t3
Semantic analysis 271
if t1error();
else = boolbool and t2 = t3
if Exp1 t1then
= Check t2 Exp (Exp1 , vtable, f table)
Implementation on the syntax tree: function calls
then Exp2 t2else
= Check error();Exp (Exp t2 2 , vtable, f table)
else
id (TYPEExp3)
Exps t3t==Check lookup( Exp (Exp
f table, 3 , vtable, f table)
getname(id))
6.5. CHECKING EXPRESSIONS 137
if ift1t==bool unbound and t 2 = t3
then t2
then error(); int
CheckExp (Exp, vtable,
num
id ( Exps ) tint
else
f table) t=
else error(); 2 case Exp of
= lookup( f table, getname(id))
filled in by lexer
((t , . . . ,tn ) ! tgetname(id))
0) = t
id
[t
= 1unbound
tif=t lookup(vtable,
, . . . ,t ] = Check Exps (Exps, vtable, f table)
scope checking
if t =error();
then 1 unboundint m
thenif error();
else m = n and int t1 = t1 , . . . ,tn = tn
else((tthen t
1t, . . . ,t0n ) ! t0 ) = t
Exp1 + Exp2 t1 [t=1else. . . ,terror();
,Check ] = (Exp
mExp Check t01 ,Exps
vtable,
(Exps, checking function
vtable, f table)
f table)
let id = Exp1 t2tif1== m Check
Check= n Exp and (Expt(Exp
1= 11,,. vtable,
2 ,tvtable,
. . ,tnf= tfntable)
table)
in Exp2 then
t1 =tint
ifvtable
Exp
0 = bind(vtable,
and t2 = int getname(id),t1 ) arguments
thenelseint
Check error();
Exp (Exp t02 , vtable , f table)
let id = Exp1 telse 1 = Checkerror(); (Exp1 , vtable, f table)
Expint
Check
in
Exp Exp 2Exp
1 =Exps tvtable
(Exps,
2 1vtable,
= Check = fbind(vtable,
table)
Exp (Exp getname(id),t
vtable,
=1 ,case Exps
f table)
of 1 )
Exp Check
t2 = Check
[Check (Exp
Exp (Exp,
Exp vtable
2 , vtable,
Exp (Exp , ff table)]
2 , vtable, table)
f table)
Exp , Exps Check if t1 Exp = t2(Exp, vtable, f table)
CheckExps (Exps, then
vtable, bool f table) = case Exps of
:: Check Exps (Exps, vtable, f table)
Exp [Check
else Exp (Exp,
error(); vtable, f table)]
bool
Exp
if Exp , Exps
1
Check
t 1 = Check
Figure
Exp (Exp, 6.2:
Exp (Exp ≈cons
vtable,
Type f table)
1 , vtable,
checking f table)
of expressions
then Exp2 t::2 Check
= Check Exps (Exps, vtable, f table)
Exp (Exp2 , vtable, f table)
else Exp3 t3 = CheckExp (Exp3 , vtable, f table)
Figure 6.2: Type checking of expressions
if t1 = bool and t2 = t3
then t2
else error(); t2
Semantic analysis 272
id ( Exps ) t = lookup( f table, getname(id))
Implementation on the syntax tree: variable declaration
if t = unbound
then error(); int
else
((t1 , . . . ,tn ) ! t0 ) = t
[t1 , . . . ,tm ] = CheckExps (Exps, vtable, f table)
6.5. TYPE CHECKING EXPRESSIONS 137
if m = n and t1 = t1 , . . . ,tn = tn
then t0
CheckExp (Exp, vtable,else f table)
error();=t0case Exp of
num
let id = Exp1 intt1 = CheckExp (Exp1 , vtable, f table) create a new
id
in Exp2 tvtable = bind(vtable,
= lookup(vtable, getname(id),t1 )
getname(id))
Check
if t = Exp (Exp2 , vtable , f table)
unbound scope
then error(); int
CheckExps (Exps, else
vtable, t f table) = case Exps of
Exp1 + Exp2 [Check
Exp t1 = CheckExp (Exp, vtable, f table)]
Exp (Exp1 , vtable, f table)
Create
, Expsa Check
new symbol table vtable 0
Exp t2 =Exp Check(Exp, Expvtable,
(Exp 2 ,fvtable,
table) f table)with the new binding
if:: Check
t1 = int Exps (Exps,
and t2 =vtable,
int f table)
Pass it as an thenargument
int for the evaluation of Exp2 (right child)
Figure 6.2: Type checking of expressions
else error(); int
Exp1 = Exp2 t1 = CheckExp (Exp1 , vtable, f table)
t2 = CheckExp (Exp2 , vtable, f table)
if t1 = t2
then bool
else error(); bool
if Exp1 t1 = CheckExp (Exp1 , vtable, f table)
then Exp2 t2 = CheckExp (Exp2 , vtable, f table)
else Exp3 t3 = CheckExp (Exp3 , vtable, f table)
Semantic analysis if t = bool and t = t 273
Implementation on the syntax tree: function declaration
6.7. TYPE CHECKING A PROGRAM 139
synthesized attribute
CheckFun (Fun, f table) = case Fun of
TypeId ( TypeIds ) = Exp ( f ,t0 ) = GetTypeId (TypeId)
vtable = CheckTypeIds (TypeIds)
t1 = CheckExp (Exp, vtable, f table)
if t0 6= t1
then error()
6.7. TYPE CHECKING A PROGRAM
GetTypeId (TypeId) = case TypeId of
inherited attributes
int id (getname(id), int) Check f table)6.7. TYPE Fun
= case CHECKING
of A PROGRAM
Fun (Fun,
bool id (getname(id), bool)
TypeId ( TypeIds ) = Exp ( f ,t0 ) = GetTypeId (TypeI
CheckFun (Fun, f table) = case Fun of
CheckTypeIds (TypeIds) = case TypeIds of vtable = Check (Ty
TypeId ( TypeIds ) = ExpTypeIds
( f ,t0 ) =
TypeId (x,t) = GetTypeId (TypeId) t1 = CheckExp (Exp, vtab
bind(emptytable, x,t) vtable =
TypeId , TypeIds (x,t) = GetTypeId (TypeId)
if t0 6= t1 t1 = Che
vtable = CheckTypeIds (TypeIds) then error() if t0 6= t1
if lookup(vtable, x) = unbound Create a symbol table then err
GetTypeId
then bind(vtable, x,t) (TypeId) = case TypeId of
with arguments
GetTypeId (TypeId) = case TypeId of
else error(); vtable
int id (getname(id),int int)
id (getname(id), int)
bool id (getname(id), bool)
Figure 6.3: Type checking a function declaration
bool id (getname(id), bool)
Semantic analysis 274
6.8. ADVANCED TYPE CHECKING 141
GetFun (Fun) = case Fun of
Implementation on the syntax tree: program
TypeId ( TypeIds ) = Exp ( f ,t0 ) = GetTypeId (TypeId)
[t1 , . . . ,tn ] = GetTypes (TypeIds)
( f , (t1 , . . . ,tn ) ! t0 )
Compound types:
They are represented by trees (constructed by a SDD)
Example: array declarations in C
int [3][4]
Production Semantic rules
array
T ! BC T .t = C .t; C .b = B.t
B ! int B.t =int
B ! float B.t =float 3 array
C ! [ NUM ]C1 C .t = array (NUM.val, C1 .t)
C !✏ C .t = C .b
4 int
Dynamic typing:
Type checking is (mostly) done at run-time
Objects (values) have types, not variables
Dynamically typed languages: Scheme, Lisp, Python, Php...
The following scheme code will generate an error at run time
(defun length
(lambda (l)
(if (null? l)
0
(+ 1 (length (cdr l))))))
(length 4)