Probleme d'analyse lexicale

Probleme d'analyse lexicale - C - Programmation

Marsh Posté le 24-02-2005 à 21:10:17    

Voila j'ai deux petits problemes avec mon lexer (pas de flex) pour le petit langage Logo.  
 
La reconnaissance des operateurs '<< ' se fait correctement mais dès que il y a un nombre (ou autre à part un espace) tout de suite apres ... ça gouille.
exemple :  
'<<20' donnera 'operateur nombre' au lieu de 'operateur operateur nombre'
alors que
'<<' donne bien 'operateur operateur'  :fou:  
 
Et ma deuxième question concerne la gestion des identificateurs (qui sont à priori gerés dans le meme état que les mot-cle et le sens), en fait il faut pouvoir reconnaitre le lexeme le plus long (par convention) donc par exemple le motcle "avancer" devra etre reconnu au lieu d'une suite d'identificateurs "a","v","a","n"...
Je pense qu'il faut d'abord que je teste la correspondance avec un motcle puis si elle echoue tester la reconnaisance d'un id.
 
 
Voici le source :
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. /* Macros pour les mots clef */
  6. #define IDENTIFICATEUR 1
  7. #define MOTCLE 2
  8. #define SENS 3
  9. #define OPERATEUR 4
  10. #define ANGLE 5
  11. #define NOMBRE 6
  12. #define FIN 7
  13. #define ERROR 0
  14. /* La fonction getkar */
  15. int getkar(FILE* fp){
  16.   int x = fgetc(fp);
  17.   if((x == '\n') || (x == '\r')) printf("\n" );
  18.   if(isspace(x))
  19.     printf("" );
  20.   else
  21.     printf("\n :- %c\n ", x); //afficher le lexeme lus
  22.   return x;
  23.    
  24. }
  25. /* La fonction lexer */
  26. int lexer(FILE* fp){
  27.   int s, z, i = 0; /* z est le carac lus et i indice du buffer */
  28.   char etat = 'a';
  29.   short exception1=0; /* Variable pour gerer l'exception du lexeme ANGLE */
  30.   char buf[50]="";
  31.   char temp;
  32.  
  33.   while(s<= 12){
  34.     printf("Etat => %c", etat);
  35.        
  36.     if(feof(fp) || z==EOF) return FIN;
  37.     s++;
  38.     z=getkar(fp);
  39.     if(isspace(z)){
  40.        i=0;
  41.        //continue;
  42.     }
  43.     if(isalpha(z)){ etat='h';}
  44.     if(z =='.') etat='d';
  45.     if(z =='<') { etat='e';}
  46.     if(z =='>') { etat='g';}
  47.     if(z == ':') { etat = 'i';}
  48.     if(strchr("+-*/(){}", z)) { etat = 'f'; }
  49.     if(isdigit(z) || exception1==1) {exception1=0; etat='b'; }
  50.     /* Pour le caractere '=' on definit l'etat selon le caractere temporisé precedement */
  51. if(z == '=')
  52. {
  53.  if (temp==':') etat='i';
  54.  else if (temp=='<') etat='e';
  55.  else if (temp=='>') etat='g';
  56.  else etat = 'f';
  57. }
  58.     /* A PARTIR D'ICI ON A LA GESTION DES ETATS */
  59.    
  60.     /* Si on se trouve dans cet etat c'est que on a deja lu un nombre.
  61.    Donc si on lit autre chose qu'un nombre (à part g ou d ou r)  
  62.    alors on renvoi un nombre etc ... */
  63. if(etat=='b'){
  64.        if(isdigit(z)){
  65.   exception1=1;
  66.   continue;
  67.  }
  68.  else{
  69.   if(strchr("gdr",z)) return ANGLE;
  70.      else return NOMBRE;
  71.  }
  72. }
  73.     /* Etat pour detecter les motcle, id et sens */
  74.     if (etat=='h'){
  75.       if (isalnum(z)){
  76.  buf[i]=z;
  77.         i++;
  78.  //printf(" buffer : %s\n", buf);
  79.  if ((strcmp(buf, "avancer" ) == 0)  ||
  80.   (strcmp(buf, "lever" ) == 0)    ||
  81.   (strcmp(buf, "poser" ) == 0)    ||
  82.   (strcmp(buf, "tourner" ) == 0)  ||
  83.                         (strcmp(buf, "pour" )  == 0)    ||
  84.                  (strcmp(buf, "sinon" ) == 0)    ||
  85.          (strcmp(buf, "tantque" ) == 0)  ||
  86.                         (strcmp(buf, "si" ) == 0))
  87.  {
  88.   
  89.    //printf(" buffer : %s\n", buf);
  90.    return MOTCLE;
  91.  }
  92.  
  93.     else if ((strcmp(buf,"gauche" )==0) || (strcmp(buf, "droite" ) == 0)) return SENS;
  94.     else continue;
  95.   }
  96.   else{
  97.    ungetc(z, fp);
  98.    continue
  99.   }
  100.     
  101.     }
  102. /* - Gestion de l'operateur '<' et '<=' */
  103. if (etat=='e'){
  104.  if(!isspace(z)){
  105.   if(z=='=' && temp=='<') return OPERATEUR;
  106.   else if(z!='=' && temp=='<') {ungetc(z, fp); return OPERATEUR;}
  107.   else {temp='<'; continue;}
  108.   }
  109.   else{
  110.   if(temp=='<') return OPERATEUR;
  111.   else continue;
  112.  }
  113.  }
  114. /* - Gestion de l'operateur '>' et '>=' */
  115.         if (etat=='g'){
  116.  if(!isspace(z)){
  117.   if(z=='=' && temp=='>') return OPERATEUR;
  118.   else if(z!='=' && temp=='>') {ungetc(z, fp); return OPERATEUR;}
  119.   else {temp='>'; continue;}
  120.   }
  121.   else{
  122.   if(temp=='>') return OPERATEUR;
  123.   else continue;
  124.  }
  125.  }   
  126.     /* Gestion de l'operateur ':=' */
  127.     if (etat=='i'){
  128.  if(!isspace(z)){
  129.   if(z=='=' && temp==':') return OPERATEUR;
  130.   else if(z!='=' && temp==':') {ungetc(z, fp); return ERROR;}
  131.   else {temp=':'; continue;}
  132.   }
  133.   else{
  134.   if(temp==':') return ERROR;
  135.   else continue;
  136.  }
  137.  }
  138.     /* Gestion de l'operateur '.' et '..' */
  139.     if (etat=='d'){
  140. if(!isspace(z)){
  141.  if(z=='.' && temp=='.') return OPERATEUR;
  142.  else if(z!='.' && temp=='.') {ungetc(z, fp); return ERROR;}
  143.  else {temp='.'; continue;}
  144.   }
  145.   else{
  146.  if(temp=='.') return ERROR;
  147.  else continue;
  148.  }
  149. }
  150.    
  151.     if (etat=='f') return OPERATEUR;
  152.    
  153.   }
  154.   return FIN;
  155. }
  156. int main(int argc, char *argv[]){
  157.   FILE* fp = fopen("source.txt", "r" );
  158.  
  159.   int x=0;
  160.   while(x!=FIN){
  161.    
  162.     x = lexer(fp);
  163.     printf(" " );
  164.     if (x==ERROR) printf("Erreur! " );
  165.     switch (x)
  166.       {
  167.       case IDENTIFICATEUR:
  168.       printf("ident " );
  169.       break;
  170.       case MOTCLE :
  171.       printf("mot-cle " );
  172.       break;
  173.       case SENS :
  174.       printf("sens " );
  175.       break;
  176.       case OPERATEUR :
  177.    printf("operateur " );
  178.    break;
  179.   case NOMBRE :
  180.      printf("nombre " );
  181.    break;
  182.       case ANGLE :
  183.    printf("angle " );
  184.    break;
  185.      
  186.       }
  187.   }
  188.   exit(0);
  189. }


Message édité par Chronoklazm le 24-02-2005 à 21:40:45

---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 21:10:17   

Reply

Marsh Posté le 24-02-2005 à 21:19:25    

mais pkoi pas de flex/yacc ? [:sisicaivrai]

Reply

Marsh Posté le 24-02-2005 à 21:35:45    

C'est surement pour que les neuneus come moi puissent éprouver un profond plaisir en utilisant flex/yacc :sweat:


Message édité par Chronoklazm le 24-02-2005 à 21:36:22

---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 21:42:16    

serieux, tu te fais du mal, la

Reply

Marsh Posté le 24-02-2005 à 21:54:58    

Et encore on a pas attaquer les generateurs d'analyseurs syntaxiques à faire à la main.


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 21:55:21    

mais mayrde quoi [:sisicaivrai]

Reply

Marsh Posté le 24-02-2005 à 22:05:59    

chrisbk a écrit :

mais mayrde quoi [:sisicaivrai]


 
Bon, je te sens chaud pour m'aider là, non ? :)


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 22:22:48    

Chronoklazm a écrit :

Voila j'ai deux petits problemes avec mon lexer (pas de flex) pour le petit langage Logo.  
 
La reconnaissance des operateurs '<< ' se fait correctement mais dès que il y a un nombre (ou autre à part un espace) tout de suite apres ... ça gouille.
exemple :  
'<<20' donnera 'operateur nombre' au lieu de 'operateur operateur nombre'
alors que
'<<' donne bien 'operateur operateur'  :fou:  
 
Et ma deuxième question concerne la gestion des identificateurs (qui sont à priori gerés dans le meme état que les mot-cle et le sens), en fait il faut pouvoir reconnaitre le lexeme le plus long (par convention) donc par exemple le motcle "avancer" devra etre reconnu au lieu d'une suite d'identificateurs "a","v","a","n"...
Je pense qu'il faut d'abord que je teste la correspondance avec un motcle puis si elle echoue tester la reconnaisance d'un id.


 
Pfffou... tout ça à débugguer je suis fatigué d'avance.
Juste pour dire que ta seconde hypothèse estvraie. Tu dois reconnaître le lexème (token) le plus long possible à chaque fois.

Reply

Marsh Posté le 24-02-2005 à 22:27:07    

Chrono> chai pas si c moi qui ait la berlu mais ton programme comporte des erreurs de programmation assez grossières. Par exemple lorsque les variables s ou temp sont utilisées pour la première fois, ces dernières ne sont pas initialisées ou définies.
Ensuite sur la forme, ce qu'on peut remarquer à première vue, c'est que la forme canonique pour écrire un AFN en langage C, utilise le switch...case pour la gestion des états, ce qui évite les continue à tout bout de champ.
Voilà pour mes premières remarques.
 
Bonne chance... ;)

Reply

Marsh Posté le 24-02-2005 à 22:47:31    

Ok merci, pour le switch.  
La variable s est initialisée a 0.
La variable temp, est comme son nom l'indique sert de mini-buffer donc bon ... mais je vais l'initialiser quand meme.


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 22:47:31   

Reply

Marsh Posté le 24-02-2005 à 23:03:00    

pains-aux-raisins a écrit :

Chrono> ... la forme canonique pour écrire un AFN en langage C, utilise le switch...case pour la gestion des états ...


 
Heu, t'as pas un exemple par hasard, google n'est pas tres bavard a ce sujet. :whistle:


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 23:06:18    

ben tout simplement

Code :
  1. switch (etat) {
  2.    case ETAT1 :
  3.       ...
  4.       break;
  5.    case ETAT2 :
  6.       ...
  7.       break;
  8.    ...
  9.    case ETATn :
  10.       ...
  11.       break;
  12.    default :
  13.       /* là c'est pas normal ! */
  14. }

Reply

Marsh Posté le 24-02-2005 à 23:18:14    

Oui ok ca j'avais compris :D je parlais plus d'exemples de codages d'automates faits entierement.


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 24-02-2005 à 23:21:55    

J'ai trouvé un petit exemple sympa sur un AFN qui vire les espaces en debut de lignes mais c'est un peu leger ...
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int
  4. main()
  5. {
  6.     int c;
  7.     enum {ETAT_DBT_LIGNE, ETAT_NORMAL } etat = ETAT_DBT_LIGNE;
  8.  
  9.     while ((c=getchar()) != EOF) {
  10.         switch (etat) {
  11.             case ETAT_DBT_LIGNE:
  12.                 switch (c) {
  13.                     case ' ':
  14.                     case '\t':
  15.                         break;
  16.                     default
  17.                         putchar(c);
  18.                         etat = ETAT_NORMAL;
  19.                         break;
  20.                 }
  21.                 break;
  22.             case ETAT_NORMAL:
  23.                 switch (c) {
  24.                     case '\n':
  25.                         putchar('\n');
  26.                         etat=ETAT_DBT_LIGNE;
  27.                         break;
  28.                     default
  29.                         putchar(c);
  30.                         break;
  31.                 }
  32.         }
  33.     }
  34.     exit(EXIT_SUCCESS);
  35. }


Message édité par Chronoklazm le 24-02-2005 à 23:22:25

---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 25-02-2005 à 08:13:19    

disons que c'est un début :D

Reply

Marsh Posté le 25-02-2005 à 08:42:18    

Chronoklazm a écrit :

Bon, je te sens chaud pour m'aider là, non ? :)


 
heuh nan, les parseurs fait main ca ressemble souvent a du spaghetti ou meme l'aventurier le plus intrepide n'ose s'aventurer [:petrus75]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed