Previous: , Up: Bison Grammar Files   [Contents][Index]

3.8 Multiple Parsers in the Same Program

Most programs that use Bison parse only one language and therefore contain only one Bison parser. But what if you want to parse more than one language with the same program? Then you need to avoid name conflicts between different definitions of functions and variables such as yyparse, yylval. To use different parsers from the same compilation unit, you also need to avoid conflicts on types and macros (e.g., YYSTYPE) exported in the generated header.

The easy way to do this is to define the %define variable api.prefix. With different api.prefixs it is guaranteed that headers do not conflict when included together, and that compiled objects can be linked together too. Specifying ‘%define api.prefix {prefix}’ (or passing the option -Dapi.prefix={prefix}, see Invoking Bison) renames the interface functions and variables of the Bison parser to start with prefix instead of ‘yy’, and all the macros to start by PREFIX (i.e., prefix upper-cased) instead of ‘YY’.

The renamed symbols include yyparse, yylex, yyerror, yynerrs, yylval, yylloc, yychar and yydebug. If you use a push parser, yypush_parse, yypull_parse, yypstate, yypstate_new and yypstate_delete will also be renamed. The renamed macros include YYSTYPE, YYLTYPE, and YYDEBUG, which is treated specifically — more about this below.

For example, if you use ‘%define api.prefix {c}’, the names become cparse, clex, …, CSTYPE, CLTYPE, and so on.

Users of Flex must update the signature of the generated yylex function. Since the Flex scanner usually includes the generated header of the parser (to get the definitions of the tokens, etc.), the most convenient way is to insert the declaration of yylex in the provides section:

%define api.prefix {c}
// Emitted in the header file, after the definition of YYSTYPE.
%code provides
  // Tell Flex the expected prototype of yylex.
  #define YY_DECL                             \
    int clex (CSTYPE *yylval, CLTYPE *yylloc)

  // Declare the scanner.

The %define variable api.prefix works in two different ways. In the implementation file, it works by adding macro definitions to the beginning of the parser implementation file, defining yyparse as prefixparse, and so on:

#define yyparse cparse
#define yylval  clval
YYSTYPE yylval;
int yyparse (void);

This effectively substitutes one name for the other in the entire parser implementation file, thus the “original” names (yylex, YYSTYPE, …) are also usable in the parser implementation file.

However, in the parser header file, the symbols are defined renamed, for instance:

extern CSTYPE clval;
int cparse (void);

The macro YYDEBUG is commonly used to enable the tracing support in parsers. To comply with this tradition, when api.prefix is used, YYDEBUG (not renamed) is used as a default value:

/* Debug traces. */
#ifndef CDEBUG
# if defined YYDEBUG
#   define CDEBUG 1
#  else
#   define CDEBUG 0
#  endif
# else
#  define CDEBUG 0
# endif
extern int cdebug;

Prior to Bison 2.6, a feature similar to api.prefix was provided by the obsolete directive %name-prefix (see Bison Symbols) and the option --name-prefix (see Output Files).

Previous: Bison Declarations, Up: Bison Grammar Files   [Contents][Index]