Segmentation fault (recorded core image) in YACC / Bison

1

ERROR while doing integer printf When I try to enter the text: WRITE 10;                                   FINISH; the segmentation fault (core image saved) error appears, since the list is a string type and I can not do integer printf.

Follow the YACC / BISON code:

%{

 #include <stdio.h>
 int yylex(void);
 int yyerror(const char *s);
 char stR[20];


%}
%union{
    char *str; /* para strings*/
    int num; /* para inteiros */
     }

%token TERMINAR ESCREVER
%token SUBTRACAO 
%token MULTIPLICACAO 
%token DIVISAO 
%token SOMA
%token<num> NUM 
%token<str> TEXTO 
%type<str> elemento
%type<num> expr 
%type<str> lista
%start s

%%

s:linha s
 |TERMINAR ';' {return 0;}
 ;

linha: ESCREVER lista ';' {printf("%s",$2);}                       
     | VARS
     ;

lista: elemento { $$=$1; }
     |lista ',' elemento 
     ;

elemento:TEXTO { $$=$1; }
        |expr  
        ;

VARS :
     | NUM 
     | TEXTO
     | expr
     | TEXTO '=' VARS ';' /* para delcaracoes */
     ;



 expr     : NUM  SOMA expr                {$$=$1+$3;}
          | NUM  SUBTRACAO expr           {$$=$1-$3;}
          | NUM  MULTIPLICACAO expr       {$$=$1*$3;}
          | NUM  DIVISAO expr             {$$=$1/$3;}
          | NUM  '+' expr                 {$$=$1+$3;}
          | NUM  '=' expr                 {$$=$1=$3;}
          | NUM  '-' expr                  {$$=$1-$3;}
          | NUM  '*' expr                 {$$=$1*$3;}
          | NUM  '/' expr                  {$$=$1/$3;}
          | NUM                           {$$=$1;   }
          ;             


%%

LEX Code

 %{
#include <stdio.h>
#include <stdlib.h>
#include "gram.h"

int yyerror(const char *s);

%}





%%

 "ESCREVER" {return   ESCREVER; }                                
 "TERMINAR" {return TERMINAR; }

  [0-9]+     { yylval.num =atoi(yytext);
               return NUM; }


  [A-Za-z0-9]* { yylval.str=strdup(yytext);
                 return TEXTO;}

"/" |
"-" |
"+" |
"*" |
"=" |
"." |
";" |
","         {return yytext[0]; }
[ \n\t]     {  }
.           { return yytext[0]; }


%%


int yywrap(){ return 1; }
    
asked by anonymous 16.01.2017 / 19:58

1 answer

0

To begin with, you need to understand the cause of the error. When you pass the entry ESCREVER 10; TERMINAR; it will be parsed as follows:

Each node in this tree corresponds to a reduction rule that will be executed. The problem is that for the rule elemento: expr you have not defined any rules then the value of $$ will be left uninitialized. More up, the linha rule will interpret this uninitialized value as a pointer to string and attempt to printf on it, and everything will explode.

To fix this, you're going to want to give a big stir in things, since there's a lot that obviously has no way of working in the current way. The first big problem is that you said elemento always produces a string but the correct thing would be that elements could be strings or integers. You can do this by using a struct that contains a union and a tag saying which of the union fields is being used:

typedef enum { TAG_INT, TAG_STR } Tag;


typedef struct {
    Tag tag;
    union {
      int intval;
      char* strval;
    } u;
} Elemento;

At the time of processing the elements you fill in these fields appropriately:

elemento:
      TEXTO {
       $$.tag = TAG_STR;
       $$.u.strval = $1;
     }

    | expr {
       $$.tag = TAG_INT;
       $$.u.intval = $1;
      }
    ;

And when it comes to printing a value you use the tag to know what has to be done:

 switch(val.tag){
     case TAG_INT:
        printf("%d\n", val.u.intval);
        break;
     case TAG_STR:
        printf("%d\n", val.u.strval);
        break;
     default:
        assert(0);
 }

Another problem that strikes you is that you said that the lista rule produces a string. The correct thing would be to say that this rule produces a list of elements. I think the simplest way to do this would be by using a linked list.

I do not guarantee that the code I wrote will work first (maybe I crapped the C or YAC syntax) but the basic idea is this.

    
16.01.2017 / 21:13