我正在使用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。
我意识到这些问题有很多变通方法......但是你应该如何正确地做到这一点?它完全逃脱了我,这让我的头脑一团糟......
答案 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
%%