COMPILATION
COMPILATION
1 2 3
4 5 6
7 8 9
Exemple de gcc Commandes du projet
4. Environnement de programmation
C Compilation
Passe 1 ([Link] page A-2)
make
C++ Projet est développé en binômes (pour les passes 1 et 2) make clean
arbre
sur ensisun. (à ne pas faire avant chaque compilation !)
Ada abstrait
Organisation des répertoires Vérification des accolades dans un fichier Aflex ou
Java Sur ensisun :
Ayacc
accolades
/usr/local/PCas
Passes 2 et 3
Pentium Extraction des commentaires
PCas
Sparc commentaire
10 11 12
5. Planning II. Passe 1 : analyse lexicale et syntaxique, Dans [Link] se trouve la fonction principale de
construction de l’arbre abstrait l’analyseur lexical, qui permet de lire le lexème
Les programmes sont ramassés automatiquement via suivant :
Git. 1. Aflex
function YYLex return Token ;
Fin de la semaine de stage : terminer la passe 1, a) Introduction
commencer la passe 2. Token est un type énuméré, défini soit par
Passe 1 à rendre le mercredi 15 février 2012, 18h00 Aflex : générateur d’analyseur lexical pour Ada (dans la l’utilisateur, soit par l’outil Ayacc (comme c’est le
lignée de Lex, générateur d’analyseur lexical pour C). cas dans le projet).
15 février - 4 avril : terminer la passe 2. Token contient au minimum les valeurs Error et
Passe 2 à rendre le 4 avril 2012, 18h00. Aflex permet, à partir d’un fichier d’entrée qui décrit la End_Of_Input.
forme d’un ensemble d’unités lexicales, de générer un
analyseur lexical. La fonction YYLex lit des caractères sur l’entrée
Fin du stage de mai : terminer la passe 3. standard, les partitionne en unités lexicales, exécute
Commande : gnaflex fich.l les actions correspondantes et retourne un lexème
correspondant à l’unité lexicale reconnue.
Cette commande produit 5 fichiers :
[Link] : unité Ada correspondant à fich.l Dans fich_dfa.ads, on trouve la fonction
fich_dfa.ads, fich_dfa.adb :
function YYText return String ;
paquetage Fich_DFA
fich_io.ads, fich_io.adb :
qui retourne la chaîne qui vient d’être reconnue.
paquetage Fich_IO.
13 14 15
16 17 18
----------------------------------------------- 2. Mise en oeuvre de l’analyse lexicale
-- Exemple simple d’utilisation de Aflex
Exemple -- Ecrit les commentaires d’un programme Cas
----------------------------------------------- a) Les types de base
":=" { return Affect_Lex ; } Le paquetage Types_Base (page C-2) définit :
"/=" { return Diff_Lex ; } -- Caractères imprimables
CAR_IMP [\040-\176] le type Entier, pour les littéraux entiers qui
Reconnaissance du préfixe le plus long possible -- Commentaires apparaissent dans un programme Cas ;
COMMENT "--"({CAR_IMP}|\t)* le type Reel, pour les littéraux réels qui
Lorsqu’il y a une ambiguïté sur la règle à appliquer, -- Caractères d’une chaîne
comme CHAINE_CAR [\040\041\043-\176] apparaissent dans un programme Cas ;
-- Chaîne de caractères le type Chaine, pour les littéraux chaînes et les
toto { action1 ; } CHAINE \"({CHAINE_CAR}|\"\")*\" identificateurs qui apparaissent dans un programme
tototi { action2 ; } Cas.
%%
19 20 21
22 23 24
Regarder les fichiers [Link] page C-15 et lexico.l Définir Chercher_Dict (qui consulte le dictionnaire,
page C-16. après avoir mis la chaîne de caractères en minuscules).
25 26 27
Le paquetage [Link] 3. Les arbres b) Spécification du paquetage Arbre (page C-8)
contient la fonction a) Syntaxe abstraite ([Link] page B-11) Le paquetage Arbre définit :
function To_Lower(Item : String)
return String ;
Syntaxe abstraite du langage Cas un type énuméré pour les différents noeuds
définit la représentation intermédiaire utilisée par les possibles : Noeud_Affect, Noeud_Chaine,
qui permet de passer une chaîne de caractères en compilateurs (ou interprètes) du langage. Cette syntaxe Noeud_Plus, Noeud_Moins...
minuscules. abstraite est définie par une grammaire d’arbres.
un type Arbre ;
Exercice
Travail à effectuer : compléter lexico.l la constante Arbre_Indef : arbre indéfini.
Donner les arbres abstraits correspondant aux Lorsqu’on construit un arbre, on peut utiliser
Programme de test fourni : test_lex page C-25. programmes Cas suivants : temporairement Arbre_Indef. Lorsqu’on a fini de
construire l’arbre, celui-ci ne doit plus contenir de
program
a : integer ;
valeurs indéfinies.
b, c : boolean ;
begin des constructeurs d’arbres, qui permettent de
a := 1 ; construire des arbres connaissant ces fils. Les
b := a + 1 ;
end ; constructeurs sont préfixés par Creation_.
program Exemples :
t : array[1..10] of array[1..5] of A1 := Creation_Ident(C, Num_Ligne) ;
integer ; A2 := Creation_Entier(4, Num_Ligne) ;
begin A3 := Creation2(Noeud_Plus, A1, A2, N) ;
t[10][5] := 0 ;
end ;
28 29 30
4. Ayacc
des sélecteurs, qui permettent de décomposer un c) Implantation des arbres, «sémantique de partage»
arbre. Les sélecteurs sont préfixés par Acces_. a) Introduction
Un arbre est un pointeur, ce qui implique qu’on a une
Exemples : « sémantique de partage ». Ayacc
Acces_Entier(A2) → 4
Exemple Générateur d’analyseurs syntaxiques pour Ada, dans la
Acces_Fils1(A3) → A1 lignée de Yacc, générateur d’analyseurs syntaxiques
Acces_Fils2(A3) → A2 A, B, C : Arbre ;
A := Creation2(Noeud_Plus,
pour C.
Creation_Entier(1),
des mutateurs, qui permettent de modifier un arbre. Creation_Entier(2)) ; A partir d’une grammaire hors-contexte, accompagnée
Les mutateurs sont préfixés par Changer_. B := A ; d’un ensemble d’actions Ada, Ayacc produit une
Changer_Fils1(B, Creation_Entier(4)) ;
procédure YYParse.
Exemples :
Changer_Fils1(A3, Creation_Entier(3)) ; Acces_Fils1(A) → Noeud_Entier(4)
YYParse réalise l’analyse syntaxique et effectue les
Donc la modification de l’arbre B a modifié l’arbre A.
des décors, qui serviront lors de la passe 2. actions associées aux règles de la grammaire.
L’affectation entre deux arbres est une affectation
des procédures d’affichage. La procédure YYParse utilise
entre pointeurs.
function YYLex return Token ;
procedure Afficher_Arbre C := Creation2(Noeud_Plus,
(A : in Arbre; Niveau : in Natural := 0);
qui peut être soit définie explicitement, soit être
Creation_Entier(4), Creation_Entier(2)) ;
produite par Aflex ;
A = B → true
permet d’afficher un arbre, avec un certain niveau A = C → false procedure YYError(S : String) ;
de détail pour les décors. Si niveau = 0, les décors qui sera appelée chaque fois qu’une erreur de
ne sont pas affichés. syntaxe est détectée.
L’égalité entre deux arbres est une égalité entre
procedure Decompiler pointeurs (et non une égalité structurelle).
(A : in Arbre; Niveau : in Natural := 0);
permet de « décompiler » un arbre abstrait, c’est-à- La plupart des types abstraits utilisés dans le projet sont
dire d’afficher le programme Cas correspondant. implémentés à l’aide de pointeurs. Pour tous ces types,
on a donc une « sémantique de partage ».
31 32 33
On affiche donc :
A -> a
A -> x A y
A -> x A y
34 35 36
La chaîne est reconnue si, après avoir empilé tous les Exemple 2. On peut reconnaître le même langage avec une
caractères et effectué toutes les réductions, la pile ne Soit le langage a b* c, engendré par la grammaire : grammaire récursive à gauche :
contient que l’axiome de la grammaire.
A : ‘a’ B A : B ‘c’
B : ‘b’ B | ‘c’ B : B ‘b’ | ‘a’
Arbre de dérivation
On considère la chaîne d’entrée : a b b b c On reprend la même chaîne d’entrée : a b b b c
A
c B b b b c
x A y b b B a B B B B A
b b b B
b b b b B
a a A Les réductions ont lieu au fur et à mesure des
a a a
x A y empilements.
37 38 39
d) Attributs Dans l’action associée à cette règle, on calcule la valeur Dans syntax_tokens.ads sont définies deux variables
de $$ en fonction des $i: globales :
A chaque terminal et non terminal de la grammaire est YYLVal, YYVal : YYSType ;
program : PROGRAM_Lex liste_decl BEGIN_Lex
associé un attribut synthétisé (c’est-à-dire un attribut liste_inst END_Lex
transmis du fils vers le père dans l’arbre de dérivation). { $$ := (NT, Creation2(Noeud_Programme,
YYLVal correspond à la valeur de l’attribut des
$2.Val_Arbre, terminaux ($i pour les XXX_Lex)
Pour les terminaux, l’attribut est la valeur YYLVal mise à $4.Val_Arbre, YYVal correspond à l’attribut de l’axiome de la
$1.Num_Ligne_Autre)) ; grammaire ($$ de program).
jour dans lexico.l : }
(Lex_Autre, Num_Ligne_Autre)
(Lex_Idf, Num_Ligne_Idf, Val_Idf) idf : IDF_Lex Dans syntax.y, on trouve la procédure principale de
... { $$ := (NT, Creation_Ident($1.Val_Idf, l’analyseur syntaxique :
$1.Num_Ligne_Idf)) ;
Pour les non-terminaux, l’attribut est de la forme : } procedure Analyser_Construire_Arbre
(NT, Val_Arbre). (A : out Arbre) is
const : CONSTENT_Lex begin
{ $$ := (NT, Creation_Entier($1.Val_Entier, YYParse ;
Ces valeurs permettent de construire l’arbre abstrait $1.Num_Ligne_Entier)) ; A := YYVal.Val_Arbre ;
associé au programme. } end ;
40 41 42
III. Passe II : vérifications contextuelles réel, qui correspond à un sous-ensemble de ℝ. Equivalence de types
équivalence structurelle ( équivalence de nom).
booléen, qui correspond à l’ensemble {vrai, faux}
Buts de la passe 2 : On a deux constantes de type booléen : true Exemple :
vérifier qu’un programme Cas est contextuellement (valeur vrai) et false (valeur faux). v1 : array[1..10] of integer ;
correct ; m : array[1..5] of array[1..10] of integer;
enrichir et décorer l’arbre abstrait pour préparer la string. Pas de syntaxe dans le langage Cas. On ne v2 : array[1..10] of integer ;
passe 3. peut donc pas déclarer de variable de type string.
m[1], m[2], ... v1 et v2 sont de même type.
On a uniquement des littéraux de type string
1. Contraintes contextuelles comme dans l’instruction : v1 := v2 ; -- ok
write( ok ) ; m[1] := v1 ; -- ok
Les contraintes contextuelles du langage Cas sont m := v1 ; -- interdit
définies dans [Link] page B-6. tableau
Syntaxe : array[ type_intervalle ] of type
a) Les types du langage Cas Exemples :
array[1..10] of integer
Les types du langage Cas sont les suivants : intervalle array[1..10] of array[1..5] of boolean
d’entiers, réel, booléen, string et tableau.
Grammaire de types du langage Cas
intervalle d’entiers
Exemple : 1..10 représente l’intervalle des entiers EXP_TYPE INTERVALLE
de 1 à 10, noté interval(1,10). | real
max_int est une constante qui représente l’entier | boolean
maximal du langage Cas, de valeur valmax. | string
Le type integer représente | array(INTERVALLE, EXP_TYPE)
interval(-valmax, valmax).
INTERVALLE interval(entier, entier)
43 44 45
L’environnement associe à chaque identificateur une c) Profils de opérateurs
b) Règles de visibilité définition.
integer : type interval(-valmax, valmax)
Les règles de visibilités du langage Cas sont les Au début de l’analyse du programme, l’environnement interval : un type intervalle quelconque interval(a,b).
suivantes : contient uniquement les identificateurs prédéfinis.
On ne peut pas re-déclarer un identificateur déjà not : boolean boolean
déclaré. Environnement prédéfini :
and, or : boolean, boolean boolean
Tout identificateur apparaissant dans un programme
Cas doit être déclaré, sauf les identificateurs boolean (type, boolean) =, <, >, /=, <=, >= : interval, interval boolean
prédéfinis. false (const(faux), boolean) interval, real boolean
Les identificateurs prédéfinis ne peuvent pas être true (const(vrai), boolean) real, interval boolean
redéfinis. integer (type, integer) real, real boolean
max_int (const(valmax), integer)
Les identificateurs d’un programme Cas sont de +, - : interval integer
real (type, real)
différentes natures : real real
identificateurs de constantes (de type intervalle,
booléen, réel ou chaîne) ; +, - , *: interval, interval integer
identificateurs de type ; interval, real real
identificateurs de variable. real, interval real
real, real real
Nature = {const, type, var}.
div, mod : interval, interval integer
Seuls des identificateurs de variables peuvent être / : interval, interval real
déclarés dans un programme Cas. Les seuls interval, real real
identificateurs de constante et de type sont donc des
real, interval real
identificateurs prédéfinis.
real, real real
La nature des identificateurs doit être vérifiée.
[ ] (indexation) array(interval, type) type
46 47 48
55 56 57