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?



Reply via email to