问题
I have this code block in bison's yacc file. This is the code from the flex/bison code for Flex & Bison book. The yacc code can be downloaded from https://github.com/GrooveStomp/Flex-Bison/blob/master/samples/purecalc.y
%{
# include "purecalc.lex.h"
# include "purecalc.h"
#define YYLEX_PARAM pp->scaninfo
%}
The issue is that I have a compilation error(Circular dependency resolution with bison generated file); they are circular dependent as purecalc.lex.h
depends on pcdata which is in purecalc.h file, whereas purecalc.h depends on purecalc.lex.h for yyscan_t.
yyscan_t is defiend in purecalc.lex.h:
typedef void* yyscan_t;
pcdata is defined as follows:
/* per-parse data */
struct pcdata {
yyscan_t scaninfo; /* scanner context */
struct symbol *symtab; /* symbols for this parse */
struct ast *ast; /* an AST for */
};
How can I break this code dependency? I tried to copy the typedef void* yyscan_t;
into the yacc source, but I got compilation error for duplicating typedef.
回答1:
Yes, some time in recent bison history, an incompatible change was made to the skeleton files, causing yyparse
to be declared much earlier, in fact before the inclusion point for %{ %}
sections. So yyparse
is being declared before purecalc.h
is included, which means that pcdata
is not declared yet when yyparse
is declared.
A simple solution would be to move the #include purecalc.h
earlier, but this creates a different problem. The actual definition of pcdata
requires yyscan_t
which is declared in purecalc.lex.h
. purecalc.lex.h
requires that YYSTYPE
be #defined, which happens in purecalc.tab.h
. And purecalc.tab.h
declares yyparse
, which requires the declaration of pcdata
.
The circularity can only be resolved by forward declaring:
struct pcdata;
But that has to happen before purecalc.tab.h
is #included.
So one possibility would be to put these three lines early purecalc.h
:
struct pcdata;
#include purecalc.tab.h
#include purecalc.lex.h
and then remove the redundant purecalc.tab.h
and purecalc.lex.h
includes from purecalc.l
and purecalc.y
, respectively. (Also, it would be a really good idea to be an include guard into purecalc.h
).
Another possibility is to put struct pcdata;
directly into purecalc.y
. But it's not good enough to use a %{ %}
block for that; it has to be inserted before yyparse
is declared. For that, you need a %code requires { }
block:
%code requires {
struct pcdata;
}
I tried that, and it compiled with bison 2.7. If you were to use the first solution, you'd need to use a %code requires { }
block for the #include purecalc.h
, so it wouldn't look that different.
来源:https://stackoverflow.com/questions/17518961/circular-dependency-resolution-with-bison-generated-file