Vous êtes sur la page 1sur 8

Université Hassiba Benbouali de Chlef 2021/2022

Faculté des sciences 3 ème année Licence


Département d’informatique Module : Compilation

CC : Mme KROLKRAL N.W

TP N°1

Les analyseurs lexicaux

I. Objectif des tps


L'objectif de ces séances de travaux pratiques de compilation est de se familiariser aux
commandes flex et bison. Le premier outil flex construit un analyseur lexical à partir d’un
ensemble de règles/actions décrites par des expressions régulières. Le second outil bison est
un compilateur de compilateur, construit un compilateur d’un langage décrit par un ensemble
de règles et actions d’une grammaire LARL sous une forme proche de la forme BNF.

II. Description de l’outil Flex


Flex (Fast Lexer) est un compilateur pour la génération automatique d’analyseurs lexicaux.
Un fichier Flex est un fichier texte qui contient la description d’un analyseur lexical en termes
d’expressions régulières et d’actions écrites en langage C.
Le compilateur Flex prend en entrée un fichier source Flex et produit en sortie un fichier
contenant le code C (ou C ++) du futur analyseur lexical.
Le fichier C généré est nommé « lex.yy.c ».
Ce dernier doit être compilé à l’aide d’un compilateur C (gcc, par exemple) pour obtenir le
code exécutable de l’analyseur lexical. Un fichier Flex porte l’extension « .lex » ou « .flex »

Figure 1 : Étapes de développement d’un analyseur lexical avec Flex.

Une fois l’analyseur lexical est mis en œuvre, il analyse le fichier source pour chercher les
occurrences d’expressions régulières.
Lorsqu’un mot est reconnu, l’analyseur lexical exécute le code C correspondant à l’expression
régulière qui dénote ce mot.

Procédure :
- On crée le fichier source avec un éditeur de texte.
- On compile le fichier source par : flex scan.flex
- On compile le fichier obtenu "lex.yy.c" par : gcc -o scan lex.yy.c –lfl

III. Format d’un programme Flex


Le contenu d’un fichier Flex comprend 3 sections séparées par une ligne contenant le symbole
« %% » :

Section des définitions


%%
Section des règles
%%
Section du code complémentaire

1. Section des définitions :


- Contient la déclaration des variables et des fonctions globales, des inclusions de
fichiers et des expressions régulières.
- Les inclusions de fichiers et les déclarations des variables et des fonctions globales
sont mises entre les symboles « %{ » et « %} » (chacun sur une seule ligne qui ne doit
pas être indentée).
Exemple :

%{
#include<stdio.h>
#define N 100
int x = 12;
float z = 1.5; // une variable globale
int fct(int, float); // une fonction globale
%}

o Définition d’une expression régulière :


Syntaxe :
Nom Expression_Régulière

- « Nom » : un identificateur qui sert à nommer une expression régulière pour l’avoir
référencer ultérieurement.
- Le nom doit être non indenté.
- Une définition d’une expression régulière doit tenir sur une seule ligne.

Exemple :

2. Section des règles :


- Une règle se présente sous la forme :
Motif Action
o Un motif ne doit pas être indenté et les actions doivent commencer dans la même ligne
que leur motif.

2
o Un motif est une expression régulière qui peut référencer les expressions régulières
définies dans la section des définitions.
o Une action est séparée de son motif par au moins un espace (ou une tabulation).
o L’analyseur lexical déclenche une action autant de fois qu’il trouve un lexème qui
correspond au motif associée à cette action.
o Les règles sont toutes écrites entre les deux symboles « %% ».

Exemple :

3. Section du code complémentaire :


- Sera copiée telle quelle dans le fichier « lex.yy.c ».
- Contient des routines pouvant être appelées par l’analyseur lexical.
- Peut aussi contenir une fonction « main ».
- Section optionnelle : si elle est absente, le second symbole « %% » peut être omis.

Exemple (complet) :

IV. Les motifs

Expression régulière dénotation


x le singleton {x}.

. n’importe quel caractère, sauf le caractère

3
'\n'.

[xyz] {x, y, z}.

[abj-oZ] a, b, j, k, l, m, n, o,Z}

[^A-Z] n’importe quel caractère sauf les lettres


majuscules
r* zéro, une ou plusieurs occurrences de r (r
étant une expression régulière valide).

r+ une ou plusieurs occurrences de r.

r? zéro ou une occurrence de r

r{2, 5} 2, 3, 4 ou 5 occurrences de r

r{2,} 2 ou plusieurs occurrences de r

r{4} exactement 4 occurrences de r

{nom} expansion de la définition « nom ».

\x les caractères ASCII comme \a, \t

\0 le caractère de code ASCII 0 (NULL).

\123 le caractère de code ASCII123.

\x2a le caractère de code ASCII hexadécimal 2a

(r) une seule occurrence de r, les parenthèses sont


utilisées pour fixer la priorité

r|s une seule occurrence de r ou de s

rs une seule occurrence de r, suivie d’une seule


occurrence de s (concaténation)

r/s une seule occurrence de r, et seulement si


cette occurrence est suivie immédiatement par
une seule occurrence de s.

^r une seule occurrence de r, mais uniquement si


cette occurrence se trouve au début d’une
ligne.

r$ une seule occurrence de r, mais uniquement si


cette occurrence se trouve à la fin d’une ligne.

<< EOF >> le caractère de fin de fichier.

V. Fonctionnement des analyseurs Flex

Comment Flex génère un analyseur ?

4
 Le compilateur Flex traduit le fichier de description en un programme source C
comportant une routine « yylex() ».
 La routine « yylex() » active sur l’entrée standard un AFD construit à partir des
expressions régulières et déclenche les actions décrites lorsqu’un lexème est reconnu.
 Flex produit un seul AFD, union des automates correspondant à chacune des
expressions régulières.
 Les états finaux de cet automate indiquent l’action à réaliser.
 Les transitions entre états sont représentées dans une table de transition.
 Cette table est parcourue dans la routine « yylex() » par le code qui anime l’automate.

Algorithme de l’automate Flex :


Ce code est invariable et est généré automatiquement pour la routine « yylex() » :

Situation à l’arrêt de l’automate :


 Si l’automate s’arrête à un état non final, c’est le dernier état final parcouru qui est
sélectionné.
 Lorsque plusieurs expressions peuvent s’appliquer pour analyser le début de la chaîne
d’entrée, les règles suivantes sont appliquées à la construction de l’automate pour
enlever l’ambiguïté entre les règles :
 La règle conduisant à la reconnaissance la plus longue est d’abord choisie.
 À égalité de longueur reconnue, c’est la première règle qui est choisie.
 Si aucun état final n’a été atteint (aucune expression ne reconnaît l’entrée) l’action par
défaut est déclenchée (recopie du caractère d’entrée sur la sortie).
 Pour désactiver l’action par défaut, il suffit de mettre une action vide en utilisant le
point virgule, comme dans le code suivant : [ \t\n] ;
 Ce code ignore simplement tout caractère blanc (espace, tabulation ou saut de ligne).

Boucle sur les unités lexicales :


– Il y a 2 façons pour contrôler cette boucle :

5
 Par défaut, la routine « yylex() » relance l’automate après la terminaison de chaque
action et ne se termine qu’à la fin du fichier d’entrée : la boucle est alors interne à «
yylex() » et les actions du fichier Flex font tout le travail du traitement des unités
lexicales.
 L’autre méthode consiste à forcer la terminaison de « yylex() » pour chaque unité
lexicale reconnue en terminant chaque action par une instruction « return i ; » ou « i »
est une expression de type « int ». Le traitement associé à une unité lexicale peut alors
être complété par l’appelant et la boucle est réalisée par ce dernier.

Les variables yytext et yyleng :


– Une fois un lexème est reconnu, l’analyseur lexical le stocke sous forme d’une chaîne de
caractères dans une variable globale appelée « yytext ».
– La longueur du lexème est également stockée sous forme d’un entier dans une variable
globale appelée « yyleng » (yyleng = strlen(yytext)).
– Il est possible de contrôler la longueur maximale d’un lexème reconnu.

Exemple :
– on peut spécifier la longueur maximale d’un lexème en utilisant la macro-définition
suivante :

Les variables yyin et yyout :


– Ce sont des variables globales de Flex de type « pointeur vers un fichier ». – La variable
yyin pointe vers le fichier d’entrée (fichier source) à analyser.
– Par défaut c’est stdin (yyin = stdin), c’est à-dire que l’analyseur va lire les données à partir
du clavier.
– On peut ouvrir un fichier source par l’instruction : « yyin = fopen(K); ».
– La variable yyout pointe vers le fichier de sortie (fichier cible).
– Par défaut c’est stdout (yyout = stdout), c’est-à-dire que l’analyseur va écrire les résultats
sur l’écran.
– On peut ouvrir un fichier cible par l’instruction : « yyout = fopen(K); ».

VI. Les actions prédéfinies


VII.
1. ECHO
- Copie le contenu de la variable yytext dans la sortie standard de l’analyseur :

2. REJECT
- demande à l’analyseur de poursuivre avec la ”deuxième meilleure” règle qui convenait
à l’entrée (ou un préfixe de l’entrée).
- Le code suivant va compter à la fois le nombre de mots en entrée, et appeler la routine
« My_routine() » à chaque fois que « bon » est rencontré :

6
7
- Sans REJECT, toute occurrence de ”bon” dans l’entrée ne sera pas comptée comme
mot, car l’analyseur n’exécute normalement qu’une action par élément lexical.
- On voit très bien alors que l’action REJECT favorise à un analyseur d’exécuter plus
qu’une action à la fois.

3. | (la barre verticale) :


- Une action consistant uniquement en une barre verticale « | » signifie ”la même chose que
l’action pour la règle suivante”.

4. La routine yymore() :

- Indique à l’analyseur que la prochaine fois qu’il reconnaît une règle, le lexème
correspondant devra être concaténé à la valeur actuelle de yytext au lieu de le remplacer.
- Exemple : pour l’entrée « mega-octets », le code suivant écrira ”mega-mega-octets” :

5. La routine yyless(n) :

-Renvoie tout sauf les « n » premiers caractères du lexème courant dans le flot d’entrée, où ils
seront réexaminés quand l’analyseur recherchera la correspondance suivante.
-Les variables globales yytext et yyleng sont ajustées adéquatement.

6. La routine yyless(n) :

Par exemple, pour l’entrée ”bonjour”, le code suivant écrira ”bonjourjour” :

7. La routine yyterminate() :

Permet d’arrêter l’analyseur lexical en retournant la valeur 0, en indiquant le message ”all


done” (terminé).

Vous aimerez peut-être aussi