循环依赖解析与野牛生成的文件

时间:2013-07-08 03:54:57

标签: c gcc bison

我在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的编译错误。

1 个答案:

答案 0 :(得分:1)

是的,在最近的野牛历史记录中,对骨架文件进行了不兼容的更改,导致yyparse更早地声明,事实上在%{ %}部分的包含点之前。因此,在yyparse被包含之前声明了purecalc.h,这意味着在声明pcdata时尚未声明yyparse

一个简单的解决方案是提前移动#include purecalc.h,但这会产生不同的问题。 pcdata的实际定义需要在yyscan_t中声明的purecalc.lex.hpurecalc.lex.h要求YYSTYPE为#defined,这发生在purecalc.tab.hpurecalc.tab.h声明yyparse,需要声明pcdata

循环性只能通过向前声明来解决:

struct pcdata;

但这必须在purecalc.tab.h为#included之前发生。

因此,一种可能性是将这三行提前purecalc.h

struct pcdata;
#include purecalc.tab.h
#include purecalc.lex.h

然后分别从purecalc.tab.hpurecalc.lex.h中删除多余的purecalc.lpurecalc.y包含。 (另外,成为purecalc.h)的包含守卫是一个非常好的主意。

另一种可能性是将struct pcdata;直接放入purecalc.y。但是使用%{ %}块不够好;它必须在声明yyparse之前插入。为此,您需要一个%code requires { }块:

%code requires {
    struct pcdata;
}

我试过了,它用bison 2.7编译。如果您要使用第一个解决方案,则需要为%code requires { }使用#include purecalc.h块,因此看起来不同。