Use of chains with bison and flex

3

I have a problem when retrieving strings that I have saved using flex in bison, I am new with these tools and I am only doing tests to create a language, but as I understand when you use the operator $ n gives you the value of the ele n of the rule (whether it is a token or missing compute), but when I use this operator with a token which should be very basic, it gives me the entire string I entered. My language makes it necessary to put the word "init" at the beginning and at the end the word "end" for test reasons I did that when flex detects init and end it will keep the words init and end in the token. But when in the rule that has the use of init I ask you to print the value of the init token it returns the entire string entered and I only want the value of the token.

Here is my flex code

%option noyywrap

%{

#include <stdio.h>
#define YY_DECL int yylex()
#include "prueba.tab.h"

%}

DIGIT[0-9]
LETRA[a-zA-Z]
ALFANUM[a-zA-Z0-9]
ASIGNACION[=]
IGUALDAD{ASIGNACION}{ASIGNACION}
TAB[ \t]
COMILLAS["]
ID{LETRA}+{ALFANUM}*
CADENA{COMILLAS}{ID}{COMILLAS}

%%
{TAB}   ;
"init" {printf("INIT es %s \n",yytext);yylval.idval = yytext;return INIT;}
"end" {printf("END es %s \n",yytext);yylval.idval = yytext;return END;}
"if" {printf("%s \n",yytext); yylval.idval = yytext;return T_IF;}
"else" {printf("%s \n",yytext); yylval.idval = yytext;return T_ELSE;}
"print" {printf("%s \n",yytext); yylval.idval = yytext; return T_PRINT;}
"define" {printf("%s \n",yytext); yylval.idval = yytext;return T_DEFINE;}
"false" {printf("BOOL %s \n",yytext); yylval.idval = yytext;return T_BOOL;}
"true" {printf("BOOL %s \n",yytext); yylval.idval = yytext;return T_BOOL;}
"exit"      {return T_QUIT;}
"quit"      {return T_QUIT;}
{IGUALDAD} {printf("%s \n",yytext); yylval.idval = yytext;return T_IG;}
{ASIGNACION} {printf("ASIG es %s \n",yytext); yylval.idval = yytext; return T_AS;}
{DIGIT}+\.{DIGIT}+  {printf("FLOAT es %s \n",yytext); yylval.idval = yytext; return T_FLOAT;}
 {DIGIT}+       {printf("INT es %s \n",yytext); yylval.idval = yytext; return T_INT;}
\n      {return T_NEWLINE;}
";"     {printf("PYC es %s \n",yytext); yylval.idval = yytext; return T_PYC;}
"+"     {yylval.idval = yytext; return T_PLUS;}
"-"     {yylval.idval = yytext; return T_MINUS;}
"*"     {yylval.idval = yytext; return T_MULTIPLY;}
"/"     {yylval.idval = yytext; return T_DIVIDE;}
"("     {printf("%s \n",yytext); yylval.idval = yytext; return T_LEFT;}
")"     {printf("%s \n",yytext); yylval.idval = yytext; return T_RIGHT;}
{ID} {printf("ID es %s \n",yytext); yylval.idval = yytext; return T_ID;}
{CADENA}    {printf("CADENA es %s \n",yytext); yylval.idval = yytext; return T_CADENA;}
%%

And my bison code

%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int yylex();
extern int yyparse();
extern FILE* yyin;

void yyerror(const char* s);
%}

%union {
    char *idval;
}

%token<idval> T_ID
%token<idval> T_INT
%token<idval> T_FLOAT
%token<idval> T_CADENA
%token<idval> T_PLUS
%token<idval> T_MINUS
%token<idval> T_MULTIPLY
%token<idval> T_DIVIDE
%token<idval> T_RIGHT
%token<idval> T_LEFT
%token<idval> T_IF
%token<idval> T_ELSE
%token<idval> T_BOOL
%token<idval> T_PRINT
%token<idval> T_DEFINE
%token<idval> T_IG
%token<idval> T_AS
%token<idval> T_PYC
%token<idval> INIT
%token<idval> END
%token T_NEWLINE T_QUIT
%left T_PLUS T_MINUS
%left T_MULTIPLY T_DIVIDE


%type<idval> expr
%type<idval> asi
%type<idval> valor
%type<idval> expri
%type<idval> ti
%type<idval> f
%type<idval> t
%type<idval> p
%type<idval> ifelse
%type<idval> cond
%type<idval> print
%type<idval> def_met
%type<idval> param
%type<idval> llam_met




%start s

%%

s: calculation 
;

calculation: inicio T_NEWLINE 
       | T_QUIT T_NEWLINE { printf("bye!\n"); exit(0); }
;

inicio: INIT p END  {printf("$1 %s \n",$1);}
;

p: {$$="";}
    | asi 
    | ifelse
    | print
    | def_met
    | llam_met
;

pi: asi
    | ifelse
    | print
    | llam_met
;

llam_met: T_ID T_LEFT param T_RIGHT T_PYC p
;

def_met: T_DEFINE T_ID T_LEFT param T_RIGHT T_LEFT pi T_RIGHT p
;

param: T_ID
    | T_ID param
;

print: T_PRINT T_INT T_PYC p
    | T_PRINT T_CADENA  T_PYC p
    | T_PRINT T_ID T_PYC p
;

ifelse: T_LEFT T_IF cond pi T_ELSE pi T_RIGHT p 
;


cond: T_ID T_IG T_ID
    | T_BOOL T_IG T_BOOL
    | T_BOOL T_IG T_ID
    | T_ID T_IG T_BOOL
    | T_BOOL
;

asi: T_ID T_AS valor T_PYC p 
;

valor:  T_CADENA  
    | expr
    | T_BOOL
;

expr: t expri
;

expri:  {$$ = "";}
    | T_PLUS t expri
    | T_MINUS t expri
;

t: f ti 
;

ti:     {$$ = "";}
    | T_MULTIPLY f ti
    | T_DIVIDE f ti
;

f:  T_LEFT expr T_RIGHT
    | T_INT /*{printf("INT, %s\n", $1);}{$$ = strcat("INT, ",$1);}*/
;
%%

int main() {
    yyin = stdin;

    do { 
        yyparse();
    } while(!feof(yyin));

    return 0;
}

void yyerror(const char* s) {
    fprintf(stderr, "Parse error: %s\n", s);
    exit(1);
}

The most basic execution that shows me the error

    
asked by Luis 21.04.2017 в 09:57
source

1 answer

0

I can not give a 100% complete answer because I have not played with flex and bison for a long time, and although I have installed them, it is taking me a long time to replicate your program.

However, this FAQ explains that the problem 1 is in the flex file; you are doing yylval.idval = yytext; with which you copy the address of the buffer where the string is, but do not copy the string itself; that's why later the flex code reuses said buffer and you get text that you do not expect.

According to the document, what you should do is replace all

yylval.idval = yytext;

for

yylval.idval = strdup(yytext);
    
answered by 21.04.2017 в 17:02