0

我在野牛的 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
%}

问题是我有一个编译错误(带有野牛生成文件的循环依赖解析);它们是循环依赖的,因为purecalc.lex.h依赖于 purecalc.h 文件中的 pcdata,而 purecalc.h 依赖于 yyscan_t 的 purecalc.lex.h。

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 时出现编译错误。

4

1 回答 1

1

是的,在最近的野牛历史中的某个时候,对骨架文件进行了不兼容的更改,导致yyparse声明得更早,实际上是在%{ %}节的包含点之前。so yyparseis being declared before purecalc.his included,这意味着在pcdata声明的时候还没有yyparse声明。

一个简单的解决方案是移动#include purecalc.h较早的位置,但这会产生不同的问题。pcdatarequires的实际定义yyscan_tpurecalc.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.hpurecalc.lex.h包括。(另外,将包含守卫加入 是一个非常好的主意)。purecalc.lpurecalc.ypurecalc.h

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

%code requires {
    struct pcdata;
}

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

于 2013-07-08T06:10:00.043 回答