Регулярное выражение Lex получает несколько дополнительных символов

#c #bison #yacc #flex-lexer #lex

#c #зубр #yacc #flex-lexer #lex

Вопрос:

У меня есть следующее определение в моем файле lex:

 L   [a-zA-Z_]                                           
A   [a-zA-Z_0-9] 
%%
{L}{A}*                 { yylval.id = yytext; return IDENTIFIER; }
 

И я делаю следующее в своем файле YACC:

 primary_expression
    : IDENTIFIER            { puts("IDENTIFIER: "); printf("%s", $1); }
 

Мой исходный код (тот, который я анализирую) имеет следующее назначение:

 ab= 10;
 

По какой-то причине эта printf("%s", $1); часть печатается ab= и не только ab .

Я почти уверен, что это тот раздел, который печатается ab= , потому что, когда я удаляю printf("%s", $1); идентификатор, он вообще не печатается.

У меня действительно закончились идеи. Что я делаю не так?

Дайте мне знать, если я могу быть более ясным.

Ответ №1:

Что я делаю не так?

Вы предполагаете, что строка, на которую указывает, yytext является постоянной. Это не так.

Время жизни строки, на которую указывает, yytext является лексическим действием связанного правила. Если это правило в конечном итоге возвращается, yytext оно сохранится до следующего yylex вызова. И это все.

bison -сгенерированные синтаксические анализаторы имеют односимвольный предварительный просмотр. Таким образом, к тому времени, когда анализатор выполняет семантическое действие, yylex оно было вызвано снова (для предварительного просмотра); следовательно, вы не можете использовать сохраненное значение yytext даже для последнего (или единственного) токена в правиле.

Решение: скопируйте строку. (Я использую strdup , но по какой-то причине некоторым людям нравятся malloc и strcpy. Если вы это сделаете, не забудьте о терминаторе NUL.) И не забудьте free() скопировать, когда закончите с этим.

Для справки: что говорится в руководстве по flex.