Создание повторного входа в бизер / флекс парсер со встроенным YYSTYPE

У меня проблемы с выполнением шагов, чтобы заставить моего парсера бизона / гибкого входа повторно войти с минимальным количеством суеты.

Проблема, кажется, в лексере. Поскольку все синтаксические анализаторы являются повторными, я больше не могу назначать yylval напрямую. Вместо этого, согласно руководству по Flex, я должен вызвать эту функцию:

void yyset_lval ( YYSTYPE * yylvalp , yyscan_t scanner );

Но проблема в том, что YYSTYPE является целочисленным типом. Это не динамически назначаемое значение и вообще не lvalue, поэтому я не могу передать указатель на него! Я что-то упустил, и если нет, то как мне установить значение yylvalue? У меня никогда не было этой проблемы с парсером, не входящим в систему!

Обновление: Хорошо, я думаю, что, возможно, преодолел проблему целочисленного типа. Теперь кажется, что анализатор дает сбой, потому что вход не настроен, и я не нахожу документацию о том, как сказать лексеру, откуда читать входные данные.

Файл Flex:

%{
#define YYSTYPE Token // Token is a typedef to an integral type
// following two lines added per suggestion from Chris Dodd
#define YYPARSE_PARAM yyscan_t scanner
#define YYLEX_PARAM scanner

%}
%option reentrant
%option bison-bridge

// ...

{D}+{IS}?               {
    *yylval = Tokenint(strtol(yytext,0,10));
     return(CONSTANT); 
}

Файл зубра:

%{
#define YYSTYPE Token
%define pure-parser
%lex-param {void * scanner}
%parse-param {void * scanner}
%token CONSTANT
// ...

Получение сбоя в этой строке в парсере:

*yy_cp = yyg->yy_hold_char;

Я подозреваю, что не могу правильно все инициализировать для разбора. Руководства очень запутанные по этому вопросу, часто ссылаются на типы или переменные, не объясняя, откуда они берутся и почему они используются. Я вызываю синтаксический анализ следующим образом:

void * scanner;
yylex_init(&scanner);
yyparse(scanner); // Note: was &scanner, this is wrong and will crash!

После чтения кода кода, yylex_init выделяет struct yyguts_t и обнулять его. Когда я достигаю сбоя, yy_cp является нулевым указателем, фактически весь struct yyguts_t все еще обнулен! Поэтому я подозреваю, что не инициализирую что-то должным образом, и это приводит к тому, что он не знает, откуда получить информацию.

Окончательное редактирование: я собираюсь пометить этот вопрос как закрытый, поскольку на мой первоначальный вопрос был дан ответ, и вновь открыть новую проблему как новый вопрос.

1 ответ

Решение

Обычно для создания реентерабельного парсера / сканера вы будете использовать %option bison-bridge в вашем .l файл и %define api.pure в вашем .y файл. Это делает yylval аргумент yylex вместо глобальной переменной. Кроме того, вам необходимо иметь:

%{
#define YYPARSE_PARAM yyscan_t scanner
#define YYLEX_PARAM scanner
%}

в верхней части вашего .y файл для передачи дополнительного scanner Параметр через ваш парсер к вашему лексеру.

Сейчас если YYSTYPE является int (у вас нет %union или декларация YYSTYPE в вашем .y файл), то вы должны установить значение токена в вашем .l просто сказав *yylval = whatever;

Другие вопросы по тегам