MÉMENTO D'UTILISATION DE FLEX

Ce mémento résume les fonctionnalités essentielles de FLEX et les illustre avec des exemples. Pour des informations plus complètes, plus techniques, ou plus à jour (dernière version), on se reportera au manuel officiel.


Sommaire
0. Récapitulatif des Méta-caractères Flex
1. Reconnaissance par fragments
2. Expressions Régulières
3. Super-Etat, Éléments prédéfinis
4. Lisibilité, Ajout de code

Sommaire


0. Récapitulatif des Méta-caractères Flex

Caractère Nom SectionRemarque
 Space | Tab | Newline2.2non concaténation (terminateur)
"Double Quotes2.1
\Back Slash2.1
|Vertical Bar2.2, 1.5
*Asterisk | star2.4, 2.2
+Plus2.4
?Question mark2.4
.Period2.3
^Carret2.3, 2.5deux interprétations différentes
$Dollar sign2.5
/Slash2.5
Minus | Hyphen2.3uniquement entre []
,Comma2.4uniquement entre {}
( )Parenthesis2.2
[ ]Square Brackets2.3
{ }Curly Braces2.4, 4.1deux interprétations différentes
< >Less|Greater-than Signs3.1

Important : Une source d'erreur fréquente est le simple quote ' qui n'a aucune signification réservée dans Flex, contrairement à Bison. Exemple : '\n' est une chaîne de trois caractères pour Flex alors qu'il sera le caractère de fin de ligne pour Bison.


1. Reconnaissance par fragments

1.1) Actions associées : report ou absorption de fragment, action vide

---- Exemple 1.1 : fragments reconnus et actions 
%%
x+	ECHO;
y+	;
z+
%%
--------------------------------------------------
ENTREE : xxxyyyzzzttt    SORTIE : xxxttt

1.2) Ambiguïté, ordre des règles, longueur reconnue

Si plusieurs expressions régulières peuvent s'appliquer :

----- Exemple 1.2 : ambiguïtés 
%%
[0-9]+		printf("[1:%s]",yytext);
[a-z0-9]+	printf("[2:%s]",yytext);
%%
--------------------------------------------------
ENTREE : 00000 X999    SORTIE : [1:00000] [2:X999]

N.B. : Si on permute les règles dans la spécification, on obtient un message "line 3: warning, rule cannot be matched"

1.3) Délimitation des fragments, variable yytext

Un fragment débute avec la reconnaissance d'une expression régulière

----- Exemple 1.3a : fragments
%%
truc		printf("[%s]",yytext);
machin		printf("[%s]",yytext);
%%
--------------------------------------------------
ENTREE : truczzmachin    SORTIE : [truc]zz[machin]

Un fragment se prolonge jusqu'à la reconnaissance d'un autre fragment ou jusqu'à la fin de l'entrée. Le reconnaisseur est dit "glouton" (greedy) par opposition à d'autres implémentations d'analyseur dites "récalcitrantes" (reluctant)

----- Exemple 1.3b : fragments étendus abusivement !
%%
truc.*		printf("[%s]",yytext);
machin.*	printf("[%s]",yytext);
   /* le point "." signifie tout caractère sauf \n */
%%
------------------------------------------------------
ENTREE : truczzmachin     SORTIE : [truczzmachin]

A cause de l'expression ".*" attrappe-tout, la 1ère règle reconnaît toute l'entrée.

1.4) Utilisation de "règle-balai"

Il peut arriver qu'un fragment se prolonge au delà de ce que l'on veut reconnaître et utiliser. Souvent, il faut donc aussi des règles (avec éventuellement une action vide) pour reconnaître les fragments inutiles, non désirés ou sans intérêt applicatif.
Une réalisation simple consiste à ajouter en fin de spécification une "regle-balai" ou "ramasse-miettes", reconnaissant tout caractère non reconnu par les expressions précédentes. C'est aussi très utile dans la phase de mise au point pour vérifier le bon fonctionnement des autres règles.

------ Exemple 1.4 : visualiser ce qui est hors fragment utile
%%
[0-9]+			printf("[ENTIER=%s]",yytext);
[0-9]+"."([0-9]+)?	printf("[REEL=%s]",yytext);
[A-Za-z0-9]+		printf("[SYMB=%s]",yytext);
.			{ printf("[%c]",yytext[0]); 
%%
-----------------------------------------------------------------
ENTREE : 123 Label1 0.999 XXX
SORTIE : [ENTIER=123][ ][SYMB=Label1][ ][REEL=0.999][ ][SYMB=XXX]

1.5) Action | ou règle multiligne

L'action notée | indique qu'il faut faire l'action de la ligne suivante. On peut aussi le voir comme l'écriture d'une expression régulière sur plusieurs lignes séparées par l'opérateur "OU".

------ Exemple 1.5 : Action |, Expression multiligne
%%
ROUGE|VERT|BLEU printf("COULEUR=%s]",yytext);
rouge    |
vert     |
bleu     printf("couleur=%s]",yytext);
%%

2. Expressions régulières et Méta-caractères Flex

2.1) Échappement : "" et \

Pour supprimer l'interprétation par Flex de certains caractères spéciaux, on dispose de :

---- Exemple 2.1 : échappement
%%
\[\]		    ;  // reconnaît et élimine la chaîne "[]"
"(.)"		    ;  // reconnaît et élimine la chaîne littérale "(.)"
\.\.\.		    ;  // reconnaît et élimine la chaîne littérale "..."
"\r\n"	printf("\n");  // remplacement de CR-LF par LF seul (Windows->Linux)
%%

2.2) Les 3 opérateurs fondamentaux, priorités et parenthèses : |,*, ( )

---- Exemple 2.2 : groupement/alternatives/*
%%
abc*                 ;  /*  ab abc abcc abccc abccc ... */
a(bc)*               ;  /* a abc abcbc abcbcbc  ... */
a(b|c)*              ;  /* a ab ac abb acc abc acb abcbcbcbccc ...*/
veu(x|s|t|lent)      |
vou(dr|l)ai(s|t|ent) ;  /* les conjugaisons de VOULOIR */
%%

2.3) Caractères et Classe de caractères : ., [ ], [^ ], [ - ]

L'alphabet de Flex est par défaut les caractères ASCII 8 bits. L'option %option 7bits permet de réduire l'alphabet de moitié.
N.B. : les caractères accentués isolatin, utf8.. peuvent être sources de problèmes.

Un caractère C dans une expression régulière peut être obtenu par :

Une classe de caractère spécifie un seul caractère choisi parmi un ensemble. on a ainsi :

A l'intérieur d'une classe [...], les seuls caractères réservés sont -,^,\ et ]. Ces caractères peuvent être inclus dans la classe en utilisant l'échappement \ (ou éventuellement en ne mettant pas le '^' en tête, ou le '-' au milieu).

---- Exemple 2.3 : spécifications  de caractères 
%%
[aeiouy]      printf("[V=%s]",yytext);    // une voyelle
[^aeiouy]     printf("[C=%s]",yytext);    // une consonne (~ hum!)
[^A-Za-z]     printf("[NA=%s]",yytext);   // un car. non alphabétique
[A-Fa-f0-9]   printf("[H=%s]",yytext);    // un chiffre hexadécimal
[-^\\\]]      printf("[SPE=%s]",yytext);  // speciaux dans une classe flex
[\^\-\\\]]    printf("[SPE=%s]",yytext);  // idwm
%%

2.4) Répétitions : *, +, ?, {}

Pour une expression r, on a les "Répétitions" de r :

----- Exemple 2.4 : facteurs de répétitions
%%
(ab|cd)?(ef)*      printf("[%s]",yytext); // ab, abef, abefef, cdef, ef ...
[0-9]+\.([0-9]+)?  |
\.[0-9]+           printf("[NB.REEL]");
(AA){1,3}          printf("[2,4,ou 6 As]");
(\n)+              printf("\n");          // élimination de lignes vides
.                  printf("[%s!!!]",yytext); // bien voir le reste
%%

2.5) Spécification de contexte, Calage sur Newline : ^, $, /

dans les différents cas, le contexte (\n ou "suite") n'est pas consommé

----- Exemple 2.5a : supprimer les blancs/tabulations en fin de ligne
%%
[ \t]+$		;
%%

----- Exemple 2.5b : contexte à droite --
%%
^[ \t]+$		     printf("[LIGNE APPAREMMENT VIDE]");
[sS]herlock[ ]+/[hH]olmes    ;  // supprimera le prénom
%%

Nota Bene :


3. Super-Etats et Éléments prédéfinis dans Flex

3.1) Start-conditions ou super-états : <etat>

Flex permet de définir des sortes de "super-états" de l'automate permettant de faire jouer certaines expressions régulières selon certaines préconditions.

----- Exemple 3.1a : reconnaissance selon un contexte a gauche
%s GOT_AUTHOR
%%
[Aa]uthor[ ]*:[ ]*              BEGIN(GOT_AUTHOR);
<GOT_AUTHOR>[A-Z][a-z]+   printf("[Author:%s]",yytext);
.                               BEGIN(INITIAL);
%%
--------------------------------------------------------------
ENTREE : Dupond - Author: Miller - Duschmoll ;
SORTIE : [Author:Miller]

----- Exemple 3.1b : suppression de commentaires en C
%s IN_COMMENTS
%%
"/*"			BEGIN(IN_COMMENTS);
<IN_COMMENTS>"*/"	BEGIN(INITIAL);
<IN_COMMENTS>.		;
%%

3.2) Variables : yytext, yylen, ...

3.3) Macros : ECHO, BEGIN, ...

3.4) Fonctions : yywrap(), ...


4. Lisibilité et Ajout de code

4.1) Définitions régulières ou MACROS-EXPRESSIONS

Il s'agit de noms symboliques utilisables dans la définition des expressions régulières

----- Exemple 4.1a : macros-expressions d'exp. régulières
ENTIER		[0-9]+
SYMBOL		[a-zA-Z][a-zA-Z0-9]+
ITYP		(char|int|long)
TYP		{ITYP}|(float|double)
%%
{ENTIER}	printf("[ENTIER:%s]",yytext);
{SYMBOL}	printf("[SYMBOL:%s]",yytext);
{ENTIER}\.{ENTIER}?	printf("[REEL:%s]",yytext);
%%

4.2 Variables et fonctions C utilisables dans les actions

a) Dans le prologue :

b) Dans l'épilogue :

4.3 Format d'une spécification et Commentaires

On peut utiliser les commentaires dans le style C pour les spécifications. Toutefois sont interdits :

    /*------- Definitions Section ------------*/
%{
/* C-code block */
%}

%s STATE   
/* une start-condition, mais pas de commentaires sur la meme ligne */
DIGIT [0-9]
/* une macro-expression, mais pas de commentaires sur la meme ligne */

%%  /*------- Rules Section ------------*/
    /* !!! des commentaires mais jamais en début de ligne !!! */
<STATE>rule    { /* C-code block */ } /* after code block */
{DIGIT}  /* before code block */  { /* C-code block */ } 
%%  /*------- User Code Section ------------*/
/* C-code block */

CSC 4508, TELECOM SudParis, P Hennequin, F. Meunier
Last modified: Juillet 2015