Vous êtes sur la page 1sur 5

LEX & YACC

Contenu

Article publié sur le blog :


http://sylvaindika.wordpress.com

Copyright © Mai 2007, DIKA


LEX & YACC
__________

Un des rêves de tout informaticien est de dialoguer avec l'ordinateur avec aisance.
Ce rêve est depuis possible grâce au couple de programmes LEX et YAC.
Si vous êtes un mordu de la programmation alors LEX et YAC vous offre d'énormes
opportunités. En effet les compilateurs rendus célèbres par tant de programmeurs en
sont issus : c, C++, pascal, PHP, etc.
Donc n'importe quelle langage, venant du fin fond de votre imagination, peut être
compris par un ordinateur : De l'analyse d'un fichier de configuration à la création
d'un interpréteur de commande, ou même d'un compilateur, ces deux programmes sont
d'excellents alliés qui permettent de d'écrire des langages complexes et structurés.
Ces deux programmes sont disponibles en environnement UNIX sous licence GNU/Linux
connu sous le nom LEX & BISON.

Mais que font au juste ces deux programmes ?

A travers quelques exemples simples, nous allons voir à quoi ressemble LEX. Puis son
interaction avec YACC, pour des réalisations plus ambitieuses; comme l'écriture d'un
compilateur, ou la lecture et l'analyse d'un fichier de configuration.

1. LEX
Commençons par notre très cher 'a'LEX. Ce programme, appelé aussi LEXER est un
analyser lexical(*)1. Il prend un flux de caractères dans l'entrée stardard, et
lorsqu'il rencontre une suite de caractères qui correspond à un mot clé défini, il
exécute certaines actions.

1.1 Structure d'un programme LEX

%{
Prologue
%}

Declaration

%%
Grammaire
%%

Epilogue

Le prologue limité par %{ et %}, contient les types de données et les variables
globales utilisées et décrites par la grammaire de votre langage. On peut aussi
utiliser les commandes du pré-processeur, des macros, ou encore les bibliothèques du
langage C; les fameux '#include'. Le gestionnaire des erreurs de grammaire va dans
cette partie. La Declatation contient le vocabulaire : C'est à dire les mots clés ou
symboles de votre futur langage. La troisième partie, Grammaire, regroupe ses règles
de construction. Enfin, la dernière partie, Epilogue, peut contenir des fonctions
supplémentaires. C'est une sorte de bibliothèque de fonctions au sens simple.

1
L'analyseur lexical constitue la première étape d'un compilateur. Sa tâche principale est de lire les
caractères d'entrée et de produire comme résultat une suite d'unités lexicales que l'analyseur syntaxique
aura à traiter
1.2 Un exemple simple.

feuxdartifice.l

%{
#include <stdio.h>
}%

%%
arret printf("Feux en arret\n") ;
marche printf("Feux en marche\n");
%%

Un simple éditeur comme Bloc-note ou Emac suffit. Mais avant, il nous faut un
vocabulaire (syntaxe) et une grammaire. Pour ce faire, les deux mots-clés 'arret' et
'marche' vont nous servir. Le programme lit les flux de caractères du clavier et
lorsqu'il rencontre l'un des mots-clés de notre language, il affiche un message
correspondant. Les mots ne correspondant pas sont affichés.

Pour compiler le programme :

$ lex feuxdartice.l
$ cc lex.yy.c -o feuxdartifice -ll

Pour exécuter le programme :

$ feuxdartice

Pour arrêter le programme : Crtl+C

IMPORTANT : Si vous utilisez flex au lieu de lex, changez '-ll' par '-lfl' pour la
compilation. Ces options permettent d'appeler la librairie de Lex (liblex), qui
contient la fonction main() absente du programme feuxdartifice. Le tableau suivant
illustre son fonctionnement.

Mot-clé Affichage
arret Feux en arrêt
marche Feux en marche

Fichier source feuxdartifice.l

fichier feuxdartifice.l
Compilation avec flex exécution sous DOS

Compilation avec flex exécution sous DOS

1.3 Les expression régulières comme vocabulaire

L'exemple suivant utilise les expressions régulières pour définir une syntaxe. Une
large documentation traites de leurs fonctionnalités pour construire des syntaxes
fortes et élégantes.

expresso.l

%{
#include <stdio.h>
}%

%%
[0-9]+ printf("NOMBRE\n') ;
[a-zA-Z][a-zA-Z0-9] printf("MOT\n");
[ \t]+ /* ignorer les espaces et la tabulation*/
%%

Ce programme décrit deux types de correspondance (match) : NOMBREs et MOTs. Examinons


à présent le programme issu d'un langage particulier :

cafecreme.caf

loger {
categorie instituteur { hlm };
categorie professeur { villa };
};

zone "." {
type appartement, immeuble;
fichier "/user/appt/std.log";
fichier "/user/imm/tulipe.log"
};

Dans ce fichier on remarque nettement les catégories de mots-clés (tokens) suivants:

• MOTs, comme 'loger', 'categorie', 'zone', 'type' ...


• NOMFICHERs, comme '/user/appt/std.log' ...
• CARACSPECIALs, comme '/' et '.'
• ACCOLADEGs, {
• ACCOLADEDs, }
• POINTV, ;
• VIRGULE,
• DOUBLEQUOTEs, "

Le programme LEX correspondant à ce vocabulaire est le suivant:

coffanalyser.l

%{
#include <stdio.h>
%}

%%
[a-zA-Z][a-zA-Z0-9]* printf("MOT\n");
[a-zA-Z0-9\/.-]+ printf("NOMFICHIER\n");
\" printf("DOUBLEQUOTE\n");
\{ printf("ACCOLADEG\n");
\} printf("ACCOLADED\n");
; printf("POINTV\n");
\n printf("\n"); /* retour à la ligne*/
[ \t]+ /* ignore espaces et tabulation*/
%%

La compilation nous fournit l'analyse coffanalyser.exe qui sera utilisé pour analyser
notre programme cafecreme.caf

programme cafecrem.caf sortie de l'analyser coffanalyer

programme cafecrem.caf sortie de l'analyser coffanalyer

fichier Lex de l'anlyser compilation de l'analyser coffanalyer

fichier Lex de l'anlyser compilation de l'analyser coffanalyer