Changes between Initial Version and Version 1 of 2009/CaoCourseTme3


Ignore:
Timestamp:
Jan 10, 2010, 11:53:40 PM (15 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 2009/CaoCourseTme3

    v1 v1  
     1{{{
     2#!html
     3<h1> TME3 : Analyseur syntaxique  pour le format de fichier ''.vst''</h1>
     4}}}
     5[[PageOutline]]
     6
     7= Objectifs =
     8
     9L'objectif de ce TME est de vous familiariser avec les outils ''flex'' et ''bison'',
     10qui sont des outils de la distribution GNU permettant de générer automatiquement des
     11analyseurs lexicaux (ou ''scaner'') et des analyseurs syntaxiques (ou ''parser'')
     12pour différents formats de fichiers. Les outils ''flex'' et ''bison'' sont des versions
     13"logiciel libre" des outils UNIX ''lex'' et ''yacc''.
     14
     15Vous allez développer un analyseur lexical, puis un analyseur syntaxique
     16pour le format de fichier ".vst". Ce format de fichier correspond au sous-ensemble
     17du  langage VHDL utilisé  par la chaîne de CAO Alliance
     18pour décrire la vue structurelle d'un circuit intégré. La structure de donnée
     19construite en mémoire sera la structure de données ''lofig'' présentée en cours.
     20On fait l'hypothèse que tous les signaux sont de type bit, et il n'est donc pas demandé de traiter
     21les vecteurs de bits.
     22Dans ce TME3, on se limitera à l'analyse grammaticale du format''.vst''. La construction effective
     23de la structure de données ''lofig'' sera réalisée dans le TME4.
     24
     25Nous ne vous donnons pas la grammaire du format ''.vst'' mais vous devrez
     26la construire en analysant la structure du fichier [wiki:CaoCourseTme3exemple exemple.vst].
     27
     28Vous pourrez également utiliser des extraits du fichier complet comme [wiki:CaoCourseTME3signal signal.vst]
     29qui ne décrit que la liste des déclarations de signaux, dans le but de mettre au point l'analyseur syntaxique partie par partie.
     30
     31Ces deux fichiers sont disponibles dans le répertoire:
     32{{{
     33/users/enseig/encadr/cao/tme3/vst
     34}}}
     35
     36Commencez par créez un répertoire ''tme3''. Il est recommandé de créer un sous-répertoire
     37pour chacune des étapes de ce TME, et à recopier vos fichiers d'un répertoire dans le suivant,
     38de façon à conserver les résultats intermédiaires.
     39
     40Si vous ne connaissez pas bien les outils lex (flex) et yacc (bison), les liens ci-dessous pourront vous aider à comprendre.
     41  [http://www-128.ibm.com/developerworks/library/l-lex.html "Lex & Yacc Essentiel"]::
     42    L'essentiel des outils est rappelé ici, à lire absolument.
     43  [http://epaperpress.com/lexandyacc/download/lexyacc.pdf "Lex & Yacc Compact"]::
     44    Un peu de théorie, et un exemple classique. Document à lire pour comprendre un peu comment ces outils fonctionnent.
     45  [http://flex.sourceforge.net/manual/ "Lex Official"]::
     46    LE manuel officiel de flex. C'est la que vous pourrez savoir quelles sont les options possibles sur la ligne de commande et toutes les fonctions.
     47    Document à feuilleter, sa lecture n'est pas nécessaire pour résoudre ce TME.
     48  [http://www.gnu.org/software/bison/manual/html_mono/bison.html "Yacc Official"]::
     49    LE manuel officiel de Yacc.
     50
     51= Etape 1 : Analyseur lexical =
     52
     53L'outil '''flex''' est un générateur d'analyseur lexical. Il prend en entrée un fichier ''vst.l''
     54contenant la définition des "token" à reconnaître, et génère en sortie un fichier ''vst.yy.c''
     55qui contient le code C de l'analyseur lexical, et en particulier la fonction yylex().
     56 
     57On appelle ''token'' une séquence de caractères lus dans le fichier texte qu'on cherche à analyser,
     58et correspondant à une expression régulière : mot-clef, identificateur, etc...
     59Le but de cette première étape est d'écrire le fichier ''vst.l'' qui définit les expressions
     60régulières correspondant à tous les "tokens" utilisés dans un fichier texte respectant le format ''.vst''.
     61
     62  1. On rappelle qu'en VHDL, les lettres majuscules et minuscules ne sont pas différenciées. Cherchez dans le manuel de '''flex''' une manière simple de générer un analyseur lexical qui ne fasse pas la différence entre majuscules et minuscules.
     63  1. Etablir la liste des mots clefs du format ''.vst'', et en déduire les expressions régulières en langage '''flex''' permettant de les reconnaître.
     64  1. Etablir la liste des opérateurs du format ''.vst'', et écrire les règles en langage '''flex''' permettant de les reconnaître. On utilisera une classe pour les opérateurs possédant un seul caractère.
     65  1. Etablir la règle de reconnaissance d'un identificateur, sachant qu'un identificateur du VHDL commence toujours par une lettre, suivied'un nombre quelconque de lettres, chiffres ou ''underscore'', avec la contrainte que l'on ne doit pas avoir 2 ''underscore'' successifs.
     66  1. Etablir la règle permettant d'absorber les commentaires, sachant qu'un commentaire commence par "--" et s'achève en fin de ligne. 
     67  1. Etablir la règle permettant d'absorber les caractères d'espace et les caractères de tabulation.
     68
     69A chaque règle reconnaissant un token particulier, on peut associer une séquence de code qui sera exécutée par
     70l'analyseur lexical chaque fois que ce token est reconnu. Dans cette première étape, on se contente d'utiliser
     71la fonction printf() pour afficher un message définissant le type de token reconnu, ainsi que la chaîne de
     72caractère correspondante. On rappelle que la variable globale {{{yytext}}} contient un pointeur sur la chaîne
     73de caractère constituant le dernier token reconnu.
     74
     75On donne ci-dessous une partie du fichier ''vst.l'' que vous devez écrire. Comme vous pouvez le constater,
     76ce fichier se termine par la définition du programme main() qui appelle la fonction {{{yylex() }}}.
     77La variable globale yyin est un pointeur sur le fichier à analyser.
     78{{{
     79%{
     80#include <string.h>
     81#include <stdio.h>
     82int yylineno = 1;     /* numero de ligne (pour les messages d'erreur) */
     83#define YY_NO_UNPUT 
     84%}
     85
     86%%
     87[ \t]                {}                 
     88\n                   {yylineno++;}
     89expression1          {printf("TOKEN1: %s\n", yytext);}
     90expression2          {printf("TOKEN2: %s\n", yytext);}
     91expression3          {printf("TOKEN3: %s\n", yytext);}
     92%%
     93
     94int main(int argc, char *argv[])
     95{
     96  if(argc != 2) {
     97    printf("\n******* usage : %s filename \n", argv[0]);
     98    exit(1);
     99  }
     100
     101  yyin = fopen(argv[1], "r");
     102
     103  if(!yyin) {
     104    printf("\n******* cannot open file : %s \n", argv[1]);
     105    exit(1);
     106  }
     107  yylex();
     108  return 0;
     109}
     110}}}
     111Modifiez ce fichier en introduisant les règles correspondant aux différents "token" à reconnaître.
     112
     113La compilation du fichier ''vst.l'' s'effectue comme suit, à charge pour vous d'intégrer cela dans un Makefile:
     114{{{
     115$ flex -t vst.l > vst.yy.c
     116$ gcc -Wall -Werror -o scanner vst.yy.c -lfl
     117}}}
     118
     119Validez votre travail en lançant l'analyseur lexical sur les fichiers ''signal.vst'' et ''exemple.vst''.
     120{{{
     121$ scanner ../signal.vst
     122}}}
     123
     124= Etape 2 : Modification de l'analyseur lexical =
     125
     126On cherche maintenant à modifier l'analyseur lexical pour préparer la communication
     127entre l'analyseur lexical et l'analyseur syntaxique. On va demander à l'analyseur lexical d'afficher non plus
     128la chaîne de caractères associée à chaque token, mais un entier représentant le type du token reconnu.
     129
     130Pour cela:
     131
     132  * Définir dans le prologue du fichier ''vst.l'' un type énuméré qui associe à chaque token un entier définissant son type. On utilise en général des valeurs supérieures à 255 pour les token correspondant à une chaîne de plusieurs caractères, de façon à pouvoir directement utiliser le code ascii du caractère dans le cas d'un token constitué d'un seul caractère.
     133  * Modifier les actions associées aux règles afin qu'elles retournent le type du token. Par exemple :
     134{{{
     135entity   {return T_ENTITY;}
     136}}}
     137  * Modifier la fonction main() pour qu'elle affiche le type des tokens reconnus. On rappelle que ''yylex'' retourne 0 lorsque la fin de fichier est lue.
     138  * Lancer cette nouvelle version de l'analyseur lexical sur les fichiers ''exemple.vst'' et ''signal.vst''.
     139{{{
     140$ scanner ../exemple.vst
     141}}}
     142
     143= Etape 3 : Analyseur syntaxique =
     144
     145L'outil '''bison''' est un générateur d'analyseur syntaxique.
     146Il prend en entrée un fichier ''vst.y'' contenant la définition des règles de la grammaire
     147correspondant au format ''.vst'', et génère la fonction yyparse() constituant l'analyseur
     148syntaxique, dans un fichier vst.tab.c.
     149
     150Cette étape vise à analyser le fichier ''signal.vst'', qui ne constitue qu'une
     151partie du fichier ''exemple.vst'', et contient une liste de déclarations de signaux.
     152On cherche à écrire une règle permettant de reconnaître un nombre variable d'arguments
     153(une liste de signaux dans notre cas).
     154
     155  1. Déclarez dans le fichier ''vst.y'', les différents token utilisés par le parser susceptibles d'être reconnus par le scaner.
     156  1. Définissez les deux règles de grammaire correspondant a la déclaration d'une liste de signaux, et implanter ces règles dans le fichier ''vst.y''. On définira successivement la règle décrivant un signal, puis la règle décrivant une liste de signaux. '''Bison''' permet d'associer à chaque règle une "action de compilation" qui est exécutée pendant l'analyse du fichier, au moment ou la règle est reconnue, mais dans cette première étape, on n'associera aucune action aux deux régles définies.
     157  1. La fonction main() est maintenant définie dans le fichier ''vst.y'', et doit appeller la fonction yyparse(). Il faut donc modifier la dernière partie du fichier du fichier ''vst.l'', qui ne contient plus que la définition de la fonction
     158
     159Voici une ébauche du fichier ''vst.y'' que vous devez modifier et compléter:
     160{{{
     161%{
     162#include <string.h>
     163#include <stdlib.h>
     164#include <stdio.h>
     165
     166extern int      yylex(void);
     167extern int      yylineno;
     168extern FILE     *yyin;
     169
     170int yyerror(char *s)
     171{
     172   fprintf(stderr, "%s line %d\n", s, yylineno);
     173   return 1;
     174}
     175%}
     176
     177%token ... déclarer ici les differents types de token
     178
     179%%
     180
     181... ecrire ici les règles grammaticales
     182
     183%%
     184
     185int main(int argc, char *argv[])
     186{
     187   if(argc != 2) {
     188        printf(usage : %s filename\n", argv[0]);
     189        exit(1);
     190   }
     191   yyin = fopen(argv[1],"r");
     192   if(!yyin) {
     193        printf(cannot open file : %s\n", argv[1]);
     194        exit(1);
     195   }
     196   yydebug = 1;
     197   yyparse();
     198   return 0;
     199}
     200}}}
     201
     202La compilation s'effectue comme suit, à charge pour vous d'intégrer ces commandes dans le Makefile.
     203  * L'option -d sur la ligne de commande de '''bison''' active le mode debug, qui vous permet de suivre le déroulement de l'analyse syntaxique du fichier. Il faut de plus affecter une valeur non-nulle à la variable globale yydebug dans la fonction main().
     204  * L'option -t sur la ligne de commande de '''bison''' demande à '''bison''' de générer un  fichier ''vst.tab.h''. Ce fichier est utilisé par '''flex''', et contient la définition des "tokens" utilisés par '''bison'''. Ce fichier doit être inclus dans l'en-tête du fichier ''vst.l'', et la compilation de '''flex''' doit dépendre de ce fichier ''vst.tab.h'' généré par '''bison'''.
     205{{{
     206bison -t -d vst.y
     207gcc -Wall -Werror -o parser vst.tab.c vst.yy.c -lfl
     208}}}
     209Validez l'ensemble en lançant l'analyse syntaxique du fichier ''signal.vst'':
     210{{{
     211$ parser ../signal.vst
     212}}}
     213
     214= Etape 4 : Extension de l'analyseur syntaxique =
     215
     216Une règle de grammaire est construction grammaticale utilisant soit des token reconnus par ''flex'',
     217soit d'autres constructions grammaticales, plus simples. La grammaire a donc une structure arborescente.
     218
     219Dessinez explicitement le graphe représentant la grammaire associée au format ''.vst''.
     220Dans ce graphe, qui a - presque - une structure d'arbre, chaque noeud correspond à une construction grammaticale (c'est à dire une règle de grammaire), et un arc orienté entre deux noeuds X et Y signifie : "La construction grammaticale Y est contenue dans la construction grammaticale X". Les constructions grammaticales élémentaires sont les tokens, et constituent les "feuilles" de l'arbre.
     221
     222La syntaxe de la construction grammaticale correspondant à la déclaration d'un signal a déjà été définie. Il faut donc :
     223  1. Définir la construction grammaticale correspondant à la déclaration d'un port
     224  1. Définir la construction grammaticale correspondant à la déclaration d'un composant
     225  1. Définir la construction grammaticale correspondant à la déclaration d'une entité
     226  1. Définir la construction grammaticale correspondant à la déclaration d'une instance
     227  1. Définir toutes les règles nécessaires à l'analyse du fichier complet.
     228
     229Dans cette étape, on n'attachera aucune action de compilation aux règles grammaticales
     230définies dans le fichier ''vst.y''.
     231
     232Vous pouvez considérer que le TME est terminé lorsque le parser, construit automatiquement
     233par le Makefile à partir des deux fichiers ''vst.l'' et ''vst.y'', est capable de lire et de reconnaitre
     234la totalité du fichier ''exemple.vst''.
     235Vous validerez le parser complet en lançant l'analyse syntaxique du fichier ''exemple.vst''.
     236{{{
     237$ parser ../exemple.vst
     238}}}
     239
     240= Compte-Rendu =
     241
     242Il n'y a pas de compte-rendu écrit à rendre pour ce TME.
     243Il vous sera demandé une démonstration de votre analyseur lexical
     244et de votre analyseur syntaxique au début du TME4.
     245Attention... Cette démonstration pourra porter sur un autre fichier
     246que le fichier ''exemple.vst''.
     247