Simple two-file test case:
/* parser.y ----------------- */
%{
#include <stdio.h>
typedef struct {
int dummy;
} private_context;
%}
%pure-parser
%parse-param{private_context *ctx}
%union {
char *str;
}
%token<str> TOK
%type<str> start
%%
start : TOK { $$ = $1; }
%%
int public_parse_wrapper(void)
{
private_context pc;
return yyparse(&pc);
}
/* lexer.c ----------------------- */
#include "y.tab.h"
int yylex(YYSTYPE *yylval)
{
yylval->str = "foo";
return TOK;
}
If we translate parser.y with "bison --yacc -d" to generate a y.tab.h
and y.tab.c,
the y.tab.h contains:
int yyparse (private_context *ctx);
The private_context type is not known outside of the parser and isn't
declared in
y.tab.h. So when we compile lexer.c, we get:
In file included from lexer.c:1:0:
y.tab.h:71:14: error: unknown type name ‘private_context’
int yyparse (private_context *ctx);
^
See, the parser doesn't have to export yyparse at all, because it
instead exports
a public wrapper. So no project-wide declaration of yyparse is necessary
at all,
and is not possible because it depends on private types. Ideally,
yyparse would be a static function in this use case.
This is a real problem in my project, in a somewhat different way.
I do have the parser context structures public, and in a header.
However, that header depends on y.tab.h: y.tab.h must be included first.
The reason is that the context structure declares members of type
YYSTYPE.
So, the declaration of yyparse creates a circular dependency. y.tab.h
needs
the "parser.h" header in order to get the argument structure types, but
those
types need "y.tab.h" to get YYSTYPE.
Is there some way I can get rid of this declaration? Or do I have to
split my
header into two just for the sake of Bison 3.x?