Анализ yytext для числа с плавающей запятой дает ноль

Я использую следующий файл lex для преобразования чисел в токены. Однако программа не может правильно анализировать числа с плавающей запятой. Для отладки я добавил операторы printf, и они показывают, что функция strtof не может правильно анализировать числа. Таким образом, ввод 4.2 дает мне результат 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;
}

Есть идеи, где проблема в приведенном выше коде? Я использовал функцию strtof (вне lex) с тем же вводом, и, похоже, она отлично работает.

Спасибо


person Arani    schedule 09.12.2012    source источник
comment
Я удалил тег Flex; поскольку этот вопрос не имеет ничего общего с UI Framework и добавил тег gnu-flex, который обычно используется для лексического анализатора.   -  person JeffryHouser    schedule 09.12.2012
comment
Здесь есть и другие проблемы. Вы должны определить yylval как объединение и использовать его соответственно. Вы не должны включать \ n в правило для социальных персонажей, и вы должны включать его в правило для пробелов. Вы можете отменить правило для специальных символов, установив правило для. return * yytext и позволяя синтаксическому анализатору обрабатывать недопустимые символы: таким образом вы также улучшите восстановление после ошибок.   -  person user207421    schedule 10.12.2012


Ответы (1)


Для отладки я добавил операторы printf, и они показывают, что функция strtof не может правильно анализировать числа.

К сожалению нет. Операторы printf показывают, что yylval, если интерпретируется как число с плавающей запятой, распечатывается как 0 в формате %f. Это ничего не говорит о результате strtof.

Независимо от lex, следующие два оператора не могут значимо появляться в одной и той же области в программе C:

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

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

yylval либо int, либо double, либо ни то, ни другое, но не может быть и тем, и другим. Обратите внимание, что формат в printf составляет обещание: если вы используете %f, вы обещаете printf, что передадите ему double. У него нет возможности проверить это, поэтому он ловит вас на слове и интерпретирует любой полученный аргумент как double. Если вы солгаете printf, вы получите бессмысленный вывод. Если вы компилируете свои программы с разумными уровнями предупреждений (-Wall на gcc или clang), компилятор предупредит вас об очевидных нарушениях. Я настоятельно рекомендую вам это сделать.

Обратите внимание, что по умолчанию yylval - это int. Если вы ничего не сделали, чтобы это изменить, то это то, что у вас есть.

person rici    schedule 10.12.2012
comment
Я определил yylval как float (используя #define YYSTYPE float в файле yacc). Но это не дает мне желаемого результата, даже если я использую только вводы с плавающей запятой. - person Arani; 10.12.2012
comment
Вы можете поместить #define YYSTYPE float в свой yacc файл, но я не верю, что это сделает его доступным в y.tab.h, поэтому я почти уверен, что flex по-прежнему будет рассматривать yylval как int. В любом случае вы не можете использовать %d и %f с yylval и ожидать получения значимого вывода; Я продолжаю предлагать вам компилировать с адекватными уровнями предупреждений, и в этом случае вы, вероятно, увидите, что происходит. - person rici; 10.12.2012
comment
Спасибо. Теперь я понимаю проблему. Добавление -Wall в файл make дает мне предупреждение. - person Arani; 10.12.2012