Reputation: 263
I'm trying a implement a flex/bison calculator which can do floating point arithmetic. My flex code looks like this
%{
#include "calc.tab.h"
#include <stdlib.h>
void yyerror(char *s);
%}
digit [0-9]
integer {digit}+
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp ({integer}|{real})[eE]-?{integer}
%%
({integer}|{real}|{exp}) { yylval = atof(yytext); return NUMBER; }
[-+*/\n] { return *yytext; }
[ \t\v\f\r] { }
. { yyerror("Unknown Character"); }
%%
int yywrap(void)
{
return 1;
}
And my bison code looks like this
%{
#include <stdio.h>
typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
void yyerror(char *s);
extern char *yytext;
extern int yylineno;
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
program: program expr '\n' { printf("%g\n", $2); }
| program '\n'
|
;
expr: expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| NUMBER { $$ = $1; }
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s at %s, line %d\n", s, yytext, yylineno);
}
int main(int argc, char *argv[])
{
yyparse();
return 0;
}
This doesn't produce the right output. Even though the lexer interprets the strings as doubles and stores them properly in the yylval
variable, when the parser adds up the numbers, it spits out only 0.0000
. However, if I declare yylval
as a union through the %union
directive consisting of only one double lf_val;
variable, and store the atof
output in this field of yylval
in the lexer and also declare %token <lf_val> NUMBER
and %type <lf_val> expr
in the parser, things seem to work.
But, why doesn't the straightforward method of typedef
ing YYSTYPE
work? I also tried #define YYSTYPE double
. That didn't work either.
Upvotes: 4
Views: 7774
Reputation: 121
Concerning %code
, Bison's documentation states:
%code requires [...] is the best place to override Bison's default YYSTYPE
and YYLTYPE definitions.
So juste add the following at the top of you bison file:
%code requires
{
#define YYSTYPE double
}
You will also want to remove these two lines:
typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
Note that YYSTYPE_IS_DECLARED is, as far as I know, not documented anywhere and is thus for Bison's internal use only.
If you are not familiar with the use of Bison's %code
directives over simple %{
prologues, you might find this section of the documentation interesting to read.
Upvotes: 5