|
|||||||||||||||||||||||||||||||||||||||||||||||
|
Ce mois-ci, nous allons étudier Flex, version AmigaOS de Lex, le célèbre utilitaire que tout utilisateur d'Unix connaît, ne serait-ce que de nom. Lex est un outil permettant de créer rapidement des analyseurs syntaxiques (ou "scanners"). Il s'agit de programmes capables de reconnaître des motifs lexicaux (ou "patterns") dans un texte et de déclencher des actions en fonction des motifs reconnus. Flex, dans son utilisation, est fort similaire à GAwk, édudié le mois dernier : il lit un fichier d'entrée (ou l'entrée standard si aucun nom de fichier ne lui est précisé) correspondant à la description de l'analyseur syntaxique à générer. Il se compose d'une suite d'expressions propres au langage Lex et de code source en C définissant, sous forme de fonctions, les actions à effectuer lors de la reconnaissance d'un motif lexical. A l'aide de ces données d'entrée, Flex génère un autre programme source en langage C, se nommant lex.yy.c et définit la routine yylex() qui est l'analyseur syntaxique créé à partir des règles de l'utilisateur. Cet analyseur syntaxique peut ensuite être utilisé tel quel ou intégré dans une application, comme n'importe quel autre source en C. Une fois compilé et relié, lex.yy.c produit un exécutable capable d'analyser un fichier et d'exécuter un certain nombre d'actions en fonction des motifs rencontrées. Syntaxe Après ce rapide descriptif des fonctionnalités de Flex, il est temps désormais d'étudier la syntaxe du fichier d'entrée. Attention, le but de cet article n'est pas de vous expliquer toutes les finesses du langage, l'intégralité de la revue n'y suffirait pas. Non, il s'agit simplement de vous familiariser avec Flex afin de vous faire découvrir toute la puissance de ce produit. Les différentes sections d'un programme Lex Le fichier d'entrée de Flex peut être décomposé en trois sections distinctes, séparées entre elles par la ligne "%%". Ces trois sections sont : Définitions, Règles et Code Utilisateur (en C). La section Définitions contient la déclaration de noms comme équivalence à une définition, ceci afin de simplifier l'écriture de certaines expressions. Cette déclaration s'effectue sous la forme :
Le nom doit impérativement commencer à la première colonne de la ligne, sous peine d'être interprété d'une autre manière comme nous le verrons plus tard. De même, la définition commence dès le premier caractère non-blanc de la ligne. Par exemple, CHIFFRE [0-9] permet de remplacer dans toutes les règles, l'expression [0-9] définissant un chiffre par le mot CHIFFRE. Ainsi :
...remplace :
La section Règles contient une série de règles de la forme :
Attention, comme dans la section Définitions, le motif doit obligatoirement commencer à la première colonne de la ligne sous peine d'une interprétation différente. Enfin, la section Code Utilisateur contient les fonctions appelées par l'analyseur syntaxique. Il s'agit de code en langage C qui sera copié tel quel dans le fichier lex.yy.c. Dans les sections Définitions et Règles, tout texte indenté ou compris entre "{%" et "%}" est copié tel quel vers le fichier de sortie (les caractères "{%" et "%}" étant enlevés lors de cette opération). Dans la section Règles, toute ligne indentée ou comprise entre "{%" et "%}" apparaissant avant la première règle effective est considérée comme une déclaration de variable locale à la fonction d'analyse syntaxique. Dans la section Définitions, pour inscrire un commentaire, il suffit que la ligne ne soit pas indentée et comprise entre et "*/". Un commentaire est recopié tel quel vers le fichier de sortie. A noter la possibilité de définir une ligne de commentaire à l'aide du "#" situé en première colonne de la ligne. Cette pratique est à éviter car elle risque de disparaître dans de futures versions. La notion de "pattern" Le motif lexical (ou pattern) est défini par une série de règles d'écriture, pour la plupart très proches de celle de GAwk. Notre propos n'est pas de passer en revue toutes ces règles mais d'en étudier quelques-unes par l'exemple.
Quand l'analyseur de syntaxe est lancé, il analyse le fichier et pour chaque ligne, recherche les occurrences qui correspondent à un ou plusieurs motifs. S'il en trouve plus d'un, il recherche d'abord celle dont un maximum de caractères correspond au motif. Si l'ambiguïté n'est pas levée, il prend la première par ordre de déclaration des règles dans le fichier Lex. Une fois le texte trouvé, celui-ci est recopié dans le pointeur "yytext" et sa longueur dans la variable "yyleng". L'action correspondante au motif est alors exécutée, et le reste de la ligne analysé. Si aucune règle n'est déclenchée (c'est-à-dire aucune occurrence de motif n'est trouvée dans la phrase), la règle par défaut est exécutée : elle consiste à copier les caractères un à un vers la sortie. Donc, un programme Flex réduit à "%%" copiera simplement le fichier d'entrée vers le fichier de sortie, sans aucune modification. La notion d'action Chaque motif dans une règle possède une action qui lui correspond. Le motif se terminant dès le premier caractère blanc rencontré, le reste de la ligne est donc l'action associée. A titre d'exemple, ce petit programme remplace les suites de caractères blancs (an anglais, "white space") par un espace. Il supprime également tous les caractères blancs en fin de ligne. Il existe de nombreuses directives Lex qui peuvent être intégrées dans les actions et qui représentent en quelque sorte des macro-commandes. Un exemple, ECHO recopie systématiquement le contenu du pointeur de caractères yytext vers la sortie de l'analyseur syntaxique. Il existe bien d'autres choses à dire sur Flex, mais la place qui m'est impartie n'étant pas élastique, passons sans plus attendre aux exemples qui vous permettront de mieux cerner son utilisation. Exemples Deux règles ont été définies : la première recherche les caractères retour chariot (\n) et incrémente les valeurs "nbr_ligne" et "nbr_car" à chaque fois qu'elle en découvre un. La seconde recherche un caractère quelconque autre que "\n" et incrémente "nbr_car" à chaque fois qu'elle en découvre un. Passons maintenant à un exemple un peu plus compliqué. Bibliographie
Comme bon nombre d'utilitaires étudiés dans ces colonnes, Flex est disponible dans le domaine public et plus particulièrement sur la disquette Fred Fish n°412. Cette disquette contient outre l'exécutable, une documentation fort complète de 35 pages (en anglais !) sur le produit et les sources du logiciel, archivés au format LHArc.
|