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 typedefing YYSTYPE work? I also tried #define YYSTYPE double. That didn't work either.