Vous êtes sur la page 1sur 6

Introduction

Lex permet de créer automatiquement le code source d’un analyseur lexical à


partir d’un fichier construit par l’utilisateur. Le code source (en c) obtenu peut être
complété par celui d’un analyseur syntaxique construit grâce à YACC. L’utilitaire Lex
lit le fichier lex et construit le fichier lex.yy.c (nom imposé par Lex) qui contient le
code source de l’analyseur.

I- Présentation de Lex
Lex est un langage de spécification d’analyseurs lexicaux.Un programme en lex
définit un ensemble de schema qui sont applicables à un flux textuel. Il prend en
entrée la définition des unités lexicales (expression régulière) ; produit le code source
C d’un AFD minimal permettant de reconnaître les mots du langage spécifié par
l’expression régulière. L’automate construit , défini la fonction yylex(void) qui
constitue l’analyseur lexical. Une modification du langage entraine une regénération
du code de l’analyseur.

I-1. Structure d’un fichier Lex


Les fichiers Lex ont pour extension « .l ». Leur structure est la suivante :

%{
Partie 1 : Déclarations pour le compilateur C
%}
Partie 2 : Définitions régulières
%%
Partie 3 : Règles traduction
%%
Partie 4 : Fonctions C supplémentaires

Explication de la structure du fichier Lex

➔ La partie 1 se compose de déclarations C qui seront simplement recopiées au


debut du fichier produit. Cette partie et les symboles%{ et%} qui l’encadrent
peuvent être omis.
➔ La partie 4 se compose des fonctions C qui seront simplement recopies à la
fin du fichier produit.

➔ Partie 2 : Les définitions régulières


Les définitions régulières sont de la forne identificateur expressionRégulière.
Exemple: lettre [a-zA-Z] ; chiffre [0-9]
Les identificateur définis peuvent être utiliser dans les règles et dans les
définitions suivantes.
Exemple : lettre [a-zA-Z] ; chiffre [0-9] ; alphanum {lettre}|{chiffre}

➔ Partie 3 : Les règles de traduction


Les règles sont sous la forme expressionRégulière {action} où expression
régulière est ecrit au debut de ligne et action est un morceau de code c qui sera
recopiée tel quel au bon endroit dans la fonction yylex. La fonction yylex ()
renvoie 1 chaque fois qu’une expression que vous avez spécifiée se trouve dans
la chaine entrée et 0 lorsque la fin du fichier est rencontrée. Chaque appel à
yylex() analyse un jeton (en supposant un retour) ; lorsque yylex() est appellée
à nouveau, elle reprend où elle s’est arrêtée.

Remarque : La compilation du fichier lex avec l'option -t lui fait écrire sa sortie sur
stdout plutôt que sur lex.yy.c, afin qu'il puisse être redirigé.

I-2- Jargon de Lex


I-3- Avantages et inconvénients de LEX
Avantages
➔ Gain de temps à la conception de l’analyseur lexical
➔ Souplesse et optimisation automatique des flux dans l’analyseur
➔ Avantages du C (La rapidité d’exécution)
Inconvénients
➔ Code source volumineux
➔ Méta-langage difficile à maitriser et parfois peu cohérent

II- Cas pratiques


Cas 1 : Donner sous lex le code permettant de reconnaitre
➢ Un opérateur
➢ Une suite de F
➢ Deux ab ou plus
➢ Des mots de longueurs 3

%{

#include<stdio.h>

%}
%%

[-+*/] {printf("OPERATOR \n");}


[F|f]+ {printf("F/f Suite \n");}
("ab"|"AB"){2,} {printf("At least 2 ab/AB \n");}
.{3} {printf("The word of three length\n");}

.* {printf("ERREUR \n");}

%%

int yywrap(){
return 1  ;
}

int main (void){


yylex();
}
cas 2: Donner sous lex le code permettant de reconnaitre
➢ Un nombre entier et un nombre réel
➢ un identificateur qui commence obligatoirement par une lettre majuscule suivi
d’au moins un caractère alphanumérique.

%{

#include<stdio.h>

%}

chiffre [0-9]
lettre [a-zA-Z]
alpha ({chiffre}|{lettre})+

%%

[-|+]?{chiffre}+ {printf("INTEGER \n");}


[-|+]?{chiffre}+"."{chiffre}+ {printf("REAL \n");}
[A-Z]{alpha} {printf("IDENTIFICATEUR \n");}

.* {printf("ERREUR \n");}

%%

int yywrap(){
return 1;
}

int main (void){


yylex();
}

Cas 3 : Donner sous Lex la spécification permettant de supprimer les espaces
multiples entre les mots dans une phrase, de compte le nombre de «a » dans cette
phrase.

%{ int yywrap(){
return 1;
#include<stdio.h> }
int nbreA = 0  ;
int main (void){
%} yylex();
}
%%

" "{2,}|"\t"+ {printf(" ");}


"a"|"A" {nbreA++;}

%%
Cas 4 : Donner sous Lex la spécification permettant de transfomer toutes les
majuscules dans une phrase en minuscule.

%{

#include <stdio.h>
#include <stdlib.h>
#include<ctype.h>

%}

%%

[A-Z] { printf(tolower(yytext)  ;}

%%

int yywrap()
{
return 1;
}

int main()
{

printf("Enter a text: \n");


yylex();
}

Cas 5 : Ajout d’un numéro à chaque ligne d’un fichier


%{
int yylineno;

%}

%%
^(.*)\n printf("%4d\t%s",++yylineno,yytext);
%%

int yywrap()
{
return 1;
}
int main(int argc,char* argv[])
{
yylineno = 0;
yyin = fopen(argv[1],"r");
yylex();
fclose(yyin);

}
PROCEDURE DE COMPILATION ET EXECUTION DE
L’ANLYSEUR
Pour executer un fichier a l’aide de lex, l’on doit suivre un ensemble d’etapes
qui sont :

➢ Compilation de notre programme lex contenu das le fichier nom_fichier.l


$ lex nom_fichier.l
à l’aide de la commande

qui genère toujours le fichier lex.yy.c qui est l’equivqlence en C de


notre automate.
➢ Compilation du programme C obtenu à l’aide de gcc par exemple.
➢ Execution de l’executable genere par le compilateur

EXEMPLE DE COMPILATION ET EXECUTION D’UN


PROGRAMME LEX CONTENU DANS UN FICHIER NOMME
lineNo.l SOUS WINDOWS

Vous aimerez peut-être aussi