Théorie des langages : Cours lex analyseur lexical
Télécharger PDFAnalyse Lexicale avec Lex
Introduction à Lex
Lex est un utilitaire sous Unix. Son équivalent GNU, fLex, est également disponible. Lex permet de définir des spécifications d'unités lexicales sous forme d'expressions régulières et génère un programme en langage C. Une fois compilé, ce programme reconnaît ces unités lexicales.
La commande Lex fichier.l produit le fichier Lex.yy.c, qui doit être compilé avec gcc Lex.yy.c -l l pour obtenir un exécutable.
Fonctionnement de Lex
Lex lit le texte d'entrée caractère par caractère. Il identifie le plus long préfixe correspondant à une expression régulière. En cas de conflit entre plusieurs règles, Lex privilégie la première règle rencontrée (de haut en bas). Si aucune règle ne correspond, il copie par défaut le caractère en sortie.
Expressions Régulières dans Lex
Lex utilise des expressions régulières composées de caractères normaux et de méta-caractères : $, ^, [ ], { }, < >, +, -, *, /, |, ?.
Voici les principales expressions régulières reconnues par Lex :
c: tout caractèrecqui n'est pas un opérateur ou un méta-caractère.\c: caractère littéralc(lorsquecest un méta-caractère)..: n'importe quel caractère, sauf retour à la ligne (\n).^: l'expression qui suit débute une ligne.$: l'expression qui précède termine une ligne.[s]: n'importe quel caractère de l'ensembles.[abc]: n'importe quel caractère parmia,b,c.[^s]: n'importe quel caractère qui n'est pas danss.r*: 0 ou plusieurs occurrences der.r+: 1 ou plusieurs occurrences der.r?: 0 ou 1 occurrence der.r{m}:moccurrences der.r{m,n}: entremetnoccurrences der.r1 r2:r1suivie der2.r1 | r2:r1our2.r1 / r2:r1si elle est suivie der2.(r):rentre parenthèses.(a | b)?c:aoub(optionnel) suivi dec.<x>r:rsi Lex se trouve dans l'étatx.
Structure d'un Fichier Lex
Un fichier de description pour Lex est organisé en trois sections :
- Déclarations (optionnelle) :
- Commence par
%{et se termine par%}, placés en début de ligne. - Contient des déclarations et définitions en C.
- Est copiée telle quelle dans
Lex.yy.c. - Les définitions et déclarations sont globales au programme produit.
- Productions :
- Contient des expressions régulières et leurs actions associées.
- La partie gauche spécifie les expressions régulières reconnues.
- La partie droite définit les actions exécutées (syntaxe C).
- Si Lex est appelé par Yacc, les attributs doivent être déposés dans
yylvalet l'unité lexicale retournée. - Procédures auxiliaires (optionnelle) :
- Permet de définir des fonctions utilisées dans les actions.
- Peut redéfinir le programme principal (
main()).
Exemple :
%{ int nbVoyelles, nbConsonnes, nbPonct; %}
Exemple :
{ident} { yylval = yytext; return(id); }
{nbre} { yylval = yytext; return(nb); }
Exemple :
int main(int argc, char *argv[]) {
yyin = fopen(argv[1], "r");
yylex();
fclose(yyin);
}
Variables et Fonctions Prédéfinies
Lex fournit plusieurs variables et fonctions prédéfinies :
char yytext[]: tableau contenant la chaîne lexicale reconnue.int yyleng: longueur de la chaîneyytext.int yylex(): lance l'analyseur et appelleyywrap().yylval: retourne la valeur associée à l'unité lexicale.ECHO: affiche la chaîne lexicale reconnue.FILE *yyout: fichier de sortie.FILE *yyin: fichier d'entrée.int yywrap(): appelée en fin de flux d'entrée, retourne0pour continuer ou1pour arrêter.unput(char c): remet le caractère dans le flux d'entrée.int yylineno: numéro de la ligne courante.yymore(): concatèneyytextavec la chaîne précédente.yyless(int k): supprime les(yyleng - k)derniers caractères deyytextet recule le pointeur de lecture.yyterminate(): stoppe l'analyseur.
Exemple Pratique : Insertion du Numéro de Ligne
Voici un exemple qui insère le numéro de ligne dans chaque ligne d'un fichier :
%{
int yylineno;
%}
%%
^(.*)\n printf("%4d\t%s", ++yylineno, yytext);
%%
int main(int argc, char *argv[]) {
yyin = fopen(argv[1], "r");
yylex();
fclose(yyin);
}
FAQ
1. Comment Lex gère-t-il les conflits entre règles ?
Lex privilégie la règle qui produit le plus long lexème. Si plusieurs règles donnent des lexèmes de même longueur, il choisit la première rencontrée.
2. Peut-on omettre les guillemets pour une chaîne de caractères dans les productions ?
Oui, pour une chaîne de lettres et de chiffres, les guillemets peuvent être omis. Par exemple, <= peut s'écrire <= sans guillemets.
3. Que se passe-t-il si aucune règle ne correspond au flux d'entrée ?
Lex utilise par défaut la règle implicite .\n {ECHO}, qui recopie le flux d'entrée sur le flux de sortie.