Search code examples
bisonflex-lexer

problem with flex output with decimal numbers


I am programming a small floating numbers calculator in Flex and Bison. So far my code is the following: Flex code

%{
# include "prb1.tab.h"
float yylval;
%}

%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
[0-9]+(\.[0-9]+)? { yylval = atof(yytext); return NUMBER; }
\n { return EOL; }
[ \t] { /* ignore whitespace */ }
. { printf("Mystery character %c\n", *yytext); }
%%
yywrap()
{
}
/*main(int argc, char **argv)
{
 int tok;
 while(tok = yylex()) {
 printf("%d", tok);
 if(tok == NUMBER) printf(" = %f\n", yylval);
 else printf("\n");
 }

}*/

Bison code

/* simplest version of calculator */
%{
#include <stdio.h>
%}
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL
%%
calclist: /* nothing */
| calclist exp EOL { printf("= %f\n", $2); }
;
exp: factor
| exp ADD factor { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
main(int argc, char **argv)
{
    yyparse();
}
yyerror(char *s)
{
    fprintf(stderr, "error: %s\n", s);
}

The problem that I have is when I run the program the answer is still in integer. How can I change it to display the answer as a floating point number?

Thanks


Solution

  • Unless you explicitly declare a semantic value type, bison/yacc assume that semantic values have type int. Declaring yylval in your flex file does not change anything, since bison never sees that file. (It leads to undefined behaviour, though, since yylval ends up being declared with two different types. I would gave expected the compiler ti complain about that.)

    You can declare a semantic value type in your bison file like this:

    %define api.value.type {double}
    

    (I used double because it is almost certainly what you want; float is a low-precision datatype which should only be used if you have a good reason.)

    You should also remove the declaration of yylval from your flex file, since it will be declared in the header file generated by bison.

    See the bison manual for more details and code examples.