Создание повторного входа в бизер / флекс парсер со встроенным 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;