Question

I am using the following lex file to convert numbers into tokens. However, the program is not able to parse floating-point numbers correctly. For debugging, I have added the printf statements, and they show that strtof function is unable to parse numbers correctly. Thus, giving the input 4.2 gives me the output 0.

%{
#include <stdlib.h>
void yyerror(char *);
#include "y.tab.h"
char *p = NULL;
%}

%%

[0-9]+\.[0-9]+  {
            printf("%s", yytext);
            yylval = strtof(yytext, &p);
            printf("%f has been read\n", yylval);
            return FLOAT;   
        }
[0-9]+      {       yylval = atoi(yytext);
            printf("%d (int) has been read\n", yylval); 
                return INTEGER;
        }

[-+*/\n]    {   printf("%s has been read", yytext);
            return *yytext;
        }

[ \t]       ;   /* skip whitespace */
.               {
            printf("Invalid character %s", yytext);
            yyerror("invalid character");
        }
%%

int yywrap(void) {
return 1;
}

Any ideas where is the problem in the above code? I have used strtof function (outside lex) with the same input, and it seems to work perfectly.

Thanks

Was it helpful?

Solution

For debugging, I have added the printf statements, and they show that strtof function is unable to parse numbers correctly.

Sadly, no. The printf statements show that yylval if interpreted as a floating point number prints out as 0 with format %f. It says nothing about the result of strtof.

Independent of lex, the following two statements cannot meaningfully appear in the same scope in a C program:

printf("%f has been read\n", yylval);

printf("%d (int) has been read\n", yylval); 

yylval is either an int or a double, or neither, but it cannot be both. Note that the format in printf amounts to a promise: if you use %f, you're promising printf that you will pass it a double. It has no way to verifying that, so it takes you at your word and interprets whatever argument it gets as a double. If you lie to printf, you will get meaningless output. If you compile your programs with reasonable warning levels (-Wall on gcc or clang), the compiler will warn you about obvious transgressions. I strongly recommend that you do this.

Note that by default yylval is an int. If you haven't done anything to change that, then that's what you have.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top