DIAB
Chaine de Code
caractères (code Analyseur Analyseur Analyseur Générateur
lexical sémantique Assembleur
source, texte …) syntaxique du Code
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.
Description Analyseur
lexicale Flex lexical
Desc_flex.l
Analyseur_L.exe
1
TP Compilation Dr. T. DIAB
Description lexicale en fichier Flex (.l) :
%{
%}
Partie 2 : Définitions régulières
%%
%%
%{
#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 :
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 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)).
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,
int main () Fonction principale contient par défaut juste l’appel à yylex ().
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 :
3
TP Compilation Dr. T. DIAB
"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
[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
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;}