Techniques de compilation Mme.
Mouna Jarraya
Licence GL2 Année Universitaire 2024/2025
TP 1 – Analyse lexicale
Dans ce premier TP, nous commençons à coder des programmes sous LEX afin de créer un analyseur lexical en
utilisant l’outil Flex.
Flex (Fast LEXical analyzer) est un générateur d’analyseurs lexicaux en langage C.
Pour cela nous allons utiliser :
1- installer le logiciel [Link]
2- ajouter à la variable d’environnement path le chemin vers le dossier bin (« C:\Program Files
(x86)\GnuWin32\bin »)
3-installer le compilateur [Link]
4- Lancer le mingw installation manager et dans Basic Setup, vous devez cochez :
Et dans all packages vous devez cocher mingw32-autoconf et mingw32-libpdcurses :
1
Enfin, vous appuyer sur Installation apply changes apply
5- ajouter à la variable d’environnement path le chemin vers le dossier bin (« C:\MinGW\bin ») et le
chemin vers le dossier msys\1.0\bin (« C:\MinGW\msys\1.0\bin »)
6-lancer la ligne de commande taper les commandes
Gcc gcc: fatal error: no input files
compilation terminated.
flex –version flex version 2.5.4
Description lexicale en fichier Flex (.l) :
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)
Exemple :
%{
#include <stdio.h>
int i ;
2
…
%}
nb [0-9]+
…
%%
[A-Z]+ {printf ("ID");}
("+"|"-"){nb} {printf ("nombre");}
…
…
%%
int yywrap()
{
return 1;
}
int main ()
{
yylex ();
return 0 ;
}
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 yylineno Numéro de la ligne courante
FILE *yyin Fichier d'entrée
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.
3
Exemple :
L'exemple suivant compte le nombre de mot écrit par l’utilisateur.
/*lex program to count number of words*/
%{
#include<stdio.h>
#include<string.h>
int i = 0;
%}
/* Rules Section*/
%%
([a-zA-Z0-9])* {i++;} /* Rule for counting
number of words*/
"\n" {printf("%d\n", i); i = 0;}
%%
int yywrap(){return 1;}
int main()
{
// The function that starts the analysis
yylex();
return 0;
}
Tableau des expressions regulières :
Expression régulière Définition
[^A-Z\n] Tous les caractères sauf un caractère en majuscule ou
un retour en ligne.
[^A-Z] Tous les caractères sauf un caractère en majuscule
[abj-oZ] Correspond au caractère ‘a’, ‘b’, n’importe quels
caractères allant de ‘j’ à ‘o’ ou Z.
[a-z,A-Z] Tous les caractères majuscules et minuscules
[^xy] Tous caractères sauf x et y
[xyz] Soit ‘x’, soit ‘y, soit ‘z’
x Correspond au caractère ‘x’
"s" chaîne de caractères
. n’importe quel caractère, sauf retour à la ligne (\n)
^ l’expression qui suit ce symbole débute une ligne
$ l’expression qui précède ce symbole termine une ligne
Exercice 1:
1- Ecrire le programme Flex suivant permettant de dire si une chaîne en entrée est un nombre binaire ou non :
Ouvrir un nouveau fichier texte et taper le code ci-dessus. Le fichier doit être enregistré avec l’extension .l
(exemple : binaire.l)
%%
(0|1)+ printf ("c'est un nombre binaire");
.* printf ("ce n'est pas un nombre binaire");
%%
int yywrap(){return 1;}
main()
{
yylex();
}
2- A partir de l’invite de commande, accéder au dossier où vous avez créez le fichier binaire.l et lancer la
commande :
flex binaire.l
3- En cas de réussite, le fichier [Link].c est généré dans le même répertoire.
4
4- Compiler le fichier [Link].c avec la commande :
gcc [Link].c
5- En cas de réussite, un fichier nommé [Link] est généré dans le même répertoire.
6- Tester le fichier [Link] obtenu pour vérifier que ça fonctionne correctement.
Exercice 2 :
1- Ecrire et compiler le fichier de spécifications suivant :
pairpair (aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*
%%
{pairpair} printf ("[%s]: nombre pair de a et de b\n", yytext);
a*b* printf ("[%s]: des a d'abord et des b ensuite\n", yytext);
.
%%
int yywrap() {return 1;}
main()
{
yylex();
}
2- Tester les entrées babbaaab abbb aabb baabbbb bbaabbba baabbbbab aaabbbba.
3- Même question en permutant les deux lignes :
a*b* printf("[%s]: des a d'abord et des b ensuite \n",yytext);
(pairpair) printf ("[%s]: nombre pair de a et de b \n",yytext);
4- Y’a-t-il une différence ? laquelle ? pourquoi ?