Changes between Initial Version and Version 1 of 2009/CaoCourseTme4


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

--

Legend:

Unmodified
Added
Removed
Modified
  • 2009/CaoCourseTme4

    v1 v1  
     1{{{
     2#!html
     3<h1>TME4 : Ecriture d'un parser ''.vst'' vers ''lofig''</h1>
     4}}}
     5[[PageOutline]]
     6
     7= Introduction =
     8
     9Ce TME constitue la suite du TME3 sur ''flex'' et ''bison''.  Cette seconde partie a pour but de
     10vous faire construire en mémoire la structure de données ''lofig'' présentée en cours.
     11A chaque règle importante de la grammaire correspond la création d'un objet de la
     12structure de données ''lofig''.
     13
     14Nous faisons l'hypothèse que l'analyseur lexical et l'analyseur syntaxique réalisés
     15dans le TME3 sont achevés et opérationnels.
     16Vous êtes donc  invités à utiliser vos propres fichiers ''vst.l'' et ''vst.y'', mais vous pouvez également
     17utiliser les fichiers ''vst.l'' et ''vst.y'' fournis avec ce TME.
     18
     19'''Attention''' : ces fichiers contiennent délibérement quelques erreurs, que vous devrez corriger,
     20afin de vous obliger à les comprendre.
     21
     22= Etape 1 : Communication entre le scaner et le parser =
     23
     24Dans le TME3, portant sur l'analyse syntaxique du format ".vst", le scaner transmettait au parser
     25des numéros de tokens définissant le type des tokens reconnus. cela a permis de vérifier que
     26les règles de grammaire étaient correctement écrites, et que les constructions grammaticales
     27du format ".vst" étaient correctement reconnues.
     28
     29Chaque fois que le scaner reconnait un token, il peut également transmettre au parser
     30une valeur associée à ce token, en utilisant la variable globale {{{yylval}}}.
     31Le type de la valeur associée à un token peut être différent suivant le token
     32(ce peut être une valeur numérique, ou un pointeur sur chaîne de caractères, ou autre chose).
     33Il faut donc définir, pour chaque token auquel on souhaite associer une valeur,
     34le type de la valeur qui sera stockée dans la variable {{{yylval}}}.
     35
     36Dans cette étape, on ne va pas directement construire la structure de données ''lofig''.
     37On va se contenter d'introduire dans le parser les ''actions de compilation'' lui
     38permettant d'afficher sur le terminal, en utilisant la fonction printf(), le texte
     39correspondant aux différentes constructions grammaticales reconnues.
     40On se limitera même à afficher les constructions grammaticales
     41correspondant à la partie {{{entity}}} du fichier analysé, puisque le but est simplement de vérifier
     42le mécanisme de transmission de valeurs entre le scaner et le parser.
     43
     44Il faut pour cela modifier les deux fichiers vst.l et vst.y.
     45
     46 *  Commencez par déterminer quels sont les tokens qui retournent une valeur significative, car les tokens n'ont pas tous besoin de transmettre une valeur. En pratique, il n'y a qu'un type de token qui doit transmettre une valeur. Pour définir le type de la valeur transmise dans le fichier  ''vst.y'', utilisez la construction
     47{{{
     48%token  <type> TOKEN
     49}}}
     50 *  On rappelle que pour chaque token reconnu par le scaner, la chaîne de caractères correspondant à ce token est stockée dans un buffer pointé par la variable {{{yytext}}}, et que le scanner réutilise ce même buffer pour chaque nouveau token. Quand on souhaite que le scanner transmette cette chaîne au parser, il faut que le scanner recopie cette chaîne de caractères dans un '''autre''' buffer et transmette au parser un pointeur sur ce nouveau buffer (dans la variable {{{yylval}}} ). Il faut donc mofifier le fichier vst.l en conséquence.
     51 *  Les valeurs transmises dans la variable {{{yylval}}} ont des types différents, qui dépendent du type du token reconnu. On utilise donc une {{{union}}} pour définir le type génétal de la vatiable {{{yylval}}} dans le fichier ''vst.y'', qui doit donc être modifié en conséquence.
     52{{{
     53%union {
     54             char* string;
     55             void* pointer;
     56             int  index;
     57}
     58}}}
     59 * Pour permettre aux différentes règles du parser de communiquer entre elles, il faut également définir le type de la variable associée à chacune des règles du parser qui renvoient une valeur.  On rappelle que la valeur associée à un token dans une règle est stockée dans la variable {{{$i}}}  (où i est l'index du token dans le membre de droite de la règle), et que la valeur du token défini par la règle  (c'est à dire la valeur du membre de gauche) est stockée dans la variable {{{$$}}}. Modifier le fichier ''vst.y'' pour définir le type des token associés aux règles du parser en utilisant la construction
     60{{{
     61%type <type> règle
     62}}}
     63 *  Ajouter enfin les ''actions de compilation'' associées aux règles qui interviennent dans la partie "entity" du fichier ''exemple.vst''. Pour chaque règle, cette ''action de compilation'' consiste simplement à afficher le texte de la règle en utilisant la fonction printf(). On pourra pour cela définir dans le fichier ''vst.y'' un objet de type {{{port_t}}}, permettant de représenter un ensemble de ports par une liste chaînée. Chaque objet {{{port_t}}} comporte un champs "NAME" définissant son nom, un champs "TYPE" définissant sa direction, et un champs "NEXT" permettant de construire la liste chaînée.  On introduira dans les règles "port" et "ports" les actions permettant de construire la liste des ports, et on utilisera dans la règle "entity" une boucle for pour parcourir cette liste et afficher les ports.
     64{{{
     65typedef struct port {
     66        struct port     *NEXT;
     67        char            *NAME;
     68        int             TYPE;
     69} port_t;
     70}}}
     71
     72'''Avertissement''' : Bison émet un avertissement "type clash on default action", lorsque
     73l'action de compilation n'est pas définie. En effet, il effectue par défaut
     74l'opération {{{{$$ = $1}}}}, et il proteste lorsque les deux tokens n'ont pas le même type.
     75Il faut définir une action de compilation vide {{{{}}}} pour éviter ce problème.''
     76
     77= Etape 2 : Affichage du fichier complet =
     78
     79Dans cette seconde partie, on souhaite complêter les actions de compilation définies
     80dans le fichier vst.y, de façon à afficher la totalité du fichier exemple.vst,
     81sous une forme qui respecte la syntaxe du format .vst.
     82Il faut donc traiter toutes les constructions grammaticales
     83correspondant à la partie "architecture" du fichier.
     84
     85 * On commencera par introduire dans la règle "architecture" les actions de compilations permettant d'afficher le début et la fin de la section "architecture".
     86 * Introduire dans les règles "component" et "signal" les actions de compilation permettant d'afficher les components et les signaux.
     87 * Introduire dans les règles "instances", "links" et "link" les actions de compilation permettant d'afficher les instances. On pourra pour cela définir dans le fichier ".vst" un objet de type {{{link_t}}}, permettant de représenter un ensemble de links sous forme d'une liste chaînée. On pourra s'inspirer de ce qui a été fait dans la première étape pour l'objet {{{port_t}}}.
     88 * Vérifier que le fichier texte généré par votre parser respecte la syntaxe du format ".vst", en utilisant le parser pour analyser le fichier qu'il a généré.
     89
     90= Etape 3 : Construction de la structure ''lofig'' =
     91
     92La construction de la structure de données ''lofig'' fait appel à des fonctions spéficiques.
     93Une page de manuel existe pour chacun des objets de cette structure et chacune
     94de ces fonctions.  Nous vous invitons à les consulter.
     95
     96Les différents objets dont vous aurez besoin sont:
     97 *  {{{lofig}}} pour représenter l'{{{entity}}} et les {{{component}}}s;
     98 *  {{{losig}}} pour représenter les {{{signal}}}s;
     99 *  {{{loins}}} pour représenter les {{{instance}}}s;
     100 *  {{{locon}}} pour représenter les {{{port}}}s;
     101 *  {{{chain}}} permet de construire des listes chaînées.
     102
     103La structure ''chain'' (parfois appelée ''bip'', comme ''bipointeur'') contient deux pointeurs, et
     104permet de construire des ensembles d'objets de même type, sous forme de listes chaînées.
     105{{{
     106typedef struct chain {
     107                struct chain     *NEXT;
     108                void             *DATA;
     109} chain_list;
     110}}}
     111
     112Les différentes fonctions dont vous aurez besoin sont:
     113 * {{{mbkenv()    }}} pour initialiser {{{Alliance}}}.
     114 * {{{addlofig()  }}} pour créer l'{{{entity}}} et les {{{component}}}s;
     115 * {{{getlofig()  }}} qui renvoie un pointeur vers une figure désignée par son nom;
     116 * {{{addlocon()  }}} pour créer les {{{port}}}, aussi bien dans les figures que dans les instances;
     117 * {{{addlosig()  }}} pour créer les {{{signal}}}s;
     118 * {{{addloins()  }}} pour créer les {{{instance}}}s;
     119 * {{{addchain()  }}} pour créer les bipointeurs;
     120 * {{{reverse()   }}} pour «renverser» l'ordre des éléments dans une liste de type chain;
     121 * {{{freechain() }}} pour libérer une liste créée par {{{addchain}}};
     122 * {{{namealloc() }}} pour insérer tous les noms dans un dictionnaire.
     123
     124La fonction {{{mbkenv() }}} ne prend aucun paramètre et ne rend rien mais elle intialise
     125un certain nombre de variables globales et elle lit l'environnement unix concernant Alliance.
     126Elle doit etre invoquée au début de la fonction main().
     127
     128Grâce à la fonction {{{namealloc() }}} différents pointeurs représentant la même chaîne de caractère
     129(et donc le même nom) pointent sur une unique zone de mémoire, permettant de tester l'identité
     130entre deux noms par un simple test d'égalité des pointeurs.
     131 
     132Un fichier utilisant ces types et fonctions doit inclure le fichier {{{alliance.h}}},
     133et l'édition de liens doit comporter {{{-lalliance}}}.  Ces fichiers référencés se trouvent
     134sous {{{~encadr/cao/include}}} et {{{~encadr/cao/lib}}}.  Modifiez vos sources
     135et votre {{{Makefile}}} en conséquence.
     136
     137'''Indication''' : Pour construire la structure de données ''lofig'', on est amené à manipuler plusieurs
     138structures de type ''lofig'' : On a une structure ''lofig'' correspondant à l'{{{entity}}} dont on souhaite
     139construire la net-list, mais on est amené à construire une structure ''lofig'' pour chacune
     140des figures instanciées (c'est à dire pour chacun des {{{component}}}). Les structures
     141lofig associées aux {{{component}}} sont des boîtes "vides", qui ne contiennent que
     142la liste de ports, mais pas d'instances et pas de signaux.
     143Vous utiliserez deux variables globales, l'une pointant sur la figure représentant
     144l'{{{entity}}}, et l'autre pointant sur le {{{component}}} en cours d'analyse,
     145et vous construirez la structure de donnée dans l'ordre suivant:
     146
     147 1. créez la figure;
     148 1. créez les ports de la figure et les signaux externes;
     149 1. créez les components;
     150 1. créez les signaux internes;
     151 1. créez les instances.
     152   
     153Vous ferez l'hypothèse simplificatrice que les connecteurs de l'instance (construction {{{port map}}} )
     154sont dans le même ordre que les connecteurs du modèle (construction {{{component}}} );
     155
     156Pour vous aider à déboguer et vérifier que la construction est correcte, vous pouvez utiliser
     157la fonction {{{viewlofig() }}}. Vous pouvez également sauvegarder sur disque la structure de données
     158construite en mémoire en utilisant la fonction {{{savelofig() }}}.
     159Il est préférable de changer le nom de la figure avant d'effectuer la sauvegarde pour éviter
     160d'écraser le fichier initial, sans oublier d'utiliser la fonction {{{namealloc() }}}.
     161
     162= Compte-Rendu =
     163
     164Vous n'avez pas de compte-rendu écrit à rendre pour ce TME4.
     165Il vous sera demandé une démonstation du parser ''.vst'' vers ''lofig'' au début du TME5.