Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1200 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [Résolu] [lex & Yacc] Segmentation fault

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu] [lex & Yacc] Segmentation fault

n°1661191
exhortae
Membre du Cartel des Médecins
Posté le 20-12-2007 à 13:23:16  profilanswer
 

Bonjour,  
 
Je suis entrain de me familiariser avec lex et yacc, en lisant un bouquin dessus, j'ai à faire l'exercise suivant.
 
1) sauvegarder des mots dans une liste chainee en fonction de leur type (verbe, nom...)
 
exemple
 
taper ^verb love : le lexer chercher si le verbe existe déjà, sinon il l'ajoute en début de la liste chainee avec son type VERBE.
 
2) après avoir mémoriser des verbes, des sujets, des pronoms, je dois taper une phrase genre exhortae needs help et le parser doit me dire si c'est une phrase simple ou composée ou si il y a erreur.
 
 
je compile, fait l'édition de lien... et lorsque je lance mon ./a.out j'ai une segmentation fault, j'ai tout revu mais j'arrive pas à voir ou est le problème.
 
 
voilà le .lex
 

Code :
  1. %{
  2. /* Analyseur lexical pouvant etre utiliser par un analyseur syntaxique
  3. */
  4. #include "y.tab.h"
  5. #define LOOKUP 0
  6. int state;
  7. int ajouter_mot (int type, char *word);
  8. int rechercher_mot (char *word);
  9. %}
  10. %%
  11. /* Fin de ligne retour a l'etat par defaut */
  12. \n {state = LOOKUP;}
  13. /* Fin de phrase */
  14. \.\n {state = LOOKUP;
  15.  return 0;
  16. }
  17. /* A chaque fois que la ligne commence par un nom reserve du langage */
  18. /* On va definir les mots de ce type */
  19. ^verb  {state = VERBE;}
  20. ^adj  {state = ADJECTIF;}
  21. ^adv  {state = ADVERBE;}
  22. ^nom  {state = NOM;}
  23. ^prep  {state = PREPOSITION;}
  24. ^pron  {state = PRONOM;}
  25. ^conj  {state = CONJONCTION;}
  26. /* un mot normal , on le defini ou on le recherche */
  27. [a-zA-Z]+ {
  28.  if (state != LOOKUP)
  29.  {
  30.   ajouter_mot (state, yytext);
  31.  }
  32.  else
  33.  {
  34.   switch (rechercher_mot (yytext))
  35.   {
  36.    case VERBE:
  37.     return VERBE;
  38.    case ADJECTIF:
  39.     return ADJECTIF;
  40.    case ADVERBE:
  41.     return ADVERBE;
  42.    case NOM:
  43.     return NOM;
  44.    case PREPOSITION:
  45.     return PREPOSITION;
  46.    case PRONOM:
  47.     return PRONOM;
  48.    case CONJONCTION:
  49.     return CONJONCTION;
  50.    default:
  51.     /* ne rien retourner, ignorer le mot */
  52.     printf ("%s : inconnu\n", yytext);
  53.   }
  54.  }
  55.  }
  56. . ; /* Ignorer le reste */
  57. %%
  58. /* On defini une liste chainee de mots et types */
  59. struct word
  60. {
  61. char *word_name;
  62. int type;
  63. struct word *p_suivant;
  64. };
  65. /* On declare le premier element de la liste */
  66. struct word *p_word_list = NULL;
  67. extern void *malloc ();
  68. /* -----------------------------------------------------------------------
  69. ajouter_mot ()
  70. -----------------------------------------------------------------------
  71. Role : ajoute un mot dans la liste (seulement si il n'y est pas deja)
  72. -----------------------------------------------------------------------
  73. */
  74. int ajouter_mot (int type, char *word)
  75. {
  76. struct word *p_word = NULL;
  77. /* On verifie d'abord que le mot ne se trouve pas deja dans la liste */
  78. if (rechercher_mot (word) != LOOKUP)
  79. {
  80.  printf ("!!! WARNING %s existe deja \n", word);
  81.  return 0;
  82. }
  83. /* On alloue un espace memoire */
  84.  p_word = malloc (sizeof *p_word);
  85.  if (p_word != NULL)
  86.  {
  87.   p_word->p_suivant = p_word_list;
  88.   p_word->type = type;
  89.   /* On alloue l'espace memoire pour la chaine de caractere */
  90.   p_word->word_name = malloc ((strlen (word) + 1) * sizeof (char));
  91.   if (p_word->word_name != NULL)
  92.   {
  93.    strcpy (p_word->word_name, word);
  94.   }
  95.   p_word_list = p_word;
  96.  }
  97. return 1;
  98. }
  99. /* ------------------------------------------------------------------------
  100. rechercher_mot ()
  101. ------------------------------------------------------------------------
  102. Role : Retourne le type du mot dans une liste chainne (LOOKUP si le mot
  103. n'existe pas)
  104. ------------------------------------------------------------------------
  105. */
  106. int rechercher_mot (char *word)
  107. {
  108. struct word *p_tmp = p_word_list;
  109. while (p_tmp != NULL)
  110. {
  111.  if (strcmp (p_tmp->word_name, word) == 0)
  112.  {
  113.   return p_tmp->type;
  114.  }
  115.  p_tmp = p_tmp->p_suivant;
  116. }
  117. return LOOKUP;
  118. }


 
et voilà le .y
 

Code :
  1. %{
  2. #include <stdio.h>
  3. %}
  4. %token NOM PRONOM VERBE ADVERBE ADJECTIF PREPOSITION CONJONCTION
  5. %%
  6. phrase : phrase_simple {printf ("Phrase simple\n" );}
  7. | phrase_composee {printf ("Phrase composee\n" );}
  8. ;
  9. phrase_simple : sujet verbe objet
  10. | sujet verbe objet phrase_preposition
  11. ;
  12. phrase_composee : phrase_simple CONJONCTION phrase_simple
  13. | phrase_composee CONJONCTION phrase_simple
  14. ;
  15. sujet : NOM
  16. | PRONOM
  17. | ADJECTIF sujet
  18. ;
  19. verbe : VERBE
  20. | ADVERBE VERBE
  21. |verbe VERBE
  22. ;
  23. objet : NOM
  24. | ADJECTIF objet
  25. ;
  26. phrase_preposition : PREPOSITION NOM
  27. ;
  28. %%
  29. extern FILE *yyin;
  30. main ()
  31. {
  32. while (!feof (yyin))
  33. {
  34.  yyparse ();
  35. }
  36. }
  37. yyerror (s)
  38. char *s;
  39. {
  40. fprintf (stderr, "%s\n", s);
  41. }


 
si quelqu'un pouvait me filer un coup de main, merci


Message édité par exhortae le 29-12-2007 à 18:05:22
mood
Publicité
Posté le 20-12-2007 à 13:23:16  profilanswer
 

n°1661807
Combi_A_Ve​ndre
Posté le 21-12-2007 à 11:38:21  profilanswer
 

Et bien compile en debug (gcc -g) et lance ton exécutable avec gdb :
 
gdb a.out
> run
 
Quand ça plante, essaye la commande bt pour voir la pile d'appel.
 
vw

n°1661863
exhortae
Membre du Cartel des Médecins
Posté le 21-12-2007 à 13:28:38  profilanswer
 

Bonjour
 
voilà ce que j'obtiens,
 

Code :
  1. [exhortae@localhost 5]$ gdb a.out
  2. GNU gdb 6.2-2mdk (Mandrakelinux)
  3. Copyright 2004 Free Software Foundation, Inc.
  4. GDB is free software, covered by the GNU General Public License, and you are
  5. welcome to change it and/or distribute copies of it under certain conditions.
  6. Type "show copying" to see the conditions.
  7. There is absolutely no warranty for GDB.  Type "show warranty" for details.
  8. This GDB was configured as "i586-mandrake-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
  9. (gdb) run
  10. Starting program: /home/exhortae/lex1/5/a.out
  11. Program received signal SIGSEGV, Segmentation fault.
  12. 0x4007c2c0 in feof () from /lib/tls/libc.so.6
  13. (gdb) bt
  14. #0  0x4007c2c0 in feof () from /lib/tls/libc.so.6
  15. #1  0x08049b32 in main ()
  16. (gdb)


 
le problème c'est que n'ayant jamais débugger, ni utiliser lex & yacc en même temps je comprends pas ce que le message d'erreur dans eof veut dire.
 

n°1661874
Combi_A_Ve​ndre
Posté le 21-12-2007 à 13:54:57  profilanswer
 

Ca veut dire que le plantage a lieu dans la procédure main, au moment ou elle appelle feof() (ligne 42)
yyin n'est pas initialisé.
 
vw

n°1661925
exhortae
Membre du Cartel des Médecins
Posté le 21-12-2007 à 14:39:37  profilanswer
 

oui effectivement ça marche quand j'enlève la boucle, par contre je peux parser qu'une seule phrase.
 
finalement en remplaçant le main du .y par
 

Code :
  1. main ()
  2. {
  3.         yyin = stdin;
  4.         while (!feof (yyin))
  5.         {
  6.                 yyparse ();
  7.         }
  8. }


ça fonctionne  
 
par contre je sais pas si c'est valide.
 
en tout cas merci pour ton aide.


Message édité par exhortae le 21-12-2007 à 14:40:27
n°1661995
Combi_A_Ve​ndre
Posté le 21-12-2007 à 16:13:30  profilanswer
 

Oui, ça m'a l'air pas mal comme ça.
 
vw

n°1662027
exhortae
Membre du Cartel des Médecins
Posté le 21-12-2007 à 17:15:53  profilanswer
 

oki,  
 
donc comme j'ai vu que yyin est *FILE, je me suis dit qu'au lieu de lui affecter stdin, j'allais lui affecter un fichier que j'ai moi même rempli (au lieu d'avoir à taper tout à la ligne de commande)
 
j'obtiens dont ça à la place du main
 

Code :
  1. main ()
  2. {
  3. yyin = fopen ("fichier.txt", "r+" );
  4. if (yyin != NULL)
  5. {
  6.  while (!feof (yyin))
  7.  {
  8.   yyparse ();
  9.  }
  10.  fclose (yyin);
  11. }
  12. else
  13. {
  14.  printf ("Impossible d'ouvrir le fichier definition\n" );
  15. }
  16. }


 
voilà le fichier text
 

Code :
  1. nom manu
  2. verb aime
  3. nom cerises
  4. conj quand
  5. nom elles
  6. verb sont
  7. nom fraiches
  8. verb dormir
  9. nom jean
  10. manu aime cerises quand elles sont fraiches.
  11. nom lit
  12. jean dormir lit.


 
et quand j'execute :
 

Code :
  1. [exhortae@localhost 5]$ ./a.out
  2. Phrase composee
  3. [exhortae@localhost 5]$


 
effectivement il ne prend en compte que la première phrase.
 
pourtant en éxécutant avec gdb j'ai pas d'erreur :
 

Code :
  1. Starting program: /home/exhortae/lex1/5/a.out
  2. Phrase composee
  3. Program exited normally.
  4. (gdb)


 
 
maintenant le programme sans utiliser de fichier (on tape à la ligne de commande) :
 
son main :
 

Code :
  1. extern FILE *yyin;
  2. main ()
  3. {
  4.         yyin = stdin;
  5.         if (yyin != NULL)
  6.         {
  7.                 while (!feof (yyin))
  8.                 {
  9.                         yyparse ();
  10.                 }
  11.         }
  12.         else
  13.         {
  14.                 printf ("Lecture impossible\n" );
  15.         }
  16. }


 
et là on parse bien toutes les phrases entrées.
 

Code :
  1. [exhortae@localhost 6]$ ./a.out
  2. nom manu
  3. verb aime
  4. nom cerises
  5. conj quand
  6. nom elles
  7. verb sont
  8. nom fraiches
  9. verb dormir
  10. nom jean
  11. manu aime cerises quand elles sont fraiches.
  12. Phrase composee
  13. nom lit
  14. jean dormir lit.
  15. Phrase simple


 
Comment faire pour parser tout le fichier :(


Message édité par exhortae le 21-12-2007 à 17:41:25
n°1662216
exhortae
Membre du Cartel des Médecins
Posté le 21-12-2007 à 23:23:38  profilanswer
 

si j'ai bien compris le code,  à chaque fois que j'ai un point suivi d'un retour à la ligne lex retourne la valeur 0 à yyparse qui sait qu'il doit parser une nouvelle ligne
 
donc en faisant

Code :
  1. main ()
  2. {
  3. yyin = fopen ("fichier.txt", "r+" );
  4. if (yyin != NULL)
  5. {
  6. while (yyparse () == 0);
  7.   fclose (yyin);
  8. }
  9. else
  10. {
  11. printf ("Impossible d'ouvrir le fichier definition\n" );
  12. }
  13. }


 
ça marche il parse toutes les lignes, par contre quand il arrive à la dernière ligne il la traite, puis affiche un syntax error, comme si il avait essayer de traiter la fin de fichier et n'avait pas trouvé sa règle dans la grammaire. Purrée je sèche là.

n°1662546
sligor
Posté le 23-12-2007 à 10:43:59  profilanswer
 

Il faut que "lex" retourne un tocken FINDEFICHIER (tu l'appelles comme tu veux) indiquant la fin de fichier et dans "yacc" il faut que ta grammaire prennes en compte ce tocken.

n°1662875
exhortae
Membre du Cartel des Médecins
Posté le 25-12-2007 à 08:50:38  profilanswer
 

Merci.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [Résolu] [lex & Yacc] Segmentation fault

 

Sujets relatifs
[Résolu] ndd.net/includes/print.php en ndd.net/print.php[Résolu]Probleme Css IE6
[C++][Résolu] Le compilateur semble ignorer une classe : pourquoi ?[Resolu] Update ADODB ne fonctionne pas
[Resolu] [Problème] [Perl,Tableaux] lire un fichier texte[RESOLU] Integration variable dans un chemin javascript
[RESOLU]Afficher le poids des fichiers listés automatiquement en PHP[c++][resolu]Problème de compilation.
[C++] [résolu] Besoin d'un coup de main pour déboguer mon algo de tri[Résolu] Site internet en japonais
Plus de sujets relatifs à : [Résolu] [lex & Yacc] Segmentation fault


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR