Bison / ya cc грамматик пропуска синтаксического анализатора, если он не разделен пробелом - "неожиданный конец $" - PullRequest
1 голос
/ 25 января 2020

Привет У меня есть сценарий, в котором бизон успешно проанализирует мой ввод, если есть пробел, разделяющий грамматику ...

Вот ситуация: я пытаюсь объявить переменную:

int a = 31 ;

Этот год успешно разбирается

int a = 31;

Не удается успешно разобрать

Я получаю сообщение об ошибке:

syntax error, unexpected $end, expecting TSEMI

Вот раздел кода бизона

%token <string> TIDENTIFIER TINTEGER TDOUBLE
%token <token> TCEQUAL TCNE TCLT TCLE TCGT TCGE TASSIGN
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TDOT TSEMI
%token <token> TPLUS TMINUS TMUL TDIV

...

var_decl : ident ident TSEMI { $$ = new VarDel($1, $2); }
         | ident ident TASSIGN expr TSEMI {$$ = new VarDel($1, $2, $4);}
         ;

ident : TIDENTIFIER { $$ = new Var($1->c_str()); delete $1; }
      ;

expr : ident { $<ident>$ = $1; }
     | numeric
     ;

numeric : TINTEGER { $$ = new Num(atol($1->c_str())); delete $1; }
        | TDOUBLE { $$ = new Num(atof($1->c_str())); delete $1; }
        ;

А вот раздел моего гибкого файла


[ \t\n]                 ;
[a-zA-Z_][a-zA-Z0-9_]*  SAVE_TOKEN; return TIDENTIFIER;
[0-9]+.[0-9]*           SAVE_TOKEN; return TDOUBLE;
[0-9]+                  SAVE_TOKEN; return TINTEGER;
"="                     return TOKEN(TASSIGN);
"=="                    return TOKEN(TCEQUAL);
"!="                    return TOKEN(TCNE);
"<"                     return TOKEN(TCLT);
"<="                    return TOKEN(TCLE);
">"                     return TOKEN(TCGT);
">="                    return TOKEN(TCGE);
"("                     return TOKEN(TLPAREN);
")"                     return TOKEN(TRPAREN);
"{"                     return TOKEN(TLBRACE);
"}"                     return TOKEN(TRBRACE);
"."                     return TOKEN(TDOT);
","                     return TOKEN(TCOMMA);
"+"                     return TOKEN(TPLUS);
"-"                     return TOKEN(TMINUS);
";"                     return TOKEN(TSEMI);
"*"                     return TOKEN(TMUL);
"/"                     return TOKEN(TDIV);
.                       printf("Unknown token!n"); yyterminate();


Почему он успешно разбирается, когда есть пробел, а не когда он есть?

Спасибо

1 Ответ

3 голосов
/ 25 января 2020

[0-9]+.[0-9]* должно быть [0-9]+\.[0-9]*. Как написано, он соответствует 31;.

. Вы бы хорошо включили отладку flex (флаг командной строки -d), чтобы увидеть, как он токенизируется. Кроме того, использование atof скрывает тот факт, что токен не является допустимым числом. Попробуйте использовать более безопасную строку → преобразователь чисел; вы найдете его в стандартной библиотеке C ++; в C это будет strtod с последующей проверкой того, что endptr находится в конце. (И вы могли бы сделать это преобразование в лексере, избегая ненужного выделения и освобождения строки.)

...