Chapter 5: The Generated Parser Class' Members

Bisonc++ generates a C++ parser class, rather than a parsing function, like Bison. Bisonc++'s class is a plain C++ class and not a fairly complex macro-based class as generated by Bison++.

The C++ class generated by bisonc++ does not require virtual members (when polymorphic semantic values are used (cf. section 4.6.1 a polymorphic base class is used, but that class has no further implications for the parser class generated by bisonc++); in this case polymorphism is merely used internally, inaccessible to bisonc++'s user, to define a common interface for the various polymorphic data types).

The generated parser class's essential member (the member parse) is generated from the grammar specification and so the software engineer will therefore hardly ever feel the need to modify that function. All but a few of the remaining predefined members have very clear definitions and meanings as well, making it unlikely that they should ever require overriding.

It is likely that members like lex and/or error need dedicated definitions with different parsers generated by bisonc++; but then again: while defining the grammar the definition of the associated support members is a natural extension of defining the grammar, and can be realized in parallel with defining the grammar, in practice not requiring any virtual members. By not requiring virtual members the parser's class organization is simplified, and calling non-virtual members will be just a trifle faster than calling these member functions as virtual functions.

In this chapter all available members and features of the generated parser class are discussed. Having read this chapter you should be able to use the generated parser class in your program (using its public members) and to use its facilities in the actions defined for the various production rules and/or use these facilities in additional class members that you might have defined yourself.

In the remainder of this chapter the class's public members are first discussed, to be followed by the class's private members. While constructing the grammar all private members are available in the action parts of the grammar's production rules. Furthermore, any member (and so not just from the action blocks) may generate errors (thus initiating error recovery procedures) and may flag the (un)successful parsing of the information given to the parser (terminating the parsing function parse).

Symbols defined in the generated parser and parser base class usually end in an underscore character. Such symbols should not be masked or redefined. Some members have names not ending in an underscore character. Those names have either historically been used (like parse and ERROR) or they can be redefined by the user (like int lex() and void print()). Their specific requirements are documented below.

5.1: Public Symbols

Parser classes generated by bisonc++ offer the following public constructor, enums, members and types (in the following overview parser class-name prefixes (e.g., Parser::) prefixes were omitted):

When the %polymorphic directive is used:

5.2: Protected Enumerations and Types

The following enumerations and types can be used by members of parser classes generated by bisonc++. They are actually protected members inherited from the parser's base class.

When the %polymorphic directive is used:

5.3: Non-public Member Functions

The following members can be used by members of parser classes generated by bisonc++. When prefixed by Base:: they are actually protected members inherited from the parser's base class. These members are shown below. Following the description of those members several more are listed: those members are used during the parsing process, andshould not be modified or masked by user-defined code.

The following members are required during the parsing process. They should not be modified or masked by user-defined code:

5.3.1: `lex()': Interfacing the Lexical Analyzer

The int lex() private member function is called by the parse() member to obtain the next lexical token. By default it is not implemented, but the %scanner directive (see section 4.5.21) may be used to pre-implement a standard interface to a lexical analyzer.

The lex() member function interfaces to the lexical scanner, and it is expected to return the next token produced by the lexical scanner. This token may either be a plain character or it may be one of the symbolic tokens defined in the Parser::Tokens enumeration. Any zero or negative token value is interpreted as `end of input', causing parse() to return.

The lex() member function may be implemented in various ways:

5.4: Protected Data Members

The following private members can be used by members of parser classes generated by bisonc++. All data members are actually protected members inherited from the parser's base class.

5.5: Types and Variables in the Anonymous Namespace

In the file defining the parse function the following types and variables are defined in the anonymous namespace. These are mentioned here for the sake of completeness, and are not normally accessible to other parts of the parser.

5.6: Summary of Special Constructions for Actions

Here is an overview of special syntactic constructions that may be used inside action blocks: