TP de compilation : une solution de l'exercice 5 du TP 1

5.1.
%%
^\n    {return 0;}
[Aa]   printf("Adenine ");
[Tt]   printf("Thymine ");
[Gg]   printf("Guanine ");
[Cc]   printf("Cytosine ");
.      {printf("\n%c: Caractère inconnu\n",yytext[0]); return 0;}

5.2.
%%
^\n    {return 0;}
[Aa]   printf("U");
[Tt]   printf("A");
[Gg]   printf("C");
[Cc]   printf("G");
.      {printf("\n%c: Caractère inconnu\n",yytext[0]); return 0;}

5.3.
Le brin analysé est sensé (voir l'énoncé) commencer par START et finir par STOP. Les codons intermédiaires ne sont reconnus qu'entre ces deux extrêmes. La variable t chargée de ce contrôle pourrait être avantageusement remplacée par :
%{
int t=0;
%}
start   [aA][uU][gG]
stop    [uU][aAgG][aAgG]
leu     ([cC][uU][aAgGcCuU])|([uU][uU][aAgG])
phe     [uU][uU][uUcC]
ser     ([uU][cC][aAcCgGuU])|([aA][gG][cCuU])
%%
^\n            {return 0;}
^{start}       {printf("start\n "); t=1;} // voir note(1)
{stop}$        {if (t==1) printf("stop\n"); t=2;}
{leu}          {if (t==1) printf("Leucine\n");}
{phe}          {if (t==1) printf("Phénylalanine\n");}
{ser}          {if (t==1) printf("Sérine\n");}
\n             {t=0;}
(1) Pour simplifier, nous avons considéré ici que le codon stop est aussi codé par UGG. Il aurait fallu sinon définir STOP avec une moindre factorisation : ([uU][aA][aAgG])|([uU][gG][aA]).

5.4.a
Il n'y a pas de difficulté majeure pour étendre le programme précédent à la reconnaissance de tous les codons, sur le principe d'une factorisation maximale des expressions régulières. Le programme suivant se contente de regrouper ces autres codons sous une rubrique "autre codon à traiter" (modifier en conséquence pour reconnaitre tous les codons) afin de se concentrer sur la gestion des erreurs.

Les erreurs suivantes peuvent intervenir dans le flot d'entrée :
 – Pas de START en début de ligne,
 – Pas de STOP en fin de ligne,
 – Le nombre de lettre n'est pas un multiple de 3,
 – Un caractère saisi n'appartient pas à l'alphabet {A,U,G,C},

Les deux premières difficultés sont déja résolues par la variable t, comme dans la question précédente. Notons que dans le TP 2 on gèrera ce genre de problème grâce aux bascules de configurations (%s configuration) de Lex. La troisième difficulté est interprétée comme la présence d'un ou deux caractères en plus ou en moins dans le brin. L'ajout de l'expression [AaUuGgCc] dans le fichier-lex résout le problème car cette expression ne sera utilisée que si l'analyseur ne peut utiliser une expression plus longue qui l'inclut (càd. un codon quelconque). Enfin la présence de tout autre caractère sera indiquée. Ces deux derniers choix empêcheront la reconnaissance ultérieure du codon STOP sur la ligne (toujours grâce à t). Dans tous les cas les commentaires de l'analyseur sont reportés au moment où il rencontre la fin de ligne. On aurait pu faire d'autres choix...
 
%{
int t=0;
%}
start   [aA][uU][gG]
stop    [uU][aAgG][aAgG]
leu     ([cC][uU][aAgGcCuU])|([uU][uU][aAgG])
phe     [uU][uU][uUcC]
ser     ([uU][cC][aAcCgGuU])|([aA][gG][cCuU])
%%
^\n            {return 0;}
^{start}       {printf("start\n "); t=1;}
{stop}$        {if (t==1) printf("stop\n"); t=2;}
{leu}          {if (t==1) printf("Leucine\n");}
{phe}          {if (t==1) printf("Phénylalanine\n");}
{ser}          {if (t==1) printf("Sérine\n");}
[aAcCgGuU]{3}  {if (t==1) printf("autre codon à traiter...\n");}
[AaUuGgCc]     {t=-1;}
.              {t=-2;}
\n             { if (t==2) printf("OK!\n");
                 else if (t==1) printf("codon STOP manquant\n");
                 else if (t==0) printf("codon START manquant\n");
                 else if (t==-1) printf("caractère(s) superflu ou manquant\n");
                 else if (t==-2) printf("caractère inconnu\n");
                 t=0; }

5.4.b
Si exc5_2 et exc5_3b sont les noms des exécutables précédents, il suffit d'enchaîner les commandes : exc5_2 | exc5_3b
Le flux de sortie du premier analyseur sera envoyé vers le flux d'entrée du second analyseur. :-)
© 2000, 2017 – A. Sigayret