Для реентерабельного лексера все сообщения должны включать состояние , которое содержится в сканере .
В любом месте вашей программы ( например, внутри main
) вы можете получить доступ к переменным состояния через специальные функции, к которым вы передадите свой сканер. Например, , в оригинале reentrant.l
вы можете сделать это:
yyscan_t scanner;
yylex_init(&scanner);
yyset_in(fopen(argv[1], "rb"), scanner);
yylex(scanner);
yylex_destroy(scanner);
Я переименовал scanner
, чтобы избежать путаницы с yyscanner
в действиях. В отличие от общего кода на C, все ваши действия происходят внутри гигантской функции yylex
, которой ваш сканер передается под именем yyscanner
. Таким образом, yyscanner
доступно для всех ваших действий. Кроме того, yylex
имеет локальную переменную с именем yyg
, которая хранит все состояние, и большинство макросов обычно ссылаются на yyg
.
Несмотря на то, что вы можете использовать макрос yyin
внутри main
, определив yyg
, как вы это сделали в своем собственном ответе, это не рекомендуется. Для реентерабельного лексера макросы предназначены только для действий.
Чтобы увидеть, как это реализовано, вы всегда можете просмотреть сгенерированный код:
/* For convenience, these vars
are macros in the reentrant scanner. */
#define yyin yyg->yyin_r
...
/* Holds the entire state of the reentrant scanner. */
struct yyguts_t
...
#define YY_DECL int yylex (yyscan_t yyscanner)
/** The main scanner function which does all the work.
*/
YY_DECL
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
...
}
В flex документах есть много других параметров reentrant
, которые включают в себя чистый пример компиляции. (Google " flex reentrant " и найдите ссылку flex.sourceforge
.) В отличие от bison , flex имеет довольно простую модель для повторного входа. Я настоятельно рекомендую использовать реентрант flex с Lemon Parser , а не с yacc / bison .