L'objectif de ces séances de travaux pratiques de
compilation est de se familiariser aux commandesflexetbison,les
deux outils de compilation par défaut sur les systèmesunix
depuis plusieurs décennies ( déjà !). Le premier outil
flex(versiongnude la commande lex) construit unanalyseur
lexical à partir d?un ensemble de règles/actions
décrites par des expressions régulières.
Le second outilbisonest un compilateur de compilateur, version gnu
de la célèbre commande yaccacronyme de « yet another
compiler of compilers ». Il construit un compilateur d?un langage décrit
par un ensemble de règles et actions d?une grammaire LARL
sous une forme proche de la forme BNF de Backus-Naur.
[ manuel flex ] [ manuel bison] [ lex/yacc ] [ lex/flex ] [ yacc/bison ]
La source yacc utilise l'analyseur lexical yylex()qui peut etre construit avec flex.
L'option -d de la commenadebison génére
un fichier entete qui doit etre inclus dans la source de votre programme
flex pour pouvoir utiliser les symboles definis par bison.
Ainsi, pour compiler l'analyseur syntaxique lysa decrit par
miny.y utilisant la definition d'un analyseur lexical mini.lex on
procede :
lysa : mini.lex mini.ybison -d -omini.c mini.y
[ 1 ] Compilez votre analyseurmini.y avec l'option -d de bison. Jetez un coup d'oeil au fichier entete qui a été créé.
[ 2 ] Ecrire l'analyseur lexical de votre calculette à mémoires avec flex.
[ 3 ] Compilez. Verifiez le bon fonctionnement
de votre calculette à mémoires.
A ce stade, votre calculette gère essentiellement deux terminaux
: MEM et NB, tous deux de type entier ( int). Pour inclure
des symboles plus complexes, on introduit un terminal nouveau symbole terminal
ID.
[ 4 ] Modifiez votre langage pour éviter
la confusion entre la case mémoire "a" et l'identificateur "a". On
pourra par exemple utiliser la chaine "$A" pour désigner la case mémoire
"A", dans ce cas, la ligne du genre :
{MEM} yylval = 'A' - yytext[0] ; return MEM;
devient
{MEM} yylval = 'A' - yytext[1] ; return MEM;
[ 5 ] Modifiez votre analyseur lexical,
pour insérer les identificateurs rencontrés dans une table
de symboles, au moyen de la règle :
{ID} if ( ! inserer( yytext ) ) printf("\ninsertion...");
else printf("\ndeja vu...");
On suppose que inserer(char *
k) recherche et renvoie/crée un pointeur une
entrée dans la table des symboles. Pour une gestion rudimentaire, on
peut utiliser :
typedef struct liste{
char * cle;
int data;
struct liste * svt;
} noeud, *liste;liste ts = NULL;
liste inserer( char * k )
{
liste aux;
aux = ts;
while ( aux ) {
if ( strcmp( aux->cle, k ) == 0 )
return aux;
aux = aux -> svt;
}
printf("\nInsertion...");
aux = ( liste ) malloc( sizeof(noeud) );
aux->cle = (char *) malloc( strlen(k) + 1 );
strcpy( aux->cle, k );
aux->data = 0;
aux->svt = ts;
ts = aux;
return ts;}
[ 6 ] Pour gérer les valeurs des
symboles, il faut manipuler plusieurs types au niveau du portyylval.
Les attributs de MEM et NBsont entiers et l'attribut de ID est de type liste.
La déclaration d'union bison
%union { int val; liste ptr;}
definit le type adéquate dans YYSTYPE.
{MEM} yylval.val = 'A' - yytext[1] ; return MEM;
{NB} yylval.val = atoi( yytext ) ; return NB;
{ID} yylval.ptr = inserer( yytext ); return ID;
Compilez votre analyseur mini.y avec l'option -d debison.
Jetez un coup d'oeil au fichier entete créé.
[ 7 ] La gestion des champs au niveau
des non-terminaux peut se faire explicitement sous la forme $<champ><numero>par exemple
:
$<val>4, $<ptr>->data$etc...
Mais aprés, une déclaration :
%type <champ> EXP
les actions sémantiques réfèrent par défaut
au champ correspondant lors de l'utilisation de l'attribut du symbole
EXP.
[ 7 ] Redéfinissez les attributs dans les actions sémantiques de votre programme. Compilez.
[ 8 ] Ajoutez l'affectation des variables.
[ 9 ] Modifiez vos analyseurs pour gérer
l'appel de fonctions prédéfinies, comme par exemple
le calcul du pgcd de deux entiers par la fonction :
int pgcd( int a, int b ) {
if ( b ) return pgcd(b, a % b);
return a;
}
[ A ] Modifiez votre langage pour gérer
les tableaux d'entiers.
[ manuel flex ] [ manuel bison] [ lex/yacc ] [ lex/flex ] [ yacc/bison ]