Forum Programmation.autre La grammaire et Bison

Posté par  (site web personnel) .
Étiquettes : aucune
0
19
nov.
2005
Bonjour,

j'ai quelques soucis avec ma grammaire sous Bison...
J'ai commencé un ptit langage miteu avec 2 fonctions, afficher et saisir, la fonction afficher marche, saisir c'est pour bientot, mais j'ai un warning pour le bloc creation.

En fait j'aimerai savoir pourquoi, et j'aimerai bien qu'on m'explique aussi un peu plus en détails les pipes dans la définition de la grammaire :

Parfois c'est entre 2 lignes, parfois c'est en début. J'ai opté pour "entre 2 lignes", mais je sais pas trop ce que ca change. De meme parfois on commence les lignes juste après le ":", puis parfois on met un retour a la ligne. Bref, j'ai cherché, et j'ai pas trouvé de réponse évidente...

Le warning : gram.y: conflits: 1 réduction/réduction
gram.y:61.9: AVERTISSEMENT: la règle n'a jamais fait de réduction en raison des conflits: creation: /* vide */


ligne:
|
ligne fonction FIN
|
ligne creation FIN

fonction:
|
FUNC_AFFICHER PAR1 CHAINE PAR2 FIN
{
printf("%s\n",$3);
}
;
|
FUNC_SAISIR PAR1 VARIABLE PAR2 FIN
{
char tab[255];
printf("input> ");
scanf("%s",tab);
}
;

creation:
|
VAR_CHAINE VARIABLE '=' CHAINE FIN
|
VAR_ENTIER VARIABLE '=' ENTIER FIN
|
VAR_REEL VARIABLE '=' REEL FIN


Si quelqu'un se sent d'humeur à m'expliquer... Merci !

P.S : les retours chariots aprés chaque ligne du .y sont du a la balise 'pre' que j'utilise pour poster et garder la mise en forme...
  • # Élémetns de réponse ;

    Posté par  (site web personnel) . Évalué à 3.

    Le conflit "réduction/réduction" (reduce/reduce conflict) vient du fait que bison est un compilateur LALR.

    En gros il y a un moment, il ne sait pas quel chemin prendre.

    Je dirais bien que ton lexème "FIN" pose problème puisqu'il peut très bien appartenir à ligne ou ses composantes (creation/fonction). Donc le compliateur ne peux pas réduire l'expression => erreur de reduce/reduce. (Il peut réduire de plusieurs manières, mais il ne fais pas de choix).


    Par ailleurs, je me trompe peut être parce que je n'ai pas fait de lex/yacc depuis un bout de temps, mais je pense que tu ne peux pas mettre une fonction comme ça directement suite aux règles.

    Tu devrais mettre ton code complet, ainsi que le flex qui va avec (sans les balises pre ou sur un site et linké ici). Ce serait plus facile de t'aider.

    Pour les pipes et les :, je fais comme ça : si il n'y a qu'un élément, je le met à la suite
    truc : machin
    Si il y en a plusieurs, alors je met à la ligne. Par contre je garde les pipe en début de ligne. C'est plus propre.
    truc :
    | machin1
    | machin2
    | machin3
    ;

    Mais bon il n'y a pas vraiment de règles et la beauté, c'est subjectif.
    • [^] # Re: Élémetns de réponse ;

      Posté par  (site web personnel) . Évalué à 1.

      Bien, tout d'abiord merci pour ta réponse. Suite a ta demande, voici l'intégralité de mon fichier .l et .y, afin de t'eclairer un peu plus :)

      Je tiens à préciser que c'est pour moi un exercice pédagogique, donc ce n'est certainement pas optimisé, ni très logique, c'est juste une tentative de "mon 1er langage" :)


      lex.l :

      %{
      #include <stdio.h>
      #include "gram.tab.h"
      %}

      %%



      afficher return FUNC_AFFICHER;
      saisir return FUNC_SAISIR;
      chaine return VAR_CHAINE;
      entier return VAR_ENTIER;
      reel return VAR_REEL;
      [0-9]+ yylval.entier = atoi(yytext); return ENTIER;
      [0-9]*\.[0-9] yylval.reel = atof(yytext); return REEL;
      \".*\" yylval.chaine = strdup(yytext+1); yylval.chaine[strlen(yylval.chaine)-1] = '\0'; return CHAINE;
      ^#.*$ return COMMENTAIRE;
      [a-zA-Z_][a-zA-Z_0-9] yylval.chaine = strdup(yytext); return VARIABLE;
      ; return FIN;
      \( return PAR1;
      \) return PAR2;
      \n
      \t
      \
      .


      gram.y :

      %{
      #include <stdio.h>
      #include <string.h>

      void yyerror(const char *str)
      {
      fprintf(stderr,"erreur: %s\n",str);
      }

      int yywrap()
      {
      return 1;
      }

      main()
      {
      yyparse();
      }

      %}

      %token FIN PAR1 PAR2 COMMENTAIRE FUNC_AFFICHER FUNC_SAISIR VAR_CHAINE VAR_ENTIER VAR_REEL EGAL

      %union
      {
      long entier;
      char *chaine;
      double reel;
      }

      %token ENTIER
      %token REEL
      %token CHAINE
      %token VARIABLE


      %%

      ligne:
      |
      ligne fonction FIN
      |
      ligne creation FIN

      fonction:
      |
      FUNC_AFFICHER PAR1 CHAINE PAR2 FIN
      {
      printf("%s\n",$3);
      }
      ;
      |
      FUNC_SAISIR PAR1 VARIABLE PAR2 FIN
      {
      char tab[255];
      fgets(variable,255,stdin);
      }
      ;

      creation:
      |
      VAR_CHAINE VARIABLE '=' CHAINE FIN
      |
      VAR_ENTIER VARIABLE '=' ENTIER FIN
      |
      VAR_REEL VARIABLE '=' REEL FIN


      Voilà. Je ne vois pas trop comment m'en dépatouiller désormais...

      En fait mon "langage" doit savoir faire 3 trucs :

      1/ Avoir une fonction afficher("chaine"); qui affiche une chaine (ca marche à l'heure actuelle)
      2/ Avoir une fonction saisie(variable); qui affiche un prompt puis stock la réponse dans variable
      3/ Peut creer 3 types de variables, chaine, entier, reel, via a déclaration suivante : chaine ma_chaine = ""; (l'initialisation est obligatoire pour l'instant)

      Le reste viendra plus tard..

      Bref, à mon avis, j'ai mal découpé mon problème initial, donc les fondations etant mauvaises....

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.