1
Compilation
Traduction
Programme en
langage source
Programme en
langage cible
2
Contenu :
Introduction à la compilation
Analyse Lexicale
Analyse Syntaxique
Traduction dirigée par la syntaxe
Analyse Sémantique
Production de code
Optimisation
Enseignants :
Stéphane Talbot
Miguel Tomasena
Volume horaire : 10.5 C / 12 TD / 12 TP
3
Références :
Compilers : Principles, Techniques and Tools (dragon book).
Alfred V. Aho, Ravi Sethi, Jeffrey. D. Ullman, Addison-Wesley,
2ème édition 2007.
Programming Language processors in Java. D. Watt & D.
Brown, Prentice-Hall, 2000.
Cours de compilation. Luc Maranget. Sur le Web.
JFlex - The Fast Scanner Generator for Java. Sur le Web.
CUP Parser Generator for Java. Sur le Web.
4
Introduction à la
compilation
Termes
Phases d'un compilateur
Importance des grammaires
Méthodes d'analyse
Compilation
5
Termes
Compilateur : programme qui traduit d'un langage source vers un
langage cible, en signalant d‘éventuelles erreurs
La compilation concerne :
Langages informatiques
Architecture de machines
Théorie des langages
Algorithmique
6
Termes
Terminologie :
La Syntaxe régit la forme, la structure d'une phrase. Exemple :
if (3+5 ==9) print ("bravo ")
Deux niveaux syntaxiques peuvent être cités :
Lexique : forme des symboles terminaux (les mots)
Syntaxique : forme d’une suite de terminaux
La Sémantique régit la signification. Exemple d’erreur
sémantique :
if (3 == false) print ("bravo ")
7
Termes
Interpréteur : interpréter c’est parcourir un graphe (structure de
données) dont les nœuds sont les instructions.
Un interprète exécute lui même les instruction du programme.
Les langages interprétés sont souvent plus simples et flexibles que
les langages compilés.
Exemples de langages interprétées : JavaScript, PHP, BASIC,
scheme, CaML, LISP, Perl, Python, Prolog.
8
Termes
Compilateur : Un compilateur est un traducteur qui permet de
transformer un programme écrit dans un langage L1 (source) en
un autre programme écrit dans L2 (cible).
L2 peut être un langage intermédiaire, assembleur ou un langage
d’une machine abstraite.
Exemples de langages compilés : C, C++, ADA, Pascal, Java.
L1 L2
9
Termes
Le P-code concerne à la fois la compilation et l’interprétation
Le code source est traduit (compilé) dans une forme binaire
compacte (pseudo-code ou p-code) qui n'est pas encore du code
machine. Lors de l’exécution le P-code est interprété.
Par exemple en Java le source est compilé pour obtenir un fichier
(.class) "byte code" qui sera interprété par une machine virtuelle.
Les interpréteurs de P-code peuvent être relativement petits et
rapides, le P-code peut s'exécuter presque aussi rapidement que du
binaire.
10
Objectifs d'un Compilateur
Qu’attend-on d’un compilateur ?
La correction : le programme compilé doit représenter le même
calcul que le programme original. Il est équivalent.
L’efficacité : le compilateur doit produire un code qui s’exécutera
aussi rapidement que possible.
11
Objectifs d'un Compilateur
Qu’attend-on d’un compilateur ?
La détection des erreurs. Exemples d'erreurs :
Identificateurs mal formés, commentaires non fermés . . .
Constructions syntaxiques incorrectes
Identificateurs non déclarés
Expressions mal typées : if 3 then "toto" else 4.5
Références non instanciées
Erreurs de Syntaxe. Erreurs détectées à la compilation, de nature
statique.
Erreurs d'exécution. Erreurs détectées à l’exécution, de nature
dynamiques (division par zéro, dépassement des bornes d'un
tableau, etc).
12
L’écriture d’un compilateur est une tâche complexe, le
programmeur a intérêt à utiliser un langage de haut niveau.
Ecriture d'un compilateur : Bootstrap
La plupart des compilateurs sont écrits en langage de haut niveau et
non en assembleur.
Si on ne dispose pas d’un langage de haut niveau, alors la stratégie
de « programme amorce » (bootstrap) peut s’appliquer.
13
Stratégie de bootstrap. Si on veut un compilateur de L, on écrit
d’abord un compilateur pour le sous-ensemble L’ avec
l’assembleur M.
Bootstrap
T-diagramme schématisant un traducteur de L’ vers M réalisé en M :
L’ M
M
Le compilateur ainsi réalisé servira à la construction d’un
compilateur de L.
L M
L’
L’ M
M
L M
M
Résultat
14
Phases d'un compilateur
Compilation
15
Structure d’un compilateur
Analyse lexicale : traduit une suite de caractères en suite de mots,
tokens, ou unités lexicales.
Analyse syntaxique (ou grammaticale) : transforme une suite
d'unités lexicales en un arbre représentant la structure de la
phrase.
Analyse
lexicale
Analyse
syntaxique
Analyse
mantique
Programme en
langage source
Programme en
langage cible
Gestion de
la table des
symboles
Génération
de cod e
Phases d'un compilateur :
Arbre de syntaxe abstraite :
Structure intermédiaire avant l'analyse sémantique .
Représente les dépendances sémantiques.
16
Structure d’un compilateur
Génération de code : transformation l'arbre syntaxique abstrait
enrichi d'informations sémantiques en code machine ou
assembleur.
Choix des instructions à émettre.
Allocation de registres : association entre les idéntifiants et les
registres du processeur.
Optimisation.
Analyse sémantique : analyse l’arbre de syntaxe abstraite pour
calculer de nouvelles informations permettant de :
Rejeter des programmes incorrects (portée, typage. . . )
Préparer la phase de génération de code (organisation de
l’environnement, construction de la table de symboles,
résolution de la surcharge . . . )
17
Phases de compilation, exemple
Analyse lexicale consiste à identifier les tokens ou unités lexicales.
Token Unité lexicale
let mot clé
position identificateur (id1)
= affectation
initial identificateur (id2)
+ addition
vitesse identificateur (id3)
+ produit
60 entier
let p = i + v * 60
Exemple :
18
Phases de compilation, exemple
Table de symboles
Adresse Symbole Informations
id1 p int
id2 i int
id3 v int
… …
Table de symboles. Le compilateur doit garder trace des noms de
variables et les information correspondantes :
mémoire réservée,
type,
portée,
pour les sous-programmes : nombre et type des paramètres,
mode de transmission de chacun, type du résultat.
let p = i + v * 60
19
Analyse syntaxique (parser) vérifie que l’ordre des unités lexicales
correspond au langage (à sa grammaire) et produit un arbre
syntaxique (de dérivation).
Phases de compilation, exemple
let p = i + v * 60
expr
=
let
p
IDENT expr
+
opbin
expr
terme
expr
*
opbin
i
IDENT
expr
terme
v
IDENT
expr
nb
60
expr
LET IDENT '=' expr
20
Arbre de dérivation :vs: arbre abstrait
L’arbre de dérivation produit par l’analyse syntaxique
possède de nombreux nœuds superflus. La grammaire peut
comporter de règles dont le but est de simplifier l’analyse
syntaxique.
Phases de compilation, exemple
Un arbre abstrait constitue une structure plus naturelle entre
l’analyse syntaxique et l’analyse sémantique, il ne garde que
les parties nécessaires.
L’arbre abstrait peut se construire lors de l’analyse
syntaxique, en associant à toute règle de la grammaire une
action sémantique.
Ou bien à partir de l'arbre de dérivation.
21
Arbre abstrait
Phases de compilation, exemple
let p = i + v * 60
p
i
v60
affectation
+
*
Analyse sémantique :
Résolution des noms. Construction d'une table des symboles
en associant des étiquettes aux identifiants.
Vérification de la cohérence de types.
Vérification des initialisations. Certains compilateurs
signalent comme erreur la non-affectation initiale d'une
variable locale.
i, v sont des entiers
précédemment déclarés
Les types sont cohérent
i, v sont déjà
initialisées (déclarés)
22
Génération de code intermédiaire.
Description d'une machine à registres :
8 registres (eax, ebx, ecx, edx, epb, esp, eflags, eip) :
eax, ebx, ecx, edx sont des registres généraux :
ebp et esp servent à gérer la pile (base et sommet de la pile) .
eflags registre d’état.
eip pointeur d’instruction.
Phases de compilation, exemple
Instructions de la forme :
op dest,source
op dest
op
Qqs instructions : add, sub, mul, div, mov, push, pop, jmp, jl, etc.
23
DATA SEGMENT
p DD
i DD
v DD
DATA ENDS
déclaration de données
DATA SEGMENT
p DD
i DD
v DD
DATA ENDS
CODE SEGMENT
...
mov eax,i
push eax
Instructions précédentes.
On mets i dans la pile
DATA SEGMENT
p DD i DD
v DD
DATA ENDS
CODE SEGMENT
...
push eax,i
mov eax,v
push eax
mov eax,60
push eax
pop ebx
pop eax
mul eax,ebx
push eax
multiplication
v60
*
DATA SEGMENT
p DD
i DD
v DD
DATA ENDS
CODE SEGMENT
...
mov eax,i
push eax
mov eax,v
push eax
mov eax,60
push eax
pop ebx
pop eax
mul eax,ebx
push eax
pop ebx
pop eax
add eax, ebx
push eax
pop eax
mov p, eax
CODE ENDS
affectation
let p = i + v * 60
Code généré, exemple :
24
Optimisation. Il existe une grande diversité de types d'optimisation.
Par exemple, dans le code précédent, il est inutile d'empiler pour
dépiler par la suite :
Phases de compilation, exemple
. . .
pop ebx
pop eax
add eax, ebx
push eax
pop eax
mov p, eax
. . .
. . .
pop ebx
pop eax
add eax, ebx
mov p, eax
. . .
25
Préprocesseur. Transformations sur un code source, avant la
compilation. Prise en compte de macros (#define) et des inclusions
de fichiers (#include).
Assembleur. Certain compilateurs produisent du code en langage
d’assembleur. Il faut donc produire du code machine
"translatable".
Chargeur. Le code "translatable" est modifié à absolu et placé en
mémoire aux emplacements appropriés.
Relieur (éditeur des liens). Il permet de constituer un programme
unique à partir de plusieurs fichiers contenant du code
"translatable".
Autre phases de compilation
26
Partie frontale ou d’Analyse.
Phases qui dépendent du langage source : lexicale,
syntaxique.
Partie finale ou de Synthèse.
Phases qui dépendent de la machine cible.
Regroupement de phases
--> On peut être amené a écrire seulement une de ces deux parties.
Partie
frontale
(analyse)
Programme en
langage source
Programme en
langage cible
Partie
finale
(synthèse)
code
intermédiaire
Passes : nombre de lectures du fichier source (une en général).
Compromis entre nombre de passes et la mémoire nécessaire.
27
Importance des grammaires
Compilation
28
Partie frontale d’un compilateur
Traduction dirigée par la syntaxe
Description d’un langage source :
Syntaxe : grammaire non contextuelle.
Sémantique : descriptions plus ou moins formelles ou des
exemples.
Une grammaire non contextuelle permet de :
Spécifier la syntaxe
Guider la traduction : traduction dirigée par la syntaxe.
Très utile pour organiser la partie frontale.
La traduction dirigée par la syntaxe est une combinaison d’un
analyseur syntaxique et d’un générateur de code intermédiaire.
29
Grammaire
L’ensemble de phrases syntaxiquement correctes d’un langage est
décrit par une grammaire.
Expression
suite de
caractères
Analyse
lexicale
suite
d’unités
lexicales
Traduction
dirigée par
la syntaxe
Représentation
intermédiaire
Une grammaire est un quadruplet G = (VT,VN, S0, P) où
VT est l’ensemble de symboles terminaux (unités lexicales),
VN est l’ensemble de symboles non terminaux,
S0 VN est l’axiome ou symbole de départ,
P est l’ensemble de productions (règles de grammaire) de la
forme


30
Grammaire
Une phrase générée par la grammaire G est obtenue en partant du
symbole initial et en appliquant des productions P jusqu'à
l'obtention des terminaux.
Le langage L(G) est l’ensemble de toutes les phrases que l’on peut
générer avec G. Formellement, on écrit :
L(G) = { w
Vt* | S0 w }
*
Exemple
VT = {il, elle, est, boit, vite, beau}
VN = {<pronom>, <verbe>, <adj>, <phrase>}
S0 = <phrase>
P = { <phrase> <pronom> <verbe> <adj> ,
<pronom> il | elle ,
<verbe> est | boit ,
<adj> vite | beau } Rmq : certaines phrases
n’ont pas de sens (il boit beau)
1 / 9 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !