.TH "bisonc++input" "7" "2005\-2024" "bisonc++\&.6\&.08\&.00" "bisonc++ grammar file organization" .PP .SH "NAME" bisonc++input \- Organization of bisonc++\(cq\&s grammar file(s) .PP .SH "DESCRIPTION" .PP \fBBisonc++\fP derives from \fBbison++\fP(1), originally derived from \fBbison\fP(1)\&. Like these programs \fBbisonc++\fP generates a parser for an LALR(1) grammar\&. \fBBisonc++\fP generates \fBC++\fP code: an expandable \fBC++\fP class\&. .PP Refer to \fBbisonc++\fP(1) for a general overview\&. This manual page covers the structure and organization of \fBbisonc++\fP\(cq\&s grammar file(s)\&. .PP \fBBisonc++\fP\(cq\&s grammar file has the following generic outline: .nf directives (see the next section) %% grammar rules .fi .PP Grammar rules have the following generic form: .nf nonterminal: production\-rules ; .fi .PP Production rules consist of zero or more sequences of terminal tokens, nonterminal tokens and/or action blocks\&. When multiple production rules are used they must be separated from each other by vertical bars\&. Action blocks are \fBC++\fP compound statements\&. .PP This manual page contains the following sections: .PP .IP o \fBDESCRIPTION\fP: this section; .IP o \fBDIRECTIVES\fP: \fBbisonc++\fP\(cq\&s grammar\-specification directives; .IP o \fBPOLYMORPHIC SEMANTIC VALUES\fP: how to use polymorphic semantic values in parsers generated by \fBbisonc++\fP; .IP o \fBDOLLAR NOTATIONS\fP: available $\-shorthand notations with single, union, and polymorphic semantic value types\&. .IP o \fBRESTRICTIONS ON TOKEN NAMES\fP: name restrictions for user\-defined symbols; .IP o \fBOBSOLETE SYMBOLS\fP: symbols available to \fBbison\fP(1), but not to \fBbisonc++\fP; .IP o \fBUSING SYMBOLIC TOKENS IN CLASSES OTHER THAN THE PARSER CLASS\fP; how to refer to tokens defined in the grammar; .IP o \fBEXAMPLE\fP: an example of using \fBbisonc++\fP; .IP o \fBSEE ALSO\fP: references to other programs and documentation; .IP o \fBAUTHOR\fP: at the end of this man\-page\&. .PP .SH "UNDERSCORES" .PP Starting with version 6\&.02\&.00 \fBbisonc++\fP reserved identifiers no longer end in two underscore characters, but in one\&. This modification was necessary because according to the \fBC++\fP standard identifiers having two or more consecutive underscore characters are reserved by the language\&. In practice this could require some minor modifications of existing source files using \fBbisonc++\fP\(cq\&s facilities, most likely limited to changing \fITokens__\fP into \fITokens_\fP and changing \fIMeta__\fP into \fIMeta_\fP\&. .PP The complete list of affected names is: .IP "Enums:" .RS DebugMode_, ErrorRecovery_, Return_, Tag_, Tokens_ .RE .IP "Enums values:" .RS PARSE_ABORT_, PARSE_ACCEPT_, UNEXPECTED_TOKEN_, sizeofTag_ .RE .IP "Type / namespace designators:" .RS Meta_, PI_, STYPE_ .RE .IP "Member functions:" .RS clearin_, errorRecovery_, errorVerbose_, executeAction_, lex_, lookup_, nextCycle_, nextToken_, popToken_, pop_, print_, pushToken_, push_, recovery_, redoToken_, reduce_, savedToken_, shift_, stackSize_, startRecovery_, state_, token_, top_, vs_, .RE .IP "Protected data members:" .RS d_acceptedTokens_, d_actionCases_, d_debug_, d_nErrors_, d_requiredTokens_, d_val_, idOfTag_, s_nErrors_ .RE .PP .SH "DIRECTIVES" .PP Quite a few directives can be specified in the initial section of the grammar specification file\&. If command\-line options for directives are available, then their specifications take precedence over the corresponding directives in the grammar file\&. Once class header or implementation header files exist directives affecting those files are ignored\&. .PP Directives accepting a `filename\(cq\& do not accept path names, i\&.e\&., they cannot contain directory separators (\fI/\fP); directives accepting a \(cq\&pathname\(cq\& may contain directory separators\&. A \(cq\&pathname\(cq\& using blank characters should be surrounded by double quotes\&. .PP Some directives may generate errors\&. This happens when their specifications conflict with the contents of files \fBbisonc++\fP cannot modify (e\&.g\&., a parser class header file exists, but doesn\(cq\&t define a namespace, but in a later run the a \fI%namespace\fP directive was provided)\&. .PP To resolve such errors the offending directive could be omitted, the existing file could be removed, or the existing file could be hand\-edited according to the directive\(cq\&s specification\&. .PP .IP o \fB%baseclass\-header\fP \fIfilename\fP .IP \fIFilename\fP defines the name of the file to contain the parser\(cq\&s base class\&. This class defines, e\&.g\&., the parser\(cq\&s symbolic tokens\&. Defaults to the name of the parser class plus the suffix \fIbase\&.h\fP\&. This directive is overruled by the \fB\-\-baseclass\-header\fP (\fB\-b\fP) command\-line option\&. .IP It is an error if this directive is used and an already existing parser class header file does not contain \fI#include \(dq\&filename\(dq\&\fP\&. .IP .IP o \fB%baseclass\-preinclude\fP \fIpathname\fP .IP \fIPathname\fP defines the path to the file preincluded by the parser\(cq\&s base\-class header\&. See the description of the \fI\-\-baseclass\-preinclude\fP option for details about this directive\&. By default, \fBbisonc++\fP surrounds \fIheader\fP by double quotes\&. However, when \fIheader\fP itself is surrounded by pointed brackets \fI#include
\fP is included\&. .IP .IP o \fB%class\-header\fP \fIfilename\fP .IP \fIFilename\fP defines the name of the file to contain the parser class\&. Defaults to the name of the parser class plus the suffix \fI\&.h\fP This directive is overruled by the \fB\-\-class\-header\fP (\fB\-c\fP) command\-line option\&. .IP It is an error if this directive is used and an already existing implementation header file does not contain \fI#include \(dq\&filename\(dq\&\fP\&. .IP .IP o \fB%class\-name\fP \fIparser\-class\-name\fP .IP Declares the name of the parser class\&. It defines the name of the \fBC++\fP class that is generated\&. If no \fI%class\-name\fP is specified the default class name \fIParser\fP is used\&. .IP It is an error if this directive is used and an already existing parser\-class header file does not define \fIclass `className\(cq\&\fP and/or if an already existing implementation header file does not define members of the class \fI`className\(cq\&\fP\&. .IP .IP o \fB%debug\fP .IP Add debugging code to the generated \fIparse\fP and its support functions, which can show (on the standard output stream) the steps performed by the parsing function while it parses input streams\&. When this directive is specified then the parsing steps are shown by default\&. The \fIsetDebug\fP members can be used to suppress outputting these parsing steps\&. \fI#ifdef DEBUG\fP macros are not used\&. Existing debugging code can be removed by rerunning \fBbisonc++\fP without specifying the \fIdebug\fP option or directive\&. .IP .IP o \fB%default\-actions\fP(d)(off|quiet|warn|std) .IP By default, \fBbisonc++\fP adds a \fI$$ = $1\fP action block to rules not having final action blocks, but not to empty production rules\&. This default behavior can also explicitly be configured using the \fIdefault\-actions std\fP option or directive\&. .IP \fBBisonc++\fP also supports alternate ways of handling rules not having final action blocks\&. When \fIoff\fP is specified, \fBbisonc++\fP does not add \fI$$ = $1\fP action blocks; when polymorphic semantic values are used, then specifying .IP \- \fIwarn\fP adds specialized action blocks, using the semantic types of the first elements of the production rules, while issuing a warning; .IP \- \fIquiet\fP adds these action blocks without issuing warnings\&. .IP When either \fIwarn\fP or \fIquiet\fP are specified the types of $$ and $1 must match\&. When \fBbisonc++\fP detects a type mismatches it issues errors\&. .IP .IP o \fB%error\-verbose\fP .IP This directive can be specified to dump the parser\(cq\&s state stack to the standard output stream when the parser encounters a syntactic error\&. The stack dump shows on separate lines a stack index followed by the state stored at the indicated stack element\&. The first stack element is the stack\(cq\&s top element\&. .IP .IP o \fB%expect\fP \fInumber\fP .IP This directive specifies the exact number of shift/reduce and reduce/reduce conflicts for which no warnings are to be generated\&. Details of the conflicts are reported in the verbose output file (e\&.g\&., \fIgrammar\&.output\fP)\&. If the number of actually encountered conflicts deviates from `\fInumber\fP\(cq\&, then this directive is ignored\&. .IP .IP o \fB%filenames\fP \fIfilename\fP .IP \fIFilename\fP is a generic filename that is used for all header files generated by \fBbisonc++\fP\&. Options defining specific filenames are also available (which then, in turn, overrule the name specified by this directive)\&. This directive is overruled by the \fB\-\-filenames\fP (\fB\-f\fP) command\-line option\&. .IP .IP o \fB%flex\fP .IP When provided, the scanner member returning the matched text is called as \fId_scanner\&.YYText()\fP, and the scanner member returning the next lexical token is called as \fId_scanner\&.yylex()\fP\&. This directive is only interpreted if the \fI%scanner\fP directive is also provided\&. .IP .IP o \fB%implementation\-header\fP \fIfilename\fP .IP \fIFilename\fP defines the name of the file to contain the implementation header\&. It defaults to the name of the generated parser class plus the suffix \fI\&.ih\fP\&. .IP The implementation header should contain all directives and declarations that are \fIonly\fP used by the parser\(cq\&s member functions\&. It is the only header file that is included by the source file containing \fIparse\fP\(cq\&s implementation\&. User defined implementation of other class members may use the same convention, thus concentrating all directives and declarations that are required for the compilation of other source files belonging to the parser class in one header file\&. .IP .IP o \fB%include\fP \fIpathname\fP .IP This directive is used to switch to \fIpathname\fP while processing a grammar specification\&. Unless \fIpathname\fP defines an absolute file\-path, \fIpathname\fP is searched relative to the location of \fBbisonc++\fP\(cq\&s main grammar specification file (i\&.e\&., the grammar file that was specified as \fBbisonc++\fP\(cq\&s command\-line option)\&. This directive can be used to split long grammar specification files in shorter, meaningful units\&. After processing \fIpathname\fP processing continues beyond the \fI%include pathname\fP directive\&. .IP .IP o \fB%left\fP \fIterminal \&.\&.\&.\fP .IP Defines the names of symbolic terminal tokens that must be treated as left\-associative\&. I\&.e\&., in case of a shift/reduce conflict, a reduction is preferred over a shift\&. Sequences of \fI%left, %nonassoc, %right\fP and \fI%token\fP directives may be used to define the precedence of operators\&. In expressions, the first used directive defines the tokens having the lowest precedence, the last used defines the tokens having the highest priority\&. See also \fI%token\fP below\&. .IP .IP o \fB%locationstruct\fP \fIstruct\-definition\fP .IP Defines the organization of the location\-struct data type \fILTYPE_\fP\&. This struct should be specified analogously to the way the parser\(cq\&s stacktype is defined using \fI%union\fP (see below)\&. The location struct is named \fILTYPE_\fP\&. By default (if neither \fIlocationstruct\fP nor \fILTYPE_\fP is specified) the standard location struct (see the next directive) is used: .IP .IP o \fB%lsp\-needed\fP .IP This directive results in \fBbisonc++\fP generating a parser using the standard location stack\&. This stack\(cq\&s default type is: .nf struct LTYPE_ { int timestamp; int first_line; int first_column; int last_line; int last_column; char *text; }; .fi \fBBisonc++\fP does \fInot\fP provide the elements of the \fILTYPE_\fP struct with values\&. Action blocks of production rules may refer to the location stack element associated with a production element using \fI@\fP variables, like \fI@1\&.timestamp, @3\&.text, @5\fP\&. The rule\(cq\&s location struct itself may be referred to as either \fId_loc_\fP or \fI@@\fP\&. .IP .IP o \fB%ltype typename\fP .IP Specifies a user\-defined token location type\&. If \fI%ltype\fP is used, \fItypename\fP should be the name of an alternate (predefined) type (e\&.g\&., \fIsize_t\fP)\&. It should not be used if a \fI%locationstruct\fP specification is defined (see below)\&. Within the parser class, this type is available as the type `\fILTYPE_\fP\(cq\&\&. All text on the line following \fI%ltype\fP is used for the \fItypename\fP specification\&. It should therefore not contain comment or any other characters that are not part of the actual type definition\&. .IP .IP o \fB%namespace\fP \fInamespace\fP .IP Define all of the code generated by \fBbisonc++\fP in the namespace \fInamespace\fP\&. By default no namespace is defined\&. If this directive is used the implementation header is provided with a commented out \fIusing namespace\fP declaration for the specified namespace\&. In addition, the parser and parser base class header files also use the specified namespace to define their include guard directives\&. .IP It is an error if this directive is used and an already existing parser\-class header file and/or implementation header file does not define \fInamespace identifier\fP\&. .IP .IP o \fB%negative\-dollar\-indices\fP .IP Do not generate warnings when zero\- or negative dollar\-indices are used in the grammar\(cq\&s action blocks\&. Zero or negative dollar\-indices are commonly used to implement inherited attributes, and should normally be avoided\&. When used, they can be specified like \fI$\-1\fP, or like \fI$\-1\fP, where \fItype\fP is empty; an \fISTYPE_\fP tag; or a field\-name\&. However, note that in combination with the \fI%polymorphic\fP directive (see below) only the \fI$\-i\fP format can be used\&. .IP .IP o \fB%no\-lines\fP .IP By default \fI#line\fP preprocessor directives are inserted just before action statements in the file containing the parser\(cq\&s \fIparse\fP function\&. These directives are suppressed by the \fI%no\-lines\fP directive\&. .IP .IP o \fB%nonassoc\fP \fIterminal \&.\&.\&.\fP .IP Defines the names of symbolic terminal tokens that should be treated as non\-associative\&. I\&.e\&., in case of a shift/reduce conflict, a reduction is preferred over a shift\&. Sequences of \fI%left, %nonassoc, %right\fP and \fI%token\fP directives may be used to define the precedence of operators\&. In expressions, the first used directive defines the tokens having the lowest precedence, the last used defines the tokens having the highest priority\&. See also \fI%token\fP below\&. .IP .IP o \fB%parsefun\-source\fP \fIfilename\fP .IP \fIFilename\fP defines the name of the file to contain the parser member function \fIparse\fP\&. Defaults to \fIparse\&.cc\fP\&. This directive is overruled by the \fB\-\-parse\-source\fP (\fB\-p\fP) command\-line option\&. .IP .IP o \fB%polymorphic\fP \fIpolymorphic\-specification(s)\fP .IP Bison\(cq\&s traditional way of handling multiple semantic values is to use a \fI%union\fP specification (see below)\&. Although \fI%union\fP is supported by \fBbisonc++\fP, a polymorphic semantic value class is preferred due to its improved type safety\&. .IP The \fI%polymorphic\fP directive defines a polymorphic semantic value class and can be used instead of a \fI%union\fP specification\&. Refer to section \fBPOLYMORPHIC SEMANTIC VALUES\fP below or to \fBbisonc++\fP\(cq\&s user manual for a detailed description of the specification, characteristics, and use of polymorphic semantic values\&. .IP .IP o \fB%prec\fP \fItoken\fP .IP Defines the precedence of a (non\-empty) production rule\&. By default, production rules have priorities that are equal to the priorities of their first terminal tokens, or they receive the maximum possible priority if they don\(cq\&t contain terminal tokens\&. To change a production rule\(cq\&s default priority the \fI%prec\fP directive is used, which assigns the directive\(cq\&s token\(cq\&s priority to the production rule\(cq\&s priority\&. A well known application of \fI%prec\fP is: .nf expression: \(cq\&\-\(cq\& expression %prec UMINUS { \&.\&.\&. } .fi Here, the default priority and precedence of the `\fI\-\fP\(cq\& token as the subtraction operator is overruled by the precedence and priority of the \fIUMINUS\fP token, which is commonly defined as .nf %right UMINUS .fi (see below) following, e\&.g\&., the \fI\(cq\&*\(cq\&\fP and \fI\(cq\&/\(cq\&\fP operators\&. .IP Refer to \fBbisonc++\fP\(cq\&s user manual for a more elaborate coverage of the \fI%prec\fP directive\&. .IP .IP o \fB%print\-tokens\fP .IP The \fIprint\fP directive provides an implementation of the Parser class\(cq\&s \fIprint_\fP function displaying the current token value and the text matched by the lexical scanner as received by the generated \fIparse\fP function\&. .IP .IP o \fB%prompt\fP .IP When adding debugging code (using the \fIdebug\fP option or directive) the debug information is displayed continuously while the parser processes its input\&. When using the \fIprompt\fP directive the generated parser displays a prompt (a question mark) at each step of the parsing process\&. Caveat: when using this option the parser\(cq\&s input cannot be provided at the parser\(cq\&s standard input stream\&. .IP .IP o \fB%required\-tokens\fP \fInumber\fP .IP Following a syntactic error, require at least \fInumber\fP successfully processed tokens before another syntactic error can be reported\&. By default \fInumber\fP is zero\&. .IP .IP o \fB%right\fP \fIterminal \&.\&.\&.\fP .IP Defines the names of symbolic terminal tokens that should be treated as right\-associative\&. I\&.e\&., in case of a shift/reduce conflict, a shift is preferred over a reduction\&. Sequences of \fI%left, %nonassoc, %right\fP and \fI%token\fP directives may be used to define the precedence of operators\&. In expressions, the first used directive defines the tokens having the lowest precedence, the last used defines the tokens having the highest priority\&. See also \fI%token\fP below\&. .IP .IP o \fB%scanner\fP \fIpathname\fP .IP Use \fIpathname\fP as the path name to the file pre\-included in the parser\(cq\&s class header\&. See the description of the \fI\-\-scanner\fP option for details about this directive\&. Similar to the convention adopted for this argument, \fIpathname\fP by default is surrounded by double quotes\&. However, when the argument is surrounded by pointed brackets \fI#include \fP is included\&. This directive results in the definition of a composed \fIScanner d_scanner\fP data member into the generated parser, and in the definition of a \fIint lex()\fP member, returning \fId_scanner\&.lex()\fP\&. .IP By specifying the \fI%flex\fP directive the function \fId_scanner\&.yylex()\fP is called\&. Any other function to call can be specified using the \fI\-\-scanner\-token\-function\fP option (or \fI%scanner\-token\-function\fP directive)\&. .IP It is an error if this directive is used and an already existing parser class header file does not include \fI`pathname\(cq\&\fP\&. .IP .IP o \fB%scanner\-class\-name\fP \fIscannerClassName\fP .IP Defines the name of the scanner class, declared by the \fIpathname\fP header file that is specified at the \fIscanner\fP option or directive\&. By default the class name \fIScanner\fP is used\&. .IP It is an error if this directive is used and either the \fIscanner\fP directive was not provided, or the parser class interface in an already existing parser class header file does not declare a scanner class \fId_scanner\fP object\&. .IP .IP o \fB%scanner\-matched\-text\-function\fP \fIfunction\-call\fP .IP The scanner function returning the text that was matched by the lexical scanner after its token function (see below) has returned\&. A complete function call expression should be provided (including a scanner object, if used)\&. Example: .nf %scanner\-matched\-text\-function myScanner\&.matchedText() .fi By specifying the \fI%flex\fP directive the function \fId_scanner\&.YYText()\fP is called\&. .IP If the function call contains white space \fIscanner\-token\-function\fP should be surrounded by double quotes\&. .IP .IP o \fB%scanner\-token\-function\fP \fIfunction\-call\fP .IP The scanner function returning the next token, called from the generated parser\(cq\&s \fIlex\fP function\&. A complete function call expression should be provided (including a scanner object, if used)\&. Example: .nf %scanner\-token\-function d_scanner\&.lex() .fi If the function call contains white space \fIscanner\-token\-function\fP should be surrounded by double quotes\&. .IP It is an error if this directive is used and the scanner token function is not called from the code in an already existing implementation header\&. .IP .IP o \fB%stack\-expansion\fP \fIsize\fP Defines the number of elements to be added to the generated parser\(cq\&s semantic value stack when it must be enlarged\&. By default 10 elements are added to the stack\&. This option/directive is interpreted only once, and only if \fIsize\fP at least equals the default stack expansion size of 10\&. .IP .IP o \fB%start\fP \fInonterminal\fP .IP The nonterminal \fInonterminal\fP should be used as the grammar\(cq\&s start\-symbol\&. If omitted, the first grammatical rule is used as the grammar\(cq\&s starting rule\&. All syntactically correct sentences must be derivable from this starting rule\&. .IP .IP o \fB%stype\fP \fItypename\fP .IP The type of the semantic value of nonterminal tokens\&. By default it is \fIint\fP\&. \fI%stype, %union,\fP and \fI%polymorphic\fP are mutually exclusive directives\&. .IP Within the parser class, the semantic value type is available as the type `\fISTYPE_\fP\(cq\&\&. All text on the line following \fI%stype\fP is used for the \fItypename\fP specification\&. It should therefore not contain comment or any other characters that are not part of the actual type definition\&. .IP .IP o \fB%tag\-mismatches\fP \fIon|off\fP .IP This directive is only interpreted when polymorphic semantic values are used\&. When \fIon\fP is specified (which is used by default) the \fIparse\fP member of the generated parser dynamically checks that the tag that is used when calling a semantic value\(cq\&s \fIget\fP member matches the actual tag of the semantic value\&. .IP If a mismatch is observed, then the parsing function aborts after displaying a fatal error message\&. If this happens, and if the option/directive \fIdebug\fP was specified when \fBbisonc++\fP created the parser\(cq\&s parsing function, then the program can be rerun, specifying \fIparser\&.setDebug(Parser::ACTIONCASES)\fP before calling the parsing function\&. As a result the case\-entry numbers of the \fIswitch\fP, defined in the parser\(cq\&s \fIexecuteAction\fP member, are inserted into the standard output stream\&. The action case number reported just before the program displays the fatal error message tells you in which of the grammar\(cq\&s action block the error was encountered\&. .IP .IP o \fB%target\-directory\fP \fIpathname\fP .IP \fIPathname\fP defines the directory where generated files should be written\&. By default this is the directory where \fBbisonc++\fP is called\&. This directive is overruled by the \fI\-\-target\-directory\fP command\-line option\&. .IP .IP o \fB%thread\-safe\fP .IP Only used with polymorphic semantic values, and then only required when the parser is used in multiple threads: it ensures that each thread\(cq\&s polymorphic code only accesses its own parser\(cq\&s error counting variable\&. .IP .IP o \fB%token\fP \fIterminal \&.\&.\&.\fP .IP Defines the names of symbolic terminal tokens\&. Sequences of \fI%left, %nonassoc, %right\fP and \fI%token\fP directives may be used to define the precedence of operators\&. In expressions, the first used directive defines the tokens having the lowest precedence, the last used defines the tokens having the highest priority\&. See also \fI%token\fP below\&. .IP \fBNOTE:\fP Symbolic tokens are defined as \fIenum\fP\-values in the parser\(cq\&s base class\&. The names of symbolic tokens may not be equal to the names of the members and types defined by \fBbisonc++\fP itself (see the next sections)\&. This requirement is \fInot\fP enforced by \fBbisonc++\fP, but compilation errors may result if this requirement is violated\&. .IP .IP o \fB%token\-class\fP \fIclassname\fP .IP \fIClassname\fP defines the name of the \fITokens\fP class that is defined when the \fI%token\-path\fP directive or option (see below) is specified\&. If \fItoken\-path\fP isn\(cq\&t specified then this directive is ignored\&. By default the class name \fITokens\fP is used\&. .IP .IP o \fB%token\-namespace\fP \fInamespace\fP .IP If \fItoken\-path\fP is specified (see below) then \fInamespace\fP defines the namespace of the \fITokens\fP class\&. By default no namespace is used\&. .IP .IP o \fB%token\-path\fP \fIpathname\fP .IP \fIPathname\fP defines the path name of the file to contain the \fIstruct Tokens\fP defining the enumeration \fITokens_\fP containing the symbolic tokens of the generated grammar\&. If this option is specified the \fIParserBase\fP class is derived from it, thus making the tokens available to the generated parser class\&. The name of the \fIstruct Tokens\fP can be altered using the \fItoken\-class\fP directive or option\&. By default (if \fItoken_path\fP is not specified) the tokens are defined as the \fIenum Tokens_\fP in the \fIParserBase\fP class\&. If \fIpathname\fP doesn\(cq\&t exist it is created by \fBbisonc++\fP\&. If the file \fIpathname\fP already exists it is rewritten at each new run of \fBbisonc++\fP\&. .IP .IP o \fB%type\fP \fI nonterminal \&.\&.\&.\fP .IP In combination with \fI%polymorphic\fP or \fI%union\fP: associate the semantic value of a nonterminal symbol with a polymorphic semantic value tag or union field defined by these directives\&. .IP .IP o \fB%union\fP \fIunion\-definition\fP .IP Acts identically to the identically named \fBbison\fP and \fBbison++\fP declaration\&. \fBBisonc++\fP generates a union, named \fISTYPE_\fP, as its semantic type\&. .IP .IP o \fB%weak\-tags\fP .IP This directive is ignored unless the \fI%polymorphic\fP directive was specified\&. It results in the declaration of \fIenum Tag_\fP rather than \fIenum class Tag_\fP\&. When in doubt, don\(cq\&t use this directive\&. .PP .SH "POLYMORPHIC SEMANTIC VALUES" .PP Like \fBbison\fP(1), \fBbisonc++\fP by default uses \fIint\fP semantic values, and also supports the \fI%stype\fP and \fI%union\fP directives for using single\-type or traditional \fBC\fP\-type unions as semantic values\&. These types of semantic values are covered in \fBbisonc++\fP\(cq\&s manual\&. .PP In addition, the \fI%polymorphic\fP directive can be specified to generate a parser using `polymorphic\(cq\& semantic values\&. In this case semantic values are specified as pairs, consisting of \fItags\fP (which are \fBC++\fP identifiers), and \fBC++\fP (pointer or value) type names\&. Tags and type names are separated by colons\&. Multiple tag and type name combinations are separated by semicolons, and an optional semicolon ends the final tag/type pair\&. .PP Here is an example, defining three semantic values: an \fIint\fP, a \fIstd::string\fP and a \fIstd::vector\fP: .nf %polymorphic INT: int; STRING: std::string; VECT: std::vector .fi The identifier to the left of the colon is called the \fItag\-identifier\fP (or simply \fItag\fP), and the type name to the right of the colon is called the \fItype\-name\fP\&. Starting with \fBbisonc++\fP version 4\&.12\&.00 the types no longer have to provide default constructors\&. .PP When polymorphic type\-names refer to types that have not yet been declared by the parser\(cq\&s base class header, then these types must be (directly or indirectly) declared in a header file whose location is specified using the \fI%baseclass\-preinclude\fP directive\&. .PP \fI%type\fP directives are used to associate (non\-)terminals with semantic value types\&. E\&.g\&., after: .nf %polymorphic INT: int; TEXT: std::string %type expr .fi the \fIexpr\fP nonterminal returns \fIint\fP semantic values\&. In a rule like: .nf expr: expr \(cq\&+\(cq\& expr { // Action block: C++ statements here\&. } .fi symbols \fI$$, $1,\fP and \fI$3\fP represent \fIint\fP values, and can be used that way in the \fBC++\fP action block\&. .PP \fBDefinitions and declarations\fP .PP The \fI%polymorphic\fP directive adds the following definitions and declarations to the generated base class header and parser source file (if the \fI%namespace\fP directive was used then all declared/defined elements are placed inside the namespace that is specified by the \fI%namespace\fP directive): .IP o All semantic value type identifiers are collected in a strongly typed `\fITag_\fP\(cq\& enumeration\&. E\&.g\&., .nf enum class Tag_ { INT, STRING, VECT }; .fi .IP o An anonymous \fIenum\fP defining the symbolic constant \fIsizeofTag_\fP equal to the number of tags in the \fITag_\fP enumeration\&. .IP .IP o The namespace \fIMeta_\fP contains almost all of the code implementing polymorphic values\&. .PP The namespace \fIMeta_\fP contains, among other classes the class \fISType\fP\&. The parser\(cq\&s semantic value type \fISTYPE_\fP is equal to \fIMeta_::SType\fP\&. .PP \fBSTYPE_ equals Meta_::SType\fP .PP \fIMeta_::SType\fP provides the standard user interface for using polymorphic semantic data types\&. It declares the following public interface: .PP .IP o Constructors: Default, copy and move constructors\&. No data can be retrieved from \fISType\fP objects that were constructed by \fISType\fP\(cq\&s default constructors, but they can accept values of defined polymorphic types, which may then be retrieved from those objects\&. .IP .IP o Operators: The standard overloaded assignment operators (copy and move assignment operators) are available\&. .IP In addition the members .nf SType &operator=(Type const &value) and SType &operator=(Type &&tmp) .fi are defined for each of the polymorphic semantic value types\&. Up to version 6\&.03\&.00 these members were defined as member templates, but sometimes awkward compilation errors were encountered as with member templates \fIType\fP must exactly match one of the defined polymorphic semantic types since \fIType\fP is used to determine the appropriate \fIMeta_::Tag_\fP value\&. As a consequence, if, e\&.g\&., a polymorphic type \fI%polymorphic INT: int\fP is defined then an assignment like \fI$$ = true\fP fails, since the inferred type is \fIbool\fP and no matching polymorphic type is available\&. Now that the assignment operators are defined as plain member functions this problem isn\(cq\&t encountered anymore because standard type conversions may then be applied by the compiler\&. Note that ambiguities may still be encountered\&. If, e\&.g\&., polymorphic types are defined for \fIint\fP and \fIchar\fP and an expression like \fI$$ = 30U\fP is used the compiler cannot tell whether \fI$$\fP refers to the \fIint\fP or to the \fIchar\fP semantic value\&. A standard (static) cast, or explicitly calling the \fIassign\fP member (see the next item) solves these kind of ambiguities\&. .IP When \fIoperator=(Type const &value)\fP is used, the left\-hand side \fISType\fP object receives a copy of \fIvalue\fP; when \fIoperator=(Type &&tmp)\fP is used, \fItmp\fP is move\-assigned to the left\-hand side \fISType\fP object; .IP .IP o \fIvoid assign(Args &&\&.\&.\&.args)\fP The \fItag\fP template argument must be a \fITag_\fP value\&. This member function constructs a semantic value of the type matching \fItag\fP from the arguments that are passed to this member (zero arguments are OK if the type associated with \fItag\fP supports default construction)\&. The constructed value (not a copy of this value) is then stored in the \fISTYPE_\fP object for which \fIassign\fP has been called\&. .IP As a \fIMeta_::Tag_\fP value must be specified when using \fIassign\fP the compiler can use the explicit tag to convert \fIassign\(cq\&s\fP arguments to an \fISType\fP object of the type matching the specified tag\&. .IP The member \fIassign\fP can be used to store a specific polymorphic semantic value in an \fISTYPE_\fP object\&. It differs from the set of \fIoperator=(Type)\fP members in that \fIassign\fP accepts multiple arguments to construct the requested \fISType\fP value from, whereas the \fIoperator=\fP members only accept single arguments of defined polymorphic types\&. .IP To initialize an \fISTYPE_\fP object with a default \fISTYPE_\fP value, direct assignment can be used (e\&.g\&., \fId_lval_ = STYPE_{}\fP)\&. To assign a semantic value to a production rule using \fIassign\fP the \fI_$$\fP notation must be used, as \fI$$\fP is interpreted as the polymorphic value type that is associated with the production rule: .nf _$$\&.assign(30U); .fi .IP .IP o \fIDataType &get()\fP, and \fIDataType const &get() const\fP These members return references to the object\(cq\&s semantic values\&. The \fItag\fP must be a \fITag_\fP value: its specification tells the compiler which semantic value type it must use\&. .IP When the option/directive \fItag\-mismatches on\fP was specified then \fIget\fP, when called from the generated \fIparse\fP function, performs a run\-time check to confirm that the specified tag corresponds to object\(cq\&s actual \fITag_\fP value\&. If a mismatch is observed, then the parsing function aborts with a fatal error message\&. When shorthand notations (like \fI$$\fP and \fI$1\fP) are used in production rules\(cq\& action blocks, then \fBbisonc++\fP can determine the correct \fItag\fP, preventing the run\-time check from failing\&. .IP But once a fatal error \fIis\fP encountered, it can be difficult to determine which action block generated the error\&. If this happens, then consider regenerating the parser specifying the \fI\-\-debug\fP option, calling .nf parser\&.setDebug(Parser::ACTIONCASES) .fi before calling the parser\(cq\&s \fIparse\fP function\&. .IP Following this the case\-entry numbers of the \fIswitch\fP which is defined in the parser\(cq\&s \fIexecuteAction\fP member are inserted into the standard output stream just before the matching statements are executed\&. The action case number that\(cq\&s reported just before the program reports the fatal error tells you in which of the grammar\(cq\&s action block the error was encountered\&. .IP .IP o \fITag_ tag() const\fP The tag matching the semantic value\(cq\&s polymorphic type is returned\&. The returned value is a valid \fITag_\fP value when the \fISType\fP object\(cq\&s \fIvalid\fP member returns \fItrue\fP; .IP By default, or after assigning a plain (default) \fISTYPE_\fP object to an \fISTYPE_\fP object (e\&.g\&., using a statement like \fI$$ = STYPE_{}\fP), \fIvalid\fP returns \fIfalse\fP, and the \fItag\fP member returns \fIMeta_::sizeofTag_\fP\&. .IP .IP o \fIbool valid() const\fP .IP The value \fItrue\fP is returned if the object contains a semantic value\&. Otherwise \fIfalse\fP is returned\&. Note that default \fISTYPE_\fP values can be assigned to \fISTYPE_\fP objects, but they do not represent valid semantic values\&. See also the previous description of the \fItag\fP member\&. .PP .SH "DOLLAR NOTATIONS" .PP Inside action blocks dollar\-notations can be used to retrieve and assign values from/to the elements of production rules\&. Type directives are used to associates dollar\-notations with semantic types\&. .PP When \fI%stype\fP is specified (and with the default \fIint\fP semantic value type) the following dollar\-notations are available: .IP o \fI$$ = \fP .IP A value is assigned to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. The right\-hand side (rhs) of the assignment expression must be an expression of a type that can be assigned to the \fISTYPE_\fP type\&. .IP .IP o \fI$$(expr)\fP .IP Same as the previous dollar\-notation: \fIexpr\(cq\&s\fP value is assigned to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. .IP .IP o \fI_$$\fP .IP This refers to the semantic value of the rule\(cq\&s nonterminal\&. .IP .IP o \fI$$\fP .IP Same as the previous item: this refers to the semantic value of the rule\(cq\&s nonterminal\&. .IP .IP o \fI$$\&.\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the member selector operator, applied to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. .IP .IP o \fI$$\->\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the pointer to member operator, applied to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. .IP .IP o \fI_$1\fP .IP This refers to the current production rule\(cq\&s first component\(cq\&s semantic value\&. .IP .IP o \fI$1\fP .IP Same as the previous dollar\-notation: this refers to the current production rule\(cq\&s first component\(cq\&s semantic value\&. .IP .IP o \fI$1\&.\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the member selector operator, applied to the current production rule\(cq\&s first component\(cq\&s semantic value\&. .IP .IP o \fI$1\->\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the pointer to member operator, applied to the current production rule\(cq\&s first component\(cq\&s semantic value\&. .IP .IP o \fI_$\-1\fP .IP This refers to the semantic value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal ($\-2 refers to a component used two elements before the current nonterminal, etc\&.)\&. .IP .IP o \fI$\-1\fP .IP Same as the previous item: this refers to the semantic value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal\&. .IP .IP o \fI$\-1\&.\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the member selector operator, applied to the semantic value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP .IP o \fI$\-1\->\fP .IP If \fISTYPE_\fP is a class\-type then this dollar\-notation is shorthand for the pointer to member operator, applied to the semantic value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .PP When \fI%union\fP is specified these dollar\-notations are available: .IP o \fI$$ = \fP .IP A value is assigned to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. If the rule\(cq\&s nonterminal was associated with one of the union\(cq\&s field types, then the matching union field receives the value of the assignment expression\(cq\&s right\-hand side\&. If no association was defined then the variable representing the nonterminal\(cq\&s semantic value is a plain union (i\&.e\&., \fISTYPE_\fP) variable\&. .IP .IP o \fI$$(expr)\fP .IP \fIExpr\(cq\&s\fP value is assigned to the rule\(cq\&s nonterminal\(cq\&s plain union (i\&.e\&., \fISTYPE_\fP) type\&. Any association that may have been defined between the nonterminal and a union field is ignored\&. .IP .IP o \fI_$$\fP .IP This refers to the rule\(cq\&s nonterminal\(cq\&s plain union (i\&.e\&., \fISTYPE_\fP) type\&. Any association that may have been defined between the nonterminal and a union field is ignored\&. .IP .IP o \fI$$\fP .IP This refers to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. If it was associated with one of the union\(cq\&s types, then \fI$$\fP refers to the associated union field\&. If no association was defined then \fI$$\fP represents a plain union (i\&.e\&., \fISTYPE_\fP) type of variable\&. .IP .IP o \fI$$\&.\fP .IP If the rule\(cq\&s nonterminal\(cq\&s semantic value was associated with one of the union\(cq\&s types, then \fI$$\&.\fP is shorthand for the member selector operator, applied to the associated union field type\&. If no association was defined then \fI$$\&.\fP is shorthand for the field selector operator, applied to the nonterminal\(cq\&s semantic value\(cq\&s plain union (i\&.e\&., \fISTYPE_\fP) type\&. .IP .IP o \fI$$\->\fP .IP If the rule\(cq\&s nonterminal\(cq\&s semantic value was associated with one of the union\(cq\&s types, then \fI$$\->\fP is shorthand for the pointer to member operator, applied to the associated union field type\&. If no association was defined then an error message is issued, as the pointer to member operator is not defined for plain union types\&. .IP .IP o \fI_$1\fP .IP This refers to the current production rule\(cq\&s first component\(cq\&s plain union (\fISTYPE_\fP) value\&. .IP .IP o \fI$1\fP .IP This shorthand refers to the semantic value of the production rule\(cq\&s first element\&. If it was associated with one of the union\(cq\&s types, then \fI$1\fP refers to the associated union field\&. If no association was defined then \fI$1\fP represents a plain union (i\&.e\&., \fISTYPE_\fP) type of variable\&. .IP .IP o \fI$1\&.\fP .IP If the production rule\(cq\&s first component\(cq\&s semantic value was associated with one of the union\(cq\&s types, then \fI$1\&.\fP is shorthand for the member selector operator, applied to the associated union field type\&. If no association was defined then \fI$1\&.\fP is shorthand for the field selector operator, applied to the first component\(cq\&s semantic value\(cq\&s plain union (i\&.e\&., \fISTYPE_\fP) type\&. .IP .IP o \fI$1\->\fP .IP If the production rule\(cq\&s first component\(cq\&s semantic value was associated with one of the union\(cq\&s types, then \fI$1\->\fP is shorthand for the pointer to member operator, applied to the associated union field type\&. If no association was defined then an error message is issued, as the pointer to member operator is not defined for plain union types\&. .IP .IP o \fI_$\-1\fP .IP This refers to the plain union (\fISTYPE_\fP) value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal ($\-2 refers to a component used two elements before the current nonterminal, etc\&.)\&. .IP .IP o \fI$\-1\fP .IP Same: this refers to the plain union (\fISTYPE_\fP) value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal ($\-2 refers to a component used two elements before the current nonterminal, etc\&.)\&. .IP .IP o \fI$\-1\&.\fP .IP This is shorthand for the field selector operator applied to to the plain union (\fISTYPE_\fP) value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP .IP o \fI$\-1\->\fP .IP This shorthand refers to tho pointer to member operator applied to the plain union (\fISTYPE_\fP) value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. Its use results in an error message, as the pointer to member operator is not defined for plain union types\&. .IP .IP o \fI$\-1\fP .IP This refers to the \fIfield\fP union field of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal\&. Note that the validity of the specified field for that particular component cannot be verified by \fBbisonc++\fP\&. .IP .IP o \fI$\-1\&.\fP .IP This refers to the member selector operator of the \fIfield\fP union field of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal\&. Note that the validity of the specified field for that particular component cannot be verified by \fBbisonc++\fP\&. .IP .IP o \fI$\-1\->\fP This refers to the pointer to member operator of the \fIfield\fP union field of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal\&. Note that the validity of the specified field for that particular component cannot be verified by \fBbisonc++\fP\&. .PP When \fI%polymorphic\fP is specified these dollar\-notations can be used: .IP o \fI$$ = \fP .IP A semantic value is assigned to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. The right\-hand side (rhs) of the assignment expression must be an expression of the type that is associated with $$\&. This assignment operation assumes that the type of the rhs\-expression equals $$\(cq\&s semantic value type\&. If the types don\(cq\&t match the compiler issues a compilation error when compiling \fIparse\&.cc\fP\&. Casting the rhs to the correct value type is possible, but in that case the function call operator (see the next item) is preferred, as it does not require casting\&. If no semantic value type was associated with $$ then the assignment \fI$$ = STYPE_{}\fP can be used\&. .IP .IP o \fI$$(expr)\fP .IP A value is assigned to the rule\(cq\&s nonterminal\(cq\&s semantic value\&. \fIExpr\fP must be of a type that can be statically cast to $$\(cq\&s semantic value type\&. The required \fIstatic_cast\fP is generated by \fBbisonc++\fP and doesn\(cq\&t have to be specified for \fIexpr\fP\&. .IP .IP o \fI_$$\fP .IP This refers to the rule\(cq\&s nonterminal\(cq\&s semantic value, disregarding any polymorphic type that might have been associated with the rule\(cq\&s nonterminal\&. .IP .IP o \fI$$\fP .IP If no polymorphic type was associated with the rule\(cq\&s nonterminal then this is shorthand for a reference to the rule\(cq\&s plain \fISTYPE_\fP value\&. If a polymorphic value type was associated with the rule\(cq\&s nonterminal then this shorthand represents a reference to a value of that particular type\&. .IP .IP o \fI$$\&.\fP .IP If no polymorphic type was associated with the rule\(cq\&s nonterminal then this is shorthand for the member selector operator, applied to a reference to the rule\(cq\&s nonterminal\(cq\&s \fISTYPE_\fP value\&. If a polymorphic value type was associated with the rule\(cq\&s nonterminal then this shorthand represents the member selector operator, applied to a reference of that particular type\&. .IP .IP o \fI$$\->\fP .IP If no polymorphic type was associated with the rule\(cq\&s nonterminal then this is shorthand for the pointer to member operator, applied to a reference to the rule\(cq\&s nonterminal\(cq\&s \fISTYPE_\fP value\&. If a polymorphic value type was associated with the rule\(cq\&s nonterminal then this shorthand represents the pointer to member operator, applied to a reference of that particular type\&. .IP .IP o \fI_$1\fP .IP This refers to the current production rule\(cq\&s first component\(cq\&s generic \fISTYPE_\fP value\&. .IP .IP o \fI$1\fP .IP This shorthand refers to the semantic value of the production rule\(cq\&s first element\&. If it was associated with a polymorphic type, then \fI$1\fP refers to a value of that particular type\&. If no association was defined then \fI$1\fP represents a generic \fISTYPE_\fP value\&. .IP .IP o \fI$1\&.\fP .IP If the production rule\(cq\&s first component\(cq\&s semantic value was associated with a polymorphic type, then \fI$1\&.\fP is shorthand for the member selector operator, applied to the value of the associated polymorphic type\&. If no association was defined then \fI$1\&.\fP is shorthand for the member selector operator, applied to the first component\(cq\&s generic \fISTYPE_\fP value\&. .IP .IP o \fI$1\->\fP .IP If the production rule\(cq\&s first component\(cq\&s semantic value was associated with a polymorphic type, then \fI$1\->\fP is shorthand for the pointer to member operator, applied to the value of the associated polymorphic type\&. If no association was defined then \fI$1\&.\fP is shorthand for the pointer to member operator, applied to the first component\(cq\&s generic \fISTYPE_\fP value\&. .IP .IP o \fI_$\-1\fP .IP This refers to the generic (\fISTYPE_\fP) value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal ($\-2 refers to a component used two elements before the current nonterminal, etc\&.)\&. .IP .IP o \fI$\-1\fP .IP Same: this refers to the generic (\fISTYPE_\fP) value of a component in a production rule, listed immediately before the current rule\(cq\&s nonterminal ($\-2 refers to a component used two elements before the current nonterminal, etc\&.)\&. .IP .IP o \fI$\-1\&.\fP .IP This is shorthand for the member selector operator applied to to the generic \fISTYPE_\fP value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP .IP o \fI$\-1\->\fP .IP This is shorthand for the pointer to member operator applied to to the generic \fISTYPE_\fP value of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP .IP o \fI$\-1\fP .IP This shorthand represents a reference to the semantic value of the polymorphic type associated with \fItag\fP of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP If, when using the generated parser\(cq\&s class \fIparse\fP function, the polymorphic type of that element turns out not to match the type that is associated with \fItag\fP then a run\-time fatal error results\&. .IP If that happens, and the \fIdebug\fP option/directive had been specified when \fBbisonc++\fP was run, then rerun the program after specifying \fIparser\&.setDebug(Parser::ACTIONCASES)\fP to locate the \fIparse\fP function\(cq\&s action block where the fatal error was encountered\&. .IP .IP o \fI$\-1\&.\fP .IP This shorthand represents the member selector operator, applied to the semantic value of the polymorphic type associated with \fItag\fP of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP If, when using the generated parser\(cq\&s class \fIparse\fP function, the polymorphic type of that element turns out not to match the type that is associated with \fItag\fP then a run\-time fatal error results\&. The procedure suggested at the previous (\fI$\-1\fP) item for solving such errors can be applied here as well\&. .IP .IP o \fI$\-1\->\fP .IP This shorthand represents the pointer to member selector operator, applied to the semantic value of the polymorphic type associated with \fItag\fP of some production rule element, 1 element before the current rule\(cq\&s nonterminal\&. .IP If, when using the generated parser\(cq\&s class \fIparse\fP function, the polymorphic type of that element turns out not to match the type that is associated with \fItag\fP then a run\-time fatal error results\&. The procedure suggested at the previous (\fI$\-1\fP) item for solving such errors can be applied here as well\&. .PP .SH "RESTRICTIONS ON TOKEN NAMES" .PP To avoid collisions with names defined by the parser\(cq\&s (base) class, the following identifiers should not be used as token names: .IP o Identifiers ending in an underscore; .IP o Any of the following identifiers: \fIABORT, ACCEPT, ERROR, clearin, debug\fP, or \fIsetDebug\fP\&. .PP .SH "OBSOLETE SYMBOLS" .PP All \fBDECLARATIONS\fP and \fBDEFINE\fP symbols not listed above but defined in \fBbison++\fP are obsolete with \fBbisonc++\fP\&. In particular, there is no \fI%header{ \&.\&.\&. %}\fP section anymore\&. Also, all \fBDEFINE\fP symbols related to member functions are now obsolete\&. There is no need for these symbols anymore as they can simply be declared in the class header file and defined elsewhere\&. .PP .SH "USING SYMBOLIC TOKENS IN CLASSES OTHER THAN THE PARSER CLASS" .PP The tokens defined in the grammar files processed by \fBbisonc++\fP must usually also be available to the lexical scanner, returning those tokens when certain regular expressions are matched\&. E\&.g\&., a \fINUMBER\fP token may be used in the grammar and the lexical scanner may be expected to return that token when the input matches the \fI[0\-9]+\fP regular expression\&. To avoid circular dependencies among classes the tokens can be written to a separate file using the \fItoken\-path\fP directive or option\&. The location and name of this file is specified by the \fItoken\-path\fP specification, and is generated from scratch at every run of \fBbisonc++\fP\&. By default the grammar\(cq\&s symbolic tokens are made available in the class \fITokens\fP, and classes may refer to its tokens using the \fITokens\fP class scope (e\&.g\&., \fITokens::NUMBER\fP)\&. .PP Before \fBbisonc++\fP version 6\&.04\&.00 tokens were made available by including the file \fIparserbase\&.h\fP, using a simple \fI#define\fP suggesting that the tokens were in fact defined by the parser class itself\&. Using this scheme lexical scanner specifications returned, e\&.g\&., \fIParser::NUMBER\fP when \fI[0\-9]+\fP was matched\&. Unless the \fItoken\-path\fP directive or option is used this approach is still available, but its use is deprecated\&. .PP .SH "EXAMPLE" .PP Using a fairly traditional example, we construct a simple calculator below\&. The basic operators as well as parentheses can be used to specify expressions, and each expression should be terminated by a newline\&. The program terminates when a \fIq\fP is entered\&. Empty lines result in a mere prompt\&. .PP First an associated grammar is constructed\&. When a syntactic error is encountered all tokens are skipped until then next newline and a simple message is printed using the default \fIerror\fP function\&. It is assumed that no semantic errors occur (in particular, no divisions by zero)\&. The grammar is decorated with actions performed when the corresponding grammatical production rule is recognized\&. The grammar itself is rather standard and straightforward, but note the first part of the specification file, containing various other directives, among which the \fI%scanner\fP directive, resulting in a composed \fId_scanner\fP object as well as an implementation of the member function \fIint lex\fP, and the \fI%token\-path\fP directive, defining the \fIclass Tokens\fP in he file \fI\&.\&./scanner/tokens\&.h\fP\&. In this example, the \fIScanner\fP class is generated by \fBflexc++\fP(1)\&. The details of constructing a class using \fIflexc++\fP is beyond the scope of this man\-page, but \fIflexc++\(cq\&s\fP specification file is shown below\&. .PP Here is \fBbisonc++\fP\(cq\&s input file: .PP .nf %filenames parser %scanner \&.\&./scanner/scanner\&.h %token\-path \&.\&./tokens/tokens\&.h // lowest precedence %token NUMBER // integral numbers EOLN // newline %left \(cq\&+\(cq\& \(cq\&\-\(cq\& %left \(cq\&*\(cq\& \(cq\&/\(cq\& %right UNARY // highest precedence %% expressions: expressions evaluate | prompt ; evaluate: alternative prompt ; prompt: { prompt(); } ; alternative: expression EOLN { cout << $1 << endl; } | \(cq\&q\(cq\& done | EOLN | error EOLN ; done: { cout << \(dq\&Done\&.\en\(dq\&; ACCEPT(); } ; expression: expression \(cq\&+\(cq\& expression { $$ = $1 + $3; } | expression \(cq\&\-\(cq\& expression { $$ = $1 \- $3; } | expression \(cq\&*\(cq\& expression { $$ = $1 * $3; } | expression \(cq\&/\(cq\& expression { $$ = $1 / $3; } | \(cq\&\-\(cq\& expression %prec UNARY { $$ = \-$2; } | \(cq\&+\(cq\& expression %prec UNARY { $$ = $2; } | \(cq\&(\(cq\& expression \(cq\&)\(cq\& { $$ = $2; } | NUMBER { $$ = stoul(d_scanner\&.matched()); } ; .fi .PP \fBBisonc++\fP processes this file, generating the following files: .IP o The parser\(cq\&s base class, which should not be modified by the programmer: .IP .nf // hdr/includes #ifndef ParserBase_h_included #define ParserBase_h_included #include #include #include // $insert preincludes #include \(dq\&\&.\&./tokens/tokens\&.h\(dq\& // hdr/baseclass namespace // anonymous { struct PI_; } // $insert parserbase class ParserBase: public Tokens { public: enum DebugMode_ { OFF = 0, ON = 1 << 0, ACTIONCASES = 1 << 1 }; // $insert tokens // $insert STYPE using STYPE_ = int; private: // state semval using StatePair = std::pair; // token semval using TokenPair = std::pair; int d_stackIdx = \-1; std::vector d_stateStack; StatePair *d_vsp = 0; // points to the topmost value stack size_t d_state = 0; TokenPair d_next; int d_token; bool d_terminalToken = false; bool d_recovery = false; protected: enum Return_ { PARSE_ACCEPT_ = 0, // values used as parse()\(cq\&s return values PARSE_ABORT_ = 1 }; enum ErrorRecovery_ { UNEXPECTED_TOKEN_, }; bool d_actionCases_ = false; // set by options/directives bool d_debug_ = true; size_t d_requiredTokens_; size_t d_nErrors_; // initialized by clearin() size_t d_acceptedTokens_; STYPE_ d_val_; ParserBase(); void ABORT() const; void ACCEPT() const; void ERROR() const; STYPE_ &vs_(int idx); // value stack element idx int lookup_() const; int savedToken_() const; int token_() const; size_t stackSize_() const; size_t state_() const; size_t top_() const; void clearin_(); void errorVerbose_(); void lex_(int token); void popToken_(); void pop_(size_t count = 1); void pushToken_(int token); void push_(size_t nextState); void redoToken_(); bool recovery_() const; void reduce_(int rule); void shift_(int state); void startRecovery_(); public: void setDebug(bool mode); void setDebug(DebugMode_ mode); }; // hdr/abort inline void ParserBase::ABORT() const { throw PARSE_ABORT_; } // hdr/accept inline void ParserBase::ACCEPT() const { throw PARSE_ACCEPT_; } // hdr/error inline void ParserBase::ERROR() const { throw UNEXPECTED_TOKEN_; } // hdr/savedtoken inline int ParserBase::savedToken_() const { return d_next\&.first; } // hdr/opbitand inline ParserBase::DebugMode_ operator&(ParserBase::DebugMode_ lhs, ParserBase::DebugMode_ rhs) { return static_cast( static_cast(lhs) & rhs); } // hdr/opbitor inline ParserBase::DebugMode_ operator|(ParserBase::DebugMode_ lhs, ParserBase::DebugMode_ rhs) { return static_cast(static_cast(lhs) | rhs); }; // hdr/recovery inline bool ParserBase::recovery_() const { return d_recovery; } // hdr/stacksize inline size_t ParserBase::stackSize_() const { return d_stackIdx + 1; } // hdr/state inline size_t ParserBase::state_() const { return d_state; } // hdr/token inline int ParserBase::token_() const { return d_token; } // hdr/vs inline ParserBase::STYPE_ &ParserBase::vs_(int idx) { return (d_vsp + idx)\->second; } #endif .fi .IP .IP o The parser class \fIparser\&.h\fP itself\&. In the grammar specification various member functions are used (e\&.g\&., \fIdone\fP) and \fIprompt\fP\&. These functions are so small that they can very well be implemented inline\&. Note that \fIdone\fP calls \fIACCEPT\fP to terminate further parsing\&. \fIACCEPT\fP and related members (e\&.g\&., \fIABORT\fP) can be called from any member called by \fIparse\fP\&. As a consequence, action blocks could contain mere function calls, rather than several statements, thus minimizing the need to rerun \fBbisonc++\fP when an action is modified\&. .IP Once \fBbisonc++\fP has created \fIparser\&.h\fP additionally required members can be added to it (\fBbisonc++\fP itself won\(cq\&t modify \fIparser\&.h\fP anymore once it is created), resulting in the following final version: .IP .nf // Generated by Bisonc++ V5\&.00\&.00 on Sun, 03 Apr 2016 17:49:17 +0200 #ifndef Parser_h_included #define Parser_h_included // $insert baseclass #include \(dq\&parserbase\&.h\(dq\& // $insert scanner\&.h #include \(dq\&\&.\&./scanner/scanner\&.h\(dq\& #undef Parser class Parser: public ParserBase { // $insert scannerobject Scanner d_scanner; public: int parse(); private: void error(); // called on (syntax) errors int lex(); // returns the next token from the // lexical scanner\&. void print(); // use, e\&.g\&., d_token, d_loc void prompt(); void done(); // support functions for parse(): void executeAction_(int ruleNr); void errorRecovery_(); void nextCycle_(); void nextToken_(); void print_(); void exceptionHandler(std::exception const &exc); }; inline void Parser::prompt() { std::cout << \(dq\&? \(dq\& << std::flush; } inline void Parser::done() { std::cout << \(dq\&Done\en\(dq\&; ACCEPT(); } #endif .fi .IP .IP o The file \fI\&.\&./tokens/tokens\&.h\fP is generated because of the \fI%token\-path\fP directive\&. To avoid circular dependencies the tokens are made available in a separate file, allowing classes used by the parser to use the grammar\(cq\&s tokens as well\&. Here is the file specifying the grammar\(cq\&s tokens: .IP .nf #ifndef INCLUDED_TOKENS_ #define INCLUDED_TOKENS_ struct Tokens { // Symbolic tokens: enum Tokens_ { NUMBER = 257, EOLN, UNARY, }; }; #endif .fi .PP For the program no additional members had to be defined in the class \fIParser\fP\&. The member function \fIparse\fP is defined by \fBbisonc++\fP in the source file \fIparse\&.cc\fP, and it includes \fIparser\&.ih\fP\&. .PP As \fIcerr\fP is used in the grammar\(cq\&s actions, a \fIusing namespace std\fP or comparable directive is required\&. It is specified in \fIparser\&.ih\fP\&. Here is the implementation header declaring the standard namespace: .PP .nf // Generated by Bisonc++ V5\&.00\&.00 on Sun, 03 Apr 2016 17:51:26 +0200 // Include this file in the sources of the class Parser\&. // $insert class\&.h #include \(dq\&parser\&.h\(dq\& inline void Parser::error() { std::cerr << \(dq\&Syntax error\en\(dq\&; } // $insert lex inline int Parser::lex() { return d_scanner\&.lex(); } inline void Parser::print() { print_(); // displays tokens if \-\-print was specified } inline void Parser::exceptionHandler(std::exception const &exc) { throw; // re\-implement to handle exceptions thrown by actions } // Add here includes that are only required for the compilation // of Parser\(cq\&s sources\&. // UN\-comment the next using\-declaration if you want to use // int Parser\(cq\&s sources symbols from the namespace std without // specifying std:: using namespace std; .fi .PP In the current context the member function \fIparse\(cq\&s\fP implementation is not very relevant (it should not be modified by the programmer anyway)\&. It is not shown here, but is available as \fIcalculator/parser/parse\&.cc\fP in the distribution\(cq\&s \fIdemos/\fP directory after building the calculator using the there provided \fIbuild\fP script\&. .PP The lexical scanner is generated by \fBflexc++\fP(1) from the following specification file, using the command \fIflexc++ lexer\fP: .PP .nf // see also regression/calculator/scanner %interactive %filenames scanner %% [ \et]+ // skip white space \en return Tokens::EOLN; [0\-9]+ return Tokens::NUMBER; \&. return matched()[0]; %% .fi .PP Finally, here is the program\(cq\&s \fImain\fP function: .PP .nf #include \(dq\&parser/parser\&.h\(dq\& int main() { Parser calculator; return calculator\&.parse(); } .fi .PP .SH "SEE ALSO" \fBbison\fP(1), \fBbison++\fP(1), \fBbisonc++\fP(1), \fBbisonc++api\fP(3), \fBbison\&.info\fP (using texinfo), \fBflexc++\fP(1), \fBhttps://fbb\-git\&.gitlab\&.io/bisoncpp/\fP .PP Lakos, J\&. (2001) \fBLarge Scale C++ Software Design\fP, Addison Wesley\&. .br Aho, A\&.V\&., Sethi, R\&., Ullman, J\&.D\&. (1986) \fBCompilers\fP, Addison Wesley\&. .PP .SH "AUTHOR" .PP Frank B\&. Brokken (f\&.b\&.brokken@rug\&.nl)\&.