<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
  <articleinfo>
    <title>Lex and YACC primer/HOWTO</title>

    <releaseinfo>v0.8</releaseinfo>

    <pubdate>2004/09/20 07:14:23</pubdate>

    <author>
      <firstname>Bert</firstname>

      <surname>Hubert</surname>

      <affiliation>
        <orgname>PowerDNS BV</orgname>

        <address>
           <email>bert@powerdns.com</email>
         </address>
      </affiliation>

      <firstname>Jeffrey</firstname>

      <surname>Sinclair</surname>

      <email>jeff CHEZ bab POINT com</email>
    </author>

    <abstract>
      <para>Ce document tente vous vous aider �� commencer �� utiliser Lex and
      YACC</para>
    </abstract>
  </articleinfo>

  <section>
    <title>Introduction</title>

    <para>Bienvenue, cher lecteur.</para>

    <para>Quelle que soit la dur��e durant laquelle vous avez programm�� sous un
    environnement Unix, vous avez rencontr�� les programmes <emphasis
    role="bold">mystiques</emphasis> Lex et YACC, ou tels qu'ils sont connus
    des utilisateurs de GNU/Linux �� travers le��monde, Flex et Bison; o�� Flex
    est une impl��mentation de Lex par Vern Paxson et Bison la version GNU de
    YACC. Nous allons appeler ces programmes Lex et YACC dans ce document -
    les nouvelles versions sont compatibles "vers le haut", vous pouvez donc
    utiliser Flex et Bison pour essayer nos exemples.</para>

    <para>Ces programmes sont tr��s utiles, mais comme pour votre compilateur
    C, leur page "man" n'explique pas le langage qu'ils comprennent, ni
    comment les utiliser. YACC utilis�� en combinaison avec Lex est vraiment
    surprenant, cependant, la page "man" ne d��crit pas comment int��grer du
    code g��n��r�� par Lex dans votre programme en Bison.</para>

    <section>
      <title>Ce que ce document n'est PAS</title>

      <para>Il existe de nombreux livres qui traitent de Lex et YACC. Lisez
      ces ouvrages de toute mani��re si vous souhaitez en savoir plus. Ils
      apportent beaucoup plus d'information que ce nous sommes en mesure de
      voir ici. Vous pouvez consulter la section ����lectures pour approfondir����
      �� la fin. Ce document a pour but de vous aider �� vous en sortir lors de
      la cr��ation de vos premiers programmes avec Lex &amp; YACC.</para>

      <para>La documentation fournie avec Lex &amp; YACC est elle aussi
      excellente, mais peu p��dagogique. Elle est cependant compl��mentaires
      avec mon Howto, et est aussi r��f��renc��e �� la fin.</para>

      <para>Je ne suis absolument pas un expert de Lex &amp; Yacc. lorsque
      j'ai commenc�� �� ��crire ce document, j'avais exactement deux jours de
      pratique. Tout ce que j'ai cherch�� �� faire, c'est rendre ces deux jours
      les plus simple possibles pour vous.</para>

      <para>N'attendez pas du HowTo qu'il vous montre comment coder proprement
      en Lex et YACC. Les exemples ont ��t�� laiss�� volontairement tr��s simples
      et il y a s��rement de meilleures mani��res de les ��crire. Si vous savez
      comment, s'il vous pla��t, contactez moi.</para>
    </section>

    <section>
      <title>T��l��chargement</title>

      <para>Notez que vous pouvez t��l��charger tous les exemples montr��s sous
      forme de code source. Visitez la Homepage pour plus de d��tails.</para>
    </section>

    <section>
      <title>Licence</title>

      <para>Copyright (c) 2001 by bert hubert. This material may be
      distributed only subject to the terms and conditions set forth in the
      Open Publication License, vX.Y or later (the latest version is presently
      available at http://www.opencontent.org/openpub/).</para>

      <para>Traduction �� titre informative et sans valeur juridique :</para>

      <para>Copyright (c) 2001, bert hubert. Ce programme ne peut ��tre
      distribu�� que selon les conditions g��n��rales ��tablies dans l'�� Open
      Publication License ��, vX.Y ou ult��rieure (la derni��re version est
      disponible �� http://www.opencontent.org/openpub/).</para>
    </section>
  </section>

  <section>
    <title>Ce que Lex &amp; YACC peuvent faire pour vous</title>

    <para>Utilis��s proprement, ces langages vous permettent d'analyser
    facilement des langages complexes. C'est un sacr�� coup de pouce lorsque
    vous souhaitez lire un fichier de configuration, ou que vous souhaitez
    ��crire un compilateur pour un langage que vous (ou n'importe qui d'autre)
    avez invent��.</para>

    <para>Avec un peu d'aide, ce que j'esp��re que ce document vous apportera,
    vous d��couvrirez finalement que vous n'��crirez plus jamais d'analyseur
    syntaxique �� la main: Lex &amp; YACC sont les outils pour le faire.</para>

    <section>
      <title>Ce que fait chaque programme</title>

      <para>M��me si ces programmes fonctionnent de mani��re optimale ensemble,
      ils servent chacun �� un but diff��rent. Les prochains chapitres
      expliqueront exactement l'action de chacun d'entre eux.</para>
    </section>
  </section>

  <section>
    <title>Lex</title>

    <para>Ce programme g��n��re ce que l'ont appelle un analyseur lexical. Il
    s'agit d'une fonction qui prend comme argument un flux de caract��res, et
    d��s qu'il aper��oit un groupe qui correspond �� un mot clef, effectue une
    certaine action. Un exemple tr��s simple :</para>

    <programlisting>
%{
#include &lt;stdio.h&gt;
%}

%%
stop	printf("Stop command received\n");
start	printf("Start command received\n");
%%
</programlisting>

    <para>La premi��re partie, entre les paires %{ et %}, est inclue
    directement dans la sortie. Nous avons besoin de cela, car nous
    utiliserons printf, qui est d��finit dans stdio.h, plus tard.</para>

    <para>Les parties sont s��par��es par %%, donc la premi��re ligne de la
    seconde section commence par le mot-clef ����stop����. A chaque fois que le
    mot-clef ����stop���� est rencontr�� dans l'entr��e, le reste de la ligne ( ici
    un appel �� printf() ) est ex��cut��.</para>

    <para>En plus de ����stop���� nous avons aussi d��finit ����start����, qui par
    ailleurs effectue sensiblement la m��me chose.</para>

    <para>Nous terminons la seconde partie avec %% encore.</para>

    <para>Pour compiler l'exemple 1, faire ceci:</para>

    <screen>
lex example1.l
cc lex.yy.c -o example1 -ll
</screen>

    <note>
      <para>si vous utilisez Flex, au lieu de Lex, vous pouvez avoir �� changer
      -|| en -lfl ans le script de compilation. RedHat 6.x et SuSE en ont
      besoin aussi, m��me en utilisant Flex au lieu de Lex !</para>
    </note>

    <para>Ceci g��n��rera un fichier ����exemple1����. Si vous le lancez, il
    attendra que de vous tapiez une entr��e. M��me si vous tapez une entr��e qui
    n'est pas ����match��e���� par un mot-clef (ici stop et start) it's output
    again. Si vous entrez 'stop', il affichera la sortie suivante ����stop
    command received����;</para>

    <para>Terminate with a EOF (^D).</para>

    <para>Vous pouvez vous demander comment fonctionnent ces programmes, car
    nous n'avons pas d��finit de fonction main(). Cette fonction est d��finit
    pour vous dans libl (liblex) que nous avons compil�� avec le programme
    gr��ce �� la commande -ll.</para>

    <section>
      <title>Analyser les expressions r��guli��res</title>

      <para>Cet exemple n'��tait pas tr��s utile en soit, et notre suivant ne
      sera pas mieux. Il va cependant nous montrer comment utiliser les
      expressions r��guli��res en Lex, qui seront tr��s utiles plus tard.</para>

      <para>Example 2:</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
%}

%%
[0123456789]+		printf("NUMBER\n");
[a-zA-Z][a-zA-Z0-9]*	printf("WORD\n");
%%
</programlisting>

      <para>Ce fichier Lex explique deux types de mots cl��s (symboles): WORD
      et NUMBER. Les expressions r��guli��res peuvent ��tre un peu intimidantes,
      mais avec un peu de travail, elles sont tr��s simples �� comprendre.
      Examinons le mot cl�� NUMBER:</para>

      <para>[0123456789]+</para>

      <para>Cela signifie: une s��quence de un ou plus de caract��res du groupe
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }. On aurait aussi pu faire plus court
      :</para>

      <para>[0-9]+</para>

      <para>Maintenant, le mot cl�� WORD est un peu plus complexe:</para>

      <para>[a-zA-Z][a-zA-Z0-9]*</para>

      <para>a premi��re partie ne rep��re qu'un et un seul caract��re entre 'a'
      et 'z', ou entre 'A' et 'Z'.En d'autres termes, une lettre. Cette lettre
      initiale doit ensuite ��tre suivie par z��ro ou plus de caract��res qui
      sont soit une lettre, soit un chiffre. Pourquoi avoir utilis�� un
      ast��risque ici ? Le '+' signifie 1 ou plus de rep��rages, mais un mot
      peut tr��s bien n'��tre qu'un seul caract��re, que nous avons alors d��j��
      match��. La seconde partie peut donc n'avoir rien �� matcher, nous
      ��crivons donc un '*'.</para>

      <para>De cette mani��re , nous avons sing�� le comportement de nombreux
      langages de programmation qui requi��rent qu'un nom de variable ����doive����
      commencer par une lettre, mais puisse contenir des chiffres ensuite. En
      d'autres mots 'temperature1' est un nom valide, mais '1temperature��' ne
      l'est pas.</para>

      <para>Essayez de compiler Example2, tout comme Exemple1, et nourrissez
      le d'un peu de texte. Voici une <emphasis role="bold">session</emphasis>
      d'��chantillons:</para>

      <screen>
$ ./example2
foo
WORD

bar
WORD

123
NUMBER

bar123
WORD

123bar
NUMBER
WORD
</screen>

      <para>Vous pourriez aussi vous demander pourquoi il y a un retour �� la
      ligne dans la sortie. La raison est simple : il ��tait dans l'entr��e, n'a
      ��t�� match�� nul part, il appara��t donc dans la sortie.</para>

      <para>La page de man de Flex documente les expressions r��guli��res en
      d��tail. Beaucoup de gens trouvent que cellle des expressions r��guli��res
      de perl est aussi tr��s utile, m��me si Flex n'impl��mente pas tout ce que
      perl fait.</para>

      <para>V��rifiez que vous n'avez pas cr��e de match de taille nulle comme
      '[0-9]*', votre lexer pourrait ��tre perdu et pourrait commencer ��
      matcher des cha��nes vides en boucle</para>
    </section>

    <section>
      <title>Un exemple plus compliqu�� pour une syntaxe proche du C</title>

      <para>Imaginons que nous voulions analyser un fichier qui ressemble ��
      ceci:</para>

      <programlisting>
logging {
	category lame-servers { null; };
	category cname { null; };
};

zone "." {
        type hint;
        file "/etc/bind/db.root";
};
</programlisting>

      <para>On voit clairement un certain nombre de cat��gories (symboles) dans
      ce fichier:</para>

      <itemizedlist>
        <listitem>
          <para>WORD, (mot) comme 'zone' et 'type'</para>
        </listitem>

        <listitem>
          <para>FILENAME, (nom de fichier) comme '/etc/bind/db.root'</para>
        </listitem>

        <listitem>
          <para>QUOTE, (guillemets)comme celles entourant le nom du
          fichier</para>
        </listitem>

        <listitem>
          <para>OOBRACE, (crochet ouvrant) {</para>
        </listitem>

        <listitem>
          <para>EBRACE, (crochet fermant) }</para>
        </listitem>

        <listitem>
          <para>SEMICOLON, (point virgule) ;</para>
        </listitem>
      </itemizedlist>

      <para>Le fichier correspondant en Lex est Exemple 3:</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
%}

%%
[a-zA-Z][a-zA-Z0-9]*    printf("WORD ");
[a-zA-Z0-9\/.-]+        printf("FILENAME ");
\"                      printf("QUOTE ");
\{                      printf("OBRACE ");
\}                      printf("EBRACE ");
;                       printf("SEMICOLON ");
\n                      printf("\n");
[ \t]+                  /* ignore whitespace */;
%%
</programlisting>

      <para>Quand nous donnons notre ficher �� notre <emphasis
      role="bold">lexer</emphasis> g��n��r�� par ce fichier Lex (en utilisant
      example3.compile), nous obtenons:</para>

      <screen>
WORD OBRACE 
WORD FILENAME OBRACE WORD SEMICOLON EBRACE SEMICOLON 
WORD WORD OBRACE WORD SEMICOLON EBRACE SEMICOLON 
EBRACE SEMICOLON 

WORD QUOTE FILENAME QUOTE OBRACE 
WORD WORD SEMICOLON 
WORD QUOTE FILENAME QUOTE SEMICOLON 
EBRACE SEMICOLON 
</screen>

      <para>Lorsque nous comparons ceci avec le fichier cit�� plus haut, il est
      clair que nous l'avons 'symbolis��e'. Chaque partie du fichier de
      configuration �� ��t�� analys��e, et convertie en symbole.</para>

      <para>Et c'est exactement ce donc nous avons besoin pour utiliser YACC
      Correctement.</para>
    </section>

    <section>
      <title>Ce que nous avons vu</title>

      <para>Nous avons vu que Lex est capable de lire une entr��e arbitraire,
      et d'analyser ce qu'est chaque partie. C'est ce qu'on appelle l'analyse
      lexicale.</para>
    </section>
  </section>

  <section>
    <title>YACC</title>

    <para>YACC peut analyser syntaxiquement un flux compos�� de symboles avec
    certaines valeurs. Cela d��crit parfaitement la relation entre YACC et Lex.
    Yacc n'a aucune id��e de ce que sont les <emphasis role="bold">'flux en
    entr��e��'</emphasis>, il a besoin de symboles au pr��alablement trait��s.
    Alors que vous pourriez ��crire vous m��me votre propre analyseur lexical,
    nous allons laisser Lex s'en charger.</para>

    <para>Une note sur les grammaires et les analyseurs syntaxiques. Lorsque
    YACC �� vu le jour, cet outil ��tait utilis�� pour analyser les fichier
    d'entr��e des compilateurs. Les programmes ��crits pour un langage de
    programmation ne sont pas ambigus (cad qu'ils n'ont qu'un seul sens). En
    tant que tel, YACC ne peut pas surmonter une ambigu��t�� ou un conflit
    d��calage/r��duction. Vous pourrez en apprendre plus sur YACC et les
    probl��mes d'ambigu��t�� ou les conflits d��calage/r��duction dans le chapitre
    'Conflits��'.</para>

    <section>
      <title>4.Un contr��leur simple de thermostat</title>

      <para>Imaginons que nous ayons un thermostat que nous voulons contr��ler
      avec un langage simple. Un dialogue avec le thermostat pourrait
      ressembler �� ceci :</para>

      <screen>
heat on
	Heater on!
heat off
	Heater off!
target temperature 22
	New temperature set!
</screen>

      <para>Les symboles que nous avons besoin de reconna��tre sont : heat,
      on/off (STATE), target, temp��rature, NUMBER.</para>

      <para>L'analyseur lexical Lex (Exemple 4) est :</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
#include "y.tab.h"
%}
%%
[0-9]+                  return NUMBER;
heat                    return TOKHEAT;
on|off                  return STATE;
target                  return TOKTARGET;
temperature             return TOKTEMPERATURE;
\n                      /* ignore end of line */;
[ \t]+                  /* ignore whitespace */;
%%
</programlisting>

      <para>Nous pouvons remarquer deux changements importants. Premi��rement,
      nous 'incluons' le fichier 'y.tab.h', et ensuite nous n'affichons plus
      rien, nous retournons les noms des ymboles. Ce changement est caus�� par
      le fait que nous fournissons d��sormais le tout �� YACC, ce qui n'a plus
      aucun rapport avec ce que nous obtenons �� l'��cran. <emphasis
      role="bold">Y.tab.h has definitions for these tokens.</emphasis></para>

      <para>Mais d'o�� viens y.tab.h ? Il est g��n��r�� par YACC �� partir du
      fichier grammaire que nous sommes allons cr��er. Comme notre langage est
      tr��s basique, voil�� notre grammaire:</para>

      <programlisting>
commands: /* empty */
        | commands command
        ;

command:
        heat_switch
        |
        target_set
        ;

heat_switch:
        TOKHEAT STATE
        {
         	printf("\tHeat turned on or off\n");
        }
        ;

target_set:
        TOKTARGET TOKTEMPERATURE NUMBER
        {
         	printf("\tTemperature set\n");
        }
        ;
</programlisting>

      <para>La premi��re partie est ce que j'appelle la 'racine'. Elle nous
      explique que nous avons des commandes, et que ces commandes consistent
      en <emphasis role="bold">individual 'command' parts</emphasis>. Comme
      vous pouvez le voir, cette r��gle es tr��s r��cursive car elle contient
      encore le mot ��command����. Ce qui signifie que le programme est d��sormais
      capable de r��duire une s��rie de commandes une par une. Lisez le chapitre
      'Comment fonctionnent Lex et YACC en d��tail��' pour des d��tails
      importants sur la r��cursivit��.</para>

      <para>la seconde r��gle d��finit ce qu'est une commande. Nous ne
      supportons que deux types de commande, la commande 'heat_switch' et la
      commande 'target_set'. C'est ce que le symbole |- signifie: une commande
      peut ��tre ou un 'heat-switch' ou un 'target-set'.</para>

      <para>Un heat-switch consiste en un symbole HEAT qui est simplement le
      mot 'heat' suivit d'un ��tat (que nous d��finirons dans le Fichier Lex
      comme 'on' ou 'off').</para>

      <para>Plus compliqu��: le 'target_set' qui consiste en un symbole TARGET
      (le mot target), le symbole TEMPERATURE (le mot temperature) et un
      nombre.</para>

      <section>
        <title>Un fichier YACC complet</title>

        <para>La section pr��c��dente n'a montr��e que la partie grammaticale du
        fichier YACC, mais il y a plus. Voici l'en t��te que nous avons
        omis:</para>

        <programlisting>
%{
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
 
void yyerror(const char *str)
{
 	fprintf(stderr,"error: %s\n",str);
}
 
int yywrap()
{
 	return 1;
} 
  
main()
{
  	yyparse();
} 

%}

%token NUMBER TOKHEAT STATE TOKTARGET TOKTEMPERATURE
</programlisting>

        <para>La fonction yyerror() est appel��e par YACC si il trouve une
        erreur. Nous renvoyons simplement le message re��u, mais il y a des
        choses plus intelligente �� faire avec. Lisez la section ����lectures
        pour approfondir���� pour en savoir plus.</para>

        <para>La fonction yywarp() peut ��tre utilis��e pour continuer la
        lecture depuis un autre fichier. C'est appel��e �� EOF et vous pouvez
        ensuite ouvrir un autre fichier et renvoyer 0; ou renvoyer 1 qui
        indique qu'il s'agit de la fin. Pour en savoir plus, lisez le chapitre
        : 'Comment fonctionnent Lex et YACC en d��tail��'.</para>

        <para>Ensuite, il y a la fonction main(), qui ne fait rien de
        particulier, mais lance le processus</para>

        <para>La derni��re ligne d��finit simplement les symboles qui seront
        utilis��s. <emphasis role="bold">Ce sont les sorties qui utilisent
        y.tab.h si YACC est appel�� avec l'option -d &lt;-- ici je ne suis pas
        sur d'avoir compris le sens de la phrase en anglais.</emphasis></para>
      </section>

      <section>
        <title>Compiler et utiliser le contr��leur de thermostat</title>

        <screen>
lex example4.l
yacc -d example4.y
cc lex.yy.c y.tab.c -o example4 
</screen>

        <para>Certaines choses ont chang��es. Nous appelons aussi YACC pour
        compiler notre grammaire, ce qui cr��e y.tab.c et y.tab.h. Nous
        appelons appelons ensuite Lex comme d'habitude. Lorsque nous
        compilons, nous retirons le drapeau -ll: nous avons d��sormais notre
        propre fonction main() et nous n'avons pas besoin de celle fournis par
        libl.</para>

        <note>
          <para>Si vous obtenez une erreur indiquant que votre compilateur
          n'est pas capable de trouver 'yylval��', ajoutez ceci �� l'��xemple4.1,
          juste sous #include &lt;y.tab.h&gt;:</para>

          <programlisting>
extern YYSTYPE yylval;
</programlisting>

          <para>Ceci est expliqu�� dans le chapitre 'comment Lex et YACC
          fonctionnent en d��tail.</para>
        </note>

        <para><emphasis role="bold">Une session d'exemple </emphasis>:</para>

        <screen>
$ ./example4 
heat on
	Heat turned on or off
heat off
	Heat turned on or off
target temperature 10
	Temperature set
target humidity 20
error: parse error
$
</screen>

        <para>Ce n'est pas vraiment ce que l'ont avait pr��vu d'obtenir, mais
        pour garder une courbe d'apprentissage praticable nous ne pouvons pas
        montrer toutes les possibilit��s en une fois.</para>
      </section>
    </section>

    <section>
      <title>��tendre le thermostat afin de supporter les param��tres</title>

      <para>Comme nous l'avons vu, nous analysons d��sormais syntaxiquement les
      commandes du thermostat correctement, et marquons m��mes les erreurs
      correctement. Mais comme vous pouvez l'avoir devin�� d'apr��s le titre le
      programme n'a aucune id��e de ce qu'il doit faire, <emphasis
      role="bold">it does not get passed any of the values you
      enter</emphasis>.</para>

      <para>Commen��ons par ajouter la possibilit�� de lire la nouvelle
      temp��rature cible. Pour faire cela, nous avons besoin de lire le NUMBER
      <emphasis role="bold">match��</emphasis> dans l'analyseur lexical pour le
      convertir en valeur enti��re, qui pourra ensuite ��tre lue avec le
      YACC.</para>

      <para>A chaques fois que le Lex <emphasis role="bold">matche</emphasis>
      une cible, il place le texte <emphasis role="bold">match��</emphasis>
      dans la suite de caract��res 'yytext'. YACC, lui, esp��re trouver une
      valeur dans la variable 'yylval'. Dans l'exemple 5, nous voyons la
      solution triviale:</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
#include "y.tab.h"
%}
%%
[0-9]+                  yylval=atoi(yytext); return NUMBER;
heat                    return TOKHEAT;
on|off                  yylval=!strcmp(yytext,"on"); return STATE;
target                  return TOKTARGET;
temperature             return TOKTEMPERATURE;
\n                      /* ignore end of line */;
[ \t]+                  /* ignore whitespace */;
%%
</programlisting>

      <para>Comme vous pouvez le constater, nous appelons atoi() sur yytext,
      et pla��ons le r��sultat dans yyval, o�� YACC peut le lire. Nous faisons ��
      peu pr��s la m��me chose pour le match STATE, nous le comparons �� 'on', et
      initialisons yylval �� 1 si c'est ��gal. Notez qu'avoir deux match separ��s
      pour 'on' et 'off' dans lex produirai un code plus rapide, mais j'ai
      voulu montrer une action plus complexe pour changer.</para>

      <para>Maintenant, nous devont apprendre YACC �� le supporter. Ce qui est
      appell�� yylval avec Lex est appel�� diff��remment avec YACC. Examinons la
      r��gle r��glant la nouvelle temperature cible: </para>

      <programlisting>
target_set: 
	TOKTARGET TOKTEMPERATURE NUMBER
	{
         	printf("\tTemperature set to %d\n",$3);
	}
        ;
</programlisting>

      <para>Pour acc��der �� la valeur de la troisi��me partie de la r��gle (cad,
      NUMBER), nous avons besoin d'utiliser $3. Quelque soit le moment du
      retour de yylex(), les contenus de yylval sont attach�� au terminal, qui
      peuvent ��tre atteint par le <emphasis role="bold">$-constructeur. &lt;-
      je ne suis pas sur du sens</emphasis></para>

      <para>Pour aller plus loin, observons la nouvelle r��gle du 'heat
      switch':</para>

      <programlisting>
heat_switch:
        TOKHEAT STATE
        {
         	if($2)
         	        printf("\tHeat turned on\n");
	 	else
                        printf("\tHeat turned off\n");
        }
        ;
</programlisting>

      <para>Si vous lancez maintenant l'exemple5, il prend en compte
      correctement ce que vous avez entr��.</para>
    </section>

    <section>
      <title>Analyser un fichier de configuration</title>

      <para>Rappelons une partie du fichier de configuration que nous avons vu
      plus haut:</para>

      <programlisting>
zone "." {
        type hint;
        file "/etc/bind/db.root";
};
</programlisting>

      <para>Souvenez vous que nous avons d��j�� ��crit un Lexer pour ce fichier.
      Tout ce dont nous avons besoin maintenant c'est d'��crire la grammaire de
      YACC et modifier l'analyseur lexical (aussi appel�� Lexer) pour qu'il
      renvoi les donn��es dans un format compr��hensible pour YACC.</para>

      <para>Dans l'analyseur lexicalde l'exemple6, nous avons :</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
#include "y.tab.h"
%}

%%

zone			return ZONETOK;
file			return FILETOK;
[a-zA-Z][a-zA-Z0-9]*    yylval=strdup(yytext); return WORD;
[a-zA-Z0-9\/.-]+        yylval=strdup(yytext); return FILENAME;
\"                      return QUOTE;
\{                      return OBRACE;
\}                      return EBRACE;
;                       return SEMICOLON;
\n                      /* ignore EOL */;
[ \t]+                  /* ignore whitespace */;
%%
</programlisting>

      <para>Si vous observez attentivement, vous pouvez voir que yylval est
      diff��rent ! Nous n'attendons plus de lui d'��tre un entier, mais nous
      acceptons le fait que ce soit un char *. Dans un but de simplicit��, nous
      utilisons strdup et gaspillons beaucoup de ressource m��moires. Veuillez
      noter que cela peut ne pas ��tre un probl��me dans beaucoup de cas,
      lorsque par exemple vous n'avez besoin d'analyser qu'un fichier, puis de
      quitter.</para>

      <para>Nous souhaitons stocker des cha��nes de caract��re, car nous ne
      travaillons presque qu'avec des noms : nom de fichiers et noms de zone?.
      Plus tard, dans un autre chapitre, nous expliquerons comment traiter
      diff��rents types de donn��es.</para>

      <para>Pour indiquer �� YACC le nouveau type de yylval, nous ajoutons
      cette ligne �� l'en-t��te de notre grammaire YACC:</para>

      <programlisting>
#define YYSTYPE char *
</programlisting>

      <para>La grammaire elle-m��me est encore une fois plus compliqu��e. Nous
      la d��coupons en parts pour la rendre plus digeste:</para>

      <programlisting>
commands:
	|	 
	commands command SEMICOLON
	;


command:
	zone_set 
	;

zone_set:
	ZONETOK quotedname zonecontent
	{
		printf("Complete zone for '%s' found\n",$2);
	}
	;
</programlisting>

      <para>Ceci est l'introduction, comprenant la racine r��cursive
      pr��c��demment cit��e. Veuillez noter que nous pr��cisons que chaque
      commande se termine par un ;. (et les commandes sont donc s��par��es par
      des ;). Nous d��finissons un type de commande : 'zone_set'. Elle consiste
      en un symbole ZONE (le mot 'zone'), suivit par un 'quotedname' et le
      'zone content'. Ce 'zonecontent��' d��bute simplement :</para>

      <programlisting>
zonecontent:
	OBRACE zonestatements EBRACE 
</programlisting>

      <para>Il a besoin de commencer avec un OBRACE, un crochet ouvert {. Puis
      suit les 'zonestatement's, suivits par un EBRACE, crochet ferm�� }.
      </para>

      <programlisting>
quotedname:
        QUOTE FILENAME QUOTE
        {
         	$$=$2;
        }
</programlisting>

      <para>Cette section d��finit ce qu'est un quotedname : un FILENAME (nom
      de fichier) entre QUOTEs (guillemets). Puis il indique quelque chose de
      sp��cial: la valeur d'un symbole 'quotedname' est la valeur du FILENAME.
      Cela signifie que la valeur du quoted name est le nom du fichier sans
      les quotes</para>

      <para>C'est ce que fait la commande magique '$$=$2;' . Elle dit : ma
      valeur est la valeur de ma seconde partie. Alors que le quoted name est
      d��sormais referenc�� par d'autres r��gles, et que vous acc��dez �� sa valeur
      gr��ce au <emphasis role="bold">$-constructeur</emphasis>, vous voyez la
      valeur que nous avons fix�� ici avec $$=$2.</para>

      <note>
        <para><emphasis role="bold"><emphasis>Cette grammaire bute sur les
        noms de fichiers ne comportant pas de '.' ou de '/'
        </emphasis></emphasis></para>
      </note>

      <programlisting>
zonestatements:
	|
	zonestatements zonestatement SEMICOLON
	;

zonestatement:
	statements
	|
	FILETOK quotedname 
	{
		printf("A zonefile name '%s' was encountered\n", $2);
	}
	;
</programlisting>

      <para>Il s'agit d'une instruction g��n��rale qui d��tecte tous les types
      d'instructions �� l'int��rieur des blocs 'zone'. Nous apercevons ici
      encore de la r��cursivit��.</para>

      <programlisting>
block: 
	OBRACE zonestatements EBRACE SEMICOLON
	;

statements:
	| statements statement
	;

statement: WORD | block | quotedname
</programlisting>

      <para>Ceci d��finit un bloc et les instructions qui peuvent ��tre trouv��e
      �� l'int��rieur.</para>

      <para>Lorsque l'on ex��cute le tout, la sortie ressemble �� cela : </para>

      <screen>
$ ./example6
zone "." {
        type hint;
        file "/etc/bind/db.root";
        type hint;
};
A zonefile name '/etc/bind/db.root' was encountered
Complete zone for '.' found
</screen>
    </section>
  </section>

  <section>
    <title>Faire un Parseur en C++</title>

    <para>Bien que Lex &amp; YACC soient ant��rieurs �� C++, il est possible de
    g��n��rer un parseur C++. Flex comprends une option pour g��n��rer un Lexer
    C++, mais nous ne l'utiliserons pas, car YAXX ne sait pas comment
    l'utiliser directement.</para>

    <para>Ma m��thode pr��f��r��e pour cr��er un parseur C++ est de faire g��n��rer ��
    Lex un fichier C clair, et de laisser YACC g��n��rer le code C++. Lorsque
    liez ensuite votre application, vous pouvez avoir quelques probl��mes car
    le code C++ fournit par d��faut ne sera pas capable de trouver les
    fonctions C, sauf si vous avez indiqu�� que ces fonction sont du C
    externe.</para>

    <para>Pour faire cela, faites un en-t��te C dans YACC, comme cela:</para>

    <programlisting>
extern "C"
{
 	int yyparse(void);
 	int yylex(void);  
 	int yywrap()
 	{
 	 	return 1;
        }

}
</programlisting>

    <para>Si vous voulez d��clarer ou changer yydebug, vous devez maintenant le
    faire comme ceci:</para>

    <programlisting>
extern int yydebug;

main()
{
	yydebug=1;
	yyparse();
}
</programlisting>

    <para>Cela est du �� la d��finition d'une r��gle en C++, qui ne permet pas
    plusieurs d��finitions de yydebug.</para>

    <para>Vous pouvez aussi avoir besoin de r��p��ter le #define de YYSTYPE dans
    votre ficher Lex �� cause du v��rificateur de type strict de C++.</para>

    <para>Pour compiler, faites quelque chose comme ceci :</para>

    <screen>
lex bindconfig2.l
yacc --verbose --debug -d bindconfig2.y -o bindconfig2.cc
cc -c lex.yy.c -o lex.yy.o
c++ lex.yy.o bindconfig2.cc -o bindconfig2 
</screen>

    <para>A cause de l'option -o, y.tab.h est d��sormais appel��
    bindconfig2.cc.h, donc prenez le en compte.</para>

    <para>Pour r��sumer: ne vous emb��tez pas �� compiler votre lexer en C++,
    laissez le en C. Faites votre parseur en C++ et expliquez �� votre
    compilateur que certaines fonctions sont des fonctions C avec des
    instructions externes.</para>
  </section>

  <section>
    <title>Comment fonctionnent Lex et YACC en d��tail</title>

    <para>Dans le fichier YACC, vous ��crivez votre propre fonction main(), qui
    appelle yyparse() �� un certain moment. La fonction yyparse()est cr����e pour
    vous par YACC, et finit dans y.tab.c.</para>

    <para>yyparse() lit un flux de symboles/paires de valeurs depuis yylex() ,
    qui doit ��tre aliment��. Vous pouvez coder cette fonction vous m��me, ou
    laisser Lex le faire pour vous. Dans nos exemples, nous avons choisit de
    laisser ce travail �� Lex.</para>

    <para>Ce yylex() ��crit par Lex lit les caract��res depuis un FILE* file
    pointer appell�� yyin. Si vous ne d��finissez pas yyin, il est d��finit par
    d��faut sur l'entr��e standard. <emphasis role="bold">It outputs to yyout,
    which if unset defaults to stdout.</emphasis> Vous pouvez aussi modifier
    yin dans la fonction yywrap() qui est appel��e �� la fin d'un fichier. Elle
    vous permet d'ouvrir un autre fichier et de continuer le parsing.</para>

    <para>Si c'est le cas, faites lui retourner 0. Si vous voulez finir le
    parsing par ce fichier, faites lui retourner 1.</para>

    <para>Chaque appel �� yylex() retourne une valeur enti��re qui repr��sente un
    type de jeton. Cela indique �� YACC quel type de jeton est lu. Le jeton
    peut ��ventuellement avoir une valeur, qui devra ��tre plac��e dans la
    variable yyval.</para>

    <para>Par d��faut yylval est du type int, mais vous pouvez le surcharger
    depuis le fichier YACC en red��finissant #define YYSTYPE.</para>

    <para>Le lexer doit ��tre capable d'acc��der �� yylval. Pour faire cela, il
    doit ��tre d��clar�� dans le champ du lexer comme une variable externe. Le
    YACC original omet de le faire, donc vous devrez ajoutez la ligne suivante
    �� votre lexer: extern YYSTYPE yyval; , juste apr��s le #include
    &lt;y.tab.h&gt;.</para>

    <programlisting>
extern YYSTYPE yylval;
</programlisting>

    <para>Bison, que la plupart des gens utilise, le fait pour vous
    automatiquement. </para>

    <section>
      <title>Valeurs des symboles</title>

      <para>Comme dit pr��c��demment, yylex() a besoin de renvoyer le type de
      jeton rencontr��, et de placer sa valeur dan yylval. Lorsque ces jetons
      sont d��finits avec la commande %token, il leur est assign�� un
      identifiant num��rique commen��ant �� 256.</para>

      <para>A cause de cela, il est possible d'avoir tous els caract��res ascii
      comme jeton. Imaginons que vous ��criviez une calculatrice, jusqu'��
      maintenant, nous aurions ��crit le lexer comme ceci:</para>

      <programlisting>
[0-9]+          yylval=atoi(yytext); return NUMBER;
[ \n]+          /* eat whitespace */;
-               return MINUS;
\*              return MULT; 
\+              return PLUS;
...
</programlisting>

      <para> Notre grammaire YACC aurait donc contenu suivant:</para>

      <programlisting>
	exp: 	NUMBER 
		|
		exp PLUS exp
		|
		exp MINUS exp
		|
		exp MULT exp
</programlisting>

      <para>Tout ceci est compliqu�� pour pas grand chose. En utilisant les
      caract��res comme abr��viations d'identifiants num��riques de jetons, nous
      pouvons r����crire notre lexer comme ceci :</para>

      <programlisting>
[0-9]+          yylval=atoi(yytext); return NUMBER;
[ \n]+          /* eat whitespace */;
.               return (int) yytext[0];
</programlisting>

      <para><emphasis role="bold">This last dot matches all single otherwise
      unmatched characters. &lt;- Cette version ne matche pas les caract��res
      seuls ou non match��s. Je n'arrive pas �� reformuler mais en gros y'a pas
      de match par default ?</emphasis></para>

      <para>Notre grammaire YACC sera donc:</para>

      <programlisting>
	exp: 	NUMBER 
		|
		exp '+' exp
		|
		exp '-' exp
		|
		exp '*' exp
</programlisting>

      <para>Cette version est beaucoup plus courte et beaucoup plus ��vidente.
      Vous n'avez pas besoin de d��clarer ces symboles ascii avec %token dans
      l'en-t��te, ils sont pr��ts �� l'emploi.</para>

      <para>Un autre avantage avec cette construction est que Lex Lex va
      d��sormais matcher tout ce que nous lui envoyons ��� en ��vitant le
      comportement par d��faut qui est de r��p��ter les entr��e non match��es vers
      la sortie standard. Si un utilisateur de la calculatrice utilise ^, par
      exemple, il va d��sormais g��n��rer une erreur de parsing, au lieu d'��tre
      renvoy�� vers la sortie standard.</para>
    </section>

    <section>
      <title>R��cursivit��: 'Droit est maladroit��'</title>

      <para>La r��cursivit�� est un aspect vital de YACC. Sans elle, vous ne
      pouvez pas sp��cifier que ce fichier consiste en une s��quence de
      commandes ou d'instructions ind��pendantes.YACC ne s'int��resse qu'a la
      premi��re r��gle, ou celle d��sign��e comme r��gle de d��part, par le symbole
      '%start'.</para>

      <para>La r��cursivit�� dans YACC existe en deux tendances : gauche ou
      droite. La r��cursivit�� �� gauche qui est celle que vous devriez utiliser
      la plupart du temps, ressemble �� ��a:</para>

      <programlisting>
commands: /* empty */
	|
	commands command
</programlisting>

      <para>Cela signifie: une commande est soit vide, soit plusieurs
      commandes, suivies par une commande. La mani��re dont YACC travaille
      signifie qu'il peut d��sormais s��parer facilement des groupes de
      commandes et les r��duire.</para>

      <para>Comparons cela �� la r��cursivit�� �� droite, qui de mani��re plut��t
      confuse para��t meilleure aux yeux de beaucoup:</para>

      <programlisting>
commands: /* empty */
	|
	command commands
</programlisting>

      <para>Mais c'est tr��s co��teux. Si on l'utilise comme r��gle %start, elle
      n��cessite que YACC conserve toutes les commandes dans la file sur le
      tas, ce qui peut prendre beaucoup de ressources m��moires. Utilisez donc
      quoi qu'il arrive la r��cursivit�� �� gauche lorsque vous analysez de
      longues instructions, comme des fichiers entiers. Il est parfois
      difficile d'��viter la r��cursivit�� �� droite, mais si vos instructions ne
      sont pas trop longues, il est naturel d'utiliser la r��cursivit�� ��
      gauche.</para>

      <para>Si vous quelque chose qui termine (et donc qui s��pare) vos
      commandes, la R��cursion �� droite para��t tr��s naturelle, mais reste tr��s
      co��teuse:</para>

      <programlisting>
commands: /* empty */
	|
	command SEMICOLON commands
</programlisting>

      <para>La mani��re adroite de programmer ceci est d'utiliser la
      r��cursivit�� �� gauche (je n'ai trouv�� cela tout seul non plus):</para>

      <programlisting>
commands: /* empty */
	|
	commands command SEMICOLON
</programlisting>

      <para>Les versions plus anciennes de ce Howto utilisaient par erreur la
      R��cursion �� droite. Markus Triska nous a gentiment inform�� �� ce
      sujet.</para>
    </section>

    <section>
      <title>Plus loin avec yylval : %union</title>

      <para>Actuellement, nous avons besoin de d��finir LE type yylval. Ce
      n'est cependant pas toujours appropri��. dans de nombreux cas nous avons
      besoin de pouvoir utiliser plusieurs types de donn��es. Retournons sur
      notre thermostat fictif, nous souhaitons peut ��tre ��tre capable de
      choisir un heater pour le contr��ler, comme ceci.</para>

      <programlisting>
heater mainbuiling
	Selected 'mainbuilding' heater
target temperature 23
	'mainbuilding' heater target temperature now 23
</programlisting>

      <para>Cela demande �� yylval d'��tre une union, qui peut supporter les
      strings et les entiers ��� mais pas simultan��ment.</para>

      <para>Souvenez vous que nous avons pr��c��demment dit �� YACC de quel type
      yylval est suppos�� ��tre en d��finissant YYSTYPE. Il serai concevable de
      d��finir YYSTYPE ainsi comme une union, mais YACC a une meilleur m��thode
      pour faire cela: les instructions %union.</para>

      <para>A partir de l'exemple 4, nous ��crivons maintenant la grammaire
      YACC de l'exemple 7. Tout d'abord l'introduction:</para>

      <programlisting>
%token TOKHEATER TOKHEAT TOKTARGET TOKTEMPERATURE

%union 
{
        int number;
        char *string;
}

%token &lt;number&gt; STATE
%token &lt;number&gt; NUMBER
%token &lt;string&gt; WORD
</programlisting>

      <para>Nous d��finissons notre union, qui contient seulement un nombre et
      un string. Puis en utilisant un une syntaxe ��tendue de %token nous
      expliquons �� YACC �� quelle partie de l'union chaque jeton doit
      acc��der.</para>

      <para>Dans ce cas, nous laissons le symbole STATE utiliser un entier
      comme pr��c��demment. Il en va de m��me pour le symbole NUMBER, que nous
      utilisons pour lire les temp��ratures.</para>

      <para>Le symbole WORD est lui par contre nouveau, et est d��clar�� pour
      avoir besoin d'un string.</para>

      <para>Le fichier Lexer change lui aussi un petit peu:</para>

      <programlisting>
%{
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include "y.tab.h"
%}
%%
[0-9]+                  yylval.number=atoi(yytext); return NUMBER;
heater			return TOKHEATER;
heat                    return TOKHEAT;
on|off                  yylval.number=!strcmp(yytext,"on"); return STATE;
target                  return TOKTARGET;
temperature             return TOKTEMPERATURE;
[a-z0-9]+		yylval.string=strdup(yytext);return WORD;
\n                      /* ignore end of line */;
[ \t]+                  /* ignore whitespace */;
%%
</programlisting>

      <para>Comme vous pouvez le voir, nous n'acc��dons plus directement ��
      yyval directement, nous ajoutons un suffixe indiquant �� quelle partie
      nous souhaitons acc��der. Nous n'avons cependant pas besoin de le faire
      dans la grammaire YACC, car YACC effectue le travail pour nous:</para>

      <programlisting>
heater_select:
        TOKHEATER WORD
	{
	 	printf("\tSelected heater '%s'\n",$2);
        	heater=$2;
	}
        ;
</programlisting>

      <para>A cause de de la d��claration %token au dessus, YACC choisit
      automatiquement la partie 'string' dans notre union. Notez aussi que
      nous stockons une copie de $2 qui est plus tard utilis��e pour indiquer ��
      l'utilisateur �� quel heater il envoie la commande:</para>

      <programlisting>
target_set:
        TOKTARGET TOKTEMPERATURE NUMBER
        {
	 	printf("\tHeater '%s' temperature set to %d\n",heater,$3);
  	}
	;
</programlisting>

      <para>Pour plus de d��tails, Consultez l'exemple 7.y.</para>
    </section>
  </section>

  <section>
    <title>D��boguage</title>

    <para>Particuliermeent lorsque l'on apprends, il est n��cessaire d'avoir
    des outils de d��boguage. Heureusement, YACC peut fournir ��norm��ment
    d'informations. Ces informations sont fournies au prix de temps syst��me,
    vous aurez donc besoin d'interrupteurs pour les activer.</para>

    <para>Lorsque vous compilez votre grammaire, ajoutez --debug et ���verbose ��
    votre ligne de commande. Dans votre l'en-t��te C de votre grammaire ,
    ajoutez :</para>

    <programlisting>
int yydebug=1;
</programlisting>

    <para>Cela g��n��rera le fichier 'y.output' qui d��taille l'automate qui a
    ��t�� cr��e.</para>

    <para>Lorsque vous lancez le binaire g��n��r��, il renverra ��norm��ment
    d'informations sur ce qui se passe. Cela inclus dans quel ��tat se trouve
    l'automate et quels symboles sont en trains d'��tre lus.</para>

    <para>Peter jinks a ��crit une page sur le <ulink
    url="http://www.cs.man.ac.uk/~pjj/cs2121/debug.html">d��boguage</ulink> qui
    contient quelques erreurs classiques et comment les r��soudre.</para>

    <section>
      <title>L'automate �� ��tat finis</title>

      <para>Sous le capot, votre analyseur syntaxique YACC fonctionne comme un
      automate fini. Comme le nom l'indique, cet automate (ou machine �� ��tats
      finis) peut se trouver dans diff��rents ��tats. Il y a ensuite des r��gles
      qui gouvernent ces transitions d'un ��tat �� l'autre. Tout d��bute avec la
      r��gle 'racine' mentionn��e plus t��t.</para>

      <para>Pour citer la sortie de l'exemple 7:</para>

      <programlisting>
state 0

    ZONETOK     , and go to state 1

    $default    reduce using rule 1 (commands)

    commands    go to state 29
    command     go to state 2
    zone_set    go to state 3
</programlisting>

      <para><emphasis role="bold">By default, this state reduces using the
      'commands' rule. This is the aforementioned recursive rule that defines
      'commands' to be built up from individual command statements, followed
      by a semicolon, followed by possibly more commands.</emphasis></para>

      <para><emphasis role="bold">This state reduces until it hits something
      it understands, in this case, a ZONETOK, ie, the word 'zone'. It then
      goes to state 1, which deals further with a zone
      command:</emphasis></para>

      <programlisting>
state 1

    zone_set  -&gt;  ZONETOK . quotedname zonecontent   (rule 4)

    QUOTE       , and go to state 4

    quotedname  go to state 5
</programlisting>

      <para><emphasis role="bold">The first line has a '.' in it to indicate
      where we are: we've just seen a ZONETOK and are now looking for a
      'quotedname'. Apparently, a quotedname starts with a QUOTE, which sends
      us to state 4.</emphasis></para>

      <para><emphasis role="bold">To follow this further, compile Example 7
      with the flags mentioned in the Debugging section.</emphasis></para>
    </section>

    <section>
      <title>7.Conflits : d��calage/r��duction, r��duction/r��duction</title>

      <para>A chaque fois que YACC vous informe de la pr��sence de conflits,
      vous pouvez avoir des soucis. R��soudre ces conflits semble un art qui
      peut vous apprendre beaucoup sur votre langage, plus que ce que vous
      n'auriez voulu en savoir.</para>

      <para>Ces probl��mes sont li��s �� l'interpr��tation de la s��quence des
      symboles. Supposons que l'on d��finisse un langage qui ait besoin
      d'accepter les deux commandes suivantes:</para>

      <programlisting>
delete heater all
delete heater number1
</programlisting>

      <para>Pour ce faire, d��finissons cette grammaire:</para>

      <programlisting>
	delete_heaters:
		TOKDELETE TOKHEATER mode
		{
			deleteheaters($3);
		}
	
	mode:	WORD

	delete_a_heater:
		TOKDELETE TOKHEATER WORD
		{
			delete($3);
		}
</programlisting>

      <para>Vous devez d��j�� sentir les ennuis arriver. L'automate commence par
      lire le mot 'delete' puis doit d��cider de la transition en se basant sur
      le symbole suivant. Le symbole suivant peut aussi bien ��tre un 'mode',
      sp��cifiant comment supprimer les 'heaters', ou le nom d'un 'heater' ��
      supprimer. </para>

      <para>Cependant le probl��me est que pour les deux commandes, le symbole
      suivant sera un 'WORD'. YACC n'a par cons��quent aucune id��e de ce qu'il
      doit faire. Cela conduit �� une alerte 'r��duction/r��duction' et une
      seconde alerte : le noeud delete_a_heater ne sera jamais atteint.</para>

      <para>Dans ce cas, le conflit est facilement r��solu en renommant la
      premi��re commande 'delete heaters all' ou en faisant de ALL un autre
      symbole. Mais parfois c'est plus difficile. Le fichier y.output g��n��r��
      lorsque vous lancez YACC avec l'opion ���verbose peut ��tre d'une aide
      formidable.</para>
    </section>
  </section>

  <section>
    <title>Lectures pour approfondir</title>

    <para>GNU YACC (Bison) est fournit avec un fichier info (.info) tr��s
    int��ressant qui documente tr��s bien la syntaxe YACC. Il ne mentionne Lex
    qu'une seule fois, mais sinon il est tr��s bon. Vous pouvez lire les
    fichiers .info avec Emacs ou avec l'outil tr��s bien fait 'pinfo'. Il est
    aussi disponible sur le site de GNU : <ulink
    url="http://www.gnu.org/manual/bison/">BISON Manual</ulink>.</para>

    <para>Flex est fournit avec une page de man qui est tr��s utile si vous
    avez d��j�� une id��e approximative de ce que Flex fait. Le <ulink
    url="http://www.gnu.org/manual/flex/">Flex Manual</ulink> est aussi
    disponible en ligne.</para>

    <para>Apr��s cette introduction �� Lex et YACC, vous pouvez avoir besoin de
    plus d'informations. Je n'ai pas encore lu ces livres, mais ils semblent
    assez bon:</para>

    <variablelist>
      <varlistentry>
        <term>Bison-The Yacc-Compatible Parser Generator</term>

        <listitem>
          <para>Par Charles Donnelly et Richard Stallman. Un lecteur d'<ulink
          url="http://www.amazon.com/exec/obidos/ASIN/0201100886/ref=sim_books/002-7737249-1404015">Amazon</ulink>
          le trouve tr��s utile.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Lex &amp; Yacc</term>

        <listitem>
          <para>Par John R. Levine, Tony Mason et Doug Brown. Consid��r�� comme
          une r��f��rence sur le sujet, bein qu'un peu vieux. Commentaires sur
          Amazon.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Compilers : Principles, Techniques, and Tools</term>

        <listitem>
          <para>par Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman. Le 'Dragon
          Book'. De 1985 et ils continuent de le r��imprimer. Consid��r�� comme
          la base sur la construction de compilateurs.. <ulink
          url="http://www.amazon.com/exec/obidos/ASIN/0201100886/ref=sim_books/002-7737249-1404015">Amazon</ulink>.</para>
        </listitem>
      </varlistentry>
    </variablelist>

    <para>Thomas Niemann a ��crit un document expliquant comment ��crire des
    compilateurs et des calculatrices avec Lex et YACC. Vous pouvez le trouver
    <ulink
    url="http://epaperpress.com/lexandyacc/index.html">ici</ulink>.</para>

    <para>La newsgroup mod��r��e comp.compilers peu aussi ��tre tr��s utile, mais
    gardez �� l'esprit que les gens l�� bas ne sont pas une hotline d��di��e aux
    parsers. Avant de poster, lisez leur <ulink
    url="http://compilers.iecc.com/">page</ulink> et plus sp��cialement la
    <ulink url="http://compilers.iecc.com/faq.txt">FAQ</ulink>.</para>

    <para>Lex - A Lexical Analyzer Generator par M. E. Lesk and E. Schmidt est
    l'une des sources de r��f��rence. Il peut ��tre trouv�� <ulink
    url="http://www.cs.utexas.edu/users/novak/lexpaper.htm">ici</ulink>.</para>

    <para>YACC: Yet Another Compiler Compiler par Stephen C. Johnson est l'une
    des sources de r��f��rence. Il peut ��tre trouv�� ici. Il contient des astuces
    sur le style.</para>
  </section>

  <section>
    <title>Remerciements</title>

    <itemizedlist>
      <listitem>
        <para>Pete Jinks &lt;pjj%cs.man.ac.uk&gt;</para>
      </listitem>

      <listitem>
        <para>Chris Lattner &lt;sabre%nondot.org&gt;</para>
      </listitem>

      <listitem>
        <para>John W. Millaway &lt;johnmillaway%yahoo.com&gt;</para>
      </listitem>

      <listitem>
        <para>Martin Neitzel &lt;neitzel%gaertner.de&gt;</para>
      </listitem>

      <listitem>
        <para>Sumit Pandaya &lt;sumit%elitecore.com&gt;</para>
      </listitem>

      <listitem>
        <para>Esmond Pitt &lt;esmond.pitt%bigpond.com&gt;</para>
      </listitem>

      <listitem>
        <para>Eric S. Raymond</para>
      </listitem>

      <listitem>
        <para>Bob Schmertz &lt;schmertz%wam.umd.edu&gt;</para>
      </listitem>

      <listitem>
        <para>Adam Sulmicki &lt;adam%cfar.umd.edu&gt;</para>
      </listitem>

      <listitem>
        <para>Markus Triska &lt;triska%gmx.at&gt;</para>
      </listitem>

      <listitem>
        <para>Erik Verbruggen &lt;erik%road-warrior.cs.kun.nl&gt;</para>
      </listitem>

      <listitem>
        <para>Gary V. Vaughan &lt;gary%gnu.org&gt; (read his awesome <ulink
        url="http://sources.redhat.com/autobook">Autobook</ulink>)</para>
      </listitem>

      <listitem>
        <para><ulink url="http://vanderwijk.info">Ivo van der Wijk</ulink>
        (<ulink url="http://www.amaze.nl">Amaze Internet</ulink>)</para>
      </listitem>
    </itemizedlist>
  </section>
</article>