"ExoFlex" : Exercices d'utilisation de Flex seul (Corrigé)



0. Sommaire
1. Premiers Pas
2. Commentaires en C
3. Pause littéraire
4. Recherche dico.
5. RegExp. sur {a,b}*
6. Filtres
7. Traduction de SVG
8. Pot Pourri

0. Sommaire et Objectifs

  1. Premiers Pas : Analyse lexicale pour un langage informatique

    Utilisation simple de flex, Notions d'unité et et de catégorie lexicale, règle-balai, echo()

  2. Commentaires en C

    Expressions régulières non triviales, Utilisation de variables, Utilisation de "start-condition".

  3. Pause littéraire

    Règle-balai et priorité des règles, Action nulle, Classe de caractères et accents, Utilisation de variables et yywrap(), "Notion" de mot

  4. Recherche dans un dictionnaire

    Expressions régulières et gestion des lignes (\n),

  5. Expressions régulières sur {a,b}* , Négation d'expressions régulières

    Expressions régulières non triviales, Point de vue théorie des langages.

  6. Filtres

    Gestion de lignes, Ordre des règles, Utilisation de variables, transformation (traduction lexicale) à la volée.

  7. Traduction de SVG

    Exemple complet issu d'un TP Noté

  8. Pot Pourri

    Des suggestions en vrac, et sans corrections.


1. Premiers Pas : Analyse lexicale pour un langage informatique

1.1) Reconnaissance d'identificateurs

La spécification Flex suivante reconnaît des mots commençant par une lettre, puis pouvant comporter plusieurs lettres ou chiffres :

------ first00.flex 
%%
[a-zA-Z][a-zA-Z0-9]*   printf("[ %s ]", yytext );
%%

Pour tester, on utilisera l'exemple de texte source suivant :

------ first.data
for( i=0; i < 10; i++ ) {
	  truc[i] = 0;
  	  machin  = 12.3;
  	  bidule  = .0;
	}

a) Compilation manuelle

Construisez et testez cet analyseur lexical :

>  flex first00.flex
>  gcc lex.yy.c -ll
>  ./a.out < first.data

Expliquez le résultat.

Variante : Si la librairie libl.a (-ll) n'existe pas, modifier first00.flex sous la forme :

------ first00-bis.flex 
%%
[a-zA-Z][a-zA-Z0-9]*   printf("[ %s ]", yytext );
%%
int yywrap(void) { return 1; }
int main(int argc, char *argv[]) { while (yylex()!=0) ; return 0; } 

Corrigé :

------ resultat
[ for ]( [ i ]=0; [ i ] < 10; [ i ]++ ) {
  [ truc ][[ i ]] = 0;
  [ machin ]  = 12.3;
  [ bidule ]  = .0;
}

Tout est imprimé, car par défaut ce qui n'est pas reconnu est reporté en sortie. Par contre, on différencie les fragments reconnus en les marquant entre crochets [ ]

b) Makefile générique du cours et prototypes de spécifications

On recommande l'utilisation de la commande make avec un fichier Makefile générique et on se donne les fichiers suivants comme base pour l'ensemble des exercices :

Fichiers Prototypes :

On suppose alors que :

Quelques recommandations génériques pour les exercices :

Adaptez la spécification précédente "first00.flex" au Makefile générique et testez

Corrigé : first0.flex

1.2) Analyse lexicale

a) Modifiez et complétez la spécification pour que l'analyseur reconnaisse les unités lexicales suivantes :

L'affichage distinguera les différentes catégories lexicales. Pour cela, définissez une fonction echo() dans la spécification flex qui affichera pour chaque fragment reconnu, sa catégorie et le contenu du fragment. i.e "[KeyWord:if][Sep:(]..."

Corrigé : first1.flex

Notez la gestion des caractères spéciaux ou méta-caractères flex

b) Complétez l'analyseur précédent :

Le fichier de test "first.data" est disponible en 3 versions, Unix first.data, DOS first.data_DOS ou MAC first.data_MAC. Quelle est la différence? Rendez l'analyseur compatible avec ces 3 versions.

Corrigé : first2.flex

N.B.: Unix utilise '\n' pour la fin de ligne, Mac utilise '\r' et DOS/Windows utilise "\r\n" !!!


2. Commentaires en C

Le but est d'écrire un analyseur lexical permettant de reconnaître et de supprimer les commentaires C du type /*... */.

2.1) Traitement d'un commentaire sur une ou plusieurs lignes

Écrivez une expression régulière pour repérer un commentaire C. Pour la mise au point, faites d'abord un analyseur qui affiche uniquement le contenu du commentaire. Ensuite, supprimez l'affichage des commentaires et rétablissez l'affichage du texte hors commentaire.

Testez sur les 2 exemples suivants

------ comment.data1 commentaire mono-ligne
i = 5; /* initialisation au nombre d'objets */

------ comment.data2 commentaire multiligne
void mafonction() {
/* ici
je dois écrire le corps de ma fonction
mais pour l'instant elle est vide
*/
}

Corrigé : comment1.flex

N.B. : ne fonctionne pas pour des commentaires successifs, cf. question suivante

2.2) Gestion de commentaires successifs

Le caractère "glouton" de flex conduit, si l'on utilise une expression régulière trop simple, à ce que l'analyseur agrège les commentaires successifs en un seul mega commentaires.

Écrivez un analyseur lexical capable de traiter les commentaires successifs avec chacune des stratégies suivantes :

  1. En utilisant une expression régulière plus complexe et insensible à l'effet glouton.
  2. En utilisant une variable comptant le niveau d'imbrication de commentaire.
  3. En utilisant les "start-conditions" et en ajoutant un super état COMMENT à l'automate de flex.
------ comment.data3 commentaire multiligne
i = 5; /* initialisation (*)
          au nombre d'objets en i*/
j = 6; /* initialisation (**)
          au nombre d'objets en j*/

Corrigé

  1. Expression régulière : comment2-er.flex
  2. Variable level : comment2-compteur.flex (N.B. : En réalité, incorrect pour les commentaires imbriqués de la question suivante)
  3. Start Condition : comment2-startcond.flex

2.3) Gestion de commentaires imbriqués (avancé)

ATTENTION:

Écrivez un analyseur capable de traiter des commentaires imbriqués et repérant le niveau d'imbrication des commentaires. On utilisera pour cela une "start-condition" COMMENT et une variable level comme initié dans la question précédente.
Pour la visualisation du résultat, on pourra utiliser la fonction SET_COLOR(i) dans l'include "proto-color.h" pour afficher d'une couleur différente chaque niveau de commentaire.

------ comment.data4 commentaires imbriqués
void mafonction2 (){
 /*
  int i;
  int j;

  i = 3;  /* cette valeur est nickel */
  j = 5; /* cette valeur 
      	    	  /* 3eme niveau 
		     /* 4eme  */    
		  */
	est a revoir */

  printf("afficher i\n");
  printf("au revoir\n");
 */
}

Corrigé : comment3.flex


3. Pause littéraire

Voilà quelques extraits de texte issus de l'Oulipo: Ouvroir de Littérature Potentielle. Pour chacun, écrire l'analyseur lexical correspondant.

3.1) Lipogramme sans e

Écrire un analyseur affichant les 'e' contenus dans le texte (utilisation de la règle-balai).

Extrait de "La Disparition" de Georges Perec :

------ lipo1.data
« Là où nous vivions jadis, il n'y avait ni autos, ni taxis, ni
autobus : nous allions parfois, mon cousin m'accompagnait, voir
Linda qui habitait dans un canton voisin. Mais, n'ayant pas
d'autos, il nous fallait courir tout au long du parcours; sinon
nous arrivions trop tard : Linda avait disparu.  Un jour vint
pourtant où Linda partit pour toujours. Nous aurions dû la bannir
à jamais ; mais voilà, nous l'aimions. Nous aimions tant son
parfum, son air rayonnant, son blouson, son pantalon brun trop
long ; nous aimions tout.  Mais voilà tout finit : trois ans plus
tard, Linda mourut; nous l'avions appris par hasard, un soir, au
cours d'un lunch. »

Corrigé :

------ lipo1.flex
%option nounput noinput
%%
e	ECHO;
[ \n\t]
.
%%
int yywrap(void) { return 1; }
int main(void) { while (yylex()!=0) ; return 0; }

3.2) Asphyxie ou lipossible

En asphyxiant un texte, c'est à dire en le privant de R, on obtient un autre texte qui est dit anaérobie du premier. Écrire un analyseur supprimant les 'r'.

------ lipo2.data
cette rosse amorale a fait crouler le parterre

Corrigé :

------ lipo2.flex
%option nounput noinput
%%
r	
[ \n\t] ECHO;
.       ECHO;
%%
int yywrap(void) { return 1; }
int main(void) { while (yylex()!=0) ; return 0; }

3.3) Variante sans haine

Écrivez un analyseur supprimant les 'n'.

------ lipo3.data
Le chant anime les nombres

Corrigé :

------ lipo3.flex
%option nounput noinput
%%
n	
[ \n\t] ECHO;
.       ECHO;
%%
int yywrap(void) { return 1; }
int main(int argc, char *argv[]) { while (yylex()!=0) ; return 0;} 

3.4) Abécédaire

Écrire un analyseur affichant la première lettre de chaque mot.

------ lipo4.data(accents iso-latin1)
A brader : cinq danseuses en froufrou (grassouillettes), huit ingénues
(joueuses) kleptomanes le matin, neuf (onze peut-être) quadragénaires
rabougries, six travailleuses, une valeureuse walkyrie, x yuppies
(zélées).

Remarques :

On pourra définir lexicalement un mot :

Pour cet exercice, utilisez la seconde stratégie. Dans l'exercice suivant vous pourrez essayer le première approche.

Corrigé : lipo4.flex

3.5) Tautogramme (texte dont les mots commencent par la même lettre)

Écrivez un analyseur comptant simultanément :

N.B. : cf. remarques de l'exercice précèdent sur la notion de mot.

------ lipo5.data (accents iso-latin15)
Voilà ! Vois en moi l'image d'un humble vétéran de vaudeville,
distribué vicieusement dans les rôles de victime et de vilain
par les vicissitudes de la vie. Ce visage, bien plus qu'un vil
vernis de vanité, est un vestige de la vox populi aujourd'hui
vacante, évanouie. Cependant, cette vaillante visite d'une
vexation passée se retrouve vivifiée et a fait v½u de
vaincre cette vénale et virulente vermine vantant le vice et
versant dans la vicieusement violente et vorace violation de
la volition. Un seul verdict : la vengeance. Une vendetta
telle une offrande votive mais pas en vain car sa valeur et sa
véracité viendront un jour faire valoir le vigilant et le
vertueux. En vérité ce velouté de verbiage vire vraiment au
verbeux, alors laisse-moi simplement ajouter que c'est un
véritable honneur que de te rencontrer. Appelle-moi V.

Discours prononcé par V dans le film "V pour Vendetta" (Traduction française par Féodor Atkin):

Résultat attendu : en comptant les 2 apostrophes et les 6 trait d'union comme séparateur de mots, on devrait obtenir 145 mots, 52 commençant par v, 23 ponctuations et 14 lignes. Comparez avec le résultat de la commande wc.

Corrigé : lipo5.flex

A titre d'illustration de l'usage du main() et de yywrap(), une version modifiée de l'analyseur qui accepte en argument de commande une liste de fichier (> lipo5-multi data1 data2 data3 ...) lipo5-multi.flex


4. Recherche dans un dictionnaire

On considère un dictionnaire comme le fichier /usr/share/dict/words qui contient des "mots" ligne a ligne, et l'on désire extraire avec flex (et donc par expressions régulières) les mots vérifiant certaines propriétés. Ceci s'apparente directement à la commande Unix grep.
Une difficulté réside dans la gestion de la fin de ligne (\n). On rappel que dans les expressions régulières de Flex :

N.B.: On pourra utiliser l'option flex "%option case-insensitive" pour la gestion des majuscules

4.1) Du cul pas cucul

Listez les mots contenant une lettre 'q' non suivie de la lettre 'u', ceci comprend les mots terminant par 'q'.

Corrigé : dico1.flex

4.2) Top Scrabble

Dans le Scrabble version anglaise, les lettres les plus chères (10 points) sont 'z' et 'q'. Listez les mots contenant au moins un 'z' et au moins un 'q'.

Corrigé : dico2.flex

4.3) Top Scrabble bis

Listez les mots contenant exactement un 'z' et un 'q'.

Corrigé : dico3.flex

4.4) Top Scrabble ter

Listez les mots contenant au moins un 'z', au moins un 'q' et au moins un 'x'.

Corrigé : dico4.flex

Une autre solution plus générique avec moins de flex et plus de code C annexe dico4-gen.flex

4.5) Dead Beef (ou hexspeak ou leet speak)

Par exemple pour construire des adresses IPv6 humoristiques ou simplement plus faciles à retenir, on cherche des chaînes de chiffres hexadécimaux qui peuvent avoir un sens "littéral". De façon stricte, cela consiste à utiliser uniquement les chiffre-lettres 'a' à 'f'; de façon plus approximative d'utiliser la proximité graphique entre certains chiffres et certaines lettres comme '0' et 'O' ou '2' et 'Z' ...

Exemple DEADBEEF, CAFEBABE, DICECA5E, B16B00B5

Corrigé : dico5.flex


5. Expressions régulières sur {a,b}* , Négation d'expressions régulières

Un alphabet aussi limité offre des exercices d'analyse non triviaux, tout en étant gérables. En effet, il permet d'imaginer des tests relativement systématiques sans que le nombre de possibilités à envisager n'explose "trop vite".

A ce titre, on donne le programme Astar.c qui écrit ligne à ligne tout les mots de taille égale (resp. inférieure ou égale) à N sur un alphabet de taille M. On donne par exemple les fichiers de test AB5 et AB10 qui sont les mots sur {a,b}* de taille inférieure ou égale à 5 et à 10. (obtenus avec Astar ab -5 >AB5; Astar ab -10 >AB10)

La théorie des langages montre que l'ensemble des langages réguliers est fermé pour l'opération ensembliste "complémentaire" (et en conséquence aussi pour l'intersection). La construction du complémentaire ou de la négation est triviale si l'on se place du point de vue des automates finis, mais peut être rapidement très difficile du point de vue des expressions régulières.

Pour chacune des questions, il s'agit de reconnaître les mots qui appartiennent et ceux qui n'appartiennent pas à un langage donnée. On s'interdit l'utilisation du mécanisme de règle-balai de flex pour réaliser la négation, mais l'on veut à chaque fois une expression régulière explicite pour chacun des 2 cas : appartient et n'appartient pas.
On suggère ainsi le squelette suivant pour la spécification flex :

------ abba-proto.flex
%option nounput noinput

%{
#include "proto-color.h"  
void echo(char *lex_cat) {
    fprintf(stdout,GREEN("[%s:%s]"), lex_cat, yytext); 
}
void echo1(char *lex_cat) {
    fprintf(stdout,REV(GREEN("[%s:%s]")), lex_cat, yytext); 
}
void echo2(char *lex_cat) {
    fprintf(stdout,RED("[%s:%s]"), lex_cat, yytext); 
}

int nbOK=0, nbNOT=0;
%}

OK   expression1
NOT  expression2

%%
^{OK}$	    echo("OK"); nbOK++;
^{NOT}$	    echo1("NOT"); nbNOT++;
\n	    ECHO;
^[ab]*$	    echo2("UNK");
.* 	    echo2("UNK");
%%

int yywrap(void) {
    printf("Nb_OK = %d, Nb_NOT = %d\n",nbOK,nbNOT);
    return 1; }
int main(int argc, char *argv[]) { while (yylex()!=0) ; return 0;}

La solution sera alors correcte (expression1 == Not (expression2) ) si :

5.1) Ancien Alcoolique Anonyme

Trouvez les expressions régulières pour reconnaître le langage des mots commençant ou finissant par la lettre "a" et le complémentaire de ce langage.

Corrigé : abba1.flex

5.2) Bébé bègue

Trouvez les expressions régulières pour reconnaître le langage des mots ne contenant pas 2 occurrences consécutives de la même lettre et le complémentaire de ce langage.

Corrigé : abba2.flex

5.3) Béaba ou b.a.-ba (exercice difficile!)

Trouvez les expressions régulières pour reconnaître le langage des mots ne contenant pas la chaîne "aba" et le complémentaire de ce langage.

Corrigé : abba3.flex

On trouvera aussi dans les Illustrations d'Automates (ExoGram/Partie1) une résolution systématique par négation sur l'automate fini.


6. Filtres

Il s'agit de transformations simples sur un fichier texte ...
On supposera conformément aux "bons usages" qu'un fichier texte se termine toujours par une fin de ligne (ou qu'il est vide). Flex ne fournit pas de moyen simple de traiter des fragments avec un contexte fin de fichier. Par exemple r$, ne reconnaît pas l'expression r en fin de fichier, sauf si "\n" existe avant la fin de fichier.

6.1) Lignes vides, Lignes "blanches","blancs" en fin de ligne

Supprimer les lignes vides d'un fichier.
Supprimer aussi les lignes "blanches" c'est à dire ne contenant que des espaces et tabulations.
Supprimer aussi les "blancs" inutiles en fin de ligne.

N.B.1 : Pour la lisibilité, on suggère de visualiser en sortie les fins de ligne par exemple avec fprintf(stdout,GREEN("[\\n]")"\n"); (idem pour blancs et tab)
N.B.2 : Attention au cas de lignes vides en début de fichier

------ filtre1.data (attention aux blancs et tabulation!)
	     


pas vide    

Corrigé : filtre1.flex

6.2) Lignes vides consécutives , "cat -s"

Remplacer les lignes vides consécutives par une seule ligne vide comme le fait la commande Unix "cat -s". Modifier pour remplacer des lignes consécutives blanches ou vides par une ligne vide.
Variante : Remplacer les blancs consécutifs par un seul blanc.

Corrigé : filtre2.flex

6.3) Commande wc

Écrire l'équivalent de la commande Unix "wc" qui affiche le nombre de lignes, le nombre de mots et le nombre de caractères d'un fichier texte. (Cf. aussi exo 3.5 "Tautogramme")
Pour suivre "wc", on appelle mot, une suite de caractères délimitée par des caractères de la classe Posix [:space:] (==[ \t\n\f\v\r])

Corrigé : filtre3.flex

6.4) Numérotation de ligne, "cat -n" et "cat -b"

Écrire l'équivalent des filtres "cat -n" et "cat -b" qui numérotent les lignes d'un fichier. (cf. aussi TP Noté CF2 2014 Sujet+Corrigé.)

Corrigé : filtre4.flex

6.5) Caractères invisible, "cat -T" et "cat -v"

Écrire un filtre qui rend visible les caractères spéciaux dans un fichier texte comme le font les commande Unix "cat -T", "cat -v" ou "cat -t". (cf. aussi TP Noté 2014)

Un fichier de test : ASCII.data

Corrigé : filtre5.flex

6.6) Détabulation, "expand" ou "col -x"

Écrire un filtre qui supprime les tabulations (\t) d'un fichier texte et les remplace par un nombre adéquat de caractères espace. On suppose que l'on a des "taquets" de tabulation tout les 8 caractères, et qu'une tabulation aligne sur le prochain taquet du texte. Ce filtre correspond aux commandes Unix "col -x" ou "expand"

Corrigé : filtre6.flex

6.7) Justification de texte, "fold -s"

Écrire un filtre qui fait la Justification d'un fichier texte sur des lignes de 80 caractères maximum. Les césures se feront sur des caractères blancs (espace ou tabulation). Les tabulations et espaces consécutifs seront remplacés par un seul espace. Les fins de ligne en entrée sont ignorées sauf pour les lignes vides qui sont conservées. Ce filtre s'apparente à la commande Unix "fold -s"

Corrigé : filtre7.flex

6.8) Fichiers texte Unix, Mac, Dos

Convertir les fins de lignes entre le mode Unix (\n) , Mac (\r) et Dos (\r\n)

Corrigé :

%%
\r\n   printf("\n");   /* Dos2Unix */
\r\n   printf("\r");   /* Dos2Mac  */
\r     printf("\r\n"); /* Mac2Dos  */
(...)
.      ECHO;
%%

7)Traduction de SVG

Un exemple complet issu du TP Noté 2006.

7.0) Présentation rapide de SVG

SVG (Scalable Vector Graphics) est un langage graphique pour définir des dessins et animations. Le codage "vectoriel" d'éléments de dessin est compact et permet de les mettre à l'échelle (scalable). Un code SVG est compatible avec la gestion du Document Object Model, les style sheets... il est donc insérable dans un fichier XML, sous cette forme:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="140" height="170">
**********  PROGRAMME SVG   ***********
</svg>

Avec un navigateur sachant interpréter SVG, les graphismes sont donc exploitables dans une page web. SVG peut s'articuler avec des langages de scripts, avec XHTML, MathML,... Exemples d'applications sans animation : description cartographiques, diagrammes UML, visualisation du graphe du web lui-même. Les aspects animation sont compatibles avec SMIL, Synchronized Multimedia Integration Language.

------  Exemple de programme SVG : svg3.data (text)
<svg width="140" height="170" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Plan</title>
<desc>Version 0</desc>
<circle cx="70" cy="95" r="50" style="stroke: black; fill: none;"/>
<circle cx="55" cy="80" r="5" stroke="black" fill="#339933"/>
<g id="voies">
  <line x1="75" y1="95" x2="135" y2="85" style="stroke: black;"/>
  <line x1="75" y1="95" x2="135" y2="105" style="stroke: black;"/>
</g>
<use xlink:href="#voies" transform="scale(-1,1) translate(-140 0)"/>
<polyline points="108 62, 90 10, 70 45, 50 10, 32 62"
          style="stroke: black; fill: none;" />
</svg>

Ce que le browser peut visualiser sous la forme :
Plan Version 0

7.1) Analyse lexicale des unités de base : valeurs, symboles, attributs

Deux exemples de fichier de test

------ svg1.data 
15 -2 0.5  .999 -0.3 1. - 3  0.1.  
14pt 14Pt
#040 #2244CC #9999
red grey none gray
rgb(20%, 30%, 50%) rgb( 20% 30% 50%)
xxxx href  #xxxx #  polyline

------  Exemple de programme SVG : svg2.data
1, 2, 3
0 0
0 0, 1 1, 2 2
stroke="black"
fill="#339933"
points="108 62, 90 10, 70 45, 50 10, 32 62"
scale(-1,1)
transform="scale(-1,1) translate(-140 0)"
style="stroke: #999;"
style="stroke: #999; fill: none;"
style="stroke: gray; fill: #339933;"
style="stroke: rgb(20%, 30%, 50%); fill: none;"
style="fill: red; stroke: green;"
style="font-family: sans-serif; font-size: 14pt; stroke: none; fill: black;"
style="font-family: serif; font-size: 8pt; stroke: none; fill: black;"

Implémenter l'analyseur lexical Flex permettant de reconnaître et d'afficher les catégories lexicales suivantes :

  1. Valeurs numériques : catégories lexicales usuelles INT et FLOAT. On admettra des valeurs positives ou négatives, de type entier ou réel.
    Exemples corrects : 15 -2 0.5 .999 -0.3 1.
    Exemples erronés : - 3 0.1.
  2. Tailles de fontes : catégorie FT_SIZE_VAL
    Une taille de fonte est une valeur entière suffixée de "pt". Exemple : 14pt
  3. Valeurs de couleurs. Reconnaître la catégorie COLOR dans 3 cas :
    Exemples corrects : #040 red #2244CC green none rgb(20%, 30%, 50%)
    Exemples erronés : #9999 grey rgb( 20% 30% 50%)
  4. Noms d'attributs.
    En SVG certaines entités ont des attributs. On reconnaîtra ainsi fill stroke font-family font-size points transform style href
    À la rencontre d'un tel nom, reconnaître une catégorie lexicale de nom similaire. (N.B. : dans les noms de "token", ne pas utiliser de '-'):
     fill -> FILL   font-family -> FONT_FAMILY  points -> POINTS  ...
    
  5. Autres valeurs simples possibles pour les attributs.
    Beaucoup d'attributs prenant des valeurs simples déjà prises en compte ci-dessus, par exemple:
     fill -> COLOR  font-size -> FT_SIZE_VAL ...
    

    Pour d'autres attributs les valeurs possibles sont des mots-clés. Par exemple: pour font-family, les valeurs possibles sont: serif sans-serif
    À la rencontre d'un de ces mots-clés, l'analyseur lexical considérera qu'il s'agit de la catégorie lexicale FONT_FAM_VAL.
  6. Symboles définis par le programmeur et références à ces symboles
    L'analyseur doit retourner :
     EX.: dans la balise <g id="voies">, "voies" est un symbole du programmeur
          dans la balise <use xlink:href="#voies" ... >, #voies est une référence
    

Corrigé : svg.flex

7.2) Suite : Analyse lexicale et syntaxique, cf TP Noté 2006 : Sujet et Corrigé


8. Pots Pourri

Des suggestions en vrac !

8.1) "aeiou"

Écrire un analyseur reconnaissant les mots contenant les 5 voyelles dans l'ordre. On supposera qu'il y a un seul mot à reconnaître par ligne.

------ aeiouy.data
oiseau
paqerisotu
oioiseseauau

Corrigé : aeiouy.flex

8.2) Nombres aérés

Écrire un analyseur lexical pour reconnaître des nombres entiers "aérés", c'est à dire des nombres entiers signés contenant éventuellement des séparateurs "_" qui sont autorisés uniquement pour les milliers et les puissances de milliers.
Exemples valides : 1234567, 1_234_567, 1234_567, 1_234567, 0_123, -12, +1_234 ...
Exemples invalides : 123_4567, 1234567_, _123, -_123

cf. exercice 1 du TP Noté 2014 : Sujet+Corrigé.

8.3) Dates/heures

a) Reconnaître des champs "date":

b) Reconnaître des champs "heure", sous la forme hh:mn, pour hh sur [0,23] et mn sur [0,59]

c) Reconnaître des champs "date/time" à partir d'une définition standard de la syntaxe (ABNF) :

8.4) Extraction d'entête mail (from: Subject: )

Utiliser les spécifications de syntaxe des RFC822 ou RFC2822 pour faire l'analyse lexicale/syntaxique de mails Internet.
cf. par exemple le TP Noté 2013 Sujet+Corrigé

8.5) Mots encadrés

a) Traiter les cas ci-dessous, supposés non imbriqués entre eux :

Traiter d'abord le cas mono-ligne, étendre au cas multiligne

b) Ajouter la possibilité d'imbrication

N.B.: en réalité, on sort des langages réguliers (cf. Exercice sur les commentaires en C)

8.6) Sélection de ligne ("grep", "grep -v")

Imprimer toutes les lignes d'un texte qui contiennent un motif donné.
Idem pour la négation : toutes les lignes qui ne contiennent pas.

8.7) Balise html

Reconnaître des balises *ml :

8.8) URLs

Reconnaître des URLs telles que "http://www.maileva.com:80/".

8.9) Table de symbole

Construire une table de symbole et liste des numéros de ligne des occurrences des symboles dans un fichier
cf. symtab.c et symtab.h pour une implémentation générique d'une table de symboles

8.10) Extraction distributive

Ventiler les lignes d'un fichier F dans différents fichiers Fk, k=1,2..N le fichier Fk recevant les lignes caractérisées par une expression EXPk


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