Segmentation failure (recorded core image) in YACC/Bison

Asked

Viewed 118 times

1

ERROR while doing integer printf When I try to enter the text : WRITE 10; TERMINATE; The Segmentation Failure error (saved core image) appears, since the list is string type and I cannot print integers.

Follow the code YACC/BISON:

%{

 #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; }
  • Missing include your lexer (and which commands you use to compile).

  • submeti. the name of my program is pro gcc -o pro lex. c gram. c, gram. c gram. h: pro. y, Bison -d -o gram. c pro. y, lex. c: pro. l gram. h, flex -o lex. c pro. l

1 answer

0


To begin, you need to understand the cause of the error. When you pass the inputESCREVER 10; TERMINAR; be parsed as follows;:inserir a descrição da imagem aqui

Each of the nodes of this tree corresponds to a reduction rule that will be executed. The problem is that for the rule elemento: expr you did not define any rule then the value of $$ will not initialize. Above, the rule of linha will interpret this uninitialized value as a pointer to string and try to printf it, and everything ends up exploding.

To fix this, you’re going to have to make a little bit of a fuss about things, since there’s a lot that obviously can’t work in the current form. The first big problem is that you said elemento always produces a string but the correct thing would be that elements can be strings or integers. You can do this using a struct that contains a Union and a tag telling 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;

Ai when processing the elements you fill these fields appropriately:

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

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

And when 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 attention is that you said the rule lista produces a string. It would be correct to say that this rule produces a list of elements. I think the simplest way to do that would be to use a chained list.


I don’t guarantee that the code I wrote will work at first (maybe I did a shit with the syntax of C or Yacc) but the basic idea is this.

  • and how to change the list to be a list of elements type %TOKEN <string,int>list , but this is not possible in Bison

  • Create a new data type ListaDeElemento, the same way we created a new guy Elemento to store a value that can be number or string.

  • you want me to create a new <pre><code>Listing:'

Browser other questions tagged

You are not signed in. Login or sign up in order to post.