OuluLinux / FOG

Flexible Object Generator. Fixed to work with modern compilers. (from http://www.computing.surrey.ac.uk/research/dsrg/fog/)
BSD 3-Clause "New" or "Revised" License
2 stars 0 forks source link

Grammar railroad diagram #1

Open mingodad opened 3 years ago

mingodad commented 3 years ago

I'm curious about this tool, I used in the past "Lzz, The Lazy C++ Compiler (https://github.com/mjspncr/lzz3)" and just found your project indirectly through https://github.com/AthrunArthur/cxxparser .

Are you still activelly using it ?

I've done a experimental tool to convert bison grammars to a kind of EBNF understood by https://www.bottlecaps.de/rr/ui to generate railroad diagrams see bellow the converted src/Fog/FogParser.y and with some hand made changes to allow view it at https://www.bottlecaps.de/rr/ui the order of the rules could be changed to a better view of the railroad diagrams. Copy and paste the EBNF bellow on https://www.bottlecaps.de/rr/ui tab Edit Grammar then switch to the tab View Diagram.

/*
 *  The // %prec resolves a conflict in identifier_word : which is forced to be a shift of a label for
 *  a labeled-statement rather than a reduction for the name of a bit-field or generalised constructor.
 *  This is pretty dubious syntactically but correct for all semantic possibilities.
 *  The shift is only activated when the ambiguity exists at the start of a statement. In this context
 *  a bit-field declaration or constructor definition are not allowed.
 /*/
identifier_word::=                    Identifier
    |                               MetaType
    |                               DERIVED | FILE | GUARD | IMPLEMENTATION
    |                               INCLUDE | INTERFACE | NOGUARD | NOIMPLEMENTATION
    |                               OVERLOAD | PATH | PREFIX | PURE | SUFFIX
    |                               ALL | PLACEHOLDER | PLACEMENT | NOAUTO
    |                               segment
    |                               utility
identifier::=                         identifier_word                     // %prec SHIFT_THERE
    |                               TreeLiteral
/*
 *  The // %prec resolves the $014.2-3 ambiguity:
 *  Identifier '<' is forced to go through the is-it-a-template-name test
 *  All names absorb TEMPLATE with the name, so that no template_test is performed for them.
 *  This requires all potential declarations within an expression to perpetuate this policy
 *  and thereby guarantee the ultimate coverage of explicit_instantiation.
 /*/
id::=                                 identifier                          // %prec SHIFT_THERE       /* Force < through test /*/
    |                               identifier template_test '+' template_argument_list '>'
    |                               identifier template_test '+' '>'
    |                               identifier template_test '-'                                /* requeued < follows /*/
    |                               template_id
template_test::=                      '<'             /* Queue '+' or '-' < as follow on /*/
global_scope::=                       SCOPE
    |                               TEMPLATE global_scope
id_scope::=                           id SCOPE
/*
 *  A :: B :: C; is ambiguous How much is type and how much name ?
 *  The // %prec maximises the (type) length which is the $07.1-2 semantic constraint.
 /*/
nested_id::=                          id                                  // %prec SHIFT_THERE       /* Maximise length /*/
    |                               id_scope nested_id
scoped_id::=                          nested_id
    |                               global_scope nested_id

/*
 *  destructor_id has to be held back to avoid a conflict with a one's complement as per $05.3.1-9,
 *  It gets put back only when scoped or in a declarator_id, which is only used as an explicit member name.
 *  Declarations of an unscoped destructor are always parsed as a one's complement.
 /*/
destructor_id::=                      '~' id
    |                               TEMPLATE destructor_id
special_function_id::=                conversion_function_id
    |                               operator_function_id
    |                               TEMPLATE special_function_id
nested_special_function_id::=         special_function_id
    |                               id_scope destructor_id
    |                               id_scope nested_special_function_id
scoped_special_function_id::=         nested_special_function_id
    |                               global_scope nested_special_function_id

/* declarator-id is all names in all scopes, except reserved words /*/
declarator_id::=                      scoped_id
    |                               scoped_special_function_id
    |                               destructor_id

/*  The standard defines pseudo-destructors in terms of type-name, which is class/enum/typedef, of which
 *  class-name is covered by a normal destructor. pseudo-destructors are supposed to support ~int() in
 *  templates, so the grammar here covers built-in names. Other names are covered by the lack of
 *  identifier/type discrimination.
 /*/
built_in_type_id::=                   built_in_type_specifier
    |                               built_in_type_id built_in_type_specifier
pseudo_destructor_id::=               built_in_type_id SCOPE '~' built_in_type_id
    |                               '~' built_in_type_id
    |                               TEMPLATE pseudo_destructor_id
nested_pseudo_destructor_id::=        pseudo_destructor_id
    |                               id_scope nested_pseudo_destructor_id
scoped_pseudo_destructor_id::=        nested_pseudo_destructor_id
    |                               global_scope scoped_pseudo_destructor_id

/*---------------------------------------------------------------------------------------------------
 * A.2 Lexical conventions
 *---------------------------------------------------------------------------------------------------/*/
/*
 *  String concatenation is a phase 6, not phase 7 activity so does not really belong in the grammar.
 *  However it may be convenient to have it here to make this grammar fully functional.
 *  Unfortunately it introduces a conflict with the generalised parsing of extern "C" which
 *  is correctly resolved to maximise the string length as the token source should do anyway.
 /*/
string::=                             StringLiteral
/*string::=                           StringLiteral                           // %prec SHIFT_THERE    /*/
/*  |                               StringLiteral string  -- Perverse order avoids conflicts --  /*/
literal::=                            IntegerLiteral
    |                               CharacterLiteral
    |                               FloatingLiteral
    |                               string
    |                               boolean_literal
    |                               NumberLiteral
string_expr::=                        string
    |                               TreeLiteral
boolean_literal::=                    FALSE
    |                               TRUE

/*---------------------------------------------------------------------------------------------------
 * A.3 Basic concepts
 *---------------------------------------------------------------------------------------------------/*/
translation_unit::=                   declaration_seq.opt
    |                               declaration_seq.opt util looping_declaration '#' bang error '#'
/* $-expression grammar /*/
    |                               '$' tree_expression
    |                               '$' '{' tree_expression ecarb
    |                               '$' bang error
    |                               '$' '{' bang error ecarb

/*---------------------------------------------------------------------------------------------------
 * A.4 Expressions
 *---------------------------------------------------------------------------------------------------
 *  primary_expression covers an arbitrary sequence of all names with the exception of an unscoped destructor,
 *  which is parsed as its unary expression which is the correct disambiguation (when ambiguous).
 *  This eliminates the traditional A(B) meaning A B ambiguity, since we never have to tack an A onto
 *  the front of something that might start with (. The name length got maximised ab initio. The downside
 *  is that semantic interpretation must split the names up again.
 *
 *  Unification of the declaration and expression syntax means that unary and binary pointer declarator operators:
 *      int * * name
 *  are parsed as binary and unary arithmetic operators (int) * (*name). Since type information is not used
 *  ambiguities resulting from a cast
 *      (cast)*(value)
 *  are resolved to favour the binary rather than the cast unary to ease AST clean-up.
 *  The cast-call ambiguity must be resolved to the cast to ensure that (a)(b)c can be parsed.
 *
 *  The problem of the functional cast ambiguity
 *      name(arg)
 *  as call or declaration is avoided by maximising the name within the parsing kernel. So
 *  primary_id_expression picks up
 *      extern long int const var = 5
 *  as an assignment to the syntax parsed as "extern long int const var". The presence of two names is
 *  parsed so that "extern long into const" is distinguished from "var" considerably simplifying subsequent
 *  semantic resolution.
 *
 *  The generalised name is a concatenation of potential type-names (scoped identifiers or built-in sequences)
 *  plus optionally one of the special names such as an operator-function-id, conversion-function-id or
 *  destructor as the final name.
 /*/
primary_expression::=                 literal
    |                               THIS
    |                               suffix_decl_specified_ids
/*  |                               SCOPE identifier                                        -- covered by suffix_decl_specified_ids /*/
/*  |                               SCOPE operator_function_id                              -- covered by suffix_decl_specified_ids /*/
/*  |                               SCOPE qualified_id                                      -- covered by suffix_decl_specified_ids /*/
    |                               abstract_expression           // %prec REDUCE_HERE_MOSTLY  /* Prefer binary to unary ops, cast to call /*/
/*  |                               id_expression                                           -- covered by suffix_decl_specified_ids /*/

/*
 *  Abstract-expression covers the () and [] of abstract-declarators.
 /*/
abstract_expression::=                parenthesis_clause
    |                               '[' expression.opt ']'
    |                               TEMPLATE parenthesis_clause

/*  Type I function parameters are ambiguous with respect to the generalised name, so we have to do a lookahead following
 *  any function-like parentheses. This unfortunately hits normal code, so kill the -- lines and add the ++ lines for efficiency.
 *  Supporting Type I code under the superset causes perhaps 25% of lookahead parsing. Sometimes complete class definitions
 *  get traversed since they are valid generalised type I parameters!
 /*/
type1_parameters::=       /*----/*/    parameter_declaration_list ';'
    |                   /*----/*/    type1_parameters parameter_declaration_list ';'
mark_type1::=                         /* empty /*/
postfix_expression::=                 primary_expression
/*  |                   /++++++/    postfix_expression parenthesis_clause                    /*/
    |                   /*----/*/    postfix_expression parenthesis_clause mark_type1 '-'
    |                   /*----/*/    postfix_expression parenthesis_clause mark_type1 '+' type1_parameters mark '{' error
                        /*----/*/
    |                   /*----/*/    postfix_expression parenthesis_clause mark_type1 '+' type1_parameters mark error
                        /*----/*/
    |                   /*----/*/    postfix_expression parenthesis_clause mark_type1 '+' error
                        /*----/*/
    |                               postfix_expression '[' expression.opt ']'
/*  |                               destructor_id '[' expression.opt ']'                    -- not semantically valid /*/
/*  |                               destructor_id parenthesis_clause                        -- omitted to resolve known ambiguity /*/
/*  |                               simple_type_specifier '(' expression_list.opt ')'       -- simple_type_specifier is a primary_expression /*/
    |                               postfix_expression '.' declarator_id
/*  |                               postfix_expression '.' TEMPLATE declarator_id           -- TEMPLATE absorbed into declarator_id. /*/
    |                               postfix_expression '.' scoped_pseudo_destructor_id
    |                               postfix_expression ARROW declarator_id
/*  |                               postfix_expression ARROW TEMPLATE declarator_id         -- TEMPLATE absorbed into declarator_id. /*/
    |                               postfix_expression ARROW scoped_pseudo_destructor_id
    |                               postfix_expression INC
    |                               postfix_expression DEC
    |                               DYNAMIC_CAST '<' type_id '>' '(' expression ')'
    |                               STATIC_CAST '<' type_id '>' '(' expression ')'
    |                               REINTERPRET_CAST '<' type_id '>' '(' expression ')'
    |                               CONST_CAST '<' type_id '>' '(' expression ')'
    |                               TYPEID parameters_clause
/*  |                               TYPEID '(' expression ')'                               -- covered by parameters_clause /*/
/*  |                               TYPEID '(' type_id ')'                                  -- covered by parameters_clause /*/
expression_list.opt::=                /* empty /*/
    |                               expression_list
expression_list::=                    assignment_expression
    |                               expression_list ',' assignment_expression

unary_expression::=                   postfix_expression
    |                               INC cast_expression
    |                               DEC cast_expression
    |                               ptr_operator cast_expression
/*  |                               '*' cast_expression                                     -- covered by ptr_operator /*/
/*  |                               '&' cast_expression                                     -- covered by ptr_operator /*/
/*  |                               decl_specifier_seq '*' cast_expression                  -- covered by binary operator /*/
/*  |                               decl_specifier_seq '&' cast_expression                  -- covered by binary operator /*/
    |                               suffix_decl_specified_scope star_ptr_operator cast_expression   /* covers e.g int ::type::* const t = 4 /*/
    |                               '+' cast_expression
    |                               '-' cast_expression
    |                               '!' cast_expression
    |                               '~' cast_expression
    |                               SIZEOF unary_expression
/*  |                               SIZEOF '(' type_id ')'                                  -- covered by unary_expression /*/
    |                               new_expression
    |                               global_scope new_expression
    |                               delete_expression
    |                               global_scope delete_expression
/*  |                               DELETE '[' ']' cast_expression       -- covered by DELETE cast_expression since cast_expression covers ... /*/
/*  |                               SCOPE DELETE '[' ']' cast_expression //  ... abstract_expression cast_expression and so [] cast_expression /*/

delete_expression::=                  DELETE cast_expression                                  /* also covers DELETE[] cast_expression /*/
new_expression::=                     NEW new_type_id new_initializer.opt
    |                               NEW parameters_clause new_type_id new_initializer.opt
    |                               NEW parameters_clause
/*  |                               NEW '(' type-id ')'                                     -- covered by parameters_clause /*/
    |                               NEW parameters_clause parameters_clause new_initializer.opt
/*  |                               NEW '(' type-id ')' new_initializer                     -- covered by parameters_clause parameters_clause /*/
/*  |                               NEW parameters_clause '(' type-id ')'                   -- covered by parameters_clause parameters_clause /*/
                                                                                /* ptr_operator_seq.opt production reused to save a // %prec /*/
new_type_id::=                        type_specifier ptr_operator_seq.opt
    |                               type_specifier new_declarator
    |                               type_specifier new_type_id
new_declarator::=                     ptr_operator new_declarator
    |                               direct_new_declarator
direct_new_declarator::=              '[' expression ']'
    |                               direct_new_declarator '[' constant_expression ']'
new_initializer.opt::=                /* empty /*/
    |                               '(' expression_list.opt ')'

/*  cast-expression is generalised to support a [] as well as a () prefix. This covers the omission of DELETE[] which when
 *  followed by a parenthesised expression was ambiguous. It also covers the gcc indexed array initialisation for free.
 /*/
cast_expression::=                    unary_expression
    |                               abstract_expression cast_expression
/*  |                               '(' type_id ')' cast_expression                             -- covered by abstract_expression /*/

pm_expression::=                      cast_expression
    |                               pm_expression DOT_STAR cast_expression
    |                               pm_expression ARROW_STAR cast_expression
multiplicative_expression::=          pm_expression
    |                               multiplicative_expression star_ptr_operator pm_expression
    |                               multiplicative_expression '/' pm_expression
    |                               multiplicative_expression '%' pm_expression
additive_expression::=                multiplicative_expression
    |                               additive_expression '+' multiplicative_expression
    |                               additive_expression '-' multiplicative_expression
shift_expression::=                   additive_expression
    |                               shift_expression SHL additive_expression
    |                               shift_expression SHR additive_expression
relational_expression::=              shift_expression
    |                               relational_expression '<' shift_expression
    |                               relational_expression '>' shift_expression
    |                               relational_expression LE shift_expression
    |                               relational_expression GE shift_expression
equality_expression::=                relational_expression
    |                               equality_expression EQ relational_expression
    |                               equality_expression NE relational_expression
and_expression::=                     equality_expression
    |                               and_expression '&' equality_expression
exclusive_or_expression::=            and_expression
    |                               exclusive_or_expression '^' and_expression
inclusive_or_expression::=            exclusive_or_expression
    |                               inclusive_or_expression '|' exclusive_or_expression
logical_and_expression::=             inclusive_or_expression
    |                               logical_and_expression LOG_AND inclusive_or_expression
logical_or_expression::=              logical_and_expression
    |                               logical_or_expression LOG_OR logical_and_expression
conditional_expression::=             logical_or_expression
    |                               logical_or_expression '?' expression ':' assignment_expression

/*  assignment-expression is generalised to cover the simple assignment of a braced initializer in order to contribute to the
 *  coverage of parameter-declaration and init-declaration.
 /*/
assignment_expression::=              conditional_expression
    |                               logical_or_expression assignment_operator assignment_expression
    |                               logical_or_expression '=' braced_initializer
    |                               throw_expression
assignment_operator::=                '=' | ASS_ADD | ASS_AND | ASS_DIV | ASS_MOD | ASS_MUL | ASS_OR | ASS_SHL | ASS_SHR | ASS_SUB | ASS_XOR

/*  expression is widely used and usually single-element, so the reductions are arranged so that a
 *  single-element expression is returned as is. Multi-element expressions are parsed as a list that
 *  may then behave polymorphically as an element or be compacted to an element. /*/
expression.opt::=                     /* empty /*/
    |                               expression
expression::=                         assignment_expression
    |                               expression_list ',' assignment_expression
constant_expression::=                conditional_expression

/*  The grammar is repeated for when the parser stack knows that the next > must end a template.
 /*/
templated_relational_expression::=    shift_expression
    |                               templated_relational_expression '<' shift_expression
    |                               templated_relational_expression LE shift_expression
    |                               templated_relational_expression GE shift_expression
templated_equality_expression::=      templated_relational_expression
    |                               templated_equality_expression EQ templated_relational_expression
    |                               templated_equality_expression NE templated_relational_expression
templated_and_expression::=           templated_equality_expression
    |                               templated_and_expression '&' templated_equality_expression
templated_exclusive_or_expression::=  templated_and_expression
    |                               templated_exclusive_or_expression '^' templated_and_expression
templated_inclusive_or_expression::=  templated_exclusive_or_expression
    |                               templated_inclusive_or_expression '|' templated_exclusive_or_expression
templated_logical_and_expression::=   templated_inclusive_or_expression
    |                               templated_logical_and_expression LOG_AND templated_inclusive_or_expression
templated_logical_or_expression::=    templated_logical_and_expression
    |                               templated_logical_or_expression LOG_OR templated_logical_and_expression
templated_conditional_expression::=   templated_logical_or_expression
    |                               templated_logical_or_expression '?' templated_expression ':' templated_assignment_expression
templated_assignment_expression::=    templated_conditional_expression
    |                               templated_logical_or_expression assignment_operator templated_assignment_expression
    |                               templated_throw_expression
templated_expression::=               templated_assignment_expression
    |                               templated_expression_list ',' templated_assignment_expression
templated_expression_list::=          templated_assignment_expression
    |                               templated_expression_list ',' templated_assignment_expression

/*---------------------------------------------------------------------------------------------------
 * A.5 Statements
 *---------------------------------------------------------------------------------------------------
 *  Parsing statements is easy once simple_declaration has been generalised to cover expression_statement.
 /*/
looping_statement::=                  start_search looped_statement
looped_statement::=                   statement
    |                               advance_search '+' looped_statement
    |                               advance_search '-'
statement::=                          control_statement
/*  |                               expression_statement                                        -- covered by declaration_statement /*/
    |                               compound_statement
    |                               declaration_statement
    |                               try_block
    |                               AUTO control_statement
    |                               AUTO meta_expression_statement
control_statement::=                  labeled_statement
    |                               selection_statement
    |                               iteration_statement
    |                               jump_statement
labeled_statement::=                  identifier_word ':' looping_statement
    |                               CASE constant_expression ':' looping_statement
    |                               DEFAULT ':' looping_statement
/*expression_statement::=             expression.opt ';'                                          -- covered by declaration_statement /*/
compound_statement::=                 '{' statement_seq.opt '}'
    |                               '{' statement_seq.opt looping_statement '#' bang error_ecarb
statement_seq.opt::=                  /* empty /*/
    |                               statement_seq.opt looping_statement
    |                               statement_seq.opt looping_statement '#' bang error ';'
/*
 *  The dangling else conflict is resolved to the innermost if.
 /*/
selection_statement::=                IF '(' condition ')' looping_statement    // %prec SHIFT_THERE
    |                               IF '(' condition ')' looping_statement ELSE looping_statement
    |                               SWITCH '(' condition ')' looping_statement
condition.opt::=                      /* empty /*/
    |                               condition
condition::=                          parameter_declaration_list
/*  |                               expression                                                  -- covered by parameter_declaration_list /*/
/*  |                               type_specifier_seq declarator '=' assignment_expression     -- covered by parameter_declaration_list /*/
iteration_statement::=                WHILE '(' condition ')' looping_statement
    |                               DO looping_statement WHILE '(' expression ')' ';'
    |                               FOR '(' for_init_statement condition.opt ';' expression.opt ')' looping_statement
for_init_statement::=                 simple_declaration
/*  |                               expression_statement                                        -- covered by simple_declaration /*/
jump_statement::=                     BREAK ';'
    |                               CONTINUE ';'
    |                               RETURN expression.opt ';'
    |                               GOTO identifier ';'
declaration_statement::=              block_declaration

/*---------------------------------------------------------------------------------------------------
 * A.6 Declarations
 *---------------------------------------------------------------------------------------------------/*/
compound_declaration::=               '{' nest declaration_seq.opt '}'
    |                               '{' nest declaration_seq.opt util looping_declaration '#' bang error_ecarb
declaration_seq.opt::=                /* empty /*/
    |                               declaration_seq.opt util looping_declaration
    |                               declaration_seq.opt util looping_declaration '#' bang error ';'
looping_declaration::=                start_search1 looped_declaration
looped_declaration::=                 declaration
    |                               advance_search '+' looped_declaration
    |                               advance_search '-'
lined_declaration::=                  line declaration
declaration::=                        block_declaration
    |                               function_definition
    |                               template_declaration
/*  |                               explicit_instantiation                                      -- covered by relevant declarations /*/
    |                               explicit_specialization
    |                               specialised_declaration
    |                               accessibility_specifier
    |                               compound_declaration
    |                               meta_control_statement
    |                               AUTO meta_control_statement
    |                               AUTO meta_class_specifier semi
    |                               AUTO meta_expression_statement
    |                               AUTO meta_function_definition
    |                               syntax_macro_definition
    |                               include_declaration semi
    |                               file_dependency_declaration
    |                               file_placement_declaration
    |                               filespace_specifier semi
specialised_declaration::=            linkage_specification
    |                               namespace_declaration
    |                               namespace_definition
    |                               TEMPLATE specialised_declaration
block_declaration::=                  simple_declaration
    |                               specialised_block_declaration
specialised_block_declaration::=      asm_definition
    |                               namespace_alias_definition
/*  |                               using_declaration                                           -- covered by simple_declaration /*/
    |                               using_directive
    |                               TEMPLATE specialised_block_declaration
simple_declaration::=                 ';'
    |                               init_declaration ';'
    |                               constructor_head ',' assignment_expression ';'
    |                               init_declarations ';'
    |                               decl_specifier_prefix simple_declaration

/*  A decl-specifier following a ptr_operator provokes a shift-reduce conflict for
 *      * const name
 *  which is resolved in favour of the pointer, and implemented by providing versions
 *  of decl-specifier guaranteed not to start with a cv_qualifier.
 *
 *  decl-specifiers are implemented type-centrically. That is the semantic constraint
 *  that there must be a type is exploited to impose structure, but actually eliminate
 *  very little syntax. built-in types are multi-name and so need a different policy.
 *
 *  non-type decl-specifiers are bound to the left-most type in a decl-specifier-seq,
 *  by parsing from the right and attaching suffixes to the right-hand type. Finally
 *  residual prefixes attach to the left.
 /*/
suffix_built_in_decl_specifier.raw::= built_in_type_specifier
    |                               suffix_built_in_decl_specifier.raw built_in_type_specifier
    |                               suffix_built_in_decl_specifier.raw decl_specifier_suffix
suffix_built_in_decl_specifier::=     suffix_built_in_decl_specifier.raw
    |                               TEMPLATE suffix_built_in_decl_specifier
suffix_named_decl_specifier::=        scoped_id
    |                               elaborate_type_specifier
    |                               suffix_named_decl_specifier decl_specifier_suffix
suffix_named_decl_specifier.bi::=     suffix_named_decl_specifier
    |                               suffix_named_decl_specifier suffix_built_in_decl_specifier.raw
suffix_named_decl_specifiers::=       suffix_named_decl_specifier.bi
    |                               suffix_named_decl_specifiers suffix_named_decl_specifier.bi
suffix_named_decl_specifiers.sf::=    scoped_special_function_id          /* operators etc /*/
    |                               suffix_named_decl_specifiers
    |                               suffix_named_decl_specifiers scoped_special_function_id
suffix_decl_specified_ids::=          suffix_built_in_decl_specifier
    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers.sf
    |                               suffix_named_decl_specifiers.sf
suffix_decl_specified_scope::=        suffix_named_decl_specifiers SCOPE
    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers SCOPE
    |                               suffix_built_in_decl_specifier SCOPE

decl_specifier_affix::=               storage_class_specifier
    |                               function_specifier
    |                               FRIEND
    |                               TYPEDEF
    |                               cv_qualifier
/*  The bogus conflict between public: as an anonymous bit-field and member-specification is resolved to the member-specification./*/
    |                               access_specifier            // %prec SHIFT_THERE
/*  using-declaration is generalised to cover a much more general concept of re-use, so using treated like typedef.
 *  Unfortunately this gives the same conflict on string as for linkage_specification, so the // %prec forces using followed
 *  by a string to be treated as an include rather than a declaration. /*/
    |                               USING                       // %prec SHIFT_THERE

decl_specifier_suffix::=              decl_specifier_affix
    |                               AUTO

decl_specifier_prefix::=              decl_specifier_affix
    |                               TEMPLATE decl_specifier_prefix

storage_class_specifier::=            REGISTER | STATIC | MUTABLE
    |                               EXTERN                  // %prec SHIFT_THERE                   /* Prefer linkage specification /*/
    |                               '!' STATIC

function_specifier::=                 EXPLICIT
    |                               INLINE                  // %prec SHIFT_THERE                   /* Prefer INLINE / IMPLEMENTATION /*/
    |                               VIRTUAL                 // %prec SHIFT_THERE                   /* Prefer VIRTUAL / PURE /*/
    |                               '!' INLINE
    |                               INLINE '/' IMPLEMENTATION
    |                               INLINE '/' INTERFACE
    |                               '!' VIRTUAL
    |                               VIRTUAL '/' PURE

type_specifier::=                     simple_type_specifier
    |                               elaborate_type_specifier
    |                               cv_qualifier
/* The following augment type_specifier rather than cv_qualifier to avoid a conflict on ! between
 *      a * ! const b     and    a * ! b    which requires a 2-token lookahead to resolve. /*/
    |                               '!' CONST
    |                               '!' VOLATILE

elaborate_type_specifier::=           class_specifier
    |                               enum_specifier
    |                               elaborated_type_specifier
    |                               TEMPLATE elaborate_type_specifier
simple_type_specifier::=              scoped_id
    |                               built_in_type_specifier
built_in_type_specifier::=            BuiltInTypeSpecifier

/*
 *  The over-general use of declaration_expression to cover decl-specifier-seq.opt declarator in a function-definition means that
 *      class X
 *  could be a function-definition or a class-specifier.
 *      enum X
 *  could be a function-definition or an enum-specifier.
 *  The function-definition is not syntactically valid so resolving the false conflict in favour of the
 *  elaborated_type_specifier is correct.
 /*/
elaborated_type_specifier::=          elaborated_class_specifier
    |                               elaborated_enum_specifier
    |                               TYPENAME scoped_id

elaborated_enum_specifier::=          ENUM scoped_id               // %prec SHIFT_THERE
enum_specifier::=                     ENUM scoped_id enumerator_clause
    |                               ENUM enumerator_clause
enumerator_clause::=                  '{' enumerator_list_ecarb
    |                               '{' enumerator_list enumerator_list_ecarb
    |                               '{' enumerator_list ',' enumerator_definition_ecarb
enumerator_list_ecarb::=              '}'
    |                               bang error_ecarb
enumerator_definition_ecarb::=        '}'
    |                               bang error_ecarb
enumerator_definition_filler::=       /* empty /*/
    |                               bang error ','
enumerator_list_head::=               enumerator_definition_filler
    |                               enumerator_list ',' enumerator_definition_filler
enumerator_list::=                    enumerator_list_head enumerator_definition
enumerator_definition::=              enumerator
    |                               enumerator '=' constant_expression
enumerator::=                         identifier

namespace_definition::=               NAMESPACE scoped_id compound_declaration
    |                               NAMESPACE compound_declaration
namespace_alias_definition::=         NAMESPACE scoped_id '=' scoped_id ';'
namespace_declaration::=              NAMESPACE scoped_id ';'

using_directive::=                    USING NAMESPACE scoped_id ';'
asm_definition::=                     ASM '(' string ')' ';'
linkage_specification::=              EXTERN string looping_declaration
/*   |                              EXTERN string compound_declaration                          -- covered by declaration /*/

/*---------------------------------------------------------------------------------------------------
 * A.7 Declarators
 *---------------------------------------------------------------------------------------------------/*/
/*init-declarator is named init_declaration to reflect the embedded decl-specifier-seq.opt/*/
init_declarations::=                  assignment_expression ',' init_declaration
    |                               init_declarations ',' init_declaration
    |                               init_object_declaration ',' init_declaration
    |                               constructor_head ',' bit_field_init_declaration
    |                               constructor_head ',' init_object_declaration
init_declaration::=                   assignment_expression
/*  |                               assignment_expression '=' initializer_clause                -- covered by assignment_expression /*/
/*  |                               assignment_expression '(' expression_list ')'               -- covered by another set of call arguments /*/
    |                               bit_field_init_declaration
    |                               init_object_declaration
init_object_declaration::=            assignment_expression object_statements_clause
    |                               bit_field_init_declaration object_statements_clause

/*declarator::=                                                                                   -- covered by assignment_expression /*/
/*direct_declarator::=                                                                            -- covered by postfix_expression /*/

star_ptr_operator::=                  '*'
    |                               star_ptr_operator cv_qualifier
nested_ptr_operator::=                star_ptr_operator
    |                               id_scope nested_ptr_operator
ptr_operator::=                       '&'
    |                               nested_ptr_operator
    |                               global_scope nested_ptr_operator
ptr_operator_seq::=                   ptr_operator
    |                               ptr_operator ptr_operator_seq
/* Independently coded to localise the shift-reduce conflict: sharing just needs another // %prec /*/
ptr_operator_seq.opt::=               /* empty /*/                         // %prec SHIFT_THERE       /* Maximise type length /*/
    |                               ptr_operator ptr_operator_seq.opt

cv_qualifier_seq.opt::=               /* empty /*/
    |                               cv_qualifier_seq.opt cv_qualifier
cv_qualifier::=                       CONST | VOLATILE /* | CvQualifier /*/

/*type_id                                                                                       -- also covered by parameter declaration /*/
type_id::=                            type_specifier abstract_declarator.opt
    |                               type_specifier type_id

/*abstract_declarator::=                                                                          -- also covered by parameter declaration /*/
abstract_declarator.opt::=            /* empty /*/
    |                               ptr_operator abstract_declarator.opt
    |                               direct_abstract_declarator
direct_abstract_declarator.opt::=     /* empty /*/
    |                               direct_abstract_declarator
direct_abstract_declarator::=         direct_abstract_declarator.opt parenthesis_clause
    |                               direct_abstract_declarator.opt '[' ']'
    |                               direct_abstract_declarator.opt '[' constant_expression ']'
/*  |                               '(' abstract_declarator ')'                                 -- covered by parenthesis_clause /*/

parenthesis_clause::=                 parameters_clause cv_qualifier_seq.opt
    |                               parameters_clause cv_qualifier_seq.opt exception_specification
parameters_clause::=                  '(' parameter_declaration_clause ')'
/* parameter_declaration_clause also covers init_declaration, type_id, declarator and abstract_declarator. /*/
parameter_declaration_clause::=       /* empty /*/
    |                               parameter_declaration_list
    |                               parameter_declaration_list ELLIPSIS
parameter_declaration_list::=         parameter_declaration
    |                               parameter_declaration_list ',' parameter_declaration

/* A typed abstract qualifier such as
 *      Class * ...
 * looks like a multiply, so pointers are parsed as their binary operation equivalents that
 * ultimately terminate with a degenerate right hand term.
 /*/
abstract_pointer_declaration::=       ptr_operator_seq
    |                               multiplicative_expression star_ptr_operator ptr_operator_seq.opt
abstract_parameter_declaration::=     abstract_pointer_declaration
    |                               and_expression '&'
    |                               and_expression '&' abstract_pointer_declaration
special_parameter_declaration::=      abstract_parameter_declaration
    |                               abstract_parameter_declaration '=' assignment_expression
    |                               ELLIPSIS
parameter_declaration::=              assignment_expression
    |                               special_parameter_declaration
    |                               decl_specifier_prefix parameter_declaration

/*  The grammar is repeated for use within template <>
 /*/
templated_parameter_declaration::=    templated_assignment_expression
    |                               templated_abstract_declaration
    |                               templated_abstract_declaration '=' templated_assignment_expression
    |                               decl_specifier_prefix templated_parameter_declaration
templated_abstract_declaration::=     abstract_pointer_declaration
    |                               templated_and_expression '&'
    |                               templated_and_expression '&' abstract_pointer_declaration

/*  function_definition includes constructor, destructor, implicit int definitions too.
 *  A local destructor is successfully parsed as a function-declaration but the ~ was treated as a unary operator.
 *  constructor_head is the prefix ambiguity between a constructor and a member-init-list starting with a bit-field.
 /*/
function_definition::=        ctor_definition
    |                       func_definition
func_definition::=            assignment_expression function_try_block
    |                       assignment_expression function_body
    |                       decl_specifier_prefix func_definition
ctor_definition::=            constructor_head function_try_block
    |                       constructor_head function_body
    |                       decl_specifier_prefix ctor_definition
constructor_head::=           bit_field_init_declaration
    |                       constructor_head ',' assignment_expression
function_try_block::=         TRY function_block handler_seq
function_block::=             ctor_initializer.opt function_body
function_body::=              compound_statement

/*  An = initializer looks like an extended assignment_expression.
 *  An () initializer looks like a function call.
 *  initializer is therefore flattened into its generalised customers.
 *initializer:              '=' initializer_clause                                      -- flattened into caller
 *  |                       '(' expression_list ')'                                     -- flattened into caller /*/
initializer_clause::=         assignment_expression
    |                       braced_initializer
braced_initializer::=         '{' initializer_list '}'
    |                       '{' initializer_list ',' '}'
    |                       '{' '}'
    |                       '{' looping_initializer_clause '#' bang error_ecarb
    |                       '{' initializer_list ',' looping_initializer_clause '#' bang error_ecarb
initializer_list::=           looping_initializer_clause
    |                       initializer_list ',' looping_initializer_clause
looping_initializer_clause::= start_search looped_initializer_clause
looped_initializer_clause::=  initializer_clause
    |                       advance_search '+' looped_initializer_clause
    |                       advance_search '-'

/*---------------------------------------------------------------------------------------------------
 * A.8 Classes
 *---------------------------------------------------------------------------------------------------
 *
 *  An anonymous bit-field declaration may look very like inheritance:
 *      class A : B = 3
 *      class A : B
 *  The two usages are too distant to try to create and enforce a common prefix so we have to resort to
 *  a parser hack by backtracking. Inheritance is much the most likely so we mark the input stream context
 *  and try to parse a base-clause. If we successfully reach a { the base-clause is ok and inheritance was
 *  the correct choice so we unmark and continue. If we fail to find the { an error token causes back-tracking
 *  to the alternative parse in elaborated_class_specifier which regenerates the : and declares unconditional success.
 /*/
colon_mark::=                 ':'
elaborated_class_specifier::= class_key scoped_id                    // %prec SHIFT_THERE
    |                       class_key scoped_id colon_mark error
class_specifier_head::=       class_key scoped_id colon_mark base_specifier_list '{'
    |                       class_key ':' base_specifier_list '{'
    |                       class_key scoped_id '{'
    |                       class_key '{'
class_key::=                  CLASS | STRUCT | UNION
class_specifier::=            class_specifier_head nest declaration_seq.opt '}'
    |                       class_specifier_head nest declaration_seq.opt util looping_declaration '#' bang error_ecarb
accessibility_specifier::=    access_specifier ':'
bit_field_declaration::=      assignment_expression ':' bit_field_width
    |                       ':' bit_field_width
bit_field_width::=            logical_or_expression
/*  |                       logical_or_expression '?' expression ':' assignment_expression  -- has SR conflict w.r.t later = /*/
    |                       logical_or_expression '?' bit_field_width ':' bit_field_width
bit_field_init_declaration::= bit_field_declaration
    |                       bit_field_declaration '=' initializer_clause

/*---------------------------------------------------------------------------------------------------
 * A.9 Derived classes
 *---------------------------------------------------------------------------------------------------/*/
/*base_clause::=              ':' base_specifier_list                                     -- flattened /*/
base_specifier_list::=        base_specifier
    |                       base_specifier_list ',' base_specifier
base_specifier::=             scoped_id
    |                       access_specifier base_specifier
    |                       VIRTUAL base_specifier
    |                       '!' VIRTUAL base_specifier
    |                       AUTO base_specifier
    |                       built_in_type_id
access_specifier::=           PRIVATE | PROTECTED | PUBLIC

/*---------------------------------------------------------------------------------------------------
 * A.10 Special member functions
 *---------------------------------------------------------------------------------------------------/*/
conversion_function_id::=     OPERATOR conversion_type_id
conversion_type_id::=         type_specifier ptr_operator_seq.opt
    |                       type_specifier conversion_type_id
/*
 *  Ctor-initialisers can look like a bit field declaration, given the generalisation of names:
 *      Class(Type) : m1(1), m2(2)
 *      NonClass(bit_field) : int(2), second_variable, ...
 *  The grammar below is used within a function_try_block or function_definition.
 *  See simple_member_declaration for use in normal member function_definition.
 /*/
ctor_initializer.opt::=       /* empty /*/
    |                       ctor_initializer
ctor_initializer::=           ':' mem_initializer_list
    |                       ':' mem_initializer_list bang error
mem_initializer_list::=       mem_initializer
    |                       mem_initializer_list_head mem_initializer
mem_initializer_list_head::=  mem_initializer_list ','
    |                       mem_initializer_list bang error ','
    |                       mem_initializer_list bang error '#'
mem_initializer::=            mem_initializer_id '(' expression_list.opt ')'
mem_initializer_id::=         scoped_id

/*---------------------------------------------------------------------------------------------------
 * A.11 Overloading
 *---------------------------------------------------------------------------------------------------/*/
operator_function_id::=       OPERATOR operator
/*
 *  It is not clear from the ANSI standard whether spaces are permitted in delete[]. If not then it can
 *  be recognised and returned as DELETE_ARRAY by the lexer. Assuming spaces are permitted there is an
 *  ambiguity created by the over generalised nature of expressions. operator new is a valid delarator-id
 *  which we may have an undimensioned array of. Semantic rubbish, but syntactically valid. Since the
 *  array form is covered by the declarator consideration we can exclude the operator here. The need
 *  for a semantic rescue can be eliminated at the expense of a couple of shift-reduce conflicts by
 *  removing the comments on the next four lines.
 /*/
operator::=             /*++++/*/      NEW
    |                 /*++++/*/      DELETE
/*  |                 / ---- /      NEW                 // %prec SHIFT_THERE
/*  |                 / ---- /      DELETE              // %prec SHIFT_THERE
/*  |                 / ---- /      NEW '[' ']'                                                 -- Covered by array of OPERATOR NEW /*/
/*  |                 / ---- /      DELETE '[' ']'                                              -- Covered by array of OPERATOR DELETE /*/
    |                               '+'
    |                               '-'
    |                               '*'
    |                               '/'
    |                               '%'
    |                               '^'
    |                               '&'
    |                               '|'
    |                               '~'
    |                               '!'
    |                               '='
    |                               '<'
    |                               '>'
    |                               ASS_ADD
    |                               ASS_SUB
    |                               ASS_MUL
    |                               ASS_DIV
    |                               ASS_MOD
    |                               ASS_XOR
    |                               ASS_AND
    |                               ASS_OR
    |                               SHL
    |                               SHR
    |                               ASS_SHR
    |                               ASS_SHL
    |                               EQ
    |                               NE
    |                               LE
    |                               GE
    |                               LOG_AND
    |                               LOG_OR
    |                               INC
    |                               DEC
    |                               ','
    |                               ARROW_STAR
    |                               ARROW
    |                               '(' ')'
    |                               '[' ']'

/*---------------------------------------------------------------------------------------------------
 * A.12 Templates
 *---------------------------------------------------------------------------------------------------/*/
template_declaration::=               template_parameter_clause declaration
    |                               EXPORT template_declaration
/*  This extension is only defined for USING, but we need to use decl_specifier_prefix to avoid conflicts. /*/
    |                               decl_specifier_prefix template_declaration
template_parameter_clause::=          TEMPLATE '<' template_parameter_list '>'
template_parameter_list::=            template_parameter
    |                               template_parameter_list ',' template_parameter
template_parameter::=                 simple_type_parameter
    |                               simple_type_parameter '=' type_id
    |                               templated_type_parameter
    |                               templated_type_parameter '=' identifier
    |                               templated_parameter_declaration
    |                               bang error
simple_type_parameter::=              CLASS
/*  |                               CLASS identifier                                            -- covered by parameter_declaration /*/
    |                               TYPENAME
/*  |                               TYPENAME identifier                                         -- covered by parameter_declaration /*/
templated_type_parameter::=           template_parameter_clause CLASS
    |                               template_parameter_clause CLASS identifier
template_id::=                        TEMPLATE identifier '<' template_argument_list '>'
    |                               TEMPLATE template_id
/*
 *  template-argument is evaluated using a templated...expression so that > resolves to end of template.
 /*/
template_argument_list::=             template_argument
    |                               template_argument_list ',' template_argument
template_argument::=                  templated_parameter_declaration
/*  |                               type_id                                                     -- covered by templated_parameter_declaration /*/
/*  |                               template_name                                               -- covered by templated_parameter_declaration /*/
/*  |                               error                                                       -- must allow template failure to re-search /*/

/*
 *  Generalised naming makes identifier a valid declaration, so TEMPLATE identifier is too.
 *  The TEMPLATE prefix is therefore folded into all names, parenthesis_clause and decl_specifier_prefix.
 /*/
/*explicit_instantiation::=           TEMPLATE declaration /*/
explicit_specialization::=            TEMPLATE '<' '>' declaration
/*  This extension is only defined for USING, but we need to use decl_specifier_prefix to avoid conflicts. /*/
    |                               decl_specifier_prefix explicit_specialization

/*---------------------------------------------------------------------------------------------------
 * A.13 Exception Handling
 *---------------------------------------------------------------------------------------------------/*/
try_block::=                          TRY compound_statement handler_seq
/*function_try_block::=                                                                           -- moved near function_block /*/
/* A handler_seq may follow a try_block in a compound_tree_statement such as:
 *      if (a) try  catch(a)  catch(b)  catch(c)  ...
 *  we resolve the conflict by maximising the handler sequence. /*/
handler_seq::=                        handler                                 // %prec SHIFT_THERE   /* Maximise length /*/
    |                               handler handler_seq
handler::=                            CATCH '(' exception_declaration ')' compound_statement
exception_declaration::=              parameter_declaration
/*                                  ELLIPSIS                                                    -- covered by parameter_declaration /*/
throw_expression::=                   THROW
    |                               THROW assignment_expression
templated_throw_expression::=         THROW
    |                               THROW templated_assignment_expression
exception_specification::=            THROW '(' ')'
    |                               THROW '(' type_id_list ')'
type_id_list::=                       type_id
    |                               type_id_list ',' type_id

/*---------------------------------------------------------------------------------------------------
 * A.14 Tree literals
 *---------------------------------------------------------------------------------------------------/*/
primary_tree_expression::=            meta_scoped_id
    |                               '(' tree_expression ')'
postfix_tree_expression::=            primary_tree_expression
    |                               postfix_tree_expression '[' ']'
    |                               postfix_tree_expression '[' constant_expression ']'
    |                               postfix_tree_expression '(' tree_argument_list.opt ')'
    |                               postfix_tree_expression '.' scoped_id
    |                               postfix_tree_expression ARROW scoped_id
tree_expression::=                    postfix_tree_expression
    |                               '*' tree_expression

/* tree_argument_list.opt are carefully coded to avoid conflicts between the components of a constructor_head at the start of a function_definition
 * and the equivalent discrete elements. There is no need to resolve a conflict on ","!, which is fortunate because it couldn't work. /*/
tree_argument_list.opt::=             tree_arguments.head
    |                               tree_arguments.head ',' tree_argument_list.opt
    |                               tree_argument.ctors
tree_argument.ctors::=                constructor_head
    |                               decl_specifier_prefix tree_argument.ctors
tree_arguments.head::=                /* empty /*/
    |                               tree_argument.most
    |                               assignment_expression
    |                               func_definition
    |                               tree_argument.ctors_comma_most
tree_argument.ctors_comma_most::=     constructor_head ',' tree_argument.most
    |                               decl_specifier_prefix tree_argument.ctors_comma_most
tree_argument.most::=                 terminated_tree_argument
    |                               ctor_definition
    |                               unterminated_tree_argument.most
    |                               unterminated_tree_argument.most ';'
    |                               tree_argument.misc
    |                               tree_argument.misc ';'
tree_argument.misc::=                 decl_specifier_prefix
/*  |                               assignment_expression                                       -- separated out /*/
/*  |                               bit_field_init_declaration                                  -- separated out into tree_argument.ctors /*/
/*  |                               function_definition                                         -- split into ctor/func_definition /*/
    |                               init_object_declaration
    |                               special_parameter_declaration
    |                               decl_specifier_prefix assignment_expression
    |                               decl_specifier_prefix tree_argument.misc

looping_unterminated_tree_argument::= start_search looped_unterminated_tree_argument
looped_unterminated_tree_argument::=  unterminated_tree_argument
    |                               advance_search '+' looped_unterminated_tree_argument
/*  |                               advance_search '-'                                           /*/
/* Omission of the preceding line which causes two reduce/reduce conflicts is justified provided the
 * looped_unterminated_tree_argument rules are only used within a compound_tree_statement, where the alternate
 * looping search for a tree_statement precedes and dominates this search. Since the cascaded advance_search '-'
 * is only used to terminate a total failure of the search for a plausible template/arithmetic syntax, it doesn't
 * matter, apart from minor error reporting niceties, whether it is the statement or unterminated argument search
 * that is deemed to have failed.
 /*/
looping_tree_statement::=             start_search looped_tree_statement
looped_tree_statement::=              tree_statement
    |                               advance_search '+' looped_tree_statement
    |                               advance_search '-'
tree_statement::=                     ';'
    |                               terminated_tree_argument
    |                               unterminated_tree_argument ';'
    |                               function_definition
compound_tree_statement::=            '{' tree_statement_seq.opt '}'
    |                               '{' tree_statement_seq.opt looping_unterminated_tree_argument '}'
    |                               '{' tree_statement_seq.opt looping_unterminated_tree_argument '#' bang error_ecarb
    |                               '{' tree_statement_seq.opt looping_tree_statement '#' bang error_ecarb
tree_statement_seq.opt::=             /* empty /*/
    |                               tree_statement_seq.opt looping_tree_statement
    |                               tree_statement_seq.opt looping_tree_statement '#' bang error ';'

/*  Terminated syntax has an unambiguous end and does not need a ; as a meta-variable initializer. /*/
terminated_tree_argument::=           asm_definition
    |                               compound_tree_statement
/*  |                               declaration_statement ';'                   -- covered by simple_tree_declaration ; /*/
/*  |                               explicit_instantiation                      -- covered by simple_tree_declaration ; /*/
    |                               explicit_specialization
/*  |                               expression_statement ';'                    -- covered by simple_tree_declaration ; /*/
    |                               file_dependency_declaration
    |                               file_placement_declaration
    |                               include_declaration semi
    |                               iteration_statement
/*  |                               jump_statement                              -- covered by BREAK ; /*/
    |                               labeled_statement
    |                               linkage_specification
    |                               namespace_alias_definition
    |                               namespace_declaration
    |                               namespace_definition
/*  |                               parameter_declaration ';'                   -- covered by simple_tree_declaration ; /*/
    |                               selection_statement
    |                               template_declaration
    |                               using_directive
    |                               AUTO meta_control_statement
    |                               AUTO meta_expression_statement
    |                               AUTO meta_function_definition
    |                               OPERATOR ';'

/*  Unterminated syntax has no obvious end and/or must have a ; as a meta-variable initializer. /*/
unterminated_tree_argument::=         unterminated_tree_argument.most
    |                               simple_tree_declaration
unterminated_tree_argument.most::=    accessibility_specifier
/*  |                               access_specifier                            -- covered by decl_specifier_affix /*/
/*  |                               base_specifier                              -- covered by simple_tree_declaration /*/
/*  |                               built_in_type_specifier                     -- covered by simple_tree_declaration /*/
/*  |                               class_specifier                             -- covered by simple_tree_declaration /*/
/*  |                               condition                                   -- covered by simple_tree_declaration /*/
/*  |                               cv_qualifier                                -- covered by simple_tree_declaration /*/
/*  |                               decl_specifier                              -- covered by simple_tree_declaration /*/
/*  |                               enum_specifier                              -- covered by simple_tree_declaration /*/
/*  |                               enumerator_definition                       -- covered by simple_tree_declaration /*/
/*  |                               exception_declaration                       -- covered by simple_tree_declaration /*/
/*  |                               exception_specification                     -- covered by simple_tree_declaration /*/
    |                               filespace_specifier
/*  |                               function_definition                         -- not part of .most /*/
    |                               function_try_block
    |                               handler_seq
/*  |                               initializer_clause                          -- covered by simple_tree_declaration, compound_statement /*/
/*  |                               mem_initializer                             -- covered by simple_tree_declaration /*/
    |                               AUTO meta_class_specifier
/*  |                               operator                                    -- mostly covered by token.punct /*/
/*  |                               parameter_declaration                       -- not part of .most /*/
/*  |                               simple_tree_declaration                     -- not part of .most /*/
    |                               simple_type_parameter
/*  |                               storage_class_specifier                     -- covered by simple_tree_declaration /*/
/*  |                               template_argument                           -- covered by simple_tree_declaration /*/
/*  |                               template_parameter                          -- covered by simple_tree_declaration /*/
/*  |                               try_block                                   -- covered by function_try_block /*/
/*  |                               type_id                                     -- covered by simple_tree_declaration /*/
/*  |                               type_parameter                              -- covered by simple_tree_declaration, template_declaration /*/
    |                               reserved_id
    |                               token.punct
    |                               AUTO
/*  |                               CATCH                                       -- awkward function-definition at end of terminated  /*/
/*  |                               CLASS                                       -- covered by simple_type_parameter /*/
/*  |                               DO                                          -- DO ; awkward /*/
    |                               ENUM
    |                               NAMESPACE
/*  |                               OPERATOR                                    -- OPERATOR , awkward /*/
    |                               STRUCT
    |                               TEMPLATE
/*  |                               THROW                                       -- covered by throw-expression /*/
/*  |                               TYPENAME                                    -- covered by simple_type_parameter /*/
    |                               UNION
/*  |                               '*' | '&' | ELLIPSIS                        -- covered by simple_tree_declaration /*/
/*  |                               '#'                                         -- used as error iteration flag /*/
/*  |                               ',' | '{' | '}' | '(' | ')' | ';'           -- awkward - major punctuation /*/
/*  |                               '/'                                         -- awkward looks like switch /*/
reserved_id::=                        ASM | BREAK | CASE | CONST_CAST | CONTINUE | DEFAULT | DELETE | DYNAMIC_CAST | ELSE | FOR
    |                               GOTO | IF | NEW | REINTERPRET_CAST | RETURN | SIZEOF | STATIC_CAST | SWITCH | TRY | TYPEID | WHILE
    |                               EXPORT
token.punct::=                        SCOPE | SHL | SHR | EQ | NE | LE | GE | LOG_AND | LOG_OR | INC | DEC | ARROW | ARROW_STAR | DOT_STAR
    |                               ASS_ADD | ASS_AND | ASS_DIV | ASS_MOD | ASS_MUL | ASS_OR | ASS_SHL | ASS_SHR | ASS_SUB | ASS_XOR
    |                               '[' | ']' | ':' | '?' | '.'
    |                               '+' | '-' | '%' | '^' | '|' | '~' | '!' | '=' | '<' | '>'
    |                               "'" | '"' | '\\'
    |                               '@' | '$'

simple_tree_declaration::=            decl_specifier_prefix
    |                               init_declaration
    |                               constructor_head ',' assignment_expression
    |                               init_declarations
    |                               special_parameter_declaration
    |                               decl_specifier_prefix simple_tree_declaration

/*---------------------------------------------------------------------------------------------------
 * A.15 Object statements
 *---------------------------------------------------------------------------------------------------/*/
object_statements_clause::=           ':' '{' object_statement_seq.opt '}'
    |                               ':' '{' object_statement_seq.opt looping_object_statement '#' bang error_ecarb
object_statement_seq.opt::=           /* empty /*/
    |                               object_statement_seq.opt looping_object_statement
    |                               object_statement_seq.opt looping_object_statement '#' bang error ';'
looping_object_statement::=           start_search looped_object_statement
looped_object_statement::=            object_statement
    |                               advance_search '+' looped_object_statement
    |                               advance_search '-'
object_statement::=                   ';'
    |                               function_used_block
    |                               '=' initializer_clause ';'
    |                               '(' expression_list ')' ';'
    |                               file_dependency_declaration
    |                               file_placement_declaration
    |                               filespace_specifier semi
    |                               meta_control_statement
    |                               AUTO meta_control_statement
    |                               AUTO meta_expression_statement
    |                               AUTO meta_function_definition
    |                               derived_clause object_statement
    |                               derived_clause ':' '{' object_statement_seq.opt '}'
    |                               derived_clause ':' '{' object_statement_seq.opt looping_object_statement '#' bang error '#'
function_used_block::=                function_block
    |                               function_try_block
    |                               ctor_initializer ';'
    |                               USING file_id_list function_used_block
    |                               segment function_used_block
segment::=                            BODY
    |                               ENTRY
    |                               EXIT
    |                               POST
    |                               PRE

/*---------------------------------------------------------------------------------------------------
 * A.16 Derivation rules
 *---------------------------------------------------------------------------------------------------/*/
derived_clause::=                     DERIVED '(' meta_conditional_expression ')'

/*---------------------------------------------------------------------------------------------------
 * A 17.1 meta-names
 *---------------------------------------------------------------------------------------------------/*/
meta_id::=                            id
    |                               meta_simple_type
    |                               AUTO
meta_scope::=                         meta_id SCOPE
meta_nested_id::=                     meta_id
    |                               meta_scope '~' meta_id
    |                               meta_scope meta_nested_id
meta_scoped_id::=                     meta_nested_id
    |                               global_scope meta_nested_id

/*---------------------------------------------------------------------------------------------------
 * A 17.2 meta-classes
 *---------------------------------------------------------------------------------------------------/*/
meta_class_specifier::=               meta_class_key meta_nested_id compound_declaration
    |                               meta_class_key meta_nested_id ':' base_specifier_list compound_declaration

/*---------------------------------------------------------------------------------------------------
 * A 17.3 meta-types
 *---------------------------------------------------------------------------------------------------
 *  The MetaType names are not reserved words so form part of identifier and consequently scoped_id /*/
/* The // %prec maximises the length of e.g. unsigned int when followed by e.g int::a /*/
meta_class_key::=                     class_key
    |                               NAMESPACE
meta_non_class_key::=                 ENUM
    |                               TYPEDEF
    |                               TYPENAME
    |                               USING
    |                               built_in_type_id                // %prec SHIFT_THERE
meta_simple_type::=                   meta_class_key
    |                               meta_non_class_key
meta_type::=                          MetaType
    |                               meta_simple_type

/*---------------------------------------------------------------------------------------------------
 * A 17.4 meta-variables
 *---------------------------------------------------------------------------------------------------/*/
/*meta_variable_declaration::=                                                                    -- covered by meta_expression_statement /*/

/*---------------------------------------------------------------------------------------------------
 * A 17.5 meta-functions, meta-constructors and meta-destructors
 *---------------------------------------------------------------------------------------------------/*/
/*          meta_postfix_expression covers the function name, tree_argument_list.opt covers the parameter list /*/
/*          meta_postfix_expression also covers the function name(tree_argument_list.opt) for exposed list /*/
meta_function_definition::=           meta_fn_postfix_expression compound_tree_statement
    |                               '~' meta_fn_postfix_expression compound_tree_statement
    |                               CONST meta_function_definition
    |                               STATIC meta_function_definition
    |                               '!' STATIC meta_function_definition
/*  |                               meta_postfix_expression '(' tree_argument_list.opt ')' object_statements_clause
                                                                                                -- covered by meta_expression_statement /*/

/*---------------------------------------------------------------------------------------------------
 * A 17.6 meta-statements
 *---------------------------------------------------------------------------------------------------/*/
meta_control_statement::=             line meta_control_statement1
meta_control_statement1::=            CASE constant_expression ':' lined_declaration
    |                               DEFAULT ':' lined_declaration
    |                               DO lined_declaration WHILE '(' expression ')' semi
    |                               IF '(' condition ')' lined_declaration     // %prec SHIFT_THERE
    |                               IF '(' condition ')' lined_declaration ELSE lined_declaration
    |                               SWITCH '(' expression ')' lined_declaration
    |                               WHILE '(' condition ')' lined_declaration
    |                               FOR '(' for_init_statement condition.opt ';' expression.opt ')' lined_declaration
    |                               jump_statement

/*---------------------------------------------------------------------------------------------------
 * A 17.7 meta-expressions
 *---------------------------------------------------------------------------------------------------/*/
meta_primary_head::=                  meta_scoped_id
    |                               MetaType meta_nested_id
    |                               meta_non_class_key meta_nested_id
meta_primary_id::=                    meta_primary_head
    |                               meta_class_key meta_nested_id
meta_primary_expression::=            literal
    |                               THIS
    |                               meta_primary_id
    |                               '(' tree_argument_list.opt ')'
meta_fn_postfix_expression::=         meta_postfix_expression '(' tree_argument_list.opt ')'
    |                               meta_postfix_expression '[' ']'
meta_postfix_expression::=            meta_primary_expression
    |                               meta_fn_postfix_expression
    |                               meta_postfix_expression '[' expression ']'
    |                               meta_postfix_expression '.' declarator_id
    |                               meta_postfix_expression ARROW declarator_id
    |                               meta_postfix_expression INC
    |                               meta_postfix_expression DEC
meta_unary_expression::=              meta_postfix_expression
    |                               INC meta_cast_expression
    |                               DEC meta_cast_expression
    |                               star_ptr_operator meta_cast_expression
    |                               '&' meta_cast_expression
    |                               '+' meta_cast_expression
    |                               '-' meta_cast_expression
    |                               '!' meta_cast_expression
    |                               '~' meta_cast_expression
    |                               SIZEOF unary_expression
meta_cast_expression::=               meta_unary_expression
meta_pm_expression::=                 meta_cast_expression
meta_multiplicative_expression::=     meta_pm_expression
    |                               meta_multiplicative_expression star_ptr_operator meta_pm_expression
    |                               meta_multiplicative_expression '/' meta_pm_expression
    |                               meta_multiplicative_expression '%' meta_pm_expression
meta_additive_expression::=           meta_multiplicative_expression
    |                               meta_additive_expression '+' meta_multiplicative_expression
    |                               meta_additive_expression '-' meta_multiplicative_expression
meta_shift_expression::=              meta_additive_expression
    |                               meta_shift_expression SHL meta_additive_expression
    |                               meta_shift_expression SHR meta_additive_expression
meta_relational_expression::=         meta_shift_expression
    |                               meta_relational_expression '<' meta_shift_expression
    |                               meta_relational_expression '>' meta_shift_expression
    |                               meta_relational_expression LE meta_shift_expression
    |                               meta_relational_expression GE meta_shift_expression
meta_equality_expression::=           meta_relational_expression
    |                               meta_equality_expression EQ meta_relational_expression
    |                               meta_equality_expression NE meta_relational_expression
meta_and_expression::=                meta_equality_expression
    |                               meta_and_expression '&' meta_equality_expression
meta_exclusive_or_expression::=       meta_and_expression
    |                               meta_exclusive_or_expression '^' meta_and_expression
meta_inclusive_or_expression::=       meta_exclusive_or_expression
    |                               meta_inclusive_or_expression '|' meta_exclusive_or_expression
meta_logical_and_expression::=        meta_inclusive_or_expression
    |                               meta_logical_and_expression LOG_AND meta_inclusive_or_expression
meta_logical_or_expression::=         meta_logical_and_expression
    |                               meta_logical_or_expression LOG_OR meta_logical_and_expression
meta_conditional_expression::=        meta_logical_or_expression
    |                               meta_logical_or_expression '?' meta_conditional_expression ':' meta_conditional_expression
meta_expression_statement::=          meta_conditional_expression semi
    |                               meta_primary_head object_statements_clause semi
    |                               meta_class_key meta_nested_id object_statements_clause semi
    |                               meta_postfix_expression '(' tree_argument_list.opt ')' object_statements_clause semi
    |                               meta_postfix_expression '[' ']' object_statements_clause semi
    |                               meta_postfix_expression '[' expression ']' object_statements_clause semi
    |                               meta_logical_or_expression assignment_operator line tree_statement
    |                               CONST meta_expression_statement
    |                               STATIC meta_expression_statement
    |                               '!' STATIC meta_expression_statement

/*---------------------------------------------------------------------------------------------------
 * A 18 Syntax macros
 *---------------------------------------------------------------------------------------------------/*/
syntax_macro_definition::=            EXPLICIT AUTO meta_type identifier '(' syntax_macro_parameter_list ')' compound_tree_statement
    |                               EXPLICIT AUTO meta_type identifier '(' syntax_macro_parameter_list ')' '[' ']' compound_tree_statement
    |                               EXPLICIT AUTO meta_type identifier '(' ')' compound_tree_statement
    |                               EXPLICIT AUTO meta_type identifier  '(' ')' '[' ']' compound_tree_statement
syntax_macro_parameter_list::=        syntax_macro_parameter
    |                               syntax_macro_parameter_list ',' syntax_macro_parameter
syntax_macro_parameter::=             meta_type identifier
    |                               meta_type identifier '[' ']'
    |                               identifier
    |                               reserved_id
    |                               token.punct
    |                               ';'
    |                               ','
    |                               '{'
    |                               '}'
    |                               '('
    |                               ')'
    |                               bang error

/*---------------------------------------------------------------------------------------------------
 * A 19 files
 *---------------------------------------------------------------------------------------------------/*/
include_declaration::=                USING string
    |                               USING '/' INCLUDE string_expr
    |                               USING '/' INCLUDE '/' utility string_expr
    |                               USING '/' utility string_expr
utility::=                            EMIT
    |                               FROZEN
    |                               POOL
    |                               UTILITY

file_dependency_declaration::=        using_implementation semi
    |                               using_interface semi
using_implementation::=               USING '/' IMPLEMENTATION file_use
    |                               USING '/' IMPLEMENTATION '=' file_use
using_interface::=                    USING '/' INTERFACE file_use
    |                               USING '/' INTERFACE '=' file_use
file_use::=                           file_id
    |                               file_entity

file_placement_declaration::=         export_implementation semi
    |                               export_interface semi
    |                               export_all semi
    |                               EXPORT '/' NOIMPLEMENTATION semi
    |                               EXPORT '/' UTILITY semi
export_implementation::=              EXPORT '/' IMPLEMENTATION implementation_file
    |                               EXPORT '/' IMPLEMENTATION '=' implementation_file
export_interface::=                   EXPORT '/' INTERFACE interface_file
    |                               EXPORT '/' INTERFACE '=' interface_file
export_all::=                         EXPORT '/' ALL interface_file
    |                               EXPORT '/' ALL '=' interface_file
implementation_file::=                file_id
    |                               file_entity
interface_file::=                     file_id
    |                               file_entity

file_name::=                          string
    |                               file_name '/' INTERFACE
    |                               file_name '/' IMPLEMENTATION
    |                               file_name '/' TEMPLATE
    |                               file_name '/' utility
    |                               file_name '/' GUARD '=' string_expr
    |                               file_name '/' NOGUARD
    |                               file_name '/' PATH '=' string_expr
    |                               file_name '/' PREFIX '=' string_expr
    |                               file_name '/' SUFFIX '=' string_expr
file_entity::=                        declarator_id
    |                               elaborated_type_specifier
    |                               NAMESPACE scoped_id
file_id::=                            file_name
    |                               file_entity '/' IMPLEMENTATION
    |                               file_entity '/' INTERFACE
file_id_list::=                       file_id
    |                               file_id_list ',' file_id

filespace_specifier::=                NAMESPACE '/' FILE file_name compound_declaration

/*---------------------------------------------------------------------------------------------------
 * Error handling aids
 *---------------------------------------------------------------------------------------------------/*/
ecarb::=                              '}'
    |                               '#'
    |                               bang error '}'
    |                               bang error ')'
    |                               bang error '#'
semi::=                               ';'
    |                               '#'
    |                               bang error_semi
error_ecarb::=                        error '}'
    |                               error '#'
error_semi::=                         error ';'
    |                               error '#'

/*---------------------------------------------------------------------------------------------------
 * Back-tracking and context support
 *---------------------------------------------------------------------------------------------------/*/
advance_search::=                     error                /* Rewind and queue '+' or '-' '#' /*/
bang::=                               /* empty /*/            /* set flag to suppress "parse error" /*/
line::=                               /* empty /*/                            /* Get current line context /*/
mark::=                               /* empty /*/                 /* Push lookahead and input token stream context onto a stack /*/
nest::=                               /* empty /*/                 /* Push a declaration nesting depth onto the parse stack /*/
start_search::=                       /* empty /*/             /* Create/reset binary search context /*/
start_search1::=                      /* empty /*/              /* Create/reset binary search context /*/
util::=                               /* empty /*/                    /* Get current utility mode /*/
/*StartDiscard/*/

// Tokens

SCOPE ::= "::"
ELLIPSIS ::= "..."
SHL ::= "<<"
SHR ::= ">>"
EQ ::= "=="
NE ::= "!="
LE ::= "<="
GE ::= ">="
LOG_AND ::= "&&"
LOG_OR ::= "||"
INC ::= "++"
DEC ::= "--"
ARROW_STAR ::= "->*"
ARROW ::= "->"
DOT_STAR ::= ".*"
ASS_ADD ::= "+="
ASS_SUB ::= "-="
ASS_MUL ::= "*="
ASS_DIV ::= "/="
ASS_MOD ::= "%="
ASS_XOR ::= "^="
ASS_AND ::= "&="
ASS_OR ::= "|="
ASS_SHR ::= ">>="
ASS_SHL ::= "<<="

HASH_BLANK ::= "# "
HASH_DEFINE ::= "#define"
HASH_ELIF ::= "#elif"
HASH_ELSE ::= "#else"
HASH_ENDIF ::= "#endif"
HASH_ERROR ::= "#error"
HASH_IF ::= "#if"
HASH_IFDEF ::= "#ifdef"
HASH_IFNDEF ::= "#ifndef"
HASH_INCLUDE ::= "#include"
HASH_LINE ::= "#line"
HASH_PRAGMA ::= "#pragma"
HASH_UNDEF ::= "#undef"
//
HASH_HASH ::= "##"
DI_HASH_HASH ::= "%:%:"
DI_HASH ::= "%:"
DI_SQUARE ::= "<:"
DI_ERAUQS ::= ":>"
DI_ECARB ::= "%>"
//
DEFINED ::= "-DEFINED-"
DO_FUNCTION ::= "-DO_FUNCTION-"
//
//          BANG ::= "-BANG-"
ERROR ::= "-ERROR-"
NIL ::= "-NIL-"
//          RAMMARG ::= "-RAMMARG-"
//

ASM ::= "asm"
BREAK ::= "break"
CASE ::= "case"
CATCH ::= "catch"
CONST_CAST ::= "const_cast"
CONTINUE ::= "continue"
DEFAULT ::= "default"
DELETE ::= "delete"
DO ::= "do"
DYNAMIC_CAST ::= "dynamic_cast"
ELSE ::= "else"
FALSE ::= "false"
FOR ::= "for"
GOTO ::= "goto"
IF ::= "if"
NEW ::= "new"
OPERATOR ::= "operator"
REINTERPRET_CAST ::= "reinterpret_cast"
RETURN ::= "return"
SIZEOF ::= "sizeof"
STATIC_CAST ::= "static_cast"
SWITCH ::= "switch"
THIS ::= "this"
THROW ::= "throw"
TRUE ::= "true"
TRY ::= "try"
TYPEID ::= "typeid"
WHILE ::= "while"
//
LOG_AND ::= "and"
ASS_AND ::= "and_eq"
NE ::= "not_eq"
LOG_OR ::= "or"
ASS_OR ::= "or_eq"
ASS_XOR ::= "xor_eq"
//
//character('&') ::= "bitand"
//character('|') ::= "bitor"
//character('~') ::= "compl"
//character('!') ::= "not"
//character('^') ::= "xor"

DERIVED ::= "derived"
FILE ::= "file"
GUARD ::= "guard"
ALL ::= "all"
IMPLEMENTATION ::= "implementation"
INCLUDE ::= "include"
INTERFACE ::= "interface"
NOGUARD ::= "noguard"
NOIMPLEMENTATION ::= "noimplementation"
PATH ::= "path"
PREFIX ::= "prefix"
PURE ::= "pure"
SUFFIX ::= "suffix"

AUTO ::= "auto"
PRIVATE ::= "private"
PROTECTED ::= "protected"
PUBLIC ::= "public"

CONST ::= "const"
VOLATILE ::= "volatile"

EXPLICIT ::= "explicit"
EXPORT ::= "export"
EXTERN ::= "extern"
FRIEND ::= "friend"
MUTABLE ::= "mutable"
REGISTER ::= "register"
TEMPLATE ::= "template"
TYPEDEF ::= "typedef"
USING ::= "using"

INLINE ::= "inline"

ENTRY ::= "entry"
PRE ::= "pre"
//          CONSTRUCT ::= "construct"
BODY ::= "body"
//          DESTRUCT ::= "destruct"
POST ::= "post"
EXIT ::= "exit"

STATIC ::= "static"

CLASS ::= "class"
ENUM ::= "enum"
NAMESPACE ::= "namespace"
STRUCT ::= "struct"
TYPENAME ::= "typename"
UNION ::= "union"

EMIT ::= "emit"
FROZEN ::= "frozen"
POOL ::= "pool"
UTILITY ::= "utility"
SeppoPakonen commented 3 years ago

Lzz seems to process files a bit like FOG.

I do not use FOG actively right now, but I have plans to use it more in the future. The upcoming C++23 reflection feature has been more interesting. It finally adds the key features of FOG to standard c++. I’ve been thinking about trying to make a FOG frontend to clang, but it seems too laborious.

That railroad diagram is really neat. 👍 It’s fun to see the extensive FOG grammar visualized. That will probably help in debugging if you make changes to the grammar.