Reputation: 65
I am new in Flex/Bison. I want to use only strings for values (is a language translator). I have this for test:
example.l:
%option noyywrap nodefault
%{
#include <string.h>
#include "example.tab.h"
%}
%%
[ \t\n] {;}
"<=" {return LEFT;}
"=>" {return RIGHT;}
[0-9]+ { yylval=strdup(yytext); return NUMBER; }
. { return yytext[0]; }
%%
example.y:
%{
#include <stdio.h>
#define YYSTYPE char const *
%}
%token NUMBER
%token LEFT "<=" RIGHT "=>"
%%
start: %empty | start tokens
tokens:
NUMBER "<=" NUMBER { printf("%s <= %s\n",$1,$3); }
| NUMBER "=>" NUMBER { printf("%s => %s\n",$1,$3); }
| NUMBER '>' NUMBER { printf("%s > %s\n",$1,$3); }
| NUMBER '<' NUMBER { printf("%s < %s\n",$1,$3); }
%%
main(int argc, char **argv) { yyparse(); }
yyerror(char *s) { fprintf(stderr, "error: %s\n", s); }
When I compiled:
bison -d example.y
flex example.l
cc -o example example.tab.c lex.yy.c -lfl
example.l: In function ‘yylex’:
example.l:13:9: warning: assignment makes integer from pointer without a cast
[0-9]+ { yylval=strdup(yytext); return NUMBER; }
^
But work as awaited.
If I don't use #define YYSTYPE char const *
and use instead the %union:
%union {
char * txt;
}
%token <txt> NUMBER
And change the assignation to [0-9]+ { yylval.txt=strdup(yytext); return NUMBER; }
, it has no warning and works.
I tried thing like define the same YYSTYPE in flex file and cast the assignation without success. What is wrong? How to fix without using %union?
Thanks.
Upvotes: 0
Views: 1969
Reputation: 65
The final working example is:
example.l:
%option noyywrap nodefault
%{
#include <string.h>
#define YYSTYPE char *
#include "example.tab.h"
%}
%%
[ \t\n] {;}
"<=" {return LEFT;}
"=>" {return RIGHT;}
[0-9]+ { yylval=strdup(yytext); return NUMBER; }
. { return yytext[0]; }
%%
example.y:
%{
#include <stdio.h>
#define YYSTYPE char *
%}
%token NUMBER
%token LEFT "<=" RIGHT "=>"
%%
start: %empty | start tokens
tokens:
NUMBER "<=" NUMBER {
printf("%s <= %s\n",$1,$3);
free($1);
free($3);
}
| NUMBER "=>" NUMBER {
printf("%s => %s\n",$1,$3);
free($1);
free($3);
}
| NUMBER '>' NUMBER {
printf("%s > %s\n",$1,$3);
free($1);
free($3);
}
| NUMBER '<' NUMBER {
printf("%s < %s\n",$1,$3);
free($1);
free($3);
}
%%
main(int argc, char **argv) { yyparse(); }
yyerror(char *s) { fprintf(stderr, "error: %s\n", s); }
Upvotes: 0
Reputation: 881
You need move #define YYSTYPE char const *
to example.l before #include "example.tab.h"
.
If you take a look inside example.tab.h you will find something like this:
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
// ...
#endif
This i mean you need define YYSTYPE before this code, i.e. before #include "example.tab.h
. Otherwise, if YYSTYPE not defined on this moment, YYSTYPE will be defined as int.
Another possibility is use bison feature %define api.value.type {char const *}
, what you need to put in example.y. In that case example.tab.h will be generated with YYSTYPE of char const *
type.
Upvotes: 2