Vous êtes sur la page 1sur 85

Structure et execution des langages de programmation

Jacques Noye
Jacques.Noye@Mines-Nantes.fr

13 mai 2016

1
1.1

Introduction
Les langages de programmation

Les langages de programmation


Quest-ce quun langage de programmation ?
Un langage qui permet decrire des programmes.
Quest-ce quun programme ?
La definition precise dun calcul effectue sur un ordinateur.
Un langage de programmation permet la communication :
humain-machine ;
humain-humain ( voici ce que je vais demander `a la machine ).
La th`
ese de Church-Turing
Alan Turing (1912-1954) et Alonzo Church (1903-1995) etudient des mod`eles de calcul abstraits
de capacites equivalentes :
le lambda-calcul (Church, annees 30) ;
la machine de Turing (1936).
Ces machines definissent un ensemble de fonctions dites calculables.

Alan

Turing

Alonzo Church

Programmes et fonctions
Un programme est essentiellement une fonction calculable (on fournit les param`etres dentrees,
on recup`ere le resultat du calcul).
Inversement, toute fonction nest pas calculable (exemple : probl`eme de larret d
u `a Turing).
La source de la puissance des ordinateurs
Un langage est dit Turing-complet sil permet dexprimer toutes les fonctions calculables.
Les ordinateurs sont des machines universelles : des machines programmables `a laide de langages Turing-complets.
Comment d
efinir un langage ?
On peut voir un langage comme :
lensemble des programmes quil permet decrire ;
les r`egles qui permettent decrire un programme (syntaxe) ;
les r`egles qui permettent dexecuter le programme (semantique).
Les deux faces dun langage
La face syntaxique/statique :
un programme en temps que texte, compose de mots, de signes de ponctuations et de
separateurs (espaces, sauts a` la ligne) (syntaxe dite concr`ete) ;
un programme en temps que structure, un arbre, un graphe... (syntaxe dite abstraite).
2

la face semantique/dynamique : le sens du programme, ce qui se passe `a lexecution.


Syntaxe concr`
ete et syntaxe abstraite
syntaxe concr`ete :
C, OCaml, Java, Scala... : n * fact(n - 1)
Lisp, Racket, Clojure... : (* n (fact (- n 1)))
*

app

fact

syntaxe abstraite :
Le sens dun programme
Soit PL lensemble des programmes ecrits dans le langage L.
Definir la semantique du langage L, cest definir le sens de tout programme p, appartenant
a PL , par exemple `
`
a laide dune fonction du domaine des entrees vers le domaine des sorties
(semantique denotationnelle) :
[[p]]L : Entrees Sorties
[[p]]L d denote lexecution du programme p applique aux donnees d. Cest une vue mathematique
abstraite du sens dun programme.

1.2

Interpr
etation

Quest-ce quun interpr


eteur ?
Informellement : un interpreteur dun langage L est un programme capable dexecuter correctement tout programme ecrit dans le langage L.
Definition 1. Soit I et S deux langages (langage dimplementation et langage source).
Un interpreteur de programmes PS , intSI , ecrit en I, est tel que :
p PS , d Entrees : [[p]]S d = [[intSI ]]I [p, d]
Attention : ne pas confondre p (du texte) et [[p]]S , le sens de p (son  execution ).
Un interpreteur permet aussi dexpliciter le sens dun programme `a deux niveaux :
statiquement ( que veut dire cette construction ?  : regarder le texte de linterpreteur) ;
dynamiquement (executer des programmes).
Cest une forme extremement concr`ete de semantique operationnelle, une forme de semantique
qui au del`
a du resultat fourni par le calcul sinteresse `a la mani`ere dont seffectue cette execution.
Machines et interpr
eteurs
Cas limite : une machine x86 est un interpreteur  materiel  de code machine x86 !
Par analogie, on parle aussi souvent de machine abstraite ou virtuelle pour des interpreteurs
 logiciels  (ex. la Java Virtual Machine ou JVM).

Composer des interpr


eteurs ?
` la base, on dispose dun ordinateur donc dun interpreteur de langage machine intM .
A
On peut alors definir un langage L1 proche de M et ecrire un interpreteur de L1 en langage
1
machine intL
ecuter des programmes ecrits en L1 :
M , ce qui permet dex
1
[[p]]L1 d = [[intL
]]
(p,
d)
M M
1
= [[intM ]](intL
M , (p, d))
Et on peut continuer de proche en proche : definir un langage L2 proche de L1 avec un
2
interpreteur intL
L1 :
L2
[[p]]L2 d = [[intL1 ]]L1 (p, d)
L2
1
= [[intL
M ]]M (intL1 , (p, d))
L1
M
2
= [[int ]](intM , (intL
L1 , (p, d))) ...

Repr
esentation graphique
Utilisation des diagrammes en T (Tombstone-diagrams) [MHW70, JGS93].

**

machine

interprteur

programme

Exemple
**
L2 = Java

L2
L2

L1 = C

L1
L1

M = x86

M
M
m

1.3

Compilation

Quest-ce quun compilateur ?


Plut
ot que dinterpreter directement un langage, on peut aussi commencer par le transformer
en un autre langage.
Informellement : un compilateur est un programme qui transforme (on dit aussi traduit) un
programme ecrit dans un langage source en un programme equivalent ecrit dans un langage cible
(si le programme est correct, sinon il emet des messages derreur).
Exemples :

compilation dun programme C en langage machine x86 ;


compilation dun programme Java en pseudo-code Java.
Quest-ce quun compilateur ?
Par rapport au cas de linterpreteur, il y a un langage supplementaire C qui est le langage
cible.
Definition 2. Un compilateur de programmes PS en PC , ecrit en I, est tel que :
p PS , p0 PC :
p0 = [[comp]]I p
Correction : d Entrees, [[p]]S d = [[p0 ]]C d
ou encore :
[[p]]S d = [[[[comp]]I p]]C d
a comparer avec :
`
[[p]]S d = [[int]]I [p, d]
` quoi
A
ca sert ?
` eventuellement se passer dinterpreteur logiciel si le langage cible est le langage machine
A
(ce qui sest passe au debut de linformatique ?).
Les compilateurs jouent un r
ole essentiel dans :
la qualite du logiciel du fait de leur capacite `a detecter des erreurs statiquement (avant
lexecution) ;
lefficacite du logiciel (temps, memoire, energie).
Composer des compilateurs et des interpr
eteurs
Le compilateur est lui-meme ecrit dans un langage de programmation (le langage dimplementation
du compilateur).
Pour executer le compilateur, il faut soit linterpreter, soit le compiler !
Repr
esentation graphique (suite)

**

interprteur

compilateur

programme

Exemples
Quels sont les langages source, cible et dimplementation de :
javac ?
la JVM ?

J = Java
P = pseudo-code
I = C/C++
M = langage machine

javac

JVM

**
J
.java

**

gcc

machine

Lid
ee de base de la compilation
Un compilateur est un programme qui transforme un programme ecrit dans un langage source
en un programme equivalent ecrit dans un langage cible.
les programmes sont ecrits dans des langages qui sont des constructions structurees (decrites
dans un manuel de reference, un interpreteur...) ;
le sens des programmes est attache `a cette structure.
Lidee va etre de :
1. collecter la semantique du programme dentree dans une representation semantique du programme (front-end responsable de lanalyse du programme source) ;
2. reformuler cette semantique dans les termes du langage cible (back-end responsable de la
synth`ese du programme cible).
Sch
ema conceptuel dun compilateur

Progamme
source

Front-end
(Analyse)

Reprsentation
smantique

Back-end
(Synthse)

Programme
cible

Back-end
interprtatif

Sortie

Compilateur

Sch
ema conceptuel dun interpr
eteur

Progamme
source

Front-end
(Analyse)

Reprsentation
smantique

Interprteur

Ce schema est tr`es proche de celui dun compilateur. Au lieu de parcourir la representation
intermediaire pour generer du code, linterpreteur parcourt cette representation pour generer des
valeurs. En general, la representation intermediaire est moins riche semantiquement que dans le
cas dun compilateur.

1.4

Interp
etation, compilation et syst`
emes dex
ecution

Compilateur ou interpr
eteur ?
Les plus de linterpreteur :
6

portabilite : il est souvent dit quun interpreteur, generalement ecrit dans un langage de
haut niveau, va tourner sur une gamme plus large dinfrastructures quun compilateur
natif (compilateur dont la cible est le langage machine). Mais on peut aussi utiliser un
compilateur dont le langage cible est tr`es portable comme C ou le pseudo-code Java.
complexite : un interpreteur est moins complexe quun compilateur :
il est plus facile `
a implementer ;
il est plus facile de sassurer de sa correction ;
il est souvent plus convivial `a utiliser (boucle read-eval-print, debogueur).
Compilateur ou interpr
eteur ?
Les plus du compilateur :
efficacite : lexecution dun programme compile est significativement plus rapide que linterpretation du meme programme (normal : toute lanalyse a dej`a ete faite durant la compilation, sans compter les optimisations realisees par le back-end). Dun autre cote, il y a
une certaine latence avant de pouvoir executer un programme (il faut dabord le compiler).
detection statique des erreurs.
Les propri
et
es attendues dun compilateur
correction
passage `
a lechelle : insensibilite `a la taille des programmes dentree (limites, efficacite
independante de la taille)
efficacite de la compilation (surtout pour la compilation dynamique)
qualite du traitement des erreurs
portabilite
efficacite du code genere (vitesse, taille memoire, energie) - suivant les besoins (attention
de ne pas trop en faire)
possibilites de reciblage (particuli`erement dans le cas des compilateurs natifs)
Les propri
et
es attendues dun interpr
eteur
correction
passage `
a lechelle
efficacite de linterpretation
qualite du traitement des erreurs
portabilite
Le syst`
eme dex
ecution
Le syst`eme dexecution (runtime) correspond `a des taches partagees (entre differents programmes ou langages) dont certaines nont de toute facon pas besoin detre recompilees
pour chaque programme ou dependent du syst`eme dexploitation ou de la machine cible.
Ces t
aches sont implementees sous la forme de biblioth`eques, liees (statiquement ou dynamiquement) par lediteur de liens (linker) au fichier executable ou integrees `a linterpreteur.
Dans ce cours, on va en particulier parler de la gestion de la memoire.

1.5

Lamorcage

Comment r
ealiser lamor
cage ?
bootstrapping : to pull oneself up by ones bootstraps :
le langage source et le langage dimplementation sont identiques ;
le programme `
a compiler est le compilateur lui-meme !
Magique ?

Exemple damor
cage

Etape
1 : on compile le compilateur de
premier compilateur de  bas niveau .

haut niveau  `a laide de lui-meme, pour obtenir un

J
compJ

compP1

J
S
Smalltalk

Etape
2 : on compile le compilateur de  haut niveau  `a laide du compilateur de

niveau pour obtenir un deuxi`eme compilateur de  bas niveau .

bas

compP1

P
compJ

compP2

P
I
JVM

Etape
3 : on compile le compilateur de  haut niveau  `a laide du deuxi`eme compilateur de
bas niveau pour obtenir un troisi`eme compilateur de  bas niveau .
compP2

P
compJ

P
I
JVM

compP3

Si le compilateur de  haut niveau  est correct, le texte des deuxi`eme et troisi`eme compilateurs
bas niveau  est identique !
Cette methode est generale (remplacer Java par nimporte quel langage source S et le pseudocode par nimporte quel langage cible C).
Un schema similaire `
a 3 niveaux permet de generer `a partir dun compilateur de haut niveau
dun langage S, dun compilateur de bas niveau dun langage S et dun compilateur de haut niveau
dun langage S, extension conservatrice de S (les programmes de S sont des programmes de S,
avec la meme semantique dans S et S - penser `a une nouvelle version de Java), un compilateur de
bas niveau de S.
de

1.6

Quelques
el
ements sur la compilation de C, Java, JavaScript

Evolution
de GCC
1

GCC Growth

OpenMP

Eclipse parser

Objective C++

3,000,000
2,800,000

Tree SSA
Fortran 95

2,600,000
2,400,000
2,200,000

Ada

2,000,000

LOC

1,800,000

libjava

1,600,000
1,400,000

Total
Runtime
Front Ends
Compiler
Ports

libstdc++
Java

1,200,000
1,000,000

C++

800,000
600,000
400,000
200,000
0
1.21
1988

1.38
1990

2.0
1992

2.8.1
1998

EGCS
1998

2.95
1999

3.0
2001

3.1
2002

4.0
2005

4.1
2006

4.2
2007

4.3
2008

Releases
1

generated using David A. Wheeler's 'SLOCCount'.

November 27, 2007

GCC Internals - 11

Transparents issus de [Nov07]. Voir aussi le projet LLVM [LLV14].


Organisation des sources

Source code

<src>

gcc
libgcc
libcpp
libada
libstdc++-v3
libgfortran
libobjc
boehm-gc
libffi
libjava
zlib
libiberty
libgomp
libssp
libmudflap
libdecnumber

Front/middle/back ends
Internal library for missing target features
Pre-processor
Ada runtime
C++ runtime
Fortran runtime
Objective-C runtime
Java runtime

Utility functions and generic data structures


OpenMP runtime
Stack Smash Protection runtime
Pointer/memory check runtime
Decimal arithmetic library

November 27, 2007

GCC Internals - 18

Source code

Core compiler and C front end

gcc

<src>

ada
config
cp
doc
fortran
ginclude
java
objc
objcp
po
testsuite
treelang

Ada front end


Architecture-specific codegen (ports)
C++ front end
User manual and internal documentation
Fortran front end
System headers (mainly freestanding support)
Java front end
Objective C front end
Objective C++ front end
Portable object files for I18N
Regression tests
Toy language front end

November 27, 2007

GCC Internals - 19

Structure

10

Compiler pipeline

C
C++

Front End
GENERIC

Middle End

Back End

GIMPLE

RTL

Assembly

Inter
Procedural
Optimizer

RTL
Optimizer

SSA
Optimizer

Final Code
Generation

Java
Fortran

Call Graph
Manager

Pass
Manager

November 27, 2007

GCC Internals - 35

Repr
esentations interm
ediaires
GENERIC : representation commune resultat des front ends.
GIMPLE : simplification de GENERIC (representation 3 adresses : 2 operandes, un resultat),
grammaire restreinte.
RTL (Register-Transfer Level ) : format proche de la machine (registres, modes dacc`es `a la
memoire...).

11

GENERIC and GIMPLE


GENERIC
if (foo (a + b,c))
c = b++ / a
endif
return c

High GIMPLE

Low GIMPLE

t1 = a + b

t1 = a + b

t2 = foo (t1, c)

t2 = foo (t1, c)

if (t2 != 0)

if (t2 != 0) <L1,L2>

t3 = b

L1:

b = b + 1

t3 = b

c = t3 / a

b = b + 1

endif

c = t3 / a

return c

goto L3
L2:
L3:
return c

November 27, 2007

GCC Internals - 40

RTL

b = a - 1
(set (reg/v:SI 59 [ b ])
(plus:SI (reg/v:SI 60 [ a ]
(const_int -1 [0xffffffff]))))

It is commonly represented in LISP-like form


Operands do not have types, but type modes
In this case they are all SImode (4-byte integers)
November 27, 2007

GCC Internals - 42

Choix dex
ecutions de Java [KCBL00]

12

Terminologie
Compilateur `
a la volee (Just-in-Time (JIT) Compiler ) : compilation de pseudo-code en
code natif juste avant lexecution du code (une fois pour toutes). En anglais, on parle
aussi, par opposition, de Ahead-Of-Time Compiler , appele Direct Compiler ci-dessus (ex. :
GCJ [gcj09]).
Compilateur dynamique : compilateur qui produit du code pour un programme en train
de sexecuter. Un compilateur `a la volee est un compilateur dynamique. Dans le schema
ci-dessus, fait reference `
a une variante de la compilation `a la volee qui calcule les points
chauds (hot spots) du programme pour compiler les parties du programme les plus sensibles
du point de vue de la performance. On parle aussi de tracing JIT .
Et encore
Interpretation directe de Java : BeanShell http://www.beanshell.org/.
Transformation source `
a source : le langage source est un sur-ensemble du langage cible.
Utilise par exemple par Polyglot [NCM03] qui permet detendre Java.
Le terme traducteur est parfois prefere au terme compilateur dans un sens generique. Le
terme compilateur est alors utilise dans un sens plus restreint (langage de destination de plus
bas niveau que le langage source ou fabrication de programmes illisibles par des humains).
JavaScript/ECMAScript
Dans le navigateur (C/C++ et JavaScript) :
1. SpiderMonkey (Brendan Eich, Netscape, 1996) : compilateur en pseudo-code specifique
et interpreteur de ce pseudo-code
2. JIT Compiler : TraceMonkey (Mozilla, 2009), un tracing JIT
3. V8 (Google, 2008) : compilation en code natif
4. compilateurs optimisants : IonMonkey (Mozilla) et Crankshaft (Google)
Sur le serveur (Java) :
1. Rhino (Netscape, 1997) : initialement un compilateur (vers du pseudo-code Java), ajout
dun interpreteur en 1998
2. Nashorn (Oracle, 2012) avec Java 8
Comme cible dun compilateur : Google Web Toolkit (2006), Scala.js (2015)...
13

Pour experimenter : Narcissus (Mozilla), un interpreteur en JavaScript, un meta-interpreteur


circulaire :
meta parce quil utilise des fonctionnalites du langage dimplementation pour implementer
le langage interprete ;
circulaire parce que langage interprete et langage dimplementation sont identiques.
Pour utiliser ES2015 (encore appele ES6) : le compilateur Babel (vers ES5, supporte par
tous les navigateurs).

1.7

Pour conclure

Quelques
el
ements historiques
1945-1960 : generation de code. On utilise surtout des assembleurs. Premier veritable langage de programmation avec son compilateur, FORTRAN (John Backus, 1954).
1960-1975 : analyse syntaxique. Profusion de nouveaux langages.
1975-present : generation de code, optimisation et nouveaux paradigmes. Reduction des
cibles, amelioration de la qualite des compilateurs. Besoins des nouveaux paradigmes (comportement dynamique plus complexe).
Besoins nouveaux : langages dedies (programmation, modelisation), composition de langages, analyse semantique, correction.
Pourquoi
etudier ces th`
emes ?
Ce cours est introductif mais donne les elements pour traiter des cas relativement simples avec
les elements conceptuels permettant daller plus loin si necessaire (en faisant appel `a la litterature
et aux outils disponibles).
Beaucoup dapplications, au del`a de limplementation des langages de programmation au
sens strict (langages de commande, traitement de donnees structurees, conversion de fichiers
dun format `
a lautre...).
Meilleure comprehension des langages de programmation.
Utilisation de beaucoup de concepts (expressions reguli`eres, grammaires non contextuelles,
grammaires `
a attributs, generateurs de programme...) et dalgorithmes et structures de
donnees (calcul de point fixe, automates...).

14

Analyse lexicale

Analyse lexicale
lexical : Linguistique. Qui concerne le lexique, le vocabulaire. La composante lexicale dune
langue (distingue de grammatical). Morphologie lexicale. Statistique lexicale. Unite lexicale. Petit
Robert
Lanalyse lexicale, effectuee par un analyseur lexical (scanner) transforme la sequence (ou flot)
de caract`eres en entree (le texte du programme) en une sequence de mots/lex`emes.
Le crible (souvent integre) filtre la suite des lex`emes et produit leur representation interne : les
unites lexicales (tokens) .
Idee : La suite de lanalyse travaille sur une representation de plus haut niveau du programme
(des unites lexicales plut
ot que des chanes de caract`eres).
Lex`
eme et unit
e lexicale
1. Le texte aPoint est lu par lanalyseur lexical (scanner).
2. Le lex`eme correspondant est la chane de charact`eres "aPoint", il est reconnu comme etant
un identificateur (son type).
3. Le crible retourne une unite lexicale pour cet identificateur, eventuellement sous la forme
dun pointeur sur la table des symboles (structure qui enregistre de mani`ere centralisee
linformation disponible sur les identificateurs).
Types de lex`
eme
Type
ID
NUM
FLOAT
IF
COMMA
NEQ
LPAR
RPAR

Exemple
i aPoint Point a_Point
-2147483648 0 00 03
3.14159 .14159 3. 1e308
if
,
!=
(
)

Note : les mots reserves (par exemple if) ne peuvent pas etre utilisees comme identificateurs.
Exemple
if (chOrEOF < 0) {
tokenClass = EOF;
return;
}

donne :
IF LPAR ID("chOrEOF") LESS NUM(0) RPAR LBRACE ... RETURN SEMI RBRACE
Notes :
Les blancs, passages `
a la ligne, tabulations ont disparus (ce ne sont pas des lex`emes).
` certains lex`emes est associee une valeur semantique.
A

15

Principe dune impl


ementation syst
ematique
1. On represente les lex`emes du langage par des expressions reguli`eres.
2. On construit un automate fini non deterministe capable de reconnatre ces expressions.
3. On transforme cet automate non deterministe en un automate deterministe.
4. On peut alors utiliser les tables de transitions correspondantes pour implementer lanalyseur.
Bonne nouvelle : un generateur danalyseur lexical va pouvoir effectuer les etapes 2 `a 4 pour
nous !

2.1

Expressions r
eguli`
eres

Expressions r
eguli`
eres
Une expression reguli`ere decrit un ensemble (eventuellement infini) de chanes de caract`eres `a
laide des expressions suivantes :
Expression
Interpretation
== Expressions primitives

la chane vide
x
la chane constituee de lunique caract`ere x
== Repetitions
R*
une sequence de zeros, un ou plusieurs R
== Composition
R1 R2
concatenation (R1 puis R2 )
R1 | R2
alternative (R1 ou R2 )
== Regroupement
(R)
R

Exemples : ab*, (ab)*.


Version
etendue
Expression
Interpretation
== Expressions de base
x
le caract`ere x
[x1 ...xn ]
un des caract`eres x1 ... xn
== Repetitions
R*
zero, un ou plusieurs R
R?
zero ou un R (R est optionnel)
R+
un ou plusieurs R
== Composition
R1 R2
concatenation (R1 puis R2 )
R1 | R2
alternative (R1 ou R2 )
== Regroupement
(R)
R

Priorit
e des op
erateurs
Ordre decroissant de priorite :
1. Operations de repetition
2. Concatenation
3. Alternative
Comparer : ab*|cd?, (ab)*|cd? et a(b*|c)d?.

16

Equivalence

x1 | ... | xn

R|
R R*

Autres abr
eviations courantes (JLex [BA03], ANTLRv4 [Par13a])
Intervalles de caract`eres :
[b-e] represente b|c|d|e
[b-eB-Efg] represente b|c|d|e|B|C|D|E|f|g
Negation :
[^0-9] represente tous les caract`eres qui ne sont pas des chiffres
Variantes (ANTLRv3 [Par13b])
Intervalles de caract`eres :
b..e
b..e|B..E|f|g
Negation :
~0..9
Caract`
eres d
echappement
Representation des caract`eres *, (... `a laide de caract`eres dechappement \ ou ". Par exemple :
\* ou "*".
Se pose alors, la representation des caract`eres dechappement eux-memes !
Ces caract`eres sont doubles : \\, """" (ou "\"").
Ainsi "a.+*" represente litteralement la chane entre guillemets.
Exemple (JLex)
IF
ID
NUM
REAL
skip
error

:
:
:
:
:
:

if
[a-z][a-z0-9]*
[0-9]+
([0-9]+"."[0-9]*)|([0-9]*"."[0-9]+)
("--"[a-z]*\n)|(" "|\n|\t)+
.

Note : . remplace tout caract`ere sauf un saut de ligne. La derni`ere ligne permet dobtenir une
specification compl`ete (toute chane est reconnue).
Il y a des ambigutes : comment interpreter if, if8, iff... ?
Exemple (ANTLRv4)
IF

:
;
ID
:
;
NUM :
;
REAL :
;
WS
:
;

if
[a-z][a-z0-9]*
[0-9]+
[0-9]+.[0-9]* | ([0-9]*.[0-9]+)
((--[a-z]*\n)|[ \n\t\r]+) -> skip

R`
egles standard
On cherche la plus longue chane reconnue.
R`egle de priorite : si pour une meme longueur de chane, il y plusieurs expressions possibles,
cest la premi`ere expression (dans lordre decriture) qui sapplique.

17

Utilit
e
Utilisable en analyse ou en synth`ese :
analyse : lexpression reguli`ere represente lensemble des chanes attendues possibles,
une chane candidate est reconnue (matches) ou rejetee ;
synth`ese : lexpression reguli`ere decrit un ensemble de chanes `a generer.
Dans le cadre de lanalyse lexicale :
Expression concise et precise des lex`emes (`a comparer avec  Un identificateur est compose de lettres, de chiffres et de caract`eres soulignes isoles. Lidentificateur commence
par une lettre et ne peut finir par un souligne ).
Base de la fabrication des analyseurs lexicaux.
Toujours en analyse : recherche de chanes de caract`eres dans un texte (grep, emacs).
Attention : Les memes caract`eres de controle sont utilises comme caract`eres jokers dans les
fichiers mais avec un sens different. Exemple :
grep bug*y Bug*y.java
Au lieu de considerer lensemble des chanes de caract`eres muni de loperateur de sequence
on peut considerer tout ensemble qui est un monode...

2.2

Langages r
eguliers

Monode
Definition 3. (E, ., e) est un monode ssi :
1. (E, .) est un semi-groupe, cest-`
a-dire que E est un ensemble muni dune loi de composition
interne . associative ;
2. E poss`ede un element neutre e pour ..
Example 4. Lensemble des applications E E muni de la composition. Quel est lelement neutre ?
Monode libre
Definition 5. Soit E un ensemble fini, le monode libre engendre par E, est le monode (E , ., )
o`
u:
E est lensemble des suites finies delements de E ;
. est loperation de concatenation : (u1 , ..., um ).(v1 , ..., vn ) = (u1 , ...., um , v1 , ..., vn ) ;
 est la suite vide (element neutre de la concatenation).
Notations
Comme le triplet (E , ., ) est compl`etement defini par la donnee de E, on confond habituellement (E , ., ) et E et on parle donc de E comme du monode libre engendre par
E.
On note | u | le nombre delements, ou longueur, dune suite. |  |= 0.
Une suite (u1 , ..., un ) est notee plus simplement u1 ...un et la concatenation de deux suites
u.v est notee plus simplement uv
Langages et monodes libres
Intuitivement, un langage (naturel ou informatique) permet de definir, `a partir dun ensemble
fini de symboles, des suites de symboles qui peuvent etre reconnus comme faisant partie du langage.
Ceci conduit `
a definir un langage formel comme un sous-ensemble dun monode A .
Suivant le contexte, differentes terminologies sont utilisees. On utilisera en particulier les terminologies suivantes :
A est lalphabet du langage. Les elements du langage sont des mots ;
A est le vocabulaire du langage. Les elements du langage sont des phrases.

18

Langages r
eguliers
Definition 6. Un langage construit `
a partir dun alphabet A est dit regulier (ou rationnel) sil
peut etre obtenu `
a partir de sous-ensembles finis de A en utilisant les trois operations + (union),

. (produit) et (iteration) sur 2A :


0
0
L+L =LL
0
L.L0 =
S{uv | iu L, v0 L }

L = i0 L avec L = {} et Li+1 = L.Li


Expressions r
eguli`
eres
On peut maintenant definir formellement les expressions reguli`eres (ou rationnelles).
Definition 7. Soit lalphabet (vocabulaire, ensemble de symboles...) A. Une expressions reguli`ere
est syntaxiquement definie de la mani`ere suivante :
 est une expression reguli`ere ;
si a A, a est une expression reguli`ere ;
si E est une expressions reguli`ere, E est une expression reguli`ere ;
si E1 et E2 sont des expressions reguli`eres, (E1 | E2 ) et (E1 E2 ) sont des expressions
reguli`eres.
Definition 8. Soit lalphabet A. Une expression reguli`ere E est semantiquement definie comme
un langage (regulier) L(E) tel que :
L() = {}
L(a) = {a}
L(E ) = L(E)
L(E1 E2 ) = L(E1 ).L(E2 )
L(E1 | E2 ) = L(E1 ) + L(E2 )
Inversement, on pourrait montrer que tout langage regulier peut-etre decrit `a laide dune
expression reguli`ere.
En existe-t-il une seule ? Sil y en a plusieurs, certaines sont-elles  meilleures  que dautres ?

2.3

Automates finis

Langages r
eguliers et automates finis
Les langages reguliers ont pour bonne propriete le fait quil est facile de construire un algorithme
efficace qui permet de reconnatre si une suite de symboles appartient `a un langage donne.
Cette construction est basee sur la correspondance entre langages reguliers et automates finis.
Syst`
emes de transitions
etiquet
es et automates finis
Definition 9. Un automate fini est un quintuplet (E, A, T, e0 , F ) o`
u:
A est un alphabet fini ;
(A, E, T ) est un syst`eme de transitions etiquete sur A (Labeled Transition System), o`
uE
est un ensemble detats et T un ensemble de transitions dun etat `a lautre, etiquetees par
des elements A, avec T E A E ;
dont lensemble detats est fini ;
e0 est un etat distingue comme etant letat initial ;
et F est un ensemble detats distingues comme des etats finaux.
Une definition equivalente consiste `a definir T comme une fonction de transition : E A 2E .

19

Exemple

Automates finis d
eterministes
Definition 10. Un automate fini deterministe (AFD ou DFA en anglais) est un automate dont
toutes les transitions partant dun etat donne ont des etiquettes differentes.
Autrement dit, les transitions T E A E sont definies par une fonction (partielle) T :
E A E.
Reconnaissance dune suite de symboles
Soit une suite de symboles de longueur n appartenant `a lalphabet A et un AFD etiquete sur
A.
On demarre `
a letat initial ;
pour chaque symbole, on effectue la transition indiquee par le symbole courant, si elle existe,
et on passe au symbole suivant,
si la transition nexiste pas, la suite est rejetee,
apr`es n transitions, si on est dans un etat final, la suite de symboles est acceptee, sinon elle
est rejetee.
Definition 11. Le langage reconnu par lautomate est lensemble des suites acceptees par lautomate.
Exemples

2.4

De lAFD `
a lanalyseur lexical

Combinaison dautomates
Soit {Ei | i [1, n]} les expressions reguli`eres necessaires `a la definition des differents types de
lex`emes.
On pourrait penser que, finalement, il suffit de construire lAFD reconnaissant lexpression
reguli`ere (E1 | ... | En ) .
Cest un peu plus complique que ca dans la mesure o`
u il est necessaire :
20

deffectuer les actions associees aux expressions reguli`eres (generation des unites lexicales) ;
de prendre en compte les r`egles de plus longue chane et de priorite.
Ceci conduit `
a sinteresser `
a la construction dun automate reconnaissant un unique lex`eme
(E1 | ... | En ) et `
a etiqueter les etats finaux avec le type de lex`eme reconnu.
Combinaison dautomates

Les etats finaux sont etiquetes par les types des lex`emes acceptes.
Letat 2 correspond `
a la fois `
a letat 2 de lautomate ID et de `a letat 2 de lautomate IF.
Il est final parce que letat 2 de lautomate ID est final.
Letat 3 correspond `
a la fois aux etats finaux des automates ID et IF. Il est etiquete IF
dapr`es la r`egle de priorite.
Note : la r`egle de plus longue chane na pas encore ete prise en compte.
Table de transition
` partir de lautomate, on peut construire une table de transitions. Representation directe de
A
la fonction de transition, elle donne pour chaque etat et chaque symbole en entree, letat suivant,
sil existe.
a
b
e0
e1
Example 12.
e1
e1 e2
e0
e2 (final)
Une implementation classique des tables de transitions consiste `a indexer les etats et les symboles et `
a utiliser des tableaux. Letat 0 est alors utilise pour representer labsence de transition
(letat 0 est un etat mort).
Trouver la plus longue chane
Exemple : if8.
Il ne faut pas sarreter quand on atteint un etat final mais noter letat lastFinal ainsi que
la position du caract`ere courant lastPosition.
On continue.
Si on rencontre un nouvel etat final, on met `a jour lastFinal et lastPosition.
Si on rencontre un etat mort, lastFinal et lastPosition indique le lex`eme reconnu ainsi
que le point de reprise de lanalyse.

2.5

Automates finis non d


eterministes

Automate fini non d


eterministe (AFND)

21

Definition 13. Un automate fini non deterministe (AFND ou NFA en anglais) est un automate
fini qui nest pas deterministe, cest-`
a-dire quil existe au moins un etat pour lequel il y a plusieurs
transitions sortantes de meme etiquette.
Un -AFND est defini comme un automate fini par un quintuplet (E, A, T, e0 , F ) sauf que les
transitions peuvent etre etiquetees soit par des elements de A soit par un symbole  qui nappartient
pas `
a A : T E A {} E
Lidee du symbole  est de donner la possibilite deffectuer des transitions sans consommer un
symbole dentree.
Linteret des -AFND est quil est tr`es facile de traduire une expression reguli`ere en un AFND.
Reconnaissance dune suite de symboles
Le principe est le meme que pour un AFD sauf que dans le cas dun choix (d
u `a la presence de
transitions de meme etiquette ou dune transition ), toutes les possibilites doivent etre considerees
ou, `
a chaque choix, le bon choix doit etre fait.
De meme que pour un AFD :
Definition 14. Le langage reconnu par un AFND est lensemble des suites acceptees par lautomate.
Principe de la traduction dune expression r
eguli`
ere en AFND
Chaque expression reguli`ere est transformee en un automate avec une queue (transition de
depart) et une tete (etat final).

Exemple
IF
ID
NUM
error

:
:
:
:

if
[a-z][a-z0-9]*
[0-9]+
.

22

Conversion dun AFND en un AFD


Idee de base : on essaye toute les possibilites `a la fois.
Sur lautomate precedent avec la chane in en entree :
On demarre en 1.
Les etapes suivantes possibles, sans consommer de caract`ere, sont {1, 4, 9, 14} (cest lfermeture de {1}).
On reconnat i : etats {2, 5, 15}, avec son -fermeture : {2, 5, 6, 8, 15}.
On reconnat n : etats {7}, avec son -fermeture : {6, 7, 8}.
Est-ce quon a atteint un etat final ? Oui, 8. Et donc cest un identificateur.
Intuitivement, les etats de lAFD correspondent aux ensembles detats de lAFND quon vient
de manipuler.

D
efinition de l-fermeture
Definition 15. Soit T la fonction de transition : E A {} E.
Soit
S un ensemble Q detats, l-fermeture(Q) est le plus petit ensemble X, tel que : X =
Q ( eX T (e, ))
Il sagit dune equation de point fixe, cest-`a-dire une equation de la forme :
X = f (X)
o`
u f est une fonction
S dun ensemble U (lensemble des parties de E) dans lui-meme avec
X U : f (X) = Q ( eX T (e, )).
Principe du calcul de l-fermeture
Les equations de point fixe nont pas toujours des solutions. Mais dans ce cas precis, lequation
a des proprietes particuli`eres :
f est une fonction monotone : si X Y alors f (X) f (Y ).
Son domaine et codomaine U est fini (du fait que E est fini).
Le theor`eme suivant sapplique :
Theorem 16. Soit un ensemble fini U , et une fonction monotone f sur les parties de U .
Lequation X = f (X) admet une solution minimale unique f n () avec n N.
D
emonstration
On consid`ere la chane (une chane dun ensemble ordonne U est un sous-ensemble totalement ordonne de U ) :
f () f (f ()) f (f (f ())) ...

23

Supposons quil nexiste pas deux elements successifs de la chane egaux, alors la chane est
infinie, ce qui contredit le fait que U soit fini. Il existe donc n tel que f n () = f n+1 ().
Cest un point fixe.
Supposons quil existe un autre point fixe A. A = f (A) par hypoth`ese et donc A = f n (A).
Comme A, f n () f n (A) par monotonicite, et donc f n () A. f n () est bien le
plus petit point fixe.
Algorithme
On calcule le point fixe par iteration. Chaque element de la chane en partant de f () = F
constitue une approximation de la solution, jusqu`a ce quon aboutisse `a deux approximations
successives egales :
RQ
faire R0 R S
R = Q ( eR0 T (e, ))
jusqu`
a R = R0
D
efinition de lAFD
Soit l-AFND (E, A, T, e0 , F ) o`
u T est la fonction de transition de lautomate.
LAFD equivalent est defini par (E 0 , A, T 0 , e00 , F 0 ) avec :
e00 = fermeture({e0 }) S
T 0 (e0 , s) = fermeture( ee0 T (e, s))
E 0 = {e00 } {T 0 (e0 , s) | e0 E 0 , s A}
F 0 = {e0 E 0 | e0 F 6= }
Algorithme de calcul des
etats et des transitions de lAFD
Les etats de lAFD sont definis incrementalement et numerotes (tableau etats). Pour chaque
etat trouve, on regarde les transitions possibles, enregistrees dans le tableau des transitions (trans),
ce qui peut conduire `
a la decouverte de nouveaux etats.
etats[0] {}; etats[1] -fermeture({e0 })
p1
// indice du dernier etat trouve
j0
// indice de letat de depart courant
tant que j p
pour tout s A
// explorations des transitions possibles
e T 0 (etats[j], s)
if e = etats[i] pour un i p
then trans[j, s] i
// etat existant
else p p + 1
// nouvel etat
etats[p] e
trans[j, s] p
j j+1

On y est presque
Il faut definir les etats finaux : ce sont les etats dont un des elements est final. Sil y a
plusieurs etats finaux, cest le premier (dans lordre decriture des expressions reguli`eres)
qui definit le type de lexpression reconnue (r`egle de priorite). Voir automate numero 3.
Le tableau des etats nest plus utile.
On peut encore minimiser lautomate obtenu. Deux etats q1 et q2 sont equivalents quand
la reconnaissance dune chane `a partir de q1 implique la reconnaissance de cette chane `a
partir de q2 et inversement. Exemple : 5, 6, 7, 8, 15 et 6, 7, 8. Dans ce cas, on peut fusionner
les etats (algorithme de minimisation).
Pour tout langage regulier, il existe un unique AFD minimal qui le reconnat.

24

2.6

R
esum
e

Pour r
esumer
Cest bien moins simple que ca pourrait paratre au premier abord. Heureusement, on dispose
de tout un arsenal mathematique et algorithmique :
pour toute expression reguli`ere e, il existe un -AFND deterministe qui accepte le langage
decrit par e ;
pour tout langage accepte par un -AFND, il existe un AFD acceptant ce langage ;
il existe des algorithmes pour produire des AFD minimaux.
Ceci permet dautomatiser la production danalyseurs lexicaux `a laide de generateurs danalyse
lexicale : lex [Les75], flex [Pax88], JLex [App98, BA03], JFlex [Kle09]....

25

Analyse syntaxique

Analyse syntaxique

syntaxe : Etude
des r`egles qui president `a lordre des mots et `a la construction des phrases,
dans une langue ; ces r`egles. Petit Robert
Pourquoi est-ce que les expressions r
eguli`
eres ne suffisent pas ?
Definition de sommes sans parenth`eses (par ex. : 23 + 515 + 12) a` laide dune description
reguli`ere
digits := [0-9]+
sum := ( digits "+" )* digits
Soit :
sum := ( [0-9]+ "+" )* [0-9]+

Definition de sommes parenthesees (par ex. : 23 + (515 + 12)) :


digits := [0-9]+
sum := expr + expr
expr := "(" sum ")" | digits
Soit :
expr := "(" expr + expr ")" | digits
expr := "(" ( "(" sum ")" | digits ) + expr ")" | digits
...
Ce nest pas une description reguli`ere : un automate fini ne peut pas reconnatre des expressions
bien parenthesees (une machine `
a n etats ne peut pas se rappeler dune imbrication de profondeur
superieure `
a n).
On doit faire appel `
a des descriptions autorisant la recursion : les grammaires non contextuelles.

3.1
3.1.1

Les grammaires non contextuelles


Introduction

Grammaires
Description de la syntaxe/structure dun langage (de programmation)
R`egles de construction de programmes (texte) bien formes `a partir de mots
Base pour la description de la semantique de ce langage
Anatomie dune grammaire
sum ::= expr + expr
expr ::= ( sum )
expr ::= digits

Une grammaire (non contextuelle) se presente comme un ensemble de r`egles de production


constituees de symboles et de loperateur ::= (ou ), que lon peut lire  se derive en  ou
 est constitu
e de .
Une r`egle de production est constituee dune partie gauche, de loperateur ::= et dune
partie droite.
La partie gauche donne un nom `a une construction syntaxique.
La partie droite explicite la structure de la construction syntaxique.
26

Anatomie dune grammaire (2)


sum ::= expr + expr
expr ::= ( sum )
expr ::= digits

Il y a deux types de symboles :


Les symboles non terminaux : correspondent `a une construction syntaxique, on les
trouve `
a gauche (dans au moins une r`egle) et `a droite. Ils napparaissent pas dans
les productions de la grammaire.
Les symboles terminaux : ils nont pas de structure definie par la grammaire. On va les
retrouver dans les productions de la grammaire.
On a aussi besoin dun symbole de depart (ici sum).
D
efinition dune grammaire (non contextuelle)
Definition 17. Une grammaire non contextuelle (context-free grammar) G est definie par un
quadruplet (T, N, S, P ), o`
u:
T est un ensemble de symboles dits terminaux,
N est un ensemble de symboles dits non terminaux, les ensembles T et N sont finis et
disjoints,
S est un symbole de depart, symbole distingue de N ,
P est un ensemble fini de couples (X, ) N (T N ) , dits r`egles de productions, notes
X ::=
Le processus de production ou d
erivation
La grammaire produit des phrases du langage qui sont des sequences de symboles terminaux
(par convention  denote la sequence vide).
Au cours du processus de production dune phrase, on se trouve face `a des phrases incompl`etes qui contiennent des symboles non terminaux.
Une etape du processus de derivation consiste `a reecrire une phrase incompl`ete en une
autre phrase en remplacant un symbole non terminal par la partie droite dune r`egle o`
u ce
symbole apparat en partie gauche. Cette nouvelle phrase est une derivation de la premi`ere.
Le processus demarre du symbole de depart.
Exemple
(1)
(2)
(3)
(4)
(5)

exp
exp
exp
op
op

( exp op exp )
1
0
+
*

derivation :
(1)@1
(2)@2
(5)@3
(1)@4
...

exp
( exp op exp )
( 1 op exp )
( 1 * exp )
( 1 * ( exp op exp ) )

Il sagit dune derivation gauche : on remplace systematiquement le symbole non terminal


le plus `
a gauche.
27

Il faut faire des choix.


La recursion introduit la possibilite de derivation infinie.
Au lieu de deriver des sequences de symboles, on peut aussi deriver des arbres syntaxiques
qui donnent la structure des constructions analysees.
Arbre syntaxique
exp

(1)@1

(2)@2

exp

op

exp

exp

(5)@3

(1)@4

op

exp

D
erivation
Definition 18. Soit G = (T, N, S, P ) une grammaire non contextuelle, la relation de derivation
associee `
a G est definie par :
Pour tout et elements de (T N ) , ssi
1 , 2 , (T N ) , X N tels que = 1 X2 , = 1 2 et (X, ) P
Definition 19.
La derivation est gauche quand 1 T .
La derivation est droite quand 2 T .
Langage d
efini par une grammaire

Definition 20.
On note la fermeture reflexive-transitive de , cad la plus petite relation
reflexive et transitive contenant :
+
k
ssi k 1 tel que

+
ssi ou =

La phrase p est reconnue par la grammaire G = (T, N, S, P ) ssi p T et S p.


Le langage L reconnue par la grammaire G est lensemble des phrases reconnues par G :

L = {p T |S p}
Arbre syntaxique
Definition 21. Soient G = (T, N, S, P ) une grammaire non contextuelle, et B un arbre ordonne.
On dit que B est un arbre syntaxique selon G, pour x T et X N ssi :
si n est un noeud etiquete par A N , alors
ou bien ses fils sont etiquetes de gauche `a droite par N1 ...Nk T N et A N1 ...Nk P
ou bien, le noeud n na quun seul fils etiquete par et A P .
la phrase formee par la concatenation des feuilles de B est x.
la racine de B est etiquetee par X.
28

3.1.2

Formes
etendues

Forme
etendue BNF
Les r`egles dont la partie gauche est identique sont fusionnees en une seule r`egle `a laide de
loperateur | (lire ou) pour exprimer des alternatives.
EXP -> "(" EXP OP EXP ")" | "1" | "0"
OP -> "+" | "*"

Cest la forme BNF (Backus-Naur Form ou Backus Normal Form).


Forme
etendue EBNF
La forme EBNF (Extended BNF) permet lexpression de loptionalite et de la repetition `a laide
de :
3 operateurs postfixes :
+ pour autoriser une ou plusieurs occurrences dun symbole (ou sequence)
pour autoriser zero ou plusieurs occurrences dun symbole (ou sequence)
? pour autoriser loccurrence ou labsence dun symbole (ou sequence)
des parenth`eses pour delimiter les sequences sur lesquelles doivent sappliquer les operateurs
Exemple
Comparer :
Example 22.

Block
Statements

::= { Statements }
::= Statement | Statements Statement

et
Example 23.

Block ::= { Statement+ }

Note : comme pour les expressions reguli`eres, attention `a ne pas confondre les symboles de la
grammaire et les symboles de la representation sous forme EBNF.
Descriptions r
eguli`
eres
Une description reguli`ere, permet de definir une expression reguli`ere de mani`ere plus lisible
en la decomposant. Elle se presente comme une grammaire non contextuelle sauf quon interdit
lutilisation dun non-terminal avant quil ne soit totalement defini.
La partie droite de la derni`ere r`egle correspond `a lexpression reguli`ere quon veut definir (cest
le symbole de depart de la grammaire).
Exemple
letter -> [a-zA-Z]
digit -> [0-9]
underscore -> _
letter_or_digit -> letter | digit
underscored_tail -> underscore letter_or_digit+
identifier -> letter letter_or_digit* underscored_tail*

En reduisant les terminaux dans la derni`ere r`egle :


identifier -> [a-zA-Z] ([a-zA-Z]|[0-9])* (_ ([a-zA-Z]|[0-9])+)*

Soit :
identifier -> [a-zA-Z] [a-zA-Z0-9]* (_ [a-zA-Z0-9]+)*

29

3.1.3

Exercices

Donner, sous forme BNF, la grammaire equivalente `a lexpression reguli`ere (a|b) abb
G=(
{a, b},
{S, X},
S,
{
S a S | a X,
XbXb|b
})

Quelles sont les caracteristiques des phrases du langage reconnu par G ?


Donner larbre syntaxique correspondant `a la reconnaissance de aabbbbb.

Ecrire
une grammaire non contextuelle pour
L1 = {an bn |n 0}
L2 = {wcwR |w (a|b) } o`
u wR est la chane miroir
n m m n
L3 = {a b c d |n 1, m 1}

Ecrire
une grammaire non contextuelle (si cest possible) pour
L4 = {wcw|w (a|b) } (ex : aabcaab)
L5 = {an bm cn dm |n 1, m 1}
L6 = {an bn cn |n 0}
Quel est le langage reconnu par S "(" S ")" S| ?
3.1.4

Vers des grammaires utilisables en pratique

Grammaires r
eduites
Definition 24. Un non-terminal A est dit inaccessible sil nexiste pas delements et de

(T N ) tels que S A

Un non-terminal A est dit improductif sil nexiste pas de phrase p T telle que A p
Une grammaire est dire reduite si elle ne contient aucun non-terminal inaccessible ou improductif.
On sefforcera de ne travailler que sur des grammaires reduites.
Ambigut
e
Definition 25. Une phrase p L(G) est ambigue si elle admet plusieurs arbres syntaxiques selon
G.
Une grammaire non contextuelle est dite ambigue lorsquelle permet au moins une phrase
ambigue.
Les techniques danalyse standard requi`erent des grammaires non ambigues.
Lexemple des expressions arithm
etiques
E
E
E
E

->
->
->
->

id
E * E
E + E
(E)

E -> num
E -> E / E
E -> E - E

Quels sont les arbres syntaxiques possibles pour 1-2-3, pour 1+2*3 ?
Grammaire non ambigue acceptant le meme langage ?
30

Tous les operateurs sont associatifs a


` gauche.
Les operateurs * et / sont prioritaires sur + et -.
expressions

termes

facteurs

E -> E + T
E -> E - T
E -> T

T -> T * F
T -> T / F
T -> F

F -> id
F -> num
F -> ( E )

Lexemple des conditionnelles


S -> if E then S
S -> if E then S else S
2 arbres possibles pour if E1 then if E2 then S1 else S2 correspondant aux deux interpretations :
if E1 then (if E2 then S1 else S2)
if E1 then (if E2 then S1) else S2
Grammaire non ambigue acceptant le meme langage ?
S -> S1 | S2
S1 -> if E then S | if E then S2 else S1
S2 -> if E then S2 else S2
Note : on a interdit de mettre dans la branche vraie dune conditionnelle `a deux branches une
conditionnelle `
a une branche ou encore on a associe chaque else avec le then le plus proche.
R
esultat important
Si la grammaire est non ambigue, la strategie de derivation est sans consequence sur larbre
resultat. Il ny a quune mani`ere de comprendre (syntaxiquement) une phrase.
Exemple
G = ({a, b, c, d}, {S, A, B, C, D}, S,
{ S aAB
A aA|b
B CD
Cc
Dd
})

La phrase aabcd peut etre reconnue par derivation gauche :


S aAB aaAB aabB aabCD aabcD aabcd
et par derivation droite :
S aAB aACD aACd aAcd aaAcd aabcd
Verifier que les arbres syntaxiques correspondants sont identiques.
3.1.5

Au del`
a des grammaires non contextuelles

La hi
erarchie de Chomsky
Langage

Dispositif de g
en
eration

Dispositif de reconnaissance

Langages r
ecursivement

enum
erables
Langages contextuels

Grammaires g
en
erales
(de type 0)
Grammaires contextuelles
(de type 1)
Grammaires alg
ebriques
ou non contextuelles
(de type 2)
Grammaires lin
eaires droites
ou descriptions r
eguli`
eres
(de type 3)

Machines de Turing
soit automates `
a 2 piles
Automates born
es
lin
eairement
Automates `
a pile
non d
eterministes

Langages non contextuels

Langages rationnels

31

Automates finis

Theorem 26. Le langage L est engendre par une grammaire generale ssi il est accepte par une
machine de Turing (ou un automate `
a deux piles). Chomsky 1959.
Les pionniers

Noam Chomsky (1928), linguiste

John Backus (1924-2007), informaticien


Grammaires g
en
erales et contextuelles
S ::= T Z
T ::= 0T 1C T ::= 
C1 ::= 1C CZ ::= Z2
1Z ::= 1
Cette grammaire generale engendre les mots de la forme 0i 1i 2i .

Example 27.

Les parties gauches des r`egles de productions dune grammaire generale sont des elements
de (T N )+
Dans le cas des grammaires contextuelles, on se restreint `a des r`egles dont les parties droites
sont au moins aussi longues que les parties gauches.

32

3.2

Analyse syntaxique descendante

Analyse syntaxique descendante


Une analyse syntaxique descendante consiste :
1. `
a generer larbre syntaxique en partant de la racine.
2. Pour chaque nud, on lit un certain nombre de lex`emes en entrees,
3. on choisit une r`egle de production,
4. ce qui donne (partie droite de la r`egle) les fils du nud courant,
5. on verifie la concordance des terminaux et
6. on continue avec les non-terminaux.
Si le choix de la r`egle de production est deterministe, limplementation va simplement consister
en un ensemble de fonctions recursives (une fonction par non-terminal).
Exemple
S -> if E then S else S
S -> begin S L
S -> print E

L -> end
L -> ; S L
E -> num = num

public enum Token {


IF, THEN, ELSE, BEGIN, END, PRINT, SEMI, NUM, EQ; } ...
public class Parser {
Token tok = getToken();
void eat(Token t) {if (tok==t) tok=getToken(); else error();}
void S() {switch(tok) {
case IF:
eat(IF); E(); eat(THEN); S();
eat(ELSE); S(); break();
case BEGIN: eat(BEGIN); S(); L(); break;
case PRINT: eat(PRINT); E(); break;
default:
error();
}}...
}

Contre-exemple
E -> E + T
E -> E - T
E -> T

T -> T * F
T -> T / F
T -> F

F -> id
F -> num
F -> ( E )

Considerer les programmes (1*2-3)+4 et (1*2-3).


Grammaires LL(k)
Intuition : Une grammaire dont la (pre)lecture de k lex`emes en entree garantit lunicite de la
r`egle `
a utiliser est dite LL(k).
LL(k) est labreviation de Leftmost scanning, Leftmost derivation, k-symbol lookahead.
Definition 28. G = (T, N, S, P ) est LL(k) ssi
3
X N, (, , ) (T N ) , (w, x, y) T 3 si

S wX w wx et

S wX w wy et
les k premiers symboles de x sont identiques aux k premiers symboles de y
alors =

33

Ensemble premiers
Definition 29. Soit une sequence de symboles (elements de V = (T N )), premiers() est
lensemble de tous les symboles terminaux susceptibles de prefixer une derivation de :

V : premiers() = {a T | aw, w V }
Example 30. E
E -> E - T
E -> T
premiers(T

-> E + T
T -> T * F
F -> id
T -> T / F
F -> num
T -> F
F -> ( E )
* F) = {id, num, (}

Cas simples
Une grammaire telle que pour toute paire de r`egles distinctes X 1 et X 2 , 1 et
2 commencent par des elements differents de T est dite simplement LL(1) (elle est aussi
LL(1), la reciproque etant fausse).
Une grammaire sans r`egle X  est LL(1) ssi pour toute paire de r`egles distinctes X 1
et X 2 , premiers(1 ) premiers(2 ) =
Prise en compte des r`
egles X 
Example 31.

Zd
Z XY Z

Y
Y c

XY
Xa

Il pourrait sembler que premiers(XY Z) = premiers(X).


Mais comme Y , et donc X, peut produire , premiers(XY Z) doit inclure premiers(Z) !
Pour calculer premiers, il faut donc savoir quels symboles sont effacables (nullable en anglais)
et quels sont les symboles qui suivent les symboles effacables.
Note : on peut aussi essayer de supprimer les  et revenir aux cas simples precedents.
D
efinitions de effa
cable et suivants

Definition 32.
X N : effacable(X) X 

X N : suivants(X) = {a T | S uXaw, (u, w) V 2 }

Principe de calcul :
etude par cas
Il est possible deffacer :
Toute la sequence de droite : X Y1 ..Yk
i [1..k], effacable(Yi ) effacable(X)
Le debut de la sequence : X Y1 ..Yi1 Yi ..Yk
i [1..k], j [1..i 1], effacable(Yj ) premiers(X) = premiers(Yi )
La fin de la sequence : X Y1 ..Yi Yi+1 ..Yk
i [1..k], j [i + 1..k], effacable(Yj ) suivants(Yi ) = suivants(X)
Une sequence intermediaire : X Y1 ..Yi Yi+1 ..Yj1 Yj ..Yk
(i, j) [1..k], i < j, l [i + 1..j 1], effacable(Yj ) suivants(Yi ) = premiers(Yj )
Les ensembles effacables, premiers et suivants sont les plus petits ensembles respectant ces
r`egles. Ils peuvent etre calcules `
a laide dun algorithme de point fixe.
Cas limites
Debut de sequence, i = 1 : premiers(X) = premiers(Y1 )
Fin de sequence, i = k : suivants(Yk ) = suivants(X)
Sequence intermediaire, j = i + 1 : suivants(Yi ) = premiers(Yi+1 )

34

Algorithme de point fixe


pour tout f N : premiers(f ) = suivants(f ) = , effacable(f ) = f aux
pour tout a T : premiers(a) = {a}
faire pour chaque r`egle X Y1 Y2 ...Yk
pour i [1, k], j [i + 1, k]
si tous les Yi sont effacables alors effacable(X) = vrai
si Y1 ...Yi1 sont effacables
alors premiers(X) := premiers(X) premiers(Yi )
si Yi+1 ...Yk sont effacables
alors suivants(Yi ) := suivants(Yi ) suivants(X)
si Yi+1 ...Yj1 sont effacables
alors suivants(Yi ) := suivants(Yi ) premiers(Yj )
jusqu`
a la stabilite de premiers, suivants et effacable dans literation
(point fixe)

Application `
a lexemple

Etat
initial :
effacable premiers suivants
Z
faux

Y
faux

X faux

Iteration 1 :
Z d : premiers(Z) := {d}
Z XY Z : suivants(Y ) := premiers(Z) = {d}
Y : effacable(Y )
Y c : premiers(Y ) := {c}
X Y : effacable(X), premiers(X) := premiers(Y ) = {c}
X a : premiers(X) := premiers(X) {a} = {a, c}

Etat
suite `
a literation 1
effacable premiers suivants
Z
faux
{d}

Y
vrai
{c}
{d}
X vrai
{a, c}

Iteration 2 :
Z XY Z : premiers(Z) := premiers(Z)premiers(X)premiers(Y ) = {a, c, d}, suivants(X) :=
premiers(Y ) = {a, c, d}, suivants(Y ) := suivants(Y ) premiers(Z) = {a, c, d}

Etat
suite `
a literation 2
effacable premiers suivants
Z
faux
{a, c, d}

Y
vrai
{c}
{a, c, d}
X vrai
{a, c}
{a, c, d}
Une nouvelle iteration napporte pas de nouvelle information : le point fixe est atteint.
G
en
eralisation des d
efinitions de premiers et effa
cable
On etend la definition de premiers et effacable `a V :
Definition 33.
premiers() =
(X, ) (N, V ), premiers(X) = premiers(X) si effacable(X)
(X, ) (N, V ), premiers(X) = premiers(X) premiers() si effacable(X)
V est effacable ssi tout symbole dans est effacable.

35

Construction dun analyseur LL(1)


` chaque paire (X, t), o`
A
u X est le non-terminal `a reconnatre et t le terminal (lex`eme) en
entree, il faut associer une r`egle unique de la grammaire.
On construit un tableau danalyse predictive. Les lignes correspondent aux non-terminaux, les
colonnes aux terminaux.
a
?
?
?

X
Y
Z

c
?
?
?

d
?
?
?

Pour chaque r`egle X :


ajouter cette r`egle dans les cases (X, t) telles que t premiers()
si est effacable, ajouter cette r`egle dans les cases (X, t) telles que t suivants(X)
Example 34. Z -> d
Y ->
X -> Y
Z -> X Y Z

Y -> c

X -> a

Z
Y
X

effacable
faux
vrai
vrai

premiers(d) = {d}
premiers(X Y Z) = {a, c}

a
Xa
XY

premiers
{a, c, d}
{c}
{a, c}

suivants
{a, c, d}
{a, c, d}

premiers() =
premiers(c) = {c}

premiers(Y) = {c}
premiers(a) = {a}

d
XY

XY
Y c
Y

Z XY Z

Z XY Z

Y
Z

Y
Zd
Z XY Z

En fait, la grammaire est ambigue : il y a plusieurs mani`eres de deriver d.


Caract
erisation compl`
ete dune grammaire LL(1)
Definition 35. Une grammaire est LL(1) ssi pour toute r`egle X 1 | ... | n , n > 1 :
1. premiers(i ) premiers(j ) = , i, j, i 6= j
2. effacable(X) premiers(X) suivants(X) =
3. effacable(X) !i [1, n], effacable(i )
En pratique : dans le cas dune utilisation dun generateur danalyseur LL(1), celui-ci pourra
generer des conflits correspondant `
a ces trois cas ((FIRST/FIRST, FIRST/FOLLOW, FOLLOW/FOLLOW).
Grammaire LL(k)
On peut generaliser premiers en premiersk qui donne toutes les sequences de k non-terminaux
susceptibles de prefixer une derivation.
Les colonnes du tableau danalyse predictive correspondent alors `a toutes les sequences possibles
de k non-terminaux. Il faut `
a nouveau quil ny ait quune r`egle par case : la lecture de k lex`emes
permet de choisir la r`egle (co
uteux en pratique).
Proprietes :
Toute grammaire LL(k) est aussi LL(k + 1).
Une grammaire ambigue nest LL(k) pour aucun k.
Une grammaire recursive a
` gauche nest LL(k) pour aucun k.
36

Rendre une grammaire LL(1)


Un certain nombre de techniques permettent de transformer une grammaire qui nest pas LL(1)
en une grammaire LL(1) equivalente (cest-`a-dire qui reconnat le meme langage) :
suppression des ambigutes dues aux priorites et associativites des operateurs (voir exemple
des expressions/termes/facteurs) ;
elimination des recursions `
a gauche ;
factorisation `
a gauche ;
substitution.
Probl`emes :
ce nest pas toujours possible ;
la grammaire transformee seloigne de la specification initiale.

Elimination
de la r
ecursion `
a gauche
E -> E + T
E -> T
premiers(T ) premiers(E + T )
Transformation de la recursion `
a gauche en recursion `a droite :
E -> T E
E -> + T E
E ->
Plus generalement sil y a des r`egles X X et X , o`
u nest pas prefixe par X, on sait
que X va produire des phrases .
X
X
X
X

X1
X2
1
2

se transforme en
X 1 X 0
X 2 X 0
X 0 1 X 0
X 0 2 X 0
X0 

Ca se complique dans le cas dune recursion indirecte (voir le Dragon Book [ALSU07]). La
recursion `
a gauche peut aussi etre cachee (r`egle X X o`
u est effacable).
Factorisation `
a gauche
Le probl`eme est similaire (et plus simple) quand deux r`egles pour le meme non-terminal commencent par le meme terminal.
S -> if E then S else S
S -> if E then S
On factorise `
a gauche :
S -> if E then S T
T ->
T -> else S
Malheureusement, ca ne resout pas les probl`emes dambigute precedemment evoques : else
premiers(T ) suivants(T ).
37

R
esolution de conflits
Une astuce classique consiste `
a resoudre le conflit en effectuant un choix entre les r`egles lors
de lanalyse :
`
a laide de r`egles de priorites ;
`
a laide dune prelecture ponctuelle de plus de un lex`eme.
Une simple r`egle de priorite suffit dans le cas de la conditionnelle. Dans le cas o`
u on cherche `a
reconnatre T et le lex`eme courant est else, il faut systematiquement choisir la r`egle T -> else S.
La grammaire ne suffit plus `
a decrire le langage. Il y a aussi des hypoth`eses sur la resolution
des conflits.
Substitution
Il sagit de remplacer un non-terminal X 0 dans la partie droite dune r`egle X 1 X 0 2 par
ses alternatives X 0 1 | ... | n pour obtenir :
X 1 1 2 | ... | 1 n 2
Ce type de transformation est utile pour rendre une grammaire simplement LL(1) ou dans
le cas de conflits qui peuvent alors etre transformes en conflits premiers/premiers `a resoudre par
factorisation.
Example 36.
SAab
Aa|

R
ecup
eration des erreurs
` IMPORTANT EN PRATIQUE.
TRES
void eat(int t) {if (tok==t) tok=getToken(); else error();}
void S() {switch(tok) {
case IF:
eat(IF); E(); eat(THEN); S();
eat(ELSE); S(); break();
case BEGIN: eat(BEGIN); S(); L(); break;
case PRINT: eat(PRINT); E(); break;
default:
error();
}}...

Que faire lorsquon ne recup`ere pas lunite lexicale attendue ?


lever une exception et arreter lanalyse : le reste du programme nest pas analyse.
on essaye de recuperer lerreur (error recovery) et de continuer.
R
ecup
eration des erreurs
Dans tous les cas : imprimer un message derreur significatif explicitant le contexte et le
probl`eme rencontre.
Ex. : Line 12, char. 34: Analyzing S, case IF, found ELSE instead of THEN.
Choix de base
insertion : on ins`ere lunite lexicale manquante. Danger : on peut creer des erreurs en
cascade sans effectivement progresser.
remplacement. Danger : on peut supprimer une unite lexicale correcte.
effacement : une solution standard consiste, en cas derreur lors de lanalyse dune construction C `
a sauter toutes les unites lexicales jusqu`a en rencontrer une appartenant `a suivants(C).
Il existe des algorithmes plus sophistiques comme la recuperation recursive o`
u lanalyse peut
etre relancee au sein meme du traitement des erreurs. Voir aussi [WM94].

38

3.3

Les arbres syntaxiques abstraits

Analyse syntaxique et analyse s


emantique
Lanalyse syntaxique (couplee) `
a lanalyse lexicale nous permet de dire si une phrase (un
programme) est bien formee (appartient au langage definie par la grammaire).
Comment aller au del`
a, passer de la syntaxe (la forme) `a la semantique (le sens) du programme ?
Lidee de base est dassocier `
a chaque construction une valeur semantique, calculee, lors de
lanalyse syntaxique, `
a laide dune action semantique.
Lexecution de ces actions semantiques realise alors lanalyse semantique du programme.
Introduction des arbres syntaxiques abstraits
Lidee precedente pose des probl`emes pratiques :
organisation peu modulaire du compilateur ;
obligation deffectuer lanalyse semantique dans le meme ordre que lanalyse syntaxique.
On va se limiter `
a generer pour le programme une valeur semantique  minimale  : un arbre
syntaxique abstrait (en anglais, abstract syntax tree ou AST), que lon peut voir comme une
simplification de larbre de syntaxe associe au programme.
Lanalyse semantique va ensuite annoter lAST avec des attributs precisant la semantique des
nuds (informations utiles pour le traitement derreur et la generation de code).
De larbre syntaxique `
a larbre syntaxique abstrait
Larbre syntaxique decrit la syntaxe concr`ete du programme et contient des details qui ne sont
plus utiles une fois lanalyse syntaxique realisee. Exemples : les separateurs, les non-terminaux
introduits pour supprimer les ambigutes...
On se debarasse de ces details pour se concentrer sur la syntaxe abstraite du programme.
Larbre syntaxique correspondant est un arbre syntaxique abstrait.
Syntaxe concr`
ete et syntaxe abstraite : exemple
S if E then S else S
Syntaxe concr`ete : S begin S L
S print E
S E S S E num num
Syntaxe abstraite : S S +
SE

Example 37.

L end
L ;S L
E num = num

Arbre syntaxique et arbre de syntaxe abstrait : exemple


Quel est larbre syntaxique (concret) et larbre syntaxique abstrait correspondant `a ce programme ?
Example 38. begin
if 1=2 then
print 1=2
else
print 2=1;
print 1=3
end
Principe dune structuration par classes dun arbre syntaxique
On suppose que la grammaire est mise sous une forme et/ou, cest-`a-dire sous la forme de
r`egles :
ou : Aou A1 | A2 | ... | An
et : Aet A1 A2 ...An
` chaque construction Aou est associee une classe abstraite.
A

39

` chaque construction Aet est associee une classe concr`ete, potentiellement sous-classe dune
A
classe abstraite. Les nuds de larbre syntaxique vont etre des instances de ces sous-classes.
Example 39.

SS ;S
E id
E(S,E)
S id := E
E num
LE ,L
S print( L ) E E op E L E
Stmt CmpStmt | AssignStmt | P rintStmt
CmpStmt Stmt Stmt
AssignStmt id Exp
P rintStmt Exps
Exp V ar | Cste | BinExp | CmpExp
V ar id
Cste num
BinExp Exp op Exp
CmpExp StmtExp
Exps SingleExp | P airedExps
SingleExp Exp
P airedExp Exps

Syntaxe concr`ete :

Syntaxe abstraite :

Example 40. abstract class Exp {


% abstract display();
};
class Var extends Exp {
private String id;
Var(String id) {this.id = id; }
}
class BinExp extends Exp {
private String op;
private Exp e1;
private Exp e2;
BinExp(String op, Exp e1, Exp e2) {
this.op = op;
this.e1 = e1;
this.e2 = e2
}
}

Principes de limpl
ementation de lanalyse syntaxique
` partir du moment o`
A
u on dispose de classes, lidee est dy inclure lanalyse des non-terminaux
Aou et Aet correspondants.
Comme dans le premier cas (r`egle ou) on ne dispose que de classes abstraites, alors que dans
le deuxi`eme cas (r`egle et), on dispose de classes concr`etes, cette inclusion va prendre une forme
particuli`ere dans chaque cas.
R`
egle ou
A A1 | A2 | ... | An
Lanalyse dun A requiert lanalyse dun A1 ou dun A2 ... ou dun An .
La classe A associee `
a A est abstraite. Elle definit les types declares des nuds (cf cidessous), mais pas leur type concret puisque les sous-classes de A correspondent `a des regles
ET.
La methode danalyse associee `a cette classe est une methode de classe (elle nest pas
associee `
a un objet particulier) par contre, cest cette methode qui cree les instances des
nuds de larbre syntaxique.
abstract class A {
public static A parseOr() {
A1 a1 = new A1();
if (a1.parseAnd()) return a1;

// analyse de a1

40

A2 a2 = new A2();
if (a2.parseAnd()) return a2;
...
An an = new An();
if (an.parseAnd()) return an;
return null;

// ou de a2

// ou de an

}
}

R`
egle et
A A1 A2 ...An
Lanalyse dun A requiert lanalyse dun A1 et dun A2 ... et dun An .
La classe A associee `
a cette r`egle definit le constructeur qui cree effectivement les nuds de
larbre syntaxique.
Elle etend une classe abstraite associee `a une r`egle ou (cf ci-dessus) qui est la classe qui
appelle le constructeur.
Une instance de A correspond `
a un nud de larbre syntaxique et ses variables dinstances
a ses fils. La methode danalyse associee `a chaque instance de A (une methode dinstance)
`
definit les valeurs de ces variables dinstances.
class A extends ... {
private A1 a1;
private A2 a2;
...
private An an;
public boolean parseAnd() {
if ((a1 = A1.parseOr()) != null) {
// analyse de a1
if ((a2 = A2.parseOr()) == null) { // et de a2
error("Missing A2");
...
if ((an = An.parseOr()) == null) { // et de an
error("Missing An");
return true;
// un A est reconnu
}
return false;
// echec de lanalyse
}
}

Le programme principal
Supposons que Program soit la classe associee au symbole de depart de la grammaire (qui
represente un programme complet) et quon dispose dans chaque classe concr`ete dune methode
display des instances/nuds de larbre syntaxique. On peut ecrire :
class Parser {
public static void main(String[] args) {
Lex.getToken(); // start lexical analyser on input stream
Program program = Program.parseOr();
program.display();
if (Lex.tokenClass != Lex.EOF)
System.err.println("Garbage at end of program ignored");
if (program == null)
System.err.println("No AST produced");
}

Notes
Ce schema general peut etre raffine de la mani`ere suivante :

41

Dans le cas dune grammaire LL(1), les methodes parseOr sont implementees `a laide
dinstructions switch comme il a ete vu precedemment.
On ne cree pas larbre syntaxique, mais lAST ou un arbre proche de lAST. Dans ce cas,
il est inutile de creer des classes pour les terminaux.
Dans le cas, o`
u il ny a pas dalternative pour un non-terminal A, la methode statique
parseOr peut etre directement definie dans la classe concr`ete associee au non-terminal.
Il nest pas toujours facile de creer directement lAST (par exemple, on peut avoir modifie la
grammaire pour des besoins danalyse et souhaiter travailler avec un AST correspondant `a
la grammaire originale). Une strategie possible consiste `a construire un arbre intermediaire
puis `
a le transformer.

42

3.4

Analyse syntaxique ascendante

Analyse syntaxique ascendante


Une analyse syntaxique ascendante, dite aussi par decalage et reduction, construit larbre
syntaxique de bas en haut, cest-`
a-dire en commencant par les feuilles et en remontant vers la
racine.
La reduction est le processus inverse de la derivation.
` chaque etape de reduction, une sequence correspondant `a la partie droite dune r`egle de
A
production est remplacee par sa partie gauche (un non-terminal). On essaye de reduire la sequence
a reconnatre pour finalement obtenir le symbole de depart de la grammaire.
`
Un decalage correspond au deplacement `a effectuer dans la sequence `a analyser pour trouver
la sous-sequence de symboles `
a remplacer.
Exemple
S aABe
A Abc | b
Bd
On cherche `
a analyser abbcde.
Analyse descendante (avec selection des sequences les plus `a gauche). On utilise la suite de
r`egles de production S, A1 , A2 , B conduisant `a la derivation (gauche) :
S aABe aAbcBe abbcBe abbcde
Analyse ascendante (avec selection des sequences les plus `a gauche). On utilise la suite de r`egles
de reduction A2 , A1 , B, S :
abbcde aAbcde aAde aABe S
La derivation correspondante est une derivation droite : S aABe aAde aAbcde
abbcde
3.4.1

Principes th
eoriques

La notion de protophrase
Lorsquon effectue des derivations ou des reductions, on manipule des sequences de symboles
qui sont des protophrases, cest-`
a-dire des sequences de symboles que lon peut deriver `a partir du
symbole de depart, ou que lon peut reduire jusqu`a obtenir le symbole de depart.
D
efinitions

V est une protophrase ssi S .


Une protophrase droite est une protophrase dont toutes les derivations elementaire sont des
derivations droites.
Lors dune analyse ascendante, on ne manipule que des protophrases droites.
Dune protophrase droite `
a lautre
Pour reduire une protophrase droite en une autre protophrase droite, il faut selectionner un
manche, cest-`
a-dire une sous-sequence de la protophrase initiale correspondant `a une partie droite
de r`egle.
D
efinition
Un manche (handle) dune protophrase droite est un couple :
r`egle de production X ,
position dans o`
u lon trouve (que lon va pouvoir reduire en X).
Autrement dit :

(w1 , w2 ) V T : = w1 w2 , S w1 Xw2 w1 w2 o`
u toutes les derivations sont
droites.
Exemple
43

S aABe
A Abc | b
Bd
abbcde aAbcde aAde aABe S
La derivation correspondante est une derivation droite : S aABe aAde aAbcde
abbcde
A b en position 2 est un manche de abbcde
A Abc en position 2 est un manche de aAbcde
R
esultat th
eorique fondamental
Proposition
Si une grammaire est non ambigue, chaque protophrase droite de cette grammaire a exactement
un manche.
Autrement dit, toute phrase dun langage non ambigu est analysable `a laide dune analyse
ascendante.
3.4.2

Principes de limpl
ementation

Principe de limpl
ementation
On utilise une pile, initialement vide, et un tampon dentree, qui contient initialement la
sequence `
a analyser. Les caract`eres $ marquent le fond de la pile et du tampon.
Pile
$

Entree
abbcde$

La pile est utilisee pour stocker le debut de la protophrase `a reconnatre, jusqu`a ce quon
trouve un manche () en sommet de pile. Le manche est alors reduit en la partie gauche (X) de
la r`egle correspondante (X , ici A b).
Pile
$ab

Entree
bcde$

reecrit en

Pile
$aA

Entree
bcde$

On reit`ere jusqu`
a ce que lanalyse soit terminee (le tampon est vide et la pile contient le
symbole de depart).
Actions de base de lanalyseur
decaler : le symbole courant du tampon dentree (au sommet du tampon) est enleve du
tampon et empile ;
reduire : un manche est detecte en sommet de pile et remplace par le non-terminal correspondant ;
accepter : fin de lanalyse ;
erreur : detection dune erreur syntaxique.
Les conflits
Un conflit correspond `
a une indecision sur loperation `a effectuer :
conflit decalage/reduction : lorsquon peut reduire, on peut en general aussi decaler. Or, il
ne faut pas toujours reduire. On peut croire avoir trouve un manche : w1 w2 w1 Xw2 ,
mais une fois cette reduction faite on narrive plus `a reduire w1 Xw2 en S ;
conflit reduction/reduction : plusieurs reductions sont possibles.
Attention
Pour une grammaire non ambigue quelconque, il nexiste pas de methode generale de determination
des manches.

44

Une impl
ementation avec retour arri`
ere
` chaque etape (obtention dune nouvelle protophrase), il existe un manche et un seul. Donc,
A
a chaque etape, si on essaye toutes les reductions, on va necessairement reduire le manche.
`
Do`
u lalgorithme :
reduire d`es que cest possible (pour ne pas rater le manche), sinon decaler ;
en cas dimpasse (nouvelle action rejeter), on retourne `a la derni`ere reduction, quon remplace par un decalage.
Cette implementation se fait tr`es facilement en Prolog et peut etre suffisante dans certains
contextes.
Exemple : analyse de abbcde
S aABe
A Abc | b
Bd

1
2
3
4
5
6
7
8
9
10

Pile
$
$a
$ab
$aA
$aAb
$aAA
$aAAc
$aAAcd
$aAAcB
$aAAcBe

Entree
abbcde$
bbcde$
bcde$
bcde$
cde$
cde$
de$
e$
e$
$

Action
decaler
decaler
reduire A2 (point de choix)
decaler
reduire A2 (point de choix)
decaler
decaler
reduire B (point de choix)
decaler
rejeter

Un retour `
a letape 8 m`ene `
a une autre impasse.
On revient a
` letape 5 :
1
2
3
4
5
6
...

$
$a
$ab
$aA
$aAb
$aAbc

abbcde$
bbcde$
bcde$
bcde$
cde$
de$

decaler
decaler
reduire A2
decaler
decaler
reduire A1

Analyses d
eterministes
Il existe une large classe de grammaires, dites LR(k), pour lesquelles il est possible de construite
des analyseurs ascendants deterministes) (cest-`a-dire sans retour arri`ere, ne pas confondre avec
les probl`emes dambigute).
LR(k) est labreviation de Lefmost scanning, Rightmost derivation, k-symbol lookahead.
3.4.3

Grammaires et analyseurs LR(k)

Grammaires et analyseurs LR(k)


Avantages :
les grammaires LR(k) sont plus expressives que les grammaires LL(k) (intuition : on prend
la decision dappliquer une r`egle apr`es avoir lu tous les symboles correspondant `a sa partie
droite) ;
les analyseurs detectent les erreurs plus tot ;
ils sont efficaces.
Inconvenients :
les analyseurs LR(k) requi`erent des tables danalyse extremement fastidieuses `a produire `a
la main (recours `
a des generateurs danalyseurs) ;
la specification de la recuperation sur erreur est aussi fastidieuse.
45

Classes de grammaires

LL(0)
LR(0)

LL(1)
LR(1)
LL(k)
LR(k)

Grammaires non ambigus


Grammaires non contextuelles

Classes de langages

LL(0)
LL(1)
LL(k)
LL
LR(1) = LR (k) = LR

Langages non contextuels non ambigus


Langages non contextuels

avec LL =

LL(k) et LR =

LR(k)

Principes g
en
eraux des analyseurs ascendants d
eterministes
La question est de savoir quand decaler et quand reduire. Si on ne sait pas, on est en
presence dun conflit et on est coince.
Conceptuellement, un analyseur est un AFD, qui ne va pas seulement sappliquer aux
symboles (terminaux) en entree (rappel : un AFD nest pas assez puissant pour ca), mais
aussi aux symboles (quelconques) sur la pile. On parle dautomates `a pile.
Pour ne pas avoir `
a systematiquement rescanner la pile pour connatre son etat, on va aussi
empiler letat courant sur la pile.
Les transitions de lautomate dependent (comme dans le cas de lanalyse lexicale) de letat
initial, du premier symbole en entree, mais aussi du contenu de la pile. Ces transitions sont
des decalages ou des reductions.
Dans le cas dun decalage, on retire le symbole (un terminal) en sommet du tampon et on
lempile (on atteint ainsi un nouvel etat qui est aussi empile).
Dans le cas dune reduction, le manche , qui se trouve en sommet de pile, est remplace par
le non-terminal X correspondant `a la r`egle utilisee. Le nouvel etat (qui est aussi empile)
depend de X.

46

Exemple danalyse
Exemple
(1) E E+T
(3) T T *F
(5) T (E)

(2) E T
(4) T F
(6) F id

Etape
1
2
3
...

Pile
0
0 id 5
0 F 3
...

Entree
id * id + id
* id + id
* id + id
...

Action
d5
r6
r4
...

Note : le fond de pile est marque par letat 0.


Tableau danalyse
Le tableau danalyse est un tableau dont les lignes sont des etats de lautomate et les colonnes des symboles. La partie du tableau correspondant aux terminaux definit une fonction
action et celle correspondant aux non-terminaux une fonction successeur.
La fonction action associe `
a un etat (letat courant, en sommet de pile) et `a un terminal
(symbole en entree) une action :
di : decaler et passer `
a letat i
rk : reduire en utilisant la r`egle k
a : accepter
e : erreur (quon ne fera pas figurer dans le tableau pour ne pas le surcharger)
La fonction successeur associe a` un etat (letat courant) et un non-terminal (resultat dune
reduction) un nouvel etat.
Algorithme
Soit p un pointeur sur le symbole courant de la sequence a
` analyser ;
Faire pointer p sur le premier symbole ; Empiler letat initial ;
Jusqu`
a acceptation ou erreur faire
soit i letat en sommet de pile et s le symbole pointe par p ;
si action(i, s) = dj alors
empiler s puis j ;
avancer p ;
si action(i, s) = rk o`
u la r`egle k est A alors
depiler 2 | | elements ;
soit j le nouvel etat en sommet de pile ;
empiler A puis successeur(j, A) ;
si action(i, s) = a alors
accepter ;
sinon erreur ;

Exemple

47

Etat
0
1
2
3
4
5
6
7
8
9
10
11

id
d5

action
*
(
d4

d6
r2
r4

d7
r4

r2
r4

a
r2
r4

r6

r6

r6

r6

d5

d4

d5
d5

successeur
E T
F
1 2
3

d4
d4
d6
r1
r3
r5

d11
r1
r3
r5

d7
r3
r5

3
10

r1
r3
r5

Analyse de id * id + id
Etape
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Pile
0
0 id 5
0 F 3
0 T 2
0 T 2 *
0 T 2 *
0 T 2 *
0 T 2
0 E 1
0 E 1 +
0 E 1 +
0 E 1 +
0 E 1 +
0 E 1

id *
*
*
*
7
7 id 5
7 F 10

6
6 id 5
6 F 3
6 T 9

id
id
id
id
id

Entree
+ id$
+ id$
+ id$
+ id$
+ id$
+ id$
+ id$
+ id$
+ id$
id$
$
$
$
$

Action
d5
r6
r4
d7
d5
r6
r3
r2
d6
d5
r6
r4
r1
a

Les analyseurs LR(k) classiques et leurs variantes


LR(0) : il ny a pas danticipation, dans certains etats on effectue une reduction quelque
soit le caract`ere en entree (utilite didactique) ;
SLR (Simple LR) : generalisation de LR(0) avec utilisation de suivants pour eviter les
conflits (on ne reduit en un non-terminal que si le caract`ere en entree est un suivant du
non-terminal) ;
LR(1) : le caract`ere danticipation limite les conflits - couvre la plupart des langages de
programmation ;
LALR(1) (Look-Ahead LR) : cas particulier de LR(1) qui permet de diminuer le nombre
detats, le standard (en particulier pour les generateurs danalyseurs).
Une grammaire est dite X sil est possible de construire un analyseur X pour cette grammaire !

3.4.4

Fabrication dun analyseur LR(0)

Analyseur LR(0)
Il ny a pas de fenetre danticipation :
en general trop faible pour etre utile en pratique,
utile pour expliquer la construction de lAFD et de la table danalyse.
Les items LR(0)
On consid`ere la grammaire :

48

(1) S (L)
(3) L S

(2) S x
(4) L L, S

augmentee de la r`egle (0) S 0 S$ pour expliciter la fin de la sequence dentree.


Initialement, la pile est vide et lentree est une derivation de S 0 , cest `a dire quon trouve une
sequence de symboles correspondant `
a la partie droite de la r`egle (0), ce que lon note :
S 0 S$, o`
u indique o`
u en est lanalyse.
Une entree qui commence par S commence par donc par une production de S, ce que lon
note :
etat 1 : S 0 S$ S x S (L)
D
efinition
Une r`egle completee par un point separant pile et entree est appelee un item LR(0).
Un etat de lautomate est un ensemble ditems.
D
ecalages
Dans letat 1, on peut decaler x ou (.
Si on decale x, seule la r`egle (2) intervient. On se retrouve dans un nouvel etat 2 :
S x
Si on decale (, lentree commence par une production de L, on inclut dans letat les items correspondants et, comme on voit que la pile peut commencer par S, les nouveaux items correspondants.
Ce qui donne letat 3 :
S (L) L L, S L S S (L) S x
R
eductions et successeurs
Une reduction peut seffectuer lorsquon trouve un point `a droite dune r`egle : le non-terminal
correspondant a ete reconnu. Par exemple dans letat 2.
Les etats successeurs correspondent `a la reconnaissance compl`ete dun non-terminal. Ainsi, si
on est parti de letat 1 et que S a ete reconnu, on va pouvoir avancer dans un nouvel etat 4 :
S0 S $
Etc.

Etats
et transitions LR(0)
(0) S 0 S$

(1) S (L)
(3) L S

(2) S x
(4) L L, S
2

S' S$
S (L)
S x

S x
x

x
x
3

S 4
S' S$
(

S (L)
L S
L L,S
S (L)
S x
S

L L,S
S (L)
S x
,

S(L)

49

L L,S
S (L)
)

L S

LL, S

G
en
eralisation
On a besoin de deux operations fermeture et successeurs.
D
efinition
Soit I un ensemble ditems, fermeture(I) est le plus petit ensemble tel que :
I fermeture(I)
si A X I et X alors X I
D
efinition
Soit X un symbole, successeurs(I, X) = fermeture(J) avec J = {A X | A X I}.
Exercice
E 0 E$
T T F |F

E E + T |T
F (E)|id

Soit I = {E 0 E$}, calculer fermeture(I).


Soit I = {E 0 E$, E E +T $}, calculer successeurs(I, +).
Construction des
etats et des transitions
E est un ensemble detats (un etat est un ensemble ditems) et T un ensemble de transitions.
E = {fermeture({S 0 S$})}
T = {}
pour chaque I E
pour chaque item A X I
soit J = successeurs(I, X)
E E {J}
X

T T {I J}

Construction de la table danalyse


On associe une ligne i `
a chaque etat I (la premi`ere ligne `a letat initial), une colonne `a chaque
symbole.
On consid`ere chaque item de Ii :
a
A a avec a terminal et Ii Jj : action(i, a) = dj .
(k)A avec A 6= S 0 , pour tout terminal a : action(i, a) = rk .
S 0 S $ : action(i, $) = a.
Les autres entrees correspondent `a une erreur.
Il y a un conflit si action nest pas une fonction (plusieurs actions sont associees `a une meme
case) : la grammaire nest pas LR(0).
La partie successeur du tableau est directement remplie `a partir de T .
Exemple

Etat
1
2
3
4
5
6
7
8
9

(
d3
r2
d3

action
x
,
d2
r2 r2 r2
d2
)

successeur
S
L
4

r2
7
a

r1
r3
d3
r4

d6
r1
r3
r4

r1
r3
d2
r4

d8
r1
r3

r1
r3

r4

r4

50

Exercice
Construire la table danalyse LR(0) de la grammaire :
(1) E 0 E$
(3) E T + E
3.4.5

(2) E T
(4) T x

Fabrication dun analyseur SLR

Analyseur SLR
SLR = Simple LR
Une amelioration simple de lalgorithme precedent consiste `a ne produire des reductions que
pour les terminaux appartenant aux suivants(A) :
(k)A avec A 6= S 0 , pour tout terminal a suivants(A) : action(i, a) = rk .
Ceci resout le probl`eme de conflit de lexemple precedent.
Limite des analyseurs SLR
La grammaire suivante (qui capture la notion des expressions, variables et dereferencement de
pointeur en C) nest pas SLR.
S 0 S$
SV =E
SE

EV
V x
V E

Lutilisation des suivants nest pas assez fine pour reduire les conflits. Au lieu dutiliser les
suivants a fortiori, on introduit dans le calcul des fermetures un symbole danticipation (lookahead).
3.4.6

Fabrication dun analyseur LR(1)

Red
efinition de f ermeture et successeurs
D
efinition
Un item LR(1) est un couple (A , a) o`
u a est un symbole terminal ($ inclus) appele symbole
danticipation.
D
efinition
Soit I un ensemble ditems, fermeture(I) est le plus petit ensemble tel que :
I fermeture(I)
si (A X, a) I et X avec b premiers(a) alors (X , b) I
D
efinition
Soit X un symbole, successeurs(I, X) = fermeture(J) avec J = {(A X , a) | (A
X, a) I}.
Constrution des tables danalyse LR(1)
Lalgorithme est identique `
a celui des tables SLR sauf pour la definition de letat initial et le
traitement des reductions lors de la construction de la table des actions :
etat initial : E = {fermeture({(S 0 S$, ?)})}
construction des actions :
(k)(A , a) avec A 6= S 0 alors : action(i, a) = rk .
(S 0 S $, ?) : action(i, $) = a.

51

3.4.7

Fabrication dun analyseur LALR(1)

Analyseur LALR(1)
Les tables LR(1) peuvent comporter beaucoup detats. Cest un probl`eme dans le cas o`
u la
memoire disponible est limitee.
Une mani`ere de reduire le nombre detats consistes `a fusionner les etats dont les items ne
diff`erent que par leur symbole danticipation, ce qui donne un analyseur LALR(1).
Suivant la grammaire, la table LALR(1) peut introduire des conflits absents de la table LR(1).
En pratique, cest toutefois assez rare et les analyseurs LALR(1) sont les analyseurs standard
quand il sagit danalyser des langages de programmation non exotiques.
Retour sur les classes de grammaires

LL(0)
LR(0)
SLR
LALR(1)
LL(1)
LR(1)
LL(k)
LR(k)

Retour sur les grammaires ambigu


es
Rappel : une grammaire ambigue nest pas LR (concr`etement il y a des conflits dans la table).
Il est toutefois possible de lever les ambigutes grace `a des r`egles specifiques (exemple : priorite
et associativite des operateurs).
On peut souvent, `
a partir de ces r`egles, resoudre les conflits lors de la construction des tables.
Exemple avec des op
erateurs
On a vu que la grammaire suivante est ambigue :
E E + E | E E | (E) | id
Elle peut etre reecrite en :
E E+T |T
T T F |F
F (E) | id
Mais lanalyseur passe alors son temps `a effectuer des reductions en utilisant les r`egles E T
et T F .
Si on consid`ere la grammaire initiale, un des etats est defini par lensemble ditems suivants :
{E E + E, E E +E, E E E}
Soit id + id * id la chane `
a reconnatre. Lorsque id * id est sur la pile, il reste *id en
entree. Faut-il considerer le premier item (reduction) ou le troisi`eme (decalage) ? Si * a la priorite
sur +, il faut decaler.
Soit id + id + id la chane `
a reconnatre. Lorsque id + id est sur la pile, il reste +id en
entree. Faut-il considerer le premier item (reduction) ou le deuxi`eme (decalage) ? Si + est associatif
a gauche, il faut reduire.
`
52

La connaissance de la priorite et de lassociativite des operateurs permet de prendre les bonnes


decisions en gardant une grammaire lisible et un analyseur tr`es efficace.
G
en
erateurs danalyseurs syntaxiques
La construction des tables est penible mais heureusement facilement automatisable. En pratique, on utilise des generateurs danalyseurs syntaxiques :
SableCC [Sab07] ;
CUP [CUP07] ;
citons aussi Yacc (Yet another compiler compiler) pour C (Bison en version GNU).
Note : il existe aussi des generateurs danalyseurs descendants (exemple : ANTLR [PF13,
Par12, Par13a]).
3.4.8

Un exemple de g
en
erateur danalyseur syntaxique

Sp
ecification CUP
Un preambule declare les symboles terminaux et non terminaux ainsi que le symbole de depart.
Exemple
terminal ID, WHILE, BEGIN, END, DO,
IF, THEN, ELSE, SEMI, ASSIGN;
non terminal prog, stm, stmlist;
start with prog;
Le preambule specifie aussi comment associer un analyseur lexical `a lanalyseur syntaxique.
Les r`egles de grammaire sont traduites directement en utilisant les symboles declares et en
utilisant ::= plut
ot quune fl`eche (attention aussi au separateur ; en fin de r`egle).
Exemple
prog ::= stmlist;
stm ::= ID ASSIGN ID
|
WHILE ID DO stm
|
BEGIN stmlist END
|
IF ID THEN stm
|
IF ID THEN stm ELSE stm;
stmlist ::= stm
|
stmlist SEMI stm;

R
esolution des conflits
Par defaut, CUP utilise les r`egles suivantes pour resoudre les conflits :
les conflits entre decalage et reduction sont regles en faveur du decalage ;
les conflits entre deux reductions sont regles en faveur de la reduction correspondant `a la
premi`ere r`egle apparaissant dans la grammaire.
Il est aussi possible de generer un rapport decrivant les etats de lanalyseur et les conflits
eventuels.
Il est fondamental de verifier sil y a des conflits ou pas, de comprendre `a quoi ils sont dus, de
les resoudre (si la strategie par defaut nest pas correcte) :
utilisation des declarations doperateur ;
reecriture de la grammaire (conflit entre reductions).

53

D
eclarations de priorit
e et dassociativit
e
Il y a trois types de declarations dassociativite :
precedence left
terminal (, terminal) ;
precedence right
terminal (, terminal) ;
precedence nonassoc terminal (, terminal) ;
Lordre de ces r`egles est utilise pour determiner la priorite des operateurs (du moins au plus
prioritaire).
Exemple
precedence left ADD, SUBSTRACT;
precedence left TIMES, DIVIDE;
Priorit
e contextuelle
- (lex`eme MINUS) a une priorite differente suivant quil sagit dun operateur unaire ou binaire.
Ce point est regle par un  truc  qui consiste `a declarer un pseudo-lex`eme UMINUS de priorite
maximale :
precedence left PLUS, MINUS;
...
precedence left UMINUS;
et dassocier cette priorite `
a MINUS contextuellement dans les r`egles de grammaire, `a laide de
la directive %prec :
exp ::= MINUS exp %prec UMINUS ;
Retour sur les actions s
emantiques
Les generateurs danalyseur syntaxique permettent dattacher des actions semantiques aux
r`egles de grammaire.
Lorsquune r`egle est utilisee dans une reduction, laction semantique est executee. Elle calcule la
valeur semantique du non-terminal en partie gauche `a partir des valeurs semantiques des symboles
en partie droite.
Les valeurs semantiques sont stockees sur la pile : lors dune reduction, on depile les symboles
et leur valeur semantique, ce qui permet de calculer la valeur semantique du symbole reconnu.
Cette valeur est empilee avec le symbole reconnu.
Exemple CUP
Dans les r`egles, loperateur : permet dassocier un identificateur `a la valeur semantique dun
symbole.
Dans les actions, RESULT designe la valeur semantique du symbole reconnu.
Exemple
terminal Integer INT;
terminal String ID;
...
precedence right SEMI;
...
prog
::= stmlist:ss
{:RESULT=ss.display(); :};
stmlist ::=
stm:s SEMI stmlist:ss
{:RESULT=new StmList(s, ss); :};
stm
::= ID:i ASSIGN exp:e {:RESULT=new Assign(i, e); :};
...

54

R
ecup
eration des erreurs
Principe de la recuperation locale (ajustement de la pile et de lentree au point o`
u lerreur est
detectee) :
isoler le non-terminal qui etait analyse et qui contient lerreur detectee ;
pretendre avoir reconnu ce non-terminal et continuer.
En pratique : utilisation de r`egles de recuperation des erreurs `a laide du symbole special error.
Exemple
exp
exps
exps
exp
exps

::=
::=
::=
::=
::=

LPAREN exps RPAREN ;


exp ;
exps SEMI exp ;
LPAREN error RPAREN ;
error SEMI exp ;

En cas derreur :
depiler jusqu`
a trouver un etat qui accepte un decalage de error,
decaler error,
eliminer les symboles en entree jusqu`a retrouver un etat qui ne correspond pas `a une erreur
(resynchronisation sur RPAREN ou SEMI dans lexemple),
reprendre lanalyse.
R
ecup
eration globale
La recuperation locale ne permet pas de recuperer des erreurs qui ne peuvent etre corrigees
quen modifiant la partie de lentree dej`a analysee lorsque lerreur est detectee.
Une recuperation globale vise `
a trouver le plus petit ensemble de suppressions et dinsertions
tel que lentree soit globalement syntaxiquement correcte.
Exemple : recuperation de Burke-Fisher (on ne sinteresse quaux k symboles precedents la
detection, voir [App98]).

55

S
emantique

4.1

Introduction

S
emantique

semantique : Etude
du langage considere du point de vue du sens. Petit Robert

4.2

La s
emantique des expressions

S
emantique des constantes enti`
eres
Syntaxe des constantes enti`eres (en base 2) : n ::= 0 | 1 | n 0 | n 1
Soit Num lensemble des constantes enti`eres, la semantique de ces constantes est donnee par
la fonction semantique :
N : Num N
n
N [[n]]

definie par les equations :


N [[0]] = 0
N [[1]] = 1
N [[n 0]] = 2N [[n]]
N [[n 1]] = 2N [[n]]+1

0 est un caract`ere alors que 0 est un nombre entier.


N est une fonction : n Num,
! n N tel que N [[n]] = n (*)
Preuve par induction sur la structure de n (lhypoth`ese dinduction est que (*) est vrai pour
les constituents immediats de n) :
cas de base : n = 0 : une seule equation sapplique : n = 0.
case de base n = 1 : meme raisonnement.
n = n0 0 : une seule equation sapplique : N [[n]] = 2N [[n0 ]]. Dapr`es lhypoth`ese dinduction,
il existe un unique n0 tel que N [[n0 ]] = n0 et donc un unique n tel que N [[n0 ]] = n0 : n = 2 n0 .
n = n0 1 : meme raisonnement.
Sch
ema g
en
eral : des d
efinitions compositionnelles
Chaque categorie syntaxique (constante enti`ere, expression, definition...) est defini au travers de sa syntaxe abstraite qui en donne les elements de base et les elements composites. Les
elements composites sont decomposees de mani`ere unique en leur constituents immediats.
La semantique dune categorie syntaxique est donnee au travers dune fonction semantique
definie compositionnellement : il y a une equation semantique par r`egle de construction
et dans le cas dune construction composite, sa semantique est definie en fonction de la
semantique de ses constituents immediats.
Sch
ema g
en
eral : des preuves par induction structurelle
Prouver la propriete pour tous les elements de base de la categorie syntaxique.
Prouver la propriete pour tous les elements composites de la categorie syntaxique : faire
lhypoth`ese de la propriete pour tous les constituents immediats de lelement composite
(hypoth`ese dinduction) et prouver la propriete pour lelement.

56

Prise en compte des variables


La semantique dune expression qui comprend des variables depend des valeurs de ces variables,
ce quon appelle letat du calcul et quon peut representer comme une fonction des variables vers
les valeurs, soit si Var est la categorie syntaxique des variables et si les valeurs sont des entiers
relatifs, un element de
State = Var Z
Un etat s associe ainsi `
a chaque variable v Var une valeur s v.
Autres representations ?
Substitution
On note s[w 7 n] letat similaire `
a s `a lexception de la variable w liee `a la valeur n :

n if v = w
(s[w 7 n])v =
s v if v =
6 w
D
efinition de la s
emantique des expressions
La fonction semantique qui definit la categorie AExp des expressions arithmetiques :
a ::= n | v | a1 +a2 | a1 -a2 | a1 *a2
prend donc deux arguments, une expression et un etat :
A : AExp (State Z)
Les
equations
A[[n]] s
A[[v]] s
A[[a1 +a2 ]] s
A[[a1 -a2 ]] s
A[[a1 *a2 ]] s

4.3

= N [[n]]
=sv
= A[[a1 ]] s+A[[a2 ]] s
= A[[a1 ]] sA[[a2 ]] s
= A[[a1 ]] sA[[a2 ]] s

La s
emantique des instructions

Syst`
eme de transitions et configurations
Les instructions changent letat. La semantique des instructions est specifiee `a laide dun
syst`eme de transitions portant sur des configurations :
< S, s > indique que linstruction S doit etre executee dans letat s.
s est une configuration terminale (il ny a plus dinstruction `a executer).
S
emantique naturelle
Dans le cas de la semantique operationnelle dite naturelle, on sinteresse `a la relation entre
letat initial et letat final de lexecution dune instruction.
Une transition secrit < S, s > s0
Considerons une categorie syntaxique Stm definie par la syntaxe :
S ::= v:=a | S1 ;S2
La relation est definie par les r`egles :
Assns

Seqns

< v:=a, s > s[v 7 A[[a]]s]

< S1 , s > s0
< S2 , s0 > s00
< S1 ;S2 , s > s00

57

Structure g
en
erale dune r`
egle
La structure generale dune r`egle est
< S1 , s1 > s0 ...
< Sn , sn > s0n
if ...
< S, s > s0
o`
u S1 ... Sn sont des constituents immediats de S (ou sont construits `a partir de ceux-ci).
Une r`egle a un ensemble de premisses (au dessus de la ligne) et une conclusion (en dessous).
Elle peut avoir des conditions dapplication (`a droite de la ligne). Lorsquil ny a pas de premisse,
il sagit dun axiome et la ligne peut ne pas apparatre.

4.4

La s
emantique des fonctions

Impact de lintroduction de fonctions


Lintroduction de fonctions demande `a la base dintroduire des noms de fonction Fname, des
definitions de fonction Func et des appels de fonctions Call.
Pour simplifier, nous allons supposer que les fonctions ne produisent pas deffet de bord. Les
appels de fonction sont donc des expressions. Toutefois :
la semantique dune expression depend non seulement de la valeur de ses variables, mais
encore de la definition des fonctions qui sont utilisees. On definit letat comme une paire
element de Statef Statev avec Statef = Fname Func et Statev = Var Z.
levaluation dun appel de fonction demande `a evaluer le corps de la fonction donc potentiellement des instructions, ce qui conduit `a etendre le syst`eme de transitions aux expressions.
Syntaxe
En supposant que la categorie syntaxique Body des corps de fonction B est definie, la syntaxe
des fonctions et des appels de fonctions est donnee par :
F ::= f (v):=B
c ::= f (a)
avec a ::= c |...
Note : la notation x represente une sequence de x : x1 ... xn .
S
emantique des expressions en pr
esence de fonctions
Il y a maintenant une r`egle par sous-categorie dexpression portant sur une variante , de
pour laquelle letat final est une simple valeur (, peut se lire  sevalue en ) :
Numns

Plusns

< n, s >, N [[n]]

< a1 , (sf , sv ) >, n1


< a2 , (sf , sv ) >, n2
< a1 +a2 , (sf , sv ) >, n1 + n2

S
emantique dun appel de fonction
sf f = f (v):=B
Callns

< ai , (sf , sv ) >, ni


< B, (sf , [vi 7 ni ]) >, n
< f (a), (sf , sv ) >, n

58

Syntaxe et s
emantique dun corps
B ::= S a

Assns

< a, (sf , sv ) >, n


< v:=a, (sf , sv ) > (sf , sv [v 7 n])

Seqns

< S1 , s > s0
< S2 , s0 > s00
< S1 ;S2 , s > s00

Bodyns

< S, s > s0
< a, s0 >, n
< S a, s >, n

Syntaxe et s
emantique dun programme
Soit Prog la categorie syntaxique des programmes P :
P ::= B|F P

Semantique ?

59

Analyse s
emantique

5.1

Introduction

Analyse s
emantique

semantique : Etude
du langage considere du point de vue du sens. Petit Robert
On sort du domaine des grammaires non contextuelles : on sinteresse `a des proprietes contextuelles des constructions du langage qui ne sont pas capturees par des grammaires non contextuelles.
Exemples
Verification de la declaration des variables, de larite des procedures, de la coherence des types...
int i1, i2;
String s1, s2;
double d;
...
i1 = i3;
s1 = i2;
System.out.println(d + i1);

Rappel : analyse syntaxique et analyse s


emantique
Lanalyse syntaxique (couplee `
a lanalyse lexicale) nous permet de dire si une phrase (un
programme) est bien formee (appartient au langage definie par la grammaire).
Comment aller au del`
a, passer de la syntaxe (la forme) `a la semantique (le sens) du programme ?
Lidee (operationnelle) de base est dassocier `a chaque construction une valeur semantique,
calculee, lors de lanalyse syntaxique, `
a laide dune action semantique.
Lexecution de ces actions semantiques realise alors une analyse semantique du programme.
Diff
erents types de valeurs s
emantiques
Les valeurs semantiques correspondent en general `a des proprietes statiques, cest-`a-dire
calculables avant lexecution : arbre syntaxique abstrait associe, type... On parle aussi de
valeurs abstraites.
On peut aussi (pas toujours) directement interpreter le programme. Les valeurs semantiques
se confondent alors avec les valeurs concr`etes.
Exemple de calcul direct
Grammaire definissant des nombres binaires non signes avec calcul de leur valeur `a laide
dactions semantiques :
terminal ZERO, ONE;
non terminal Number, Digit;
Number ::= Digit:d {: RESULT = d; :};
Number ::= Number:n Digit:d {: RESULT = n * 2 + d; :};
Digit ::= ZERO {: RESULT = 0 :};
Digit ::= ONE {: RESULT = 1 :};
On calcule la valeur dun nud en fonction de la valeur de ses fils.

60

Sauf que...
En general, cest plus complique, meme dans le cas dun interpreteur !
Exemple
Considerer un nud representant un appel de methode en Java.
Arbre syntaxique abstrait annot
e
On decoupe le probl`eme :
1. On calcule une premi`ere valeur semantique : un AST.
2. On utilise lAST pour calculer de nouvelles valeurs semantiques qui vont pouvoir prendre
la forme dannotations de lAST (on parle dAST annote), cest-`a-dire de nouveaux champs
qui compl`etent les nuds de larbre (type du nud pour une expression, pointeur sur le
nud correspondant `
a la definition de la methode pour un appel de methode...). Lanalyse
semantique peut etre structuree en differentes passes, sinteressant `a differents types de
valeurs semantiques.

5.2

Gestion des identificateurs

La table des symboles


Traditionnellement, une partie des annotations, celles associees aux identificateurs (en Java :
classes, methodes, nom de champs, variables...) sont stockees dans la table des symboles qui associe
a chaque identificateur, les differentes valeurs semantiques qui lui sont associees.
`
Ces valeurs sont :
definies (ecrites) lorsquon rencontre une declaration, ou definition de lidentificateur ;
utilisees (lues) lorsquon rencontre une utilisation de lidentificateur.
Il est possible dinitialiser la table des symboles lors de lanalyse lexicale. La valeur semantique
associee `
a un identificateur nest plus la chane de caract`eres reconnue comme un identificateur
mais une entree dans la table des symboles (un pointeur). La chane est stockee dans la table.
Complication : les valeurs associees `a un identificateur peuvent dependre de loccurrence de
lidentificateur au sein de lAST.
Validit
e et visibilit
e des identificateurs
Un identificateur est un symbole utilise pour designer une certaine entite : type, classe, variable,
methode...
La declaration dun identificateur est linstruction qui lintroduit comme designation dune
entite.
La definition dun identificateur est linstruction qui lui donne une valeur. On parle de liaison
(binding) entre un identificateur et une valeur.
Les autres occurrences dun identificateur sont ses utilisations.
Un identificateur peut etre declare et pas defini, defini et pas declare, defini et declare et pas
utilise (code mort)...
Espaces de nommage
Les espaces de nommage ou namespaces definissent des contextes dans lesquels le meme identificateur peut etre utilise.
Exemples :
Java a quatre espaces de nommage (champs, methodes, types, paquetages) ;
class Foo {
String foo = "foo";
String foo() { return "foo"; }
}
Scala en a deux (valeurs et types).

61

Port
ee dun identificateur
La portee (scope) dune declaration dun identificateur id est la partie du programme dans
laquelle une definition ou une utilisation de id se rapporte `a cette declaration (on peut aussi
sinteresser `
a la portee dune definition).
Il existe en general des constructions (par exemple des blocs) qui reduisent la portee des identificateurs.
Les langages de programmation autorisent en general plusieurs declarations du meme identificateur pour designer des entites differentes.
Reconnaissance des identificateurs
La reconnaissance des identificateurs est la tache qui consiste `a reperer quelle declaration/definition
sapplique `
a une utilisation donnee.
Il peut en fait y avoir plusieurs declarations qui sappliquent (exemple du polymorphisme
dinclusion en Java).
Un identificateur peut etre cache au sein de sa portee par une nouvelle declaration.
{
int a = 0;
a = a + 1;
{
int a = 0;
a = a + 2;
}
print(a);
}
R`
egles de port
ee
Des r`egles de portee-visibilite peuvent permettre de rendre visible les identificateurs caches.
class
int
}
class
int

A {
a;
B extends A {
a;

... a...
... super.a...
}
Retour sur les d
efinitions (ou d
eclarations) multiples
Il y a deux mani`eres de base pour gerer ce probl`eme :
le faire disparatre en eliminant les definitions multiples par une phase preliminaire de
renommage des identificateurs ;
faire evoluer la table des symboles au cours de lanalyse :
version fonctionnelle : on manipule des tables des symboles locales (des environnements) ;
version imperative : la table reste globale. Les modifications sont gerees `a laide dune
pile.
Renommage des identificateurs
Creer une entree par definition dans la table des symboles. Lastuce consiste `a effectuer une
passe danalyse semantique qui va renommer tous les identificateurs en fonction de leur contexte.
Dans le cas de Java, on va par exemple prealablement, au sein de chaque corps de methode,
numeroter les blocs et renommer la variable id qui apparat dans le bloc i de la methode m de la
classe C : C.m.i.id.
62

D
efinition dun environnement
Une mani`ere classique dexpliciter la semantique (operationnelle) dun langage est decrire un
interpreteur le plus simple possible de ce langage sous une forme fonctionnelle (sans affectation).
Dans ce cas, on utilise des environnements qui correspondent `a une version fonctionnelle de la
deuxi`eme solution. Un environnement est une fonction qui associe une valeur `a un identificateur :
: Identifier V alue
Ajouter une liaison, rend un nouvel environnement qui prend en compte cette nouvelle liaison.
add : Identifier V alue (Identifier V alue) (Identifier V alue)
Exemple
{
int i;
...
j = i + 1;
{
boolean i;
...
t = !i;
}
...
j = i - 1;

= 0 , 0 (i) = int
= 1 , 1 = add(i, boolean, 0 )
= 1 , 1 (i) = boolean

= 0 , 0 (i) = int

Impl
ementation
En programmation fonctionnelle, limplementation est directe :
Exemple (Scala)

def add(id: Identifier, value: Value,


env: Identifier => Value) =
(id2: Identifier) =>
if (id2 == id) value
else env(id2)
On peut aussi utiliser des listes dassociations (des listes de paires clef/valeur) ou des mappes
immutables.
Table des symboles ou environnement global
En programmation imperative, quand on rencontre une nouvelle definition, cette definition
vient ecraser lancienne qui est toutefois enregistree sur une pile.
Quand on quitte la portee de la definition, la pile sert `a reinstaller la definition precedente.

5.3

Les grammaires attribu


ees

Les grammaires attribu


ees
Considerer plusieurs valeurs semantiques simultanement nest pas simple :
il existe differents schemas de calcul des valeurs semantiques ;
les differentes valeurs semantiques peuvent etre dependantes lune de lautre.

63

Les grammaires attribuees (ou grammaires `a attributs) fournissent un cadre conceptuel qui
permet de matriser ces probl`emes et de generer des analyseurs semantiques (on peut penser
disposer `
a terme doutils robustes de generateurs danalyseurs semantiques, voir par exemple
Silver [VWBKG07, Mel07] et JastAdd [EH07, Jas08]).
La notion dattribut correspond directement `a la notion de type de valeur semantique. Cest
une propriete des constructions du langage `a laquelle on donne un nom.
Les grammaires `
a attributs permettent dexprimer les dependances fonctionnelles entre attributs.
Sous certaines conditions sur ces dependances il est possible devaluer les attributs associes `a
un arbre syntaxique correct.
Retour sur lexemple du nombre binaire
r`egle de production
N
N
C
C

C
N1 C
O
1

r`egle semantique
N.val
N.val
C.val
C.val

=
=
=
=

C.val
N1 .val * 2 + C.val
0
1

val est le nom de lattribut considere.


Lindice 1 dans N1 permet de distinguer les 2 occurrences de N.
Un autre exemple
Declaration de types (ex : int a, b, c).
D -> T L

D.type = T.type
D.type = L.type

T -> int
T -> float
L -> L1, id

T.type = entier
T.type = flottant
L.type = L1.type ;
{ajoutTable(id, L.type)}

L -> id

{ajoutTable(id, L.type)}

Attributs synth
etis
es et h
erit
es
La specification peut se lire :
de mani`ere declarative (independamment de toute evaluation) : les egalites sont des egalites
mathematiques. On parle de r`egles semantiques.
de mani`ere operationnelle (on sinteresse `a levaluation des attributs) : les egalites sont des
affectations.
Les attributs du premier exemple sont evalues en commencant par les feuilles : ce sont
des attributs synthetises.
Les attributs du deuxi`eme exemple sont distribues aux feuilles en commencant haut
dans larbre : ce sont des attributs herites.
Un attribut ne peut pas etre `
a la fois synthetise et herite.
M
elange dattributs h
erit
es et synth
etis
es (Silver)
aspect production add
sum::Expr ::= l::Expr r::Expr
{
64

sum.bpp = if wrapInParens(sum.enclosingOpPrecedence, 1,
sum.leftOrRight, "left" )
then "(" ++ l.bpp ++ " + " ++ r.bpp ++ ")"
else l.bpp ++ " + " ++ r.bpp ;
l.enclosingOpPrecedence = 1 ;
r.enclosingOpPrecedence = 1 ;
l.leftOrRight = "left" ;
r.leftOrRight = "right" ;
}
D
efinition dune grammaire attribu
ee
Definition 41. Une grammaire attribuee (attribute grammar)
G est definie par un triplet (G, A, R), o`
u:
G est une grammaire non-contextuelle ;
A un S
ensemble fini dattributs, partitionne en attributs herites et synthetises :
A = XV A(X) avec A(X) = I(X) S(X) tel que I(X) S(X) = , I(X) = si
X T {S} ;
R un ensemble de r`egles semantiques.
D
efinition des r`
egles s
emantiques
Definition 42. Un ensemble fini Rp de r`egles semantiques Xi .a = f (y1 , ..., yk0 ) est associe `a
chaque r`egle de production p P : X0 X1 ...Xn0 avec a A(X) :
Il y a exactement une r`egle pour chaque occurrence dattribut Xi .a avec soit i = 0 et
a S(X0 ) ou i 0 et a I(Xi ) ;
les yj sont des occurrences dattributs Xk .b definis en dehors de la production : soit k = 0
et b I(X0 ) ou k 0 et b S(Xl ).
Flot des attributs
rgle de production A <- B C D

Attributs hrits de A

Attributs synthtiss de
A

rgles
d'valuation
des attributs

Attr. hr.

Attr. syn.

Attr. hr.

65

Attr. syn.

Attr. hr.

Attr. syn.

Principe du calcul des attributs


De mani`ere generale, le calcul peut etre vu comme un calcul dirige par les donnees (data
flow). Une occurrence peut etre calculee si les occurrences dont elle depend ont ete calculees
precedemment.
Ceci requiert que le graphe de dependance soit acyclique. Le determiner est dune complexite
exponentielle en temps.
En pratique, on utilise des caracterisations qui permettent de revenir `a des algorithmes de
complexite polynomiale [WM94].
Caract
erisations simples
Les caracterisations simples sont locales. Il suffit de raisonner sur la forme des r`egles semantiques
pour chaque r`egle de production :
Grammaire S-attribuee : il ny a que des attributs synthetises. Le calcul peut seffectuer
par une traversee postfixe de lAST (ou etre fait au cours dune analyse LR).
Grammaire L-attribuee : il y a en plus des attributs herites. Mais une occurrence Xi>0 .a ne
depend que de symboles plus `
a gauche dans la r`egle de production. Le calcul peut seffectuer
par une traversee prefixe de lAST (ou etre integre `a une analyse LL).
Exercice
Reprendre lexemple de la declaration de type en utilisant un attribut table `a la place dun
effet de bord.
Cet attribut est-il herite ou synthetise ?
Limites des grammaires `
a attributs
Intuitivement, la possibilite de calculer efficacement les attributs sappuie sur labsence de
recursion de la specification (voir par exemple [GBJL00]).
On arrive toutefois assez rapidement (par exemple inference de type en presence de fonctions
recursives) `
a des specifications recursives (qui ont du sens). Il faut alors faire appel `a des techniques plus puissantes (analyse de flots de donnees, inference de type, analyse par contraintes,
interpretation abstraite... [NNH99]).

5.4

Analyse de flots de donn


ees

Analyse de flots de donn


ees
Defs 1 Def Defs 2
Def Var = Exp ;

x = 1;
y = x;
z = x + y;

Defs 1 .in = Def .in


Defs 1 .out = Defs 2 .out
Def .out = Defs 2 .in

66

Analyse en arri`
ere (backward analysis)

Traitement des points de jonction


Conditional if Exp Defs 1 else Defs 2

x = 1;
if (...)
y = x;
else
z = x + y;
Defs 1 .in = Conditional .in
Defs 2 .in = Conditional .in
Conditional .out = ?

Principe
Une analyse de flots de donnees est definie par :
Un graphe de flot de contr
ole (on peut utiliser un arbre de syntaxe abstrait si le flot de
contr
ole est structure : une entree et une sortie par construction).
Un treillis (un ensemble partiellement ordonne dont toute paire delements a une borne
superieure et une borne inferieure) qui represente les valeurs prises par la propriete analysee.
Des fonctions de transfert qui indiquent comment les blocs du graphe de flot de controle
font evoluer la valeur de la propriete.
Une hauteur finie du treillis et des fonctions de transfert monotones garantissent lexistence
dun point fixe.
Exemple : calcul de signe

67

int x = 0;
do {
x++;
} while (...)

68

6
6.1

Gestion de la m
emoire
Lorganisation de la m
emoire

Architecture de Von Neumann


Architecture de Von Neumann (issue de la conception de lEDVAC, 1945, conceptualisee par
le mathematicien John Von Neumann) : une seule memoire stocke le code et les donnees (le code
nest pas essentiellement different des donnees) contrairement `a larchitecture de Harvard (deux
memoires et deux chemins de donnees).
Larchitecture de Harvard modifiee est une architecture intermediaire qui est larchitecture
standard aujourdhui : il y a deux hierarchies de caches et deux chemins de donnees qui permettent :
de paralleliser lacces au code et aux donnees ;
mais la memoire centrale est unique, ce qui permet de traiter le code comme des donnees.
Chemins des donn
ees et du contr
ole

13.2 The Instruction Execution Unit


R

beq,bne

syscall

31

op

25

rs

20

15

rd

10

sh

fn

5 bits

5 bits

5 bits

5 bits

6 bits

Opcode

Source 1
or base

Source 2
or destn

Destination

Unused

Opcode ext

imm
Operand / Offset, 16 bits

Next addr

bltz,jr

jta

jta
Jump target address, 26 bits

j,jal

inst
Instruction, 32 bits

rs,rt,rd

PC

Instr
cache

rt

6 bits

(rs)

12 A/L,
lui,
lw,sw

Reg
file

inst

ALU

22 instructions

Address
Data

Data
cache

(rt)
imm
op fn

Control

Harvard
architecture

Fig. 13.2
Abstract view of the instruction execution unit for MicroMIPS.
For naming of instruction fields, see Fig. 13.1.
Feb. 2011

Computer Architecture, Data Path and Control

Chemins des donn


ees et du contr
ole

69

Slide 8

13.3 A Single-Cycle Data Path


Incr PC

Next addr
jta

Next PC
(PC)

PC

Instr
cache

rs
rt

inst
rd
31
imm
op

0
1
2

Instruction fetch

Register
writeback

(rs)
Ovfl

Reg
file

ALU
(rt)

/
16

ALU
out

Data
addr

Data
cache

Data
out

Data
in

Func

0
32
SE / 1

0
1
2

Register input

fn

RegDst
RegWrite

Br&Jump

Fig. 13.3

ALUOvfl

ALUSrc
ALUFunc

Reg access / decode

ALU operation

DataRead
RegInSrc
DataWrite

Data access

Key elements of the single-cycle MicroMIPS data path.

Feb. 2011

Computer Architecture, Data Path and Control

Slide 9

M
emoire physique, logique et virtuelle
Compilateurs et interpreteurs sont des applications comme les autres et adressent de la memoire
logique :
un tableau doctets ou de mots (32 ou 64 bits) ;
taille est determinee par le nombre de bits disponibles pour ladressage, typiquement 232
octets pour des adresses de 32 bits et un adressage au niveau de loctet.
Le syst`eme dexploitation, aide par le materiel, traduit ces adresses logiques en adresses physiques de la memoire centrale, qui ne sont pas forcement contigues.
En presence de memoire virtuelle, la memoire logique est divisee en pages, des blocs contigus de
taille donnee (au moins 4 ko) qui ne sont pas tous stockes en memoire centrale. La non-disponibilite
dune adresse logique en memoire centrale induit un defaut de page et un rapatriement de la page
correspondante en memoire centrale, au detriment dune autre.
Hi
erarchie m
emoire
registres : 32 bits, 1 ns
cache de premier niveau : 16-64 ko, 5-10 ns
cache de deuxi`eme niveau : 128 ko-4 Mo, 40-60 ns
memoire centrale (memoire physique) : 256 Mo-2 Go, 100-150 ns
disque (memoire virtuelle) : > 2 Go, 3-15 ms
Variable, adresse et pointeur
#include <stdio.h>
int main() {
int i, j, *ip;
ip = &i; // &i est ladresse de la case m
emoire i
i = 22;

70

j = *ip; // *ip est le contenu de la case dadresse ip


printf("i : %i\n", i);
printf("ip : %p\n", (void *) ip);
printf("j : %i\n", j);
}
i : 22
ip : 0x7fff5e5b7b68
j : 22
int main() {
...
*ip = 17;
ip[1] = 18;
printf("i : %i\n", i);
printf("ip[0] : %i\n", ip[0]);
printf("&ip[1] : %p\n", &ip[1]);
}
i : 17
ip[0] : 17
&ip[1] : 0x7fff5e5b7b6c
int main() {
...
int **ipp = &ip;
printf("ipp : %p\n", (void *) ipp);
int k = **ipp;
printf("k : %i\n", k);
}
ipp : 0x7fff56498b58
k : 17
int main() {
int *ip;
ip = NULL;
int i = *ip;
}
Segmentation fault: 11

Organisation de la m
emoire

71

adresses basses
Code

Donnes statiques

Tas (Heap)

Mmoire disponible

Pile (Stack)
adresses hautes

Arbre des appels : Quicksort


public class QuickSort {
private int[] a;
public QuickSort(int[] anArray){ a = anArray; }
public void sort() { sort(0, a.length - 1); }
public void sort(int low, int high) {
if (low >= high) return;
int p = partition(low, high);
sort(low, p);
sort(p + 1, high);
}
private int partition(int low, int high) {
int pivot = ...;
...
return j; // a[j] = pivot
}
}

72

Environnement dappel (x86)


En anglais : stack frame ou activation record.

73

empil par l'appelant

adresses hautes

EBP+12

low

EBP+8

high

EBP+4

return address
saved EBP

EBP-4

EBP (Base/Frame Pointer)

ESP (Stack Pointer)

adresses basses

empil par l'appel

Environnement dappel (x86)


_partition:
; sauvegarde du pointeur denvironnement pr
ec
edent
push ebp
; ebp doit pointer sur lenvironnement courant
mov ebp, esp
; allocatin de lespace pour les variables locales
sub esp, 4
...
; nettoyage des variables locales et
; restauration du pointeur denvironnement pr
ec
edent
leave
;
equivalent `
a
;
mov esp, ebp
;
pop ebp
ret

Utilisation des registres


Une machine moderne a de nombreux registres (typiquement 32) qui vu leur rapidite doivent
etre utilises autant que possible :
Pointeur sur la pile, sur lenvironnement courant.
Adresse de retour (empilee seulement si necessaire).
Arguments (typiquement les 4 ou 6 premiers).
Variables locales (si possible).

74

La sauvegarde des registres peut etre `a la charge de lappelant (caller-saved ) ou de lappele


(callee-saved ).
Exemple du MIPS : les registres 16-23 sont `a la charge de lappele, les autres de lappelant.
Int
er
et de la pile
Une allocation et une recuperation tr`es simple de la memoire.
Sinon, on pourrait tr`es bien sen passer et seulement utiliser le tas !
Probl
ematique de la gestion du tas
Fragmentation due `
a lallocation et la recuperation repetee de petites quantites de memoire
contigue.
Non recuperation de memoire qui nest plus utilisee : fuite de memoire (memory leak ).
Reference vers des donnees effacees : pointeur ballant (dangling pointer ).

6.2

La r
ecup
eration automatique de la m
emoire

La r
ecup
eration automatique de la m
emoire
Cest une idee ancienne (elle est arrivee avec Lisp `a la fin des annees 50).
Elle evite les fuites de memoire, frequente dans le cas dune gestion manuelle.
Elle a cependant un co
ut. De nombreuses approches ont ete proposees offrant divers compromis
vis-`
a-vis de differents param`etres :
performance en temps ;
performance en espace ;
latence ;
localite des donnees.
Pr
erequis : un langage bien typ
e
Une recuperation automatique requiert detre capable de determiner le type de chaque mot
de la memoire et en particulier de savoir si ce mot peut etre utilise comme un pointeur sur une
portion (chunk ) de memoire et la taille de cette portion de memoire.
Ca pose des probl`emes pour des langages comme C et C++.
Les donn
ees accessibles
Les racines de la recuperation sont les donnees directement accessibles par le programme (sans
suivre de pointeur). Recursivement, toute donnee accessible `a travers un pointeur accessible est
aussi accessible.
Lensemble des donnees accessibles change au cours du temps au travers de :
lallocation de nouvelles donnees rend ces nouvelles donnees accessibles ;
une affectation x = y propage laccessibilite en rendant y accessible au travers de x ;
par contre, la valeur precedente de x nest plus accessible au travers de x. Si elle etait
uniquement accessible au travers de x, elle est maintenant inacessible ;
de la meme mani`ere, lors dun appel le passage de param`etres et le retour propage laccessibilite ;
lors dun retour, la recuperation de lenvironnement rend les variables temporaires inaccessibles ainsi que les donnees uniquement accessibles au travers de ces variables.
Trouver les donn
ees inaccessibles
Il y a deux moyens de trouver les donnees inacessibles :
capturer le moment o`
u une donnee passe de letat accessible `a letat inaccessible : ce principe
est utilise dans les recuperateurs par comptage de references ;
tracer reguli`erement `
a partir des racines toutes les donnees accessibles et en deduire les
donnees inaccessibles.

75

Comptage des r
ef
erences
Chaque donnee est munie dun compteur :
initialise `
a lallocation ;
incremente lors de la creation dune nouvelle reference/pointeur ;
decremente lors de la suppression dune reference sur la donnee (ou transitivement sur une
donnee englobante).
Avantage : incrementalite.
Inconvenients : co
ut, gestion des cycles.
Trace
Les donnees accessibles sont tracees `a partir des racines, puis :
Mark-and-sweep : les donnees inaccessibles sont liberees ;
Mark-and-compact : les donnees accessibles sont compactees ;
Mark-and-copy : les donnees accessibles sont copiees dans un tas alternatif (semispace).
Diminuer le temps de latence
Recuperation incrementale : execution et recuperation sont entrelacees.
Recuperation partielle : seule une partie de la memoire est soumis `a la recuperation.
Exemple : recuperation par generation. Le tas est decoupe en generations. Seules les generations
pleines les plus jeunes sont tracees (principe de localite). Les donnees accessibles sont promues.

76

Conclusion

Retour sur la structure g


en
erale dun compilateur
fichiers
source

Saisie du
texte

Optimisation

caractres

code intermdiaire

Analyse
lexicale

Gnration
de code
symbolique

units lexicales
Analyse
syntaxique

code symbolique
code
intermdiaire

Optimisation

AST

code symbolique

Analyse
smantique

Gnration
de code
machine

AST annote

code machine

Gnration
de code
intermdiaire

Gnration
d'un fichier
excutable

fichier
excutable

Analyse
Acquisition du programme : localisation et lecture du texte du programme (en general
plusieurs fichiers) en cooperation avec le syst`eme dexploitation.
Analyseur lexical : traduit le flot de caract`eres dentree en unites lexicales (type et valeur). Idealement genere `
a partir dune description des lex`emes. Expressions et descriptions
reguli`eres, AFND, AFD.
Analyseur syntaxique : traduit le flot de lex`emes en AST (en separant eventuellement la
reconnaissance des constructions syntaxiques et la construction de lAST). Grammaires non
contextuelles, automates `
a pile.
Analyseur semantique : annote lAST. Grammaires attribuees, analyse statique.
Synth`
ese (1)
Partie independante de larchitecture de la machine cible.
Generation de code intermediaire : traduction de constructions specifiques en constructions
plus generales mais plus proche des machines cibles (expressions et instructions de flot de
contr
ole). Exemples :
suppression de toutes les constructions de flot de controle specifiques au profit de tests,
etiquettes et sauts.
ajout de code de lookup `
a un appel de methode.
Fortes variations suivant les paradigmes de programmation (imperatif, fonctionnel, logique,
objet, concurrence et distribution).
Optimisation de code intermediaire : pliage et propagation de constantes, mise en ligne des
appels de procedure (inlining).
Generation de code : traduit le code intermediaire en une liste dinstructions en langage
machine symbolique (allocation de registres).
Alternative : generer du code C.
Synth`
ese (2)
Partie dependante de larchitecture de la machine cible.
Exemple dun compilateur natif :
Optimisation du code cible : en fonction de proprietes specifiques de la machine cible (par
exemple, pipelines, coprocesseurs).

77

Generation de code machine : traduit les instructions en bits, determines les adresses du
code et des donnees et produit des tables de constantes et de relocalisation. Alternative :
utiliser lassembleur.
Generation du programme executable : mise en forme des informations precedentes en
collaboration avec le syst`eme dexploitation pour fabriquer un fichier executable.
Un autre point de vue [GS93]

Figure 1 Vision traditionnelle

Figure 2 Prise en compte de la table des symboles

Figure 3 Vision
Repr
esenter une grammaire en UML
Expression Literal
| Variable
| Expression Op Expression
| ( Expression )

78

moderne 

Expression Literal
| Variable
| BinaryExpression(Op, Expression1 , Expression2 )
| P arenExpression(Expression)

Expression

Literal
int val

Variable
String id

BinaryExpression
Op op
Expression e1
Expression e2

ParenExpression
Expression e

Commentaires divers
On est loin davoir explore les differents types danalyseur. Les analyseurs GLR (Generalized
LR) semblent avoir le vent en poupe. Ils traitent toutes les grammaires non contextuelles
(grammaires ambigues incluses). Voir par exemple SDF [vdBSVV02, SEN07].
Importance (grandissante) de la programmation generative.
Des mondes parall`eles (qui tendent `a se rejoindre) : XML, UML et ingenierie des mod`eles.
Il faudrait aussi parler des syst`emes dexecution avec un sujet majeur : la gestion de la
memoire.
Deux exemples de problematiques actuelles : certification des compilateurs, composition
des langages et donc des grammaires, voire des analyseurs.
Il ny a pas que les compilateurs, il y a aussi les interpreteurs.
Il ny a pas que des langages de programmation. Il y a aussi des langages de representations
de donnees plus ou moins specialises : CSV, HTML, XML, LaTeX, JSON... sans compter
des langages de configuration dedies `a une application donnee.
Les concepts et outils abordes permettent de specifier et analyser ces langages et deffectuer
des traductions de lun `
a lautre.
Nhesitez pas `
a faire appel `
a la  litterature .

Figure 5 Compilers Dragon  [ALSU07]


Figure 4 Modern Compiler
Implementation
in
Java [App98]

Le
Figure 6 Programming Languages - Application and Interpretation [Kri07]

79

Index
, 22, 27
-AFND, 22
-fermeture, 23
epsilon, 16, 18
epsilon-fermeture, 23
editeur de liens, 7
equation semantique, 56
etat, 19, 57
LR(0), 49
final, 19
initial, 19
successeur, 49
abstract syntax tree, voir arbre syntaxique abstrait
action
lexicale, 21
semantique, 39, 54, 60
AFD, voir automate fini deterministe
AFND, voir automate fini non deterministe
Ahead-Of-Time compiler, 13
allocation de registres, 77
alphabet, 18
ambigute, 30
amorcage, 7
analyse, 6
lexicale, 15, 39
semantique, 39, 60
syntaxique, 39
ascendante, 43
descendante, 33
analyse par contraintes, 66
analyseur lexical, 15
analyseur syntaxique
LALR(1), 52
LL(1), 36
LL(k), 36
LR(0), 48
LR(1), 51
SLR, 51
ascendant
deterministe, 45
non deterministe, 45
GLR, 79
annotations, 61
anticipation, 48, 51
ANTLR, 53
arbre syntaxique, 28
abstrait, 39
annote, 61
AST, voir abstract syntax tree

attribut, 39, 64
herite, 64
synthetise, 64
automate
`a 2 piles, 32
`a pile, 46
fini, 19
deterministe, 16, 20
non deterministe, 16, 22
minimisation, 24
axiome, 58
back-end, 6
Backus, John, 14, 29, 32
binding, voir liaison
Bison, 53
bloc, 62
BNF, 29
bootstrap, 7
bytecode, voir pseudo-code
C, 5, 77
calcul dirige par les donnees, 66
calculabilite, 2
caract`ere
echappement, 17
intervalle de caract`eres, 17
categorie syntaxique, 56
chane, 23
Chomsky, Noam, 32
la hierarchie de Chomsky, 31
Church, 2
code
intermediaire, 77
mort, 61
compilateur, 4, 5, 13
`a la volee, 13
certification, 79
dynamique, 13
natif, 7, 77
compilation
dynamique, 7
complexite, 7
composition, 79
concatenation, 18
conditionnelle, 37
configuration, 57
conflit, 46, 50, 53
decalage/reduction, 44, 53
premier/premier, 36
premier/suivant, 36

80

reduction/reduction, 44, 53
gestion de la memoire, 7, 79
resolution, 38, 52
grammaire
suivant/suivant, 36
LALR(1), 48
construction syntaxique, 26
LL(1), 34, 36
context-free grammar, voir grammaire non contexsimplement LL(1), 34
tuelle
LL(k), 33, 36
correction, 4, 5, 7
LR(0), 48
crible, 15
LR(1), 48
CUP, 53
LR(k), 45
SLR(0), 48
debogueur, 7
equivalence de grammaires, 37
decalage, 43, 44
attribuee, 64
derivation, 27, 43
contextuelle, 32
droite, 28, 43
generale, 32
fermeture reflexive-transitive, 28
non contextuelle, 26, 27
gauche, 27, 28
ambigue, 30, 52
infinie, 28
classes de grammaires, 52
relation, 28
non ambigue, 31, 44
data flow, voir calcul dirige par les donnees
reduite, 30
description reguli`ere, 26, 29
grammaire `a attributs, voir grammaire attribuee
DFA, voir AFD
identificateur, 15, 18, 23, 61
EBNF, 29
cache, 62
efficacite, 5, 7
declaration, 61
Eich, Brendan, 13
definition, 61
environnement, 63
liaison, 63
erreur, 4
portee, 62
detection statique, 5, 7
r`egles de portee, 62
recuperation, 38, 45
reconnaissance, 62
de Burke-Fisher, 55
utilisation, 61
globale, 55
induction, 56
locale, 55
inference de types, 66
recursive, 38
interpretation abstraite, 66
traitement, 7
interpreteur, 3, 63
expression arithmetique, 33, 47, 52, 54
correction, 3
expression reguli`ere, 16, 22
item
definition semantique, 19
LR(0), 49
definition syntaxique, 19
LR(1), 51
extension conservatrice, 9
successeurs dun ensemble ditems et dun
symbole, 51
factorisation `
a gauche, 37
fermeture dun ensemble ditems, 50, 51
Java, 5, 62
flex, 25
javac, 5
fonction
JavaScript, 13
monotone, 23
JFlex, 25
semantique, 56
JIT
FORTRAN, 14
tracing, 13
front-end, 6
JIT (Just-In-Time compiler), voir compilateur
`a la volee
generateur
JLex, 17, 25
danalyseur lexical, 16, 25
JVM, 3, 5
danalyseur syntaxique, 48
ascendant, 53
labeled transition system, voir syst`eme de trandescendant, 53
sitions etiquete

81

lambda-calcul, 2
langage
cible, 3, 4
dimplementation, 5
formel, 18
machine, 4
regulier, 19
rationnel, voir langage regulier
reconnu par un AFND, 22
reconnu par un automate, 20
reconnu par une grammaire, 28
source, 3, 4
Turing-complet, 2
langage de pogrammation, 2
lex, 25
lex`eme, 15
type, 15
liaison, 61
linker, voir editeur de liens
liste dassociation, 63
lookahead, voir anticipation
lookup, 77
meta-interpreteur circulaire, 14
machine
abstraite, 3
universelle, 2
virtuelle, 3
machine de Turing, 2, 32
manche, 43
mappe, 63
monode, 18
monode libre, 18
mot, 15, 18
reserve, 15
negation, 17
Naur, Peter, 29
NFA, voir AFND
OCaml, 63
operateur
associativite, 31, 37, 54
priorite, 31, 37, 54
contextuelle, 54
ordinateur, 2
passage a` lechelle, 7
phrase, 18, 27
incompl`ete, 27
point fixe, 34
polymorphisme dinclusion, 62
portee, voir identificateur
portabilite, 7

premisse, 58
programmation generative, 79
programme, 2
Prolog, 45
proprietes contextuelles, 60
statique, 60
protophrase, 43
droite, 43
pseudo-code, 5
reecriture, 27
recursion, 26, 28, 66
elimination de la recursion `a gauche, 37
reduction, 43, 44, 49
r`egle de production, 26, 27
deterministe, 33
r`egle semantique, 64
reciblage, 7
retour arri`ere, 45
runtime, voir syst`eme dexecution
semantique, 2, 3, 56, 60
equation, voir equation semantique
action, voir action semantique
denotationnelle, 3
fonction, voir fonction semantique
naturelle, 57
operationnelle, 3, 57, 63
SableCC, 53
scanner, 15
scope, voir portee
SDF, 79
Silver, 64
successeurs dun ensemble ditems et dun symbole, 50
symbole, 18, 26
de depart, 27
effacable, 34
non terminal, 27
improductif, 30
inaccessible, 30
premier, 34
suite de symboles, 18
suivant, 34, 48, 51
terminal, 27
syntaxe, 2, 26
abstraite, 2, 39
concr`ete, 2, 39
synth`ese, 6
syst`eme dexecution, 7, 79
syst`eme de transitions, 57
etiquete, 19
table danalyse

82

LR(0), 50
LR(1), 51
table de transitions, 16, 21
table des symboles, 15, 61
tableau danalyse, 47
predictive, 36
token, voir unite lexicale
traducteur, 13
Transformation source `
a source, 13
transition, 19
fonction de transition, 19
Turing, 2
UML, 79
unite lexicale, 15
valeur
abstraite, 60
concr`ete, 60
valeur semantique, 15, 39, 60
dependances, 63
dependances fonctionnelles, 64
type, 64
vocabulaire, 18
XML, 79
Yacc, 53

83

R
ef
erences
[ALSU07]

Alfred V. Aho, Monica S. Lam, Ravi Sethi, and Jeffrey D. Ullman. Compilers
Principles, Techniques, and Tools. Addison-Wesley, 2nd edition, 2007.

[App98]

Andrew W. Appel. Modern Compiler Implementation in Java. Cambridge University


Press, 1998.

[BA03]

Elliot Joel Berk and C. Scott Ananian. The JLex web site. http://www.cs.
princeton.edu/~appel/modern/java/JLex/, 2003.
CUP Team at TUM. The CUP web site. http://www2.cs.tum.edu/projects/
cup/, 2007. Initially at http://www.cs.princeton.edu/~appel/modern/java/
CUP/.

[CUP07]

[EH07]

Torbj
orn Ekman and G
orel Hedin. The JastAdd extensible Java compiler. In Richard P. Gabriel, David F. Bacon, Cristina Videira Lopes, and Guy L. Steele, Jr,
editors, OOPSLA 2007, Proceedings of the 22nd Annual ACM SIGPLAN Conference
on Object-Oriented Programming, Systems, Languages, and Applications, pages 1
18. ACM Press, October 2007.

[GBJL00]

Dick Grune, Henri E. Bal, Ceriel J.H. Jacobs, and Koen G. Langendoen. Modern
Compiler Design. Wiley, 2000.

[gcj09]

The
GNU
compiler
for
http://gcc.gnu.org/java/, 2009.

[GS93]

David Garlan and Mary Shaw. Advances in Software Engineering and Knowledge
Engineering, volume I, chapter An Introduction to Software Architecture. World
Scientific Publishing Company, 1993.

[Jas08]

The JastAdd website, 2008. http://jastadd.org.

[JGS93]

N.D. Jones, C.K. Gomard, and P. Sestoft. Partial Evaluation and Automatic Program Generation. International Series in Computer Science. Prentice Hall, 1993.
http://www.dina.kvl.dk/~sestoft/pebook/.

[KCBL00]

I.H. Kazi, H.H. Chen, Stanley B., and D.J. Lilja. Techniques for obtaining high
performance in Java programs. Communications of the ACM, 32(3) :213240, September 2000.

[Kle09]

Gerwin Klein. The JFlex web site. http://jflex.de, 2009. A rewrite of [BA03].

[Kri07]

Shriram Krishnamurthi. Programming Languages - Application and Interpretation. ?, 2007. Available on-line at http://www.cs.brown.edu/~sk/Publications/
Books/ProgLangs/.

[Les75]

M.E. Lesk. Lex - a lexical analyzer generator. Technical report, Bell Laboratories,
Murray Hill, NJ, USA, 1975.

the

Java

programming

language.

[LLV14]

The LLVM compiler infrastructure. http://llvm.org, 2014.

[Mel07]

Melt group at University of Minnesota. The Silver web site. http://www.cs.umn.


edu/melt/silver.html, 2007.

[MHW70]

W.M. McKeeman, J.J. Horning, and D.B. Wortman. A compiler generator. Prentice
Hall, 1970.

[NCM03]

Nathaniel Nystrom, Michael Clarkson, and Andrew Myers. Polyglot : An extensible


compiler framework for Java. In Gorel Hedin, editor, Compiler Construction : 12th
International Conference, CC 2003, number 2622 in Lecture Notes in Computer
Science, pages 138152, Warsaw, Poland, April 2003. Springer-Verlag.

[NNH99]

F. Nielson, H.R. Nielson, and C. Hankin. Principles of Program Analysis. SpringerVerlag, 1999.

[Nov07]

Diego Novillo. GCC internals. Slides, November 2007. http://www.airs.com/


dnovillo/200711-GCC-Internals/200711-GCC-Internals-1-condensed.pdf.
84

[Par12]

Terence Parr. The Definitive ANTLR 4 Reference. The Pragmatic Programmers,


2012.

[Par13a]

Terence Parr. The ANTLR web site. http://www.antlr.org, 2013.

[Par13b]

Terence Parr. The ANTLRv3 web site. http://www.antlr3.org, 2013.

[Pax88]

Vern Paxson. flex fast lexical analyzer generator. Free Software Foundation, 1988.

[PF13]

Terence Parr and Kathleen Fisher. LL(*) : the foundation of the ANTLR parser
generator. In Proceedings of the 2011 ACM SIGPLAN Conference on Programming
Language Design and Implementation (PLDI 11), pages 425436, San Jose, CA,
USA, June 2013. ACM SIGPLAN Notices, 46(6).

[Sab07]

Sable group at McGill University. The SableCC web site. http://sablecc.org,


2007.

[SEN07]

SEN 1 Group, CWI and University of Amsterdam. The SDF web site. http:
//www.program-transformation.org/Sdf/WebHome, 2007.

[vdBSVV02] Mark van den Brand, Jeroen Scheerder, Jurgen J. Vinju, and Eelco Visser. Disambiguation filters for scannerless generalized lr parsers. In R. Nigel Horspool, editor,
Compiler Construction, 11th International Conference, CC 2002, Held as Part of
the Joint European Conferences on Theory and Practice of Software, ETAPS 2002,
Grenoble, France, April 8-12, 2002, Proceedings, volume 2304 of Lecture Notes in
Computer Science, pages 143158. Springer-Verlag, 2002.
[VWBKG07] E. Van Wyk, D. Bodin, L. Krishnan, and J. Gao. Silver : an extensible attribute
grammar system. In Proceedings of LDTA 2007, 7th Workshop on Language Descriptions, Tools, and Analysis, 2007.
[WM94]

R. Wilhelm and D. Maurer. Les compilateurs - theorie, construction, generation.


Masson, 1994.

85