BISON++(1)

✨ BISON++ ✨

okay bestie, gather round πŸ’– this is BISON++(1) from the COMMANDS section of the manual, and it's a whole vibe. it's a parser generator, it's giving main character energy, and yes we're gonna read the entire thing together. no skimming. periodt.


πŸŽ€ NAME πŸŽ€

bison++ β€” generate a parser in c or c++.


🌸 SYNOPSIS 🌸

bison++ [-dltvyVu] [-b file-prefix] [-p name-prefix] [-o outfile] [-h
headerfile] [-S skeleton] [-H header-skeleton] [--debug] [--defines]
[--fixed-output-files] [--no-lines] [--verbose] [--version] [--yacc]
[--usage] [--help] [--file-prefix=prefix] [--name-prefix=prefix]
[--skeleton=skeletonfile] [--headerskeleton=headerskeletonfile]
[--output=outfile] [--header-name=header] grammar-file

πŸ¦‹ DESCRIPTION πŸ¦‹

so like. it generates a parser. that's the whole job πŸ’…

it's based on bison version 1.19, and for the details of the main functionality you should go look at bison(1). only the changes get reported here β€” that's the whole point of this page.

okay so here's the tea: if you're compiling with a C++ compiler, you now generate a C++ class. the generated header is far more rich than before, and it's made from a skeleton-header. the code skeleton is also richer, and the generated code matters less compared to the skeletons themselves. which means β€” iconic behaviour β€” you can modify a whole bunch of stuff just by changing the two skeletons. obsessed.

and in plain C? bison++ is compatible with standard bison. no notes. 🫢


πŸ’… OPTIONS πŸ’…

  • --name-prefix=prefix, -p prefix β€” sets the prefix of the names of yylex and yyerror. it's kept for compatibility, but honestly you should prefer %define LEX newname, and similar. iykyk.
  • --skeleton=skeleton, -S skeleton β€” sets the filename of the code skeleton. default is bison.cc.
  • --headerskeleton=header-skeleton, -H header-skeleton β€” sets the filename of the header skeleton. default is bison.h.
  • --header-name=header, -h header β€” sets the filename of the header skeleton. default is y.tab.h, or prefix.h if option -b is used, or c_basename.h if -o is used. the .c, .cc, .C, .cpp, .cxx options for output files get replaced by .h for the header name.

🌈 DECLARATIONS 🌈

these are the new declarations you can put in the declaration section:

  • %name parser_name β€” declares the name of this parser. used for the C++ class name, and to render many names unique. default is parse. must be given before %union and %define, or never.
  • %define define_name content... β€” declares a macro symbol in the header and in the code. the name of the symbol is YY_'parser_name'_'define_name'. the content goes after it, just like with #define. newlines can be escaped the same way as with #define. lots of symbols are proposed for customisation. ✨
  • %union β€” as with bison, generates a union for the semantic type. the difference is that the union is named yy_'parser_name'_stype.
  • %pure_parser β€” as with bison in C. in C++ it generates a parser where yylval, and yylloc (if needed) are passed as parameters to yylex, and where some instance variables are local to yyparse (like yydebug...). not very useful, honestly, since you can just create multiple instances for reentering another parser. πŸ’€
  • %header{ β€” like %{, but it includes this text both in the header and in the code. end it with %}. when you put it in the declaration section, the text is added before the definitions. it can be put in the last section so that the text is added after all definitions in the header, and in the last section at the current position in the code.
⚠️ heads up bestie: the order of these declarations matters, because they get translated into preprocessor symbols, typedefs or code depending on their type. for example, use %name before any %define, since the name is needed to compose the name of the define symbols. and the order of %header and %union matters too, since the type may be undefined.

πŸ’œ DECLARATION DEFINE SYMBOLS πŸ’œ

these are the symbols you can define with %define in the declaration section, or that are already defined. remember: they get replaced by a preprocessor #define YY_'parser_name'_'name'.

  • BISON β€” defined to 1 in the code. used for conditional code. don't redefine it.
  • h_included β€” defined in the code, and in the header. used for include anti-reload. don't redefine it.
  • COMPATIBILITY β€” indicates whether obsoleted defines are to be used and produced. if defined to 0, it means no compatibility is needed; otherwise, if defined to non-0, it generates it. if it's undefined, the default is to be compatible if classes are not used.
  • USE_GOTO β€” indicates (if defined as 1) that goto is to be used (for backward compatibility) in the parser function. by default goto is replaced with a switch construction, to avoid problems with some compilers that don't support goto and destructor in the same function block. if COMPATIBILITY is 1, and USE_GOTO is not defined, then USE_GOTO is defined to 1, to be compatible with older bison.
  • USE_CONST_TOKEN β€” indicates (if defined as 1) that static const int is to be used in C++, for token IDs. by default an enum is used to define the token IDs instead of const.
  • ENUM_TOKEN β€” when enums are used instead of static const int for token IDs, this symbol defines the name of the enum type. defined to yy_'parser_name'_enum_token by default.
  • PURE β€” indicates that %pure_parser is asked... don't redefine it.
  • LSP_NEEDED β€” if defined, indicates that the @ construct is used, so the LLOC stack is needed. can be defined to force use of the location stack.
  • DEBUG β€” if defined to non-0, activates debugging code. see YYDEBUG in bison.
  • ERROR_VERBOSE β€” if defined, activates dumping the parser stack when an error happens.
  • STYPE β€” the type of the semantic value of a token. defined by %union. default is int. see YYSTYPE in bison. don't redefine it, if you use a %union.
  • LTYPE β€” the token location type. if needed, default is yyltype. see YYLTYPE in bison. the default yyltype is a typedef and struct defined as in old bison.
  • LLOC β€” the token location variable name. if needed, default is yylloc. see yylloc in bison.
  • LVAL β€” the token semantic value variable name. default is yylval. see yylval in bison.
  • CHAR β€” the lookahead token value variable name. default is yychar. see yychar in bison.
  • LEX β€” the scanner function name. default is yylex. see yylex in bison.
  • PARSE β€” the parser function name. default is yyparse. see yyparse in bison.
  • PARSE_PARAM β€” the parser function parameters declaration. default is void in C++ or ANSIC, and nothing if old C. in ANSIC and C++ it contains the prototype. in old-C it contains just the list of parameter names. doesn't allow default value.
  • PARSE_PARAM_DEF β€” the parser function parameters definition, for old style C. default is nothing. for example, to use an int parameter called x, PARSE_PARAM is x, and PARSE_PARAM_DEF is int x;. in ANSIC or C++ it is unuseful and ignored.
  • ERROR β€” the error function name. default is yyerror. see yyerror in bison.
  • NERRS β€” the error count name. default is yynerrs. see yynerrs in bison.
  • DEBUG_FLAG β€” the runtime debug flag. default is yydebug. see yydebug in bison.

and these ones? only used if a class is generated. πŸ‘‘

  • CLASS β€” the class name. default is the parser name.
  • INHERIT β€” the inheritance list. don't forget the : before it, if the list is not empty.
  • MEMBERS β€” list of members to add to the class definition, before ending it.
  • LEX_BODY β€” the scanner member function body. may be defined to =0 for a pure function, or to an inline body.
  • ERROR_BODY β€” the error member function body. may be defined to =0 for a pure function, or to an inline body.
  • CONSTRUCTOR_PARAM β€” list of parameters of the constructor. doesn't allow default value.
  • CONSTRUCTOR_INIT β€” list of initialisation before the constructor call. if it's not empty, don't forget the : before the list of initialisation.
  • CONSTRUCTOR_CODE β€” code added after internal initialisation in the constructor.

πŸ™ˆ OBSOLETED PREPROCESSOR SYMBOLS πŸ™ˆ

if you use the new features, the following symbols should not be used, even though they are still proposed. the symbol COMPATIBILITY controls their disponibility. incoherence may arise if they are defined simultaneously with the new symbol. 😭

  • YYLTYPE β€” prefer %define LTYPE.
  • YYSTYPE β€” prefer %define STYPE.
  • YYDEBUG β€” prefer %define DEBUG.
  • YYERROR_VERBOSE β€” prefer %define ERROR_VERBOSE.
  • YYLSP_NEEDED β€” prefer %define LSP_NEEDED.
  • yystype β€” now a preprocessor symbol instead of a typedef. prefer yy_'parser_name'_stype.

🧚 CONSERVED PREPROCESSOR SYMBOLS 🧚

these symbols are kept, and cannot be defined elsewhere, since they control private parameters of the generated parser, or are actually unused. you can #define them to the value you need, or indirectly to the name of a %define generated symbol if you want to be clean. ✨

  • YYINITDEPTH β€” initial stack depth.
  • YYMAXDEPTH β€” stack overflow limit depth.
  • yyoverflow β€” instead of expanding with alloca, realloc manually or raise an error.

⭐ OTHER ADDED PREPROCESSOR SYMBOLS ⭐

  • YY_USE_CLASS β€” indicates that a class will be produced. default if C++.

πŸ’– C++ CLASS GENERATED πŸ’–

okay so to keep the notation from being a whole mess, we write %SYMBOLNAME for the preprocessor symbol that gets generated by a %define of that name. fr fr, go look at how %define works to see its actual real name, that's where the truth lives.

And heads up bestie: sometimes two symbols differ by literally just one underscore, like yywrap and yy_wrap, and they are NOT the same thing at all. Not even close. In that case yy_wrap() is a virtual member function, and yywrap() is a macro. iykyk. πŸ’…


🌈 General Class declaration

class %CLASS %INHERIT

{

public:

#if %USE_CONST_TOKEN != 0

static const TOKEN_NEXT;

static const AND_SO_ON;

// ...

#else

enum %ENUM_TOKEN { %NULL_TOKEN

       ,TOKEN_FIRST=256

       ,TOKEN_NEXT=257

       ,AND_SO_ON=258

} ;

// ...

#endif

public:

int %PARSE (%PARSE_PARAM);

virtual void %ERROR(char *msg) %ERROR_BODY;

#ifdef %PURE

       // if %PURE , we must pass the value and (eventually) the
       location explicitely

       #ifdef %LSP_NEEDED

       // if and only if %LSP_NEEDED , we must pass the location
       explicitely

       virtual int %LEX (%STYPE *%LVAL,%LTYPE *%LLOC) %LEX_BODY;

       #else

       virtual int %LEX (%STYPE *%LVAL) %LEX_BODY;

       #endif

#else

       // if not %PURE , we must declare member to store the value and
       (eventually) the location explicitely

       // if not %PURE ,%NERRS and %CHAR are not local variable to
       %PARSE, so must be member

       virtual int %LEX() %LEX_BODY;

       %STYPE %LVAL;

       #ifdef %LSP_NEEDED

       %LTYPE %LLOC;

       #endif

       int %NERRS;

       int %CHAR;

#endif

#if %DEBUG != 0

int %DEBUG_FLAG; /* nonzero means print parse trace */

#endif

public:

%CLASS(%CONSTRUCTOR_PARAM);

public:

%MEMBERS

};

// here are defined the token constants

// for example:

#if %USE_CONST_TOKEN != 0

       const %CLASS::TOKEN_FIRST=1;

#endif

// here is the construcor

%CLASS::%CLASS(%CONSTRUCTOR_PARAM) %CONSTRUCTOR_INIT

{

#if %DEBUG != 0

%DEBUG_FLAG=0;

#endif

%CONSTRUCTOR_CODE;

};

πŸ¦‹ Default Class declaration

this is the whole vibe when you %define absolutely nothing β€” the header just makes this for you:

// Here is the default declaration made in the header when you %define
nothing

// typical yyltype

typedef struct yyltype

{

int timestamp;

int first_line;

int first_column;

int last_line;

int last_column;

char *text;

} yyltype;

// class definition

class parser

{

public:

enum yy_parser_enum_token { YY_parser_NULL_TOKEN

       ,TOKEN_FIRST=256

       ,TOKEN_NEXT=257

       ,AND_SO_ON=258

} ;

// ...

public:

int yyparse (yyparse_PARAM);

virtual void yyerror(char *msg) ;

#ifdef YY_parser_PURE

       #ifdef YY_parser_LSP_NEEDED

       virtual int yylex (int *yylval,yyltype *yylloc) ;

       #else

       virtual int yylex (int *yylval) ;

       #endif

#else

       virtual int yylex() %LEX_BODY;

       int yylval;

       #ifdef YY_parser_LSP_NEEDED

       yyltype yylloc;

       #endif

       int yynerrs;

       int yychar;

#endif

#if YY_parser_DEBUG != 0

int yydebug;

#endif

public:

parser();

public:

};

// here is the constructor code

parser::parser()

{

#if YY_parser_DEBUG != 0

yydebug=0;

#endif

};

✨ USAGE ✨

Should replace bison, because it generate a far more customisable parser, still beeing compatible. like, it does everything bison does but cuter and with more knobs. πŸ’…

You should always use the header facility. no cap.

Use it with flex++ (same author). they're a matching set, a little duo, iconic. 🫢


πŸŽ€ EXEMPLES πŸŽ€

This man page has been produced through a parser made in C++ with this version of bison and our version of flex++ (same author). yes bestie it's self-referential, it's giving meta, we love that for us. ✨


🌸 FILES 🌸

  • bison.cc β€” main skeleton. the whole main character of skeletons.
  • bison.h β€” header skeleton.
  • bison.hairy β€” old main skeleton for semantic parser. Not adapted to this version. Kept for future works. (it's in the archive, bestie, do not touch it for now πŸ₯²)

πŸ’œ ENVIRONNEMENT πŸ’œ

nothing here. empty. silence. the calmest section on the whole page. πŸ§˜β€β™€οΈ

🌈 DIAGNOSTICS 🌈

also nothing! we simply do not have diagnostics content. moving on, gorgeous. πŸ’…

⭐ SEE ALSO ⭐


πŸ¦‹ DOCUMENTATION πŸ¦‹

yeah so this one is empty too. no thoughts, head empty, just vibes. πŸ™ˆ

πŸ’€ BUGS πŸ’€

Tell us more ! fr fr, we want to know.

The %semantic_parser is no more supported. If you want to use it, adapt the skeletons, and maybe bison++ generator itself. The reason is that it seems unused, unuseful, not documented, and too complex for us to support. tell us if you use, need, or understand it. 😭

Header is not included in the parser code. Change made in the generated header are not used in the parser code, even if you include it volontarily, since it is guarded against re-include. So don't modify it. periodt.

For the same reasons, if you modify the header skeleton, or the code skeleton, report the changes in the other skeleton if applicable. If not done, incoherent declarations may lead to unpredictable result. πŸ‘‘ (and not the fun kind of unpredictable, the scary kind)

Use of defines for YYLTYPE, YYSTYPE, YYDEBUG is supported for backward compatibility in C, but should not be used with new features, as %defines or C++ classes. You can define them, and use them as with old bison in C only.

Parameters are richer than before, and nothing is removed. POSIX compliance can be enforced by not using extensions. If you want to forbide them, there is a good job ! πŸ˜…


πŸ”₯ FUTUR WORKS πŸ”₯

tell us !

  • Support semantic parser. Is it really used ?
  • POSIX compliance. is'nt it good now ?
  • Use lex and yacc (flex/bison) to generate the scanner/parser. It would be comfortable for futur works, though very complicated. Who feel it good ?
  • iostream : this is a great demand. this work will be done as soon as possible. The virtual members permit such work still easily.

πŸŽ€ INSTALLATION πŸŽ€

With this install the executable is named bison++. rename it bison if you want, because it could replace bison. your call bestie, both are valid. πŸ’…


🌟 TESTS 🌟

empty! nothing to report! we're just chilling! πŸ“

πŸ‘‘ AUTHORS πŸ‘‘

Alain Coetmeur (coetmeur@icdc.fr), R&D department (RDT), Informatique-CDC, France. iconic. 🫢


🌈 RESTRICTIONS 🌈

The words 'author', and 'us' mean the author and colleages, not GNU. We don't have contacted GNU about this, nowaday. If you're in GNU, we are ready to propose it to you, and you may tell us what you think about. no hard feelings, we're just saying. πŸ’–

Based on GNU version 1.21 of bison. Modified by the author.


and that's the whole page, bestie β€” courtesy of GNU and RDT, dated 3/3/93, filed under BISON++(1). go forth and generate parsers, you absolute legend πŸ’…βœ¨