Obligement - L'Amiga au maximum

Samedi 20 avril 2024 - 01:53  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


En pratique : Utilisation de Yacc (analyse lexicale et routines utilisateur)
(Article écrit par Pascal Amiable et extrait d'Amiga News Tech - avril 1992)


Fin de notre analyseur grammatical français avec d'une part, l'analyse lexicale réalisée grâce à Flex et d'autre part, le développement de routines "utilisateur" propres.

Nous allons définir les trois parties de l'analyseur lexical dans l'ordre d'apparition des sections du programme Lex à créer, mais avant tout, un rapide rappel de la syntaxe utilisée par Lex sera sans doute le bienvenu. Chaque expression de Lex est une chaîne de caractères, constituée d'un ensemble de caractères, de motifs ou de sous-expressions. Par exemple, [A-Za-z]* signifie toute chaîne de caractères contenant une ou plusieurs expressions des lettres A à Z et a à z. La liste ci-dessous reprend les expressions de base les plus courantes avec leur signification.
  • x : le caractère "x".
  • "x" "x" : même si "x" est un caractère spécial.
  • \x "x" : même si "x" est un caractère spécial.
  • [s] : n'importe quel caractère de la chaîne s.
  • [x-y] : n'importe quel caractère compris entre x et y.
  • [^s] : tout caractère n'appartenant pas à la chaîne s.
  • ^x : un x en début de ligne.
  • x$ : un x en fin de ligne.
  • x* : 0 ou plusieurs occurrences de x.
  • x+ : 1 ou plusieurs occurrences de x.
  • x|y : un x ou un y.
  • (x) : un x.
  • x/y : un x suivi d'un y.
  • {s} : une expression définie par s dans la zone déclaration.
  • x{m,n}m : à travers n occurrences de x.
La section Définitions

La seule chose que nous allons définir dans cette section est le terminateur de mot. Un mot peut être terminé par une virgule, un point, un espace ou le caractère retour chariot ('\n').

La section Règles

La section Règles tient compte des spécifications établies le mois dernier (contenant la liste des mots à reconnaître) ainsi que d'éventuelles dérivées (Vert, Verte), des majuscules et minuscules (Disquette, disquette)... A chaque expression est associée une action, écrite sous la forme d'un programme C indu entre deux accolades. Les expressions définies représentent les mots à reconnaître, suivis par "\fin_mot" qui correspond au terminateur défini dans la section Définitions. On considère que les noms communs peuvent commencer par une minuscule ou une majuscule, les noms propres quant à eux commençant obligatoirement par une majuscule.

Pour un mot reconnu, Lex envoie le symbole associé. Ce symbole est passé au programme Yacc par l'intermédiaire des actions définies à côté de l'expression reconnue. Par exemple pour un nom, la fonction exécutée est nom(). Ces fonctions sont décrites dans la section Utilisateur.

La section Utilisateur

Dans cette section se trouve, sous forme de source C, la description des différentes actions définies dans la partie Règles. Ces fonctions ont pour but de retourner le symbole associé (NOM, VERBE, ADJECTIF, NOMBRE...) à la partie Yacc de notre analyseur de texte. Elles positionnent également certains attributs, comme un index dans un dictionnaire (ind_nom par exemple) et le type du mot (comme pluriel ou singulier). Les nombres sont quant à eux indexés sur leurs valeurs avec le cas particulier des articles "le" et "la", qui reçoivent arbitrairement l'index "0". Gràce à cette intégration d'index, la modification du programme (en vue de l'ajout d'un dictionnaire par exemple) sera grandement facilitée. Mais cette étude sort du cadre de cet article.

Voici donc le programme Lex complet :

fin_mot                 [,. \n]
%%
Stéphane/{fin_mot}      {return(nom(1,1));}
Christine/{fin_mot}     {return(nom(2,1));}
Anne/{fin_mot}          {return(nom(3,1));}
[Dd]isquette/{fin_mot}  {return(nom(4,1));}
[Dd]isquettes/{fin_mot} {return(nom(4,2));}

prend/{fin_mot}         {return(verbe(1,2));}
prennent/{fin_mot}      {return(verbe(1,1));}
range/{fin_mot}         {return(verbe(2,2));}
range/{fin_mot}         {return(verbe(2,1));}
donne/{fin_mot}         {return(verbe(3,2));}
donnent/{fin_mot}       {return(verbe(3,1));}

petit/{fin_mot}     {return(adjectif(1,1));}
petite/{fin_mot}    {return(adjectif(1,2));}
petits/{fin_mot}    {return(adjectif(1,3));}
petites/{fin_mot}   {return(adjectif(1,4));}
vert/{fin_mot}      {return(adjectif(2,1));}
verte/{fin_mot}     {return(adjectif(2,2));}
verts/{fin_mot}     {return(adjectif(2,3));}
vertes/{fin_mot}    {return(adjectif(2,4));}
rouge/{fin_mot}     {return(adjectif(3,1));}
rouges/{fin_mot}    {return(adjectif(3,2));}

[Ll][ea]/{fin_mot}      {return(nombre(0));}
1/{fin_mot}             {return(nombre(1));}
[Uu]n/{fin_mot}             {return(nombre(1));}
2/{fin_mot}             {return(nombre(2));}
[Dd]eux/{fin_mot}             {return(nombre(2));}
3/{fin_mot}             {return(nombre(3));}
[Tt]rois/{fin_mot}             {return(nombre(3));}
4/{fin_mot}             {return(nombre(4));}
[Qq]uatre/{fin_mot}             {return(nombre(4));}
5/{fin_mot}             {return(nombre(5));}
[Cc]inq/{fin_mot}             {return(nombre(5));}
6/{fin_mot}             {return(nombre(6));}
[Ss]ix/{fin_mot}             {return(nombre(6));}
7/{fin_mot}             {return(nombre(7));}
[Ss]ept/{fin_mot}             {return(nombre(7));}
8/{fin_mot}             {return(nombre(8));}
[Hh]uit/{fin_mot}             {return(nombre(8));}
9/{fin_mot}             {return(nombre(9));}
[Nn]euf/{fin_mot}             {return(nombre(9));}
10/{fin_mot}            {return(nombre(10));}
[Dd]ix/{fin_mot}            {return(nombre(10));}


[ \.]               {/* caractères non pris en compte*/}
\n                  {return(yytext[0]);}

[A-Za-z]+/{fin_mot} {printf("Je ne connais pas le mot : %s\n",yytext);return(INCONNU);}

[0-9A-Za-z \.\n]    {printf("Il s'agit d'un caractère du contrôle : %s\n",yytext);return(CONTROLE);}
%%

nom(i,n)

int i,n;
{
    ind_nom = i;
    type  = n;
    printf(" nom : %s\n",yytext);
    return(NOM);
}

verbe(i,n)

int i,n;
{
    ind_verbe = i;
    type  = n;
    printf(" verbe : %s\n",yytext);
    return(VERBE);
}



adjectif(i,n)

int i,n;
{
    ind_adjectif = i;
    type  = n;
    printf(" adjectif : %s\n",yytext);
    return(ADJECTIF);
}


nombre(i)

int i;
{
    ind_nombre = i;
    printf(" nombre : %s\n",yytext);
    return(NOMBRE);
}

Connection Flex-Yacc

Le programme Lex ci-dessus a été sauvegardé dans le fichier lexicall. Il doit être transformé en source C par la commande flex -8 -v lexical.1. Le résultat est contenu dans le fichier lex.yy.c, qui doit être inclus dans le programme Yacc à l'aide de la directive #include "lex.yy.c à la place de la définition de la fonction yylex() qui avait été laissée vide. On devra de plus modifier légèrement le source Yacc pour tenir compte des deux nouveaux symboles, à savoir INCONNU pour les mots non reconnus par l'analyseur, et CONTROLE, dans le cas de caractères non alphanumériques. On remplacera donc la ligne %token VERBE NOM ADJECTIF NOMBRE par %token VERBE NOM ADJECTIF NOMBRE INCONNU CONTROLE.

On ajoutera également en tête du programme Yacc, un fichier lexical.h contenant la déclaration des variables globales utilisées dans la section Utilisateur. Ce fichier lexical.h est listé ci-dessous.


/*--------------------------------------------------------*/
/*  Déclaration des variables globales de l'analyseur      */
/*--------------------------------------------------------*/

int ind_nom, ind_verbe, ind_adjectif, ind_nombre;

int type;

Voici donc le programme Yacc complet et modifié pour prendre en compte le résultat des cogitations de FLex.

%{
#include "lexical.h"
%}

%token VERBE NOM ADJECTIF NOMBRE INCONNU CONTROLE
%%

Phrase        : Sujet Predicat '\n' { printf(" Phrase déclarative \n");}
              |  Predicat      '\n' { printf(" Phrase impérative \n");}
              |  error              { printf("Erreur de Syntaxe \n");}
              ;
Predicat      :  VERBE Complement   { printf(" Prédicat \n");}
              ;
Sujet         :  Objet	             { printf(" Sujet \n");}
              ;
Complement    :  Objet              { printf(" Complément \n");}
              ;
Objet         :  NOM
              |NOMBRE NOM
	          |ADJECTIF NOM	
	          |NOMBRE ADJECTIF NOM
	          |NOMBRE NOM ADJECTIF
	          |NOMBRE ADJECTIF NOM ADJECTIF
              ;
%%

#include "lex.yy.c"

main()
   {
    while(1)
      {  
       printf("? ");
       yyparse();
      }
   }
yyerror()
   {
   }

Il ne reste dès lors plus qu'à passer exemple.y à la moulinette de Yacc avec la commande Yacc exemple.y puis à compiler et relier le programme C généré par le -Lc y.tab.c. L'exécutable se nommera tout naturellement y.tab et il peut être lancé directement. Voici un exemple des résultats obtenus.

Yacc
Yacc

Débogage

Il arrive parfois que l'on souhaite étudier ce que l'analyseur traite réellement. C'est tout à fait possible : Yacc peut générer au sein du source C une partie d'affichage des itérations du programme en cours d'exécution.

Pour activer cette phase de débogage, deux choses sont à réaliser :
  • Éditer le fichier y.tab.c et y insérer, tout en haut, la ligne #define YYDEBUG 1.
  • Rechercher la déclaration de la variable yydebug, int yydebug; et la remplacer par int yydebug = 1;.
Après compilation et édition des liens, le résultat d'exécution devient tout de suite plus transparent. Voici à titre d'exemple ce qui est obtenu pour la phrase Stéphane prend trois petites disquettes vierges, à comparer avec le résultat obtenu plus haut.

Yacc

C'est aussi simple que cela ! Les fichiers sources lex.yy.c et y.tab.c ainsi que l'exécutable y.tab se trouvent dans le répertoire ToolBox de la disquette d'accompagnement de ce numéro.


[Retour en haut] / [Retour aux articles] [Article précédent]