Беспорядок декларации бизонов / флексов ... как и куда мне включать / декларировать? - PullRequest
7 голосов
/ 30 сентября 2011

Я использую Bison и Flex для создания пары сканеров и анализаторов, но не могу обернуться, где все должно быть включено и объявлено.

Прежде всего, я использую повторно входящий Flex, поэтому мне нужно сначала передать тип сканера yyscan_t в Bison, объявив %parse-param {yyscan_t scanner}, а затем заставить Bison передать его во Flex, объявив %lex-param {yyscan_t scanner}. Но yyscan_t не объявляется Bison, поэтому я должен включить сгенерированный Flex файл заголовка сканера (который я назвал scanner.flex.h) в мой файл Bison. Но так как мой Flex-файл включает в себя мой заголовок Bison, а мой заголовок Bison теперь включает в себя заголовок Flex, я получаю циклическое включение, которое запутывает вещи непредсказуемым образом!

И скажем, я хочу добавить отслеживание местоположения с помощью %locations в моем файле Bison и %bison-locations в моем файле Flex. Теперь мне нужно изменить объявление моего yyerror и моего yylex (кажется, я должен определить yylex AGAIN, даже если он определен в сгенерированном заголовке Flex, но я не могу включить это, помните?) В моем файле Bison, чтобы включить указатель YYLTYPE , Но что теперь? Кажется, что объявление YYLTYPE по умолчанию помещается ПОСЛЕ вставки пролога, и поэтому я не могу использовать этот YYLTYPE по умолчанию в объявлении моего yyerror и моего yylex.

Я понимаю, что есть много способов обойти эти проблемы ... но как вы должны делать это правильно? Это полностью ускользает от меня, и это просто оставляет мою голову в беспорядке ...

Ответы [ 2 ]

4 голосов
/ 30 сентября 2011

В верхней части вашего бизона вам нужно отправить объявление этих значений.Вы можете сделать это в общем заголовке или в файле кода, прежде чем включать файлы flex и bison.yyscan_t это просто определение типа void *, поэтому я объявил параметры как указатели void, чтобы заставить его работать.

CommonHeader.h

int yylex (union YYSTYPE * yyval_param, struct YYLTYPE * yylloc_param, void * yyscanner);
int yyerror(struct YYLTYPE * yylloc_param, void *scanner, const char *s);

Пример yyerror

int yyerror(struct YYLTYPE * yylloc_param, void *scanner, const char *s)
{
    printf("*** Lexical Error %s %d.%d-%d.%d\n", s, 
         yylloc_param->first_line, yylloc_param->first_column, 
         yylloc_param->last_line, yylloc_param->last_column);
}
1 голос
/ 22 января 2014

Наткнулся на это, когда искал что-то еще.

Ответ таков: Bison выдает внутреннюю декларацию для YYLTYPE после спецификации% union.Следовательно, помещение прототипов функций и прочего в раздел пролога после% union позволяет избежать проблемы объявления YYLTYPE самостоятельно;это вполне нормально, Bison допускает несколько прологов:

%{

/* Prologue 1 */

%}

%this

%that

%union {}

%{

/* Prologue 2, YYLTYPE declared */

%}

%%

blah:  talk | blah talk

%%
...