Vous êtes sur la page 1sur 5

TP Compilation Dr. T.

DIAB

Compilation d’un programme (texte, chaine de caractères…) :

Compilateur (C, C++ …)

Chaine de Code
caractères (code Analyseur Analyseur Analyseur Générateur
lexical sémantique Assembleur
source, texte …) syntaxique du Code

(1) (2) (3) (4)

1. Analyse lexicale :

Analyseur lexical
Chaine de (Reconnait les mots)
caractères (code 1- Eliminer les caractères Unité_lexicale_1 Unité_lexicale_2 …
source, texte …) superflus (espaces,
commentaires)
2- Identifier les unités
lexicales.

 Générer l’analyseur lexical en utilisant l’outil Flex :

Flex : Fast LEXical analyzer


- Générateur d'analyseurs lexicaux en C,
- Version GNU de Lex.
- Lex (LEXical analyser):
- Utilitaire d’UNIX.
- Années 1970, laboratoires Bell,

Description Analyseur
lexicale Flex lexical

Desc_flex.l
Analyseur_L.exe

Description Programme Analyseur


Compilateur en C Compilateur
lexicale Flex C lexical
lex.yy.c
Desc_flex.l
Flex Analyseur_L.exe

1
TP Compilation Dr. T. DIAB
Description lexicale en fichier Flex (.l) :

%{

Partie 1 : Déclaration des variables, constantes, includes … (en C)

%}
Partie 2 : Définitions régulières

%%

Partie 3 : Règles de traduction (Colonne droite en C)

%%

Partie 4 : Bloc principal (fonction main) et fonctions auxiliaires (en C)


Fichier_flex.l

%{
#include <stdio.h>
int i ; // Partie 1 : Déclaration des variables, constantes, includes … (en C)

%}
nb [0-9]+
// Partie 2 : Définitions régulières

%%
[A-Z]+ {printf ("ID");} // Partie 3 : Règles de traduction
("+"|"-"){nb} {printf ("nombre");}
… (Colonne droite en C)

%%
int yywrap()
{
return 1; // Partie 4 : Bloc principal (fonction main)
}
int main () et fonctions auxiliaires (en C)
{
yylex ();
return 0 ;
}

Fichier_flex.l

2
TP Compilation Dr. T. DIAB
Variables et fonctions prédéfinies :

Variable/ fonction Signification

char yytext [] Tableau de caractères qui contient la chaine de caractères entrée par l’utilisateur et acceptée
par une expression régulière.

Le contenu de ce tableau peut être récupéré devant chaque expression régulière → Ce tableau
va contenir la chaine de caractère acceptée par cette expression régulière.

int yyleng Variable contient la longueur de ce tableau (yytext).

int yylex () Fonction qui lance l’analyseur lexical (et appelle la fonction yywrap () à la fin du fichier
d’entrée).

int yywrap () Fonction appelée à la fin du fichier d’entrée (le fichier qui contient la chaine de caractères (le
programme qu’on veut analyser lexicalement). Dans le TP, nous n’avons pas utilisé ce
fichier, nous avons utilisé l’entrée standard sdtin (taper les caractères avec le clavier)).

yywrap () peut retourner deux valeurs :

1 : Si on veut utiliser l’entrée standard stdin (si on n’a pas de fichier d’entrée), ou si on
veut analyser un seul ficher d’entrée,

0 : Si on veut analyser plusieurs fichiers d’entrée.

int main () Fonction principale contient par défaut juste l’appel à yylex ().

yyterminate () Fonction qui stoppe l’analyseur lexical.

Remarques :
- L’analyseur lexical obtenu lit le texte d’entrée caractère par caractère jusqu’à ce qu’il trouve la plus longue
chaine de caractères du texte d’entrée qui corresponde à l’une des expressions régulières :
• Si plusieurs règles sont possibles => la première règle de ces règles (de haut en bas) est exécutée.
• Si aucune règle ne peut être sélectionnée => copier le caractère lu en entrée vers la sortie (l’écran).
- Les expressions régulières doivent commencer en colonne 0.
- Les actions sont des blocs d’instructions en C (si plusieurs instructions, elles doivent être entre {}) doivent
commencer en colonne 1 et sur la même ligne que l’expression correspondante.
Cas exceptionnels :

Exemple Flex Chaine de caractères Résultat Commentaires


entrée
\< {printf (“Meta_c”);} < Meta_c Le caractère \ est utilisé pour :
- Afficher les métacaractères
\n {printf (“Entrer”);} (Cliquer sur Entrer) Entrer littéralement,
- Exécuter la signification de certains
\H {printf (“Maj”);} H Maj caractères (\n, \t…),
- Peut être utilisé pour afficher des
\5 {printf (“Chiffre”);} Chiffre chiffres et majuscules.
5

3
TP Compilation Dr. T. DIAB

ab(puis tapez Entrer)


ab\nc {printf (“id”);} id id est affichée après le deuxième Entrer
(puis tapez c)c
Entrer la chaine de caractères qu’elle est entre ""
"abc*+" {printf (“id”);} abc*+ id littéralement (sauf le caractère \)
"abc*+\\" {printf (“id”);} abc*+\ id Pour afficher \, écrire \\

"abc*+\n" {printf (“id”);} Abc*+(puis taper Entrer) id A l’intérieur des "", le caractère \ voit le caractère
qui suit pour exécuter sa signification :
"ab\tc*+" {printf (“id”);} ab c*+(ab puis tabulation id \n => Entrer
puis c*+) \t => tabulation

"ab\Ac*+" {printf (“id”);} abAc*+ id A l’intérieur des "", si après le caractère \ un


majuscule, chiffre, symbole (autre qu’un
"ab\6c*+" {printf (“id”);} ab6c*+ id minuscule) => affiche ce caractère littéralement

"ab\-c*+" {printf (“id”);} ab-c*+ id


A l’intérieur des [], un seul caractère est
[dgh+*] {printf (“id”);} d (ou) g (ou) h (ou) + (ou) * id concerné (sauf \ et -)

[d\nf\t\Si\8] {printf d (ou) Entrer (ou) f (ou) id A l’intérieur des [], le caractère \ voit le caractère
(“id”);} qui suit pour exécuter sa signification
tabulation (ou) S (ou) i (ou) 8

a (ou n’importe quel caractère id Si le caractère – est au milieu des caractères


[ah-n*+] {printf (“id”);} entre h et n) (ou) * (ou) + entre [] => il signifie l’ensemble des caractères
entre le caractère à gauche et celui à droite
[ah*+-] {printf (“id”);} a (ou) h (ou) * (ou) + (ou) – id Si le caractère – est au début ou à la fin => il
signifie le – littéralement
[-ah*+] {printf (“id”);} - (ou) a (ou) h (ou) * (ou) + id
A l’intérieur des [], le caractère | (ou) devient un
[ah|k] {printf (“id”);} a (ou) h (ou) | (ou) k id caractère normal
%%
abab IdErrErr ^ signifie le début de la ligne (première ab)
^ab {printf (“Id”);}
. {printf (“Err”);}
%%
ab(au début) …
^ab|xy {printf (“id”);} id … ^ab|xy égale à ^(ab|xy)
(ou)
xy(au début) …

a^b {printf (“id”);} a^b id Si ^ n’est pas au début de l’expression =>


devient caractère normal
(^ab) {printf (“id”);} ^ab id
%%
abab ErrErrId $ signifie la fin de la ligne (dernière ab)
ab$ {printf (“Id”);}
. {printf (“Err”);}
%%
a$b {printf (“id”);} a$b id Si $ n’est pas à la fin de l’expression => devient
caractère normal
(ab$) ab$ id
*, + et ? concerne le dernier caractère à gauche
machine* {printf (“id”);} machin (ou) machineee … id (machin(e*))

4
TP Compilation Dr. T. DIAB
3 occurrences du dernier caractère à gauche
machine{3} {printf (“id”);} machineee id machin(e{3})
%%
abj Id1Id2 ab est suivie par j donc => exécuter l’action de
ab/j {printf (“Id1”);}
ab puis l’action de j
j {printf (“Id2”);}
%%
(ab/j) (Erreur) (Erreur) Ne pas mettre le caractère / entre ()
%{
(Erreur) (Erreur) Ne pas mettre le caractère / dans les définitions
%}
régulières
ident ab/j
%%
%{
(Erreur) (Erreur) Ne pas mettre le caractère ^ dans les définitions
%}
régulières
ident ^ab
%%
%{
(Erreur) (Erreur) Ne pas mettre le caractère $ dans les définitions
%}
régulières
ident ab$
%%
%%
prog id L’analyseur lexical choisit la première
“prog“ {printf (“id”);}
expression régulière la plus longue qui
[a-z]+ {printf correspond la chaine de caractère entrée
(“identificateur”);}
programme identificateur “prog“ contient prog et elle est en premier =>
%% id
“prog“ ne contient pas programme mais
[a-z]+ le contient => identificateur
%%
prog identificateur [a-z]+ contient prog et programme et elle est
[a-z]+ {printf
en premier => identificateur
(“identificateur”);}
“prog“ {printf (“id”);}
programme identificateur
%%
[a-z]+ {printf (“%s”,
abc abc printf (“%s”, yytext); et ECHO; sont les
yytext);}
mêmes
(ou)
abc abc
[a-z]+ {ECHO;}

Vous aimerez peut-être aussi