我在bison的yacc文件中有这个代码块。这是Flex & Bison本书的flex / bison代码中的代码。 yacc代码可以从https://github.com/GrooveStomp/Flex-Bison/blob/master/samples/purecalc.y
下载%{
# include "purecalc.lex.h"
# include "purecalc.h"
#define YYLEX_PARAM pp->scaninfo
%}
问题是我有编译错误(Circular dependency resolution with bison generated file);它们是循环相关的,因为purecalc.lex.h
依赖于purecalc.h文件中的pcdata,而purecalc.h依赖于purecalc.lex.h而不是yyscan_t。
yyscan_t在purecalc.lex.h中是不确定的:
typedef void* yyscan_t;
pcdata定义如下:
/* per-parse data */
struct pcdata {
yyscan_t scaninfo; /* scanner context */
struct symbol *symtab; /* symbols for this parse */
struct ast *ast; /* an AST for */
};
如何打破这段代码依赖?我试图将typedef void* yyscan_t;
复制到yacc源代码中,但是我遇到了复制typedef的编译错误。
答案 0 :(得分:1)
是的,在最近的野牛历史记录中,对骨架文件进行了不兼容的更改,导致yyparse
更早地声明,事实上在%{ %}
部分的包含点之前。因此,在yyparse
被包含之前声明了purecalc.h
,这意味着在声明pcdata
时尚未声明yyparse
。
一个简单的解决方案是提前移动#include purecalc.h
,但这会产生不同的问题。 pcdata
的实际定义需要在yyscan_t
中声明的purecalc.lex.h
。 purecalc.lex.h
要求YYSTYPE
为#defined,这发生在purecalc.tab.h
。 purecalc.tab.h
声明yyparse
,需要声明pcdata
。
循环性只能通过向前声明来解决:
struct pcdata;
但这必须在purecalc.tab.h
为#included之前发生。
因此,一种可能性是将这三行提前purecalc.h
:
struct pcdata;
#include purecalc.tab.h
#include purecalc.lex.h
然后分别从purecalc.tab.h
和purecalc.lex.h
中删除多余的purecalc.l
和purecalc.y
包含。 (另外,成为purecalc.h
)的包含守卫是一个非常好的主意。
另一种可能性是将struct pcdata;
直接放入purecalc.y
。但是使用%{ %}
块不够好;它必须在声明yyparse
之前插入。为此,您需要一个%code requires { }
块:
%code requires {
struct pcdata;
}
我试过了,它用bison 2.7编译。如果您要使用第一个解决方案,则需要为%code requires { }
使用#include purecalc.h
块,因此看起来不同。