2016-09-29 3 views
0

Je travaille sur un interpréteur, mais j'ai quelques problèmes.Analyseur lexical répétitif, erreur de segmentation

Dans mon lex:

<INITIAL>\{     {BEGIN(BLOC);} 
<BLOC>[^}]*\}    {BEGIN(INITIAL);strncpy(yylval.sval, yytext, MAXVARSIZE); 
          temp = strlen(yylval.sval); 
          yylval.sval[temp-1] = '\0'; 
          return BLOCK;} 

lex retourné un bloc entre {}, et dans mon analyseur de bison, je mis le tampon flex:

ifs: 
    IF PAREOPEN condition PARECLOSE BLOCK {if($3 > 0){scan_string($5);}} 

; 
[...] 

void scan_string(const char* str) 
{ 
    yy_switch_to_buffer(yy_scan_string(str)); 

} 

int main(int argc, char *argv[]) { 
    yyin = stdin; 
      do { 
     printf("aqui2\n"); 
     yyparse(); 

    } while(!feof(yyin)); 

} 

Mais le bison produit plus tard, une erreur de segmentation. Je veux restaurer le tampon à yyin comme il était à l'origine.

+0

Il n'y a pas de récursion ici. – EJP

Répondre

1

Je ne pense pas que cette approche fonctionnera. Voir ci-dessous.

Vous ne devez pas appeler yy_switch_to_buffer; yy_scan_string le fait automatiquement. En outre, pour revenir à yyin, vous devez avoir une règle <<EOF>> qui détecte l'indication de fin de fichier (ou la fin du tampon, dans ce cas) et repasse à yyin. Pour vous assurer de conserver le tampon d'origine, vous devez conserver YY_CURRENT_BUFFER dans une variable temporaire et appeler le yy_switch_to_buffer sur cette variable temporaire; Si vous créez un nouveau tampon à partir de yyin, vous perdrez toute entrée mise en mémoire tampon.

Une façon plus simple de gérer une pile de tampons d'entrée consiste à utiliser une pile tampon; Vous pouvez ensuite appeler yypush_buffer_state pour commencer à analyser le nouveau tampon et yypop_buffer_state dans votre règle <<EOF>>. Cependant, il existe une interaction étrange entre yy_scan_string et yypush_buffer_state, ce qui vous oblige à d'abord pousser une copie du tampon en cours et ensuite le remplacer par l'état de tampon créé par yy_scan_string. Voir this answer pour un exemple. (Vous pourriez vouloir read the relevant section of the Flex manual, qui a un exemple complet bien que ce soit pour imbriquer des fichiers, pas des chaînes.)

Sans voir plus de votre code, il est difficile de savoir d'où vient le segfault. Il peut s'agir d'une erreur dans votre gestionnaire <<EOF>>, que vous n'affichez pas. Il pourrait également être lié à la manipulation de yylval.sval; Si c'est un pointeur vers un tampon (c'est-à-dire un char*), alors il n'est apparemment initialisé nulle part, ce qui est susceptible de produire une erreur lorsque vous y entrez.

Mais il me semble plus probable que vous avez inclus un tableau de caractères de longueur fixe dans le cadre de votre union sémantique. C'est une très mauvaise idée pour un certain nombre de raisons, dont la moindre est que cela gaspille énormément d'espace dans la pile de l'analyseur: chaque entrée inclura le tampon de longueur fixe. De plus, les tampons à longueur fixe ne sont jamais une bonne idée. vous pouvez facilement les déborder.

Dans ce cas, il ne peut pas fonctionner du tout car le tableau fera partie d'une entrée de pile de l'analyseur bison et cette entrée sera retirée de la pile dès que l'action ifs se terminera. Cela laissera le tampon de Flex avec un pointeur qui est quasiment certain de créer des problèmes.

Ainsi, vous pouvez essayer ce qui suit:

  • Modifier le membre sval dans l'union à char* (ce qui nécessitera une variété de changements dans votre code)

  • Remplacer le motif <BLOC> dans votre fichier flexible avec quelque chose comme ceci ;:

    <INITIAL>\{   { BEGIN(BLOC); } 
    <BLOC>[^}]*\}  { BEGIN(INITIAL); 
             yylval.sval = malloc(yyleng); 
             memcpy(yylval.sval, yytext, yyleng - 1); 
             yylval.sval[yyleng - 1] = '\0'; 
             return BLOCK; 
            } 
    
  • Modifier le ifs action dans votre analyseur bison afin qu'il free s le tampon de chaîne alloué dynamiquement (il peut le faire parce que yy_scan_string fait une copie). Ajoutez une règle <<EOF>> et modifiez scan_string pour utiliser une pile tampon, comme ci-dessus.

Même avec tout cela, je ne pense pas que ce soit une très bonne stratégie. Changer le tampon flexible au milieu d'une action de bison ne fonctionnera que si l'analyseur n'a pas lu un jeton de recherche, ce qui le rend très fragile. (Et cela ne fonctionnera pas du tout avec d'autres générateurs d'analyseurs de type yacc, qui lisent toujours un jeton lookahead.) Et il n'est pas évident que cela finisse par fonctionner avec des blocs imbriqués, que vous voudrez probablement implémenter à un moment donné .