Bison / Flex声明混乱......我应该如何包含/声明在哪里?

时间:2011-09-30 15:06:12

标签: include bison flex-lexer

我正在使用Bison和Flex制作一个可重入的扫描器/解析器对,但无法将我的头包裹在所有要包含和声明的地方。

首先,我正在使用可重入的Flex,因此我需要首先将yyscan_t扫描程序类型传递给Bison,方法是声明%parse-param {yyscan_t scanner},然后通过声明{{1}使Bison将此传递给Flex }。但是Bison没有宣布%lex-param {yyscan_t scanner},所以我必须在我的Bison文件中包含Flex生成的扫描程序头文件(我将其命名为scanner.flex.h)。但是由于我的Flex文件包含了我的Bison标题,而我的Bison标题现在包含了Flex标题,我得到了循环包含,这会以不可预测的方式混淆内容!

让我们说我想在我的Bison文件中添加yyscan_t位置跟踪,在我的Flex文件中添加%locations。现在我需要更改我的yyerror和yylex的声明(似乎我必须定义yylex AGAIN,即使它是在Flex生成的头中定义的但我不能包括那个,记得吗?)我的Bison文件中的函数包含YYLTYPE指针。但现在呢?似乎在插入序言后放置了默认的YYLTYPE声明,因此我不能在我的yyerror和yylex的声明中使用这个默认的YYLTYPE。

我意识到这些问题有很多变通方法......但是你应该如何正确地做到这一点?它完全逃脱了我,这让我的头脑一团糟......

2 个答案:

答案 0 :(得分:4)

在bison文件的顶部,您需要转发声明这些值。在包含flex和bison文件之前,可以在公共头或代码文件中执行此操作。 yyscan_t只是void *的typedef所以我将参数声明为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 :(得分:1)

在寻找其他东西时遇到了这个。

答案是Bison在%union规范之后发出YYLTYPE的内部声明。因此,在%union之后将函数原型和其他东西放在序言部分中避免了自己声明YYLTYPE的问题;这很好,Bison允许不止一个序言部分:

%{

/* Prologue 1 */

%}

%this

%that

%union {}

%{

/* Prologue 2, YYLTYPE declared */

%}

%%

blah:  talk | blah talk

%%