Flex 2.5.35 yy_scan_buffer не инициализирует номера строк и столбцов

Я использую flex 2.5.35 и bison 2.7 (хотя, по-моему, это гибкая проблема, поэтому я пропустил parser.y)

Моя грамматика Flex очень проста:

lexer.l

%{
#define YY_NO_INPUT
#include "parser.h"

#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; \
    yylloc->first_column = yycolumn; yylloc->last_column = yycolumn + (int)yyleng - 1; \
    yycolumn += (int)yyleng;

%}

%option yylineno
%option outfile="lexer.c" header-file="lexer.h"
%option warn
%option reentrant noyywrap never-interactive nounistd
%option nounput
%option bison-bridge
%option bison-locations

%%

[ \n\r\t]*               { /* Skip blanks. */ }
[A-Za-z0-9_\[email protected]]+       { yylval->value = strdup(yytext); return TOKEN_VAR; }
"&&"                   { return TOKEN_AND; }
"||"                   { return TOKEN_OR; }
"!"                    { return TOKEN_NOT; }
"("                    { return TOKEN_LPAREN; }
")"                    { return TOKEN_RPAREN; }

%%

При сканировании строки значения для номера строки и столбца были неинициализированным мусором. Я проследил код и добавил следующие строки в yy_scan_buffer в сгенерированном файле lexer.c:

b->yy_bs_lineno = 1;
b->yy_bs_column = 1;

Теперь значения ожидаются.

Это ошибка? yy_create_buffer корректно инициализирует эти поля, но yy_scan_buffer нет.

Могу ли я использовать параметр % yylineno при разборе строк?

Есть ли работа вокруг, или мне действительно нужно изменить сгенерированный файл lexer.c?

4
nl ja de

4 ответы

Да, я могу подтвердить, что это проблема с бизоном. Случилось со мной, я исправил это, инициализируя их в моей «функции компилятора»,

void myParseFunction(const char* code, ...){
    yyscan_t myscanner;
    yylex_init(&myscanner);
    struct yyguts_t * yyg = (struct yyguts_t*)myscanner;

    yy_delete_buffer(YY_CURRENT_BUFFER,myscanner);
    yy_scan_string(code, myscanner);

   //[HACK] Those are not properly initialized for non file parsers
   //and becuase of that we get garbage in yyerror...
    yylineno = 1;
    yycolumn = 0;

    bool nasi = yyparse(myscanner, );
        yylex_destroy(myscanner);
        return nasi;
}

Обратите внимание, что yylineno и yycolumn работают отлично с помощью реентерабельных парсеров, поскольку они определяются как маркос, которые относятся к «yyg».

2
добавлено

Да, я могу подтвердить, что это проблема с бизоном. Случилось со мной, я исправил это, инициализируя их в моей «функции компилятора»,

void myParseFunction(const char* code, ...){
    yyscan_t myscanner;
    yylex_init(&myscanner);
    struct yyguts_t * yyg = (struct yyguts_t*)myscanner;

    yy_delete_buffer(YY_CURRENT_BUFFER,myscanner);
    yy_scan_string(code, myscanner);

   //[HACK] Those are not properly initialized for non file parsers
   //and becuase of that we get garbage in yyerror...
    yylineno = 1;
    yycolumn = 0;

    bool nasi = yyparse(myscanner, );
        yylex_destroy(myscanner);
        return nasi;
}

Обратите внимание, что yylineno и yycolumn работают отлично с помощью реентерабельных парсеров, поскольку они определяются как маркос, которые относятся к «yyg».

2
добавлено

Да, я могу подтвердить, что это проблема с бизоном. Случилось со мной, я исправил это, инициализируя их в моей «функции компилятора»,

void myParseFunction(const char* code, ...){
    yyscan_t myscanner;
    yylex_init(&myscanner);
    struct yyguts_t * yyg = (struct yyguts_t*)myscanner;

    yy_delete_buffer(YY_CURRENT_BUFFER,myscanner);
    yy_scan_string(code, myscanner);

   //[HACK] Those are not properly initialized for non file parsers
   //and becuase of that we get garbage in yyerror...
    yylineno = 1;
    yycolumn = 0;

    bool nasi = yyparse(myscanner, );
        yylex_destroy(myscanner);
        return nasi;
}

Обратите внимание, что yylineno и yycolumn работают отлично с помощью реентерабельных парсеров, поскольку они определяются как маркос, которые относятся к «yyg».

2
добавлено

Вы скопировали код YY_USER_ACTION из раздела «Добавление местоположений в Lexer» в oreilly книга

Я считаю, что вы забыли добавить int yycolumn = 1; до определения YY_USER_ACTION, как это сделано в примере кода в ссылке.

1
добавлено
Итак, я увидел это в примере и поместил его изначально. Однако, возможно, из-за параметров конфигурации это не будет компилироваться. yycolumn не является целым числом, а макросом, и в этот момент его нельзя назначить.
добавлено автор Seb Rose, источник