"# This is a C++ grammar from the C++ standard [1].\n#\n# The grammar is a superset of the true grammar requring semantic constraints to\n# resolve ambiguities. The grammar is context-free and ambiguous (beyond the\n# limit of LR(k)). We use general parsing algorithm (e.g GLR) to handle the\n# grammar and generate a transition table which is used to drive the parsing.\n#\n# It aims to align with the ISO C++ grammar as much as possible. We adjust it\n# to fit the need for the grammar-based parser:\n# - attributes are omitted, which will be handled as comments;\n# - we don't allow nullable nonterminal symbols. There are few nullable\n# nonterminals in the spec grammar, they are adjusted to be non-nullable;\n# - the file merely describes the core C++ grammar. Preprocessor directives and\n# lexical conversions are omitted as we reuse clang's lexer and run a fake\n# preprocessor;\n# - grammar rules with the >> token are adjusted, the greatergreater token is\n# split into two > tokens, to make the GLR parser aware of nested templates\n# and right shift operator;\n#\n# Guidelines:\n# - nonterminals are lower_case; terminals (aka tokens) correspond to\n# clang::TokenKind, written as \"IDENTIFIER\", \"USING\", \"::\" etc;\n# - optional symbols are supported, with a _opt suffix;\n#\n# [1] https://isocpp.org/files/papers/N4860.pdf\n\n# _ lists all the start-symbols which we support parsing.\n#\n# We list important nonterminals as start symbols, rather than doing it for all\n# nonterminals by default, this reduces the number of states by 30% and LRTable\n# actions by 16%.\n_ := translation-unit EOF\n_ := statement-seq EOF\n_ := declaration-seq EOF\n\n# gram.key\n#! we don't distinguish between namespaces and namespace aliases, as it's hard\n#! and uninteresting.\nnamespace-name := IDENTIFIER\ntemplate-name := IDENTIFIER\n\n# gram.basic\n#! Custom modifications to eliminate optional declaration-seq\ntranslation-unit := declaration-seq\ntranslation-unit := global-module-fragment_opt module-declaration declaration-seq_opt private-module-fragment_opt\n\n# gram.expr\n# expr.prim\nprimary-expression := literal\nprimary-expression := THIS\nprimary-expression := ( expression )\nprimary-expression := id-expression\nprimary-expression := lambda-expression\nprimary-expression := fold-expression\nprimary-expression := requires-expression\nid-expression := unqualified-id\nid-expression := qualified-id\nunqualified-id := IDENTIFIER\nunqualified-id := operator-function-id\nunqualified-id := conversion-function-id\nunqualified-id := literal-operator-id\nunqualified-id := ~ type-name\nunqualified-id := ~ decltype-specifier\nunqualified-id := template-id\nqualified-id := nested-name-specifier TEMPLATE_opt unqualified-id\nnested-name-specifier := :: [guard]\nnested-name-specifier := type-name ::\nnested-name-specifier := namespace-name ::\nnested-name-specifier := decltype-specifier ::\nnested-name-specifier := nested-name-specifier IDENTIFIER ::\nnested-name-specifier := nested-name-specifier TEMPLATE_opt simple-template-id ::\nlambda-expression := lambda-introducer lambda-declarator_opt compound-statement\nlambda-expression := lambda-introducer < template-parameter-list > requires-clause_opt lambda-declarator_opt compound-statement\n#! We allow a capture-default to appear anywhere in a capture-list.\n# This simplifies the grammar and error recovery.\nlambda-introducer := [ capture-list_opt ]\nlambda-declarator := ( parameter-declaration-clause_opt ) decl-specifier-seq_opt noexcept-specifier_opt trailing-return-type_opt requires-clause_opt\ncapture-list := capture\ncapture-list := capture-list , capture\ncapture := capture-default\ncapture := simple-capture\ncapture := init-capture\ncapture-default := &\ncapture-default := =\nsimple-capture := IDENTIFIER ..._opt\nsimple-capture := & IDENTIFIER ..._opt\nsimple-capture := THIS\nsimple-capture := * THIS\ninit-capture := ..._opt IDENTIFIER initializer\ninit-capture := & ..._opt IDENTIFIER initializer\nfold-expression := ( cast-expression fold-operator ... )\nfold-expression := ( ... fold-operator cast-expression )\nfold-expression := ( cast-expression fold-operator ... fold-operator cast-expression )\nfold-operator := +\nfold-operator := -\nfold-operator := *\nfold-operator := /\nfold-operator := %\nfold-operator := ^\nfold-operator := |\nfold-operator := <<\nfold-operator := greatergreater\nfold-operator := +=\nfold-operator := -=\nfold-operator := *=\nfold-operator := /=\nfold-operator := %=\nfold-operator := ^=\nfold-operator := &=\nfold-operator := |=\nfold-operator := <<=\nfold-operator := >>=\nfold-operator := =\nfold-operator := ==\nfold-operator := !=\nfold-operator := <\nfold-operator := >\nfold-operator := <=\nfold-operator := >=\nfold-operator := &&\nfold-operator := ||\nfold-operator := ,\nfold-operator := .*\nfold-operator := ->*\nrequires-expression := REQUIRES requirement-parameter-list_opt requirement-body\nrequirement-parameter-list := ( parameter-declaration-clause_opt )\nrequirement-body := { requirement-seq }\nrequirement-seq := requirement\nrequirement-seq := requirement-seq requirement\nrequirement := simple-requirement\nrequirement := type-requirement\nrequirement := compound-requirement\nrequirement := nested-requirement\nsimple-requirement := expression ;\ntype-requirement := TYPENAME nested-name-specifier_opt type-name ;\ncompound-requirement := { expression } NOEXCEPT_opt return-type-requirement_opt ;\nreturn-type-requirement := -> type-constraint\nnested-requirement := REQUIRES constraint-expression ;\n# expr.post\npostfix-expression := primary-expression\npostfix-expression := postfix-expression [ expr-or-braced-init-list ]\npostfix-expression := postfix-expression ( expression-list_opt )\npostfix-expression := simple-type-specifier ( expression-list_opt )\npostfix-expression := typename-specifier ( expression-list_opt )\npostfix-expression := simple-type-specifier braced-init-list\npostfix-expression := postfix-expression . TEMPLATE_opt id-expression\npostfix-expression := postfix-expression -> TEMPLATE_opt id-expression\npostfix-expression := postfix-expression ++\npostfix-expression := postfix-expression --\npostfix-expression := DYNAMIC_CAST < type-id > ( expression )\npostfix-expression := STATIC_CAST < type-id > ( expression )\npostfix-expression := REINTERPRET_CAST < type-id > ( expression )\npostfix-expression := CONST_CAST < type-id > ( expression )\npostfix-expression := TYPEID ( expression )\npostfix-expression := TYPEID ( type-id )\n#! Standard defines expression-list in terms of initializer-list, but our\n# initializer-list allows designators.\nexpression-list := initializer-clause ..._opt\nexpression-list := expression-list , initializer-clause ..._opt\n# expr.unary\nunary-expression := postfix-expression\nunary-expression := unary-operator cast-expression\nunary-expression := ++ cast-expression\nunary-expression := -- cast-expression\nunary-expression := await-expression\nunary-expression := SIZEOF unary-expression\nunary-expression := SIZEOF ( type-id )\nunary-expression := SIZEOF ... ( IDENTIFIER )\nunary-expression := ALIGNOF ( type-id )\nunary-expression := noexcept-expression\nunary-expression := new-expression\nunary-expression := delete-expression\nunary-operator := *\nunary-operator := &\nunary-operator := +\nunary-operator := -\nunary-operator := !\nunary-operator := ~\nawait-expression := CO_AWAIT cast-expression\nnoexcept-expression := NOEXCEPT ( expression )\nnew-expression := ::_opt NEW new-placement_opt new-type-id new-initializer_opt\nnew-expression := ::_opt NEW new-placement_opt ( type-id ) new-initializer_opt\nnew-placement := ( expression-list )\nnew-type-id := type-specifier-seq new-declarator_opt\nnew-declarator := ptr-operator new-declarator_opt\nnew-declarator := noptr-new-declarator\nnoptr-new-declarator := [ expression_opt ]\nnoptr-new-declarator := noptr-new-declarator [ constant-expression ]\nnew-initializer := ( expression-list_opt )\nnew-initializer := braced-init-list\ndelete-expression := ::_opt DELETE cast-expression\ndelete-expression := ::_opt DELETE [ ] cast-expression\ncast-expression := unary-expression\ncast-expression := ( type-id ) cast-expression\n# expr.mptr.oper\npm-expression := cast-expression\npm-expression := pm-expression .* cast-expression\npm-expression := pm-expression ->* cast-expression\n# expr.mul\nmultiplicative-expression := pm-expression\nmultiplicative-expression := multiplicative-expression * pm-expression\nmultiplicative-expression := multiplicative-expression / pm-expression\nmultiplicative-expression := multiplicative-expression % pm-expression\n# expr.add\nadditive-expression := multiplicative-expression\nadditive-expression := additive-expression + multiplicative-expression\nadditive-expression := additive-expression - multiplicative-expression\n# expr.shift\nshift-expression := additive-expression\nshift-expression := shift-expression << additive-expression\nshift-expression := shift-expression greatergreater additive-expression\n# expr.spaceship\ncompare-expression := shift-expression\ncompare-expression := compare-expression <=> shift-expression\n# expr.rel\nrelational-expression := compare-expression\nrelational-expression := relational-expression < compare-expression\nrelational-expression := relational-expression > compare-expression\nrelational-expression := relational-expression <= compare-expression\nrelational-expression := relational-expression >= compare-expression\n# expr.eq\nequality-expression := relational-expression\nequality-expression := equality-expression == relational-expression\nequality-expression := equality-expression != relational-expression\n# expr.bit.and\nand-expression := equality-expression\nand-expression := and-expression & equality-expression\n# expr.xor\nexclusive-or-expression := and-expression\nexclusive-or-expression := exclusive-or-expression ^ and-expression\n# expr.or\ninclusive-or-expression := exclusive-or-expression\ninclusive-or-expression := inclusive-or-expression | exclusive-or-expression\n# expr.log.and\nlogical-and-expression := inclusive-or-expression\nlogical-and-expression := logical-and-expression && inclusive-or-expression\n# expr.log.or\nlogical-or-expression := logical-and-expression\nlogical-or-expression := logical-or-expression || logical-and-expression\n# expr.cond\nconditional-expression := logical-or-expression\nconditional-expression := logical-or-expression ? expression : assignment-expression\n# expr.ass\nyield-expression := CO_YIELD assignment-expression\nyield-expression := CO_YIELD braced-init-list\nthrow-expression := THROW assignment-expression_opt\nassignment-expression := conditional-expression\nassignment-expression := yield-expression\nassignment-expression := throw-expression\nassignment-expression := logical-or-expression assignment-operator initializer-clause\nassignment-operator := =\nassignment-operator := *=\nassignment-operator := /=\nassignment-operator := %=\nassignment-operator := +=\nassignment-operator := -=\nassignment-operator := >>=\nassignment-operator := <<=\nassignment-operator := &=\nassignment-operator := ^=\nassignment-operator := |=\n# expr.comma\nexpression := assignment-expression\nexpression := expression , assignment-expression\n# expr.const\nconstant-expression := conditional-expression\n\n# gram.stmt\nstatement := labeled-statement\nstatement := expression-statement\nstatement := compound-statement\nstatement := selection-statement\nstatement := iteration-statement\nstatement := jump-statement\nstatement := declaration-statement\nstatement := try-block\ninit-statement := expression-statement\ninit-statement := simple-declaration\ncondition := expression\ncondition := decl-specifier-seq declarator brace-or-equal-initializer\nlabeled-statement := IDENTIFIER : statement\nlabeled-statement := CASE constant-expression : statement\nlabeled-statement := DEFAULT : statement\nexpression-statement := expression_opt ;\ncompound-statement := { statement-seq_opt [recover=Brackets] }\nstatement-seq := statement\nstatement-seq := statement-seq statement\nselection-statement := IF CONSTEXPR_opt ( init-statement_opt condition ) statement [guard]\nselection-statement := IF CONSTEXPR_opt ( init-statement_opt condition ) statement ELSE statement\nselection-statement := SWITCH ( init-statement_opt condition ) statement\niteration-statement := WHILE ( condition ) statement\niteration-statement := DO statement WHILE ( expression ) ;\niteration-statement := FOR ( init-statement condition_opt ; expression_opt ) statement\niteration-statement := FOR ( init-statement_opt for-range-declaration : for-range-initializer ) statement\nfor-range-declaration := decl-specifier-seq declarator\nfor-range-declaration := decl-specifier-seq ref-qualifier_opt [ identifier-list ]\nfor-range-initializer := expr-or-braced-init-list\njump-statement := BREAK ;\njump-statement := CONTINUE ;\njump-statement := RETURN expr-or-braced-init-list_opt ;\njump-statement := coroutine-return-statement\njump-statement := GOTO IDENTIFIER ;\ncoroutine-return-statement := CO_RETURN expr-or-braced-init-list_opt ;\ndeclaration-statement := block-declaration\n\n# gram.dcl\ndeclaration-seq := declaration\ndeclaration-seq := declaration-seq declaration\ndeclaration := block-declaration\ndeclaration := nodeclspec-function-declaration\ndeclaration := function-definition\ndeclaration := template-declaration\ndeclaration := deduction-guide\ndeclaration := explicit-instantiation\ndeclaration := explicit-specialization\ndeclaration := export-declaration\ndeclaration := linkage-specification\ndeclaration := namespace-definition\ndeclaration := empty-declaration\ndeclaration := module-import-declaration\nblock-declaration := simple-declaration\nblock-declaration := asm-declaration\nblock-declaration := namespace-alias-definition\nblock-declaration := using-declaration\nblock-declaration := using-enum-declaration\nblock-declaration := using-directive\nblock-declaration := static_assert-declaration\nblock-declaration := alias-declaration\nblock-declaration := opaque-enum-declaration\nnodeclspec-function-declaration := function-declarator ;\nalias-declaration := USING IDENTIFIER = defining-type-id ;\nsimple-declaration := decl-specifier-seq init-declarator-list_opt ;\nsimple-declaration := decl-specifier-seq ref-qualifier_opt [ identifier-list ] initializer ; [guard]\nstatic_assert-declaration := STATIC_ASSERT ( constant-expression ) ;\nstatic_assert-declaration := STATIC_ASSERT ( constant-expression , string-literal ) ;\nempty-declaration := ;\n# dcl.spec\ndecl-specifier := storage-class-specifier\ndecl-specifier := defining-type-specifier\ndecl-specifier := function-specifier\ndecl-specifier := FRIEND\ndecl-specifier := TYPEDEF\ndecl-specifier := CONSTEXPR\ndecl-specifier := CONSTEVAL\ndecl-specifier := CONSTINIT\ndecl-specifier := INLINE\ndecl-specifier-seq := decl-specifier\ndecl-specifier-seq := decl-specifier decl-specifier-seq [guard]\nstorage-class-specifier := STATIC\nstorage-class-specifier := THREAD_LOCAL\nstorage-class-specifier := EXTERN\nstorage-class-specifier := MUTABLE\nfunction-specifier := VIRTUAL\nfunction-specifier := explicit-specifier\nexplicit-specifier := EXPLICIT ( constant-expression )\nexplicit-specifier := EXPLICIT\ntype-specifier := simple-type-specifier\ntype-specifier := elaborated-type-specifier\ntype-specifier := typename-specifier\ntype-specifier := cv-qualifier\ntype-specifier-seq := type-specifier\ntype-specifier-seq := type-specifier type-specifier-seq [guard]\ndefining-type-specifier := type-specifier\ndefining-type-specifier := class-specifier\ndefining-type-specifier := enum-specifier\ndefining-type-specifier-seq := defining-type-specifier\ndefining-type-specifier-seq := defining-type-specifier defining-type-specifier-seq [guard]\nsimple-type-specifier := nested-name-specifier_opt type-name\nsimple-type-specifier := nested-name-specifier TEMPLATE simple-template-id\nsimple-type-specifier := decltype-specifier\nsimple-type-specifier := placeholder-type-specifier\nsimple-type-specifier := nested-name-specifier_opt template-name\nsimple-type-specifier := SHORT\nsimple-type-specifier := LONG\nsimple-type-specifier := SIGNED\nsimple-type-specifier := UNSIGNED\nsimple-type-specifier := builtin-type\n#! builtin-type added to aid in classifying which specifiers may combined.\nbuiltin-type := CHAR\nbuiltin-type := CHAR8_T\nbuiltin-type := CHAR16_T\nbuiltin-type := CHAR32_T\nbuiltin-type := WCHAR_T\nbuiltin-type := BOOL\nbuiltin-type := INT\nbuiltin-type := FLOAT\nbuiltin-type := DOUBLE\nbuiltin-type := VOID\n#! Unlike C++ standard grammar, we don't distinguish the underlying type (class,\n#! enum, typedef) of the IDENTIFIER, as these ambiguities are \"local\" and don't\n#! affect the final parse tree. Eliminating them gives a significant performance\n#! boost to the parser.\ntype-name := IDENTIFIER\ntype-name := simple-template-id\nelaborated-type-specifier := class-key nested-name-specifier_opt IDENTIFIER\nelaborated-type-specifier := class-key simple-template-id\nelaborated-type-specifier := class-key nested-name-specifier TEMPLATE_opt simple-template-id\nelaborated-type-specifier := elaborated-enum-specifier\nelaborated-enum-specifier := ENUM nested-name-specifier_opt IDENTIFIER\ndecltype-specifier := DECLTYPE ( expression )\nplaceholder-type-specifier := type-constraint_opt AUTO\nplaceholder-type-specifier := type-constraint_opt DECLTYPE ( AUTO )\ninit-declarator-list := init-declarator\ninit-declarator-list := init-declarator-list , init-declarator\n#! The standard grammar allows:\n#! 1) an initializer with any declarator, including a function declarator, this\n#! creates an ambiguity where a function definition is misparsed as a simple\n#! declaration;\n#! 2) an function-body with any declarator, includeing a non-function\n#! declarator, this creates an ambiguity whwere a simple-declaration is\n#! misparsed as a function-definition;\n#! We extend the standard declarator to function-declarator and non-function-declarator\n#! to eliminate these false parses.\ninit-declarator := non-function-declarator initializer_opt\ninit-declarator := function-declarator requires-clause_opt\nfunction-declarator := declarator [guard]\nnon-function-declarator := declarator [guard]\ndeclarator := ptr-declarator\ndeclarator := noptr-declarator parameters-and-qualifiers trailing-return-type\nptr-declarator := noptr-declarator\nptr-declarator := ptr-operator ptr-declarator\nnoptr-declarator := declarator-id\nnoptr-declarator := noptr-declarator parameters-and-qualifiers\nnoptr-declarator := noptr-declarator [ constant-expression_opt ]\nnoptr-declarator := ( ptr-declarator )\nparameters-and-qualifiers := ( parameter-declaration-clause_opt [recover=Brackets] ) cv-qualifier-seq_opt ref-qualifier_opt noexcept-specifier_opt\ntrailing-return-type := -> type-id\nptr-operator := * cv-qualifier-seq_opt\nptr-operator := &\nptr-operator := &&\nptr-operator := nested-name-specifier * cv-qualifier-seq_opt\ncv-qualifier-seq := cv-qualifier cv-qualifier-seq_opt\ncv-qualifier := CONST\ncv-qualifier := VOLATILE\nref-qualifier := &\nref-qualifier := &&\ndeclarator-id := ..._opt id-expression\ntype-id := type-specifier-seq abstract-declarator_opt\ndefining-type-id := defining-type-specifier-seq abstract-declarator_opt\nabstract-declarator := ptr-abstract-declarator\nabstract-declarator := noptr-abstract-declarator_opt parameters-and-qualifiers trailing-return-type\nabstract-declarator := abstract-pack-declarator\nptr-abstract-declarator := noptr-abstract-declarator\nptr-abstract-declarator := ptr-operator ptr-abstract-declarator_opt\nnoptr-abstract-declarator := noptr-abstract-declarator_opt parameters-and-qualifiers\nnoptr-abstract-declarator := noptr-abstract-declarator_opt [ constant-expression_opt ]\nnoptr-abstract-declarator := ( ptr-abstract-declarator )\nabstract-pack-declarator := noptr-abstract-pack-declarator\nabstract-pack-declarator := ptr-operator abstract-pack-declarator\nnoptr-abstract-pack-declarator := noptr-abstract-pack-declarator parameters-and-qualifiers\nnoptr-abstract-pack-declarator := noptr-abstract-pack-declarator [ constant-expression_opt ]\nnoptr-abstract-pack-declarator := ...\n#! Custom modifications to avoid nullable clause.\nparameter-declaration-clause := parameter-declaration-list\nparameter-declaration-clause := parameter-declaration-list_opt ...\nparameter-declaration-clause := parameter-declaration-list , ...\nparameter-declaration-list := parameter-declaration\nparameter-declaration-list := parameter-declaration-list , parameter-declaration\nparameter-declaration := decl-specifier-seq declarator\nparameter-declaration := decl-specifier-seq declarator = initializer-clause\nparameter-declaration := decl-specifier-seq abstract-declarator_opt\nparameter-declaration := decl-specifier-seq abstract-declarator_opt = initializer-clause\n# dcl.init\ninitializer := brace-or-equal-initializer\ninitializer := ( expression-list )\nbrace-or-equal-initializer := = initializer-clause\nbrace-or-equal-initializer := braced-init-list\ninitializer-clause := assignment-expression\ninitializer-clause := braced-init-list\n#! Allow mixed designated/non-designated init-list.\n# This is standard C, and accepted by clang and others as an extension.\n# FIXME: Decouple recovery from is-there-a-trailing-comma!\nbraced-init-list := { initializer-list [recover=Brackets] }\nbraced-init-list := { initializer-list , }\nbraced-init-list := { }\ninitializer-list := initializer-list-item\ninitializer-list := initializer-list , initializer-list-item\ninitializer-list-item := initializer-clause ..._opt\ninitializer-list-item := designator brace-or-equal-initializer ..._opt\ndesignator := . IDENTIFIER\n#! Array designators are legal in C, and a common extension in C++.\ndesignator := [ expression ]\nexpr-or-braced-init-list := expression\nexpr-or-braced-init-list := braced-init-list\n# dcl.fct\nfunction-definition := decl-specifier-seq_opt function-declarator virt-specifier-seq_opt function-body\nfunction-definition := decl-specifier-seq_opt function-declarator requires-clause function-body\nfunction-body := ctor-initializer_opt compound-statement\nfunction-body := function-try-block\nfunction-body := = DEFAULT ;\nfunction-body := = DELETE ;\n# dcl.enum\nenum-specifier := enum-head { enumerator-list_opt }\nenum-specifier := enum-head { enumerator-list , }\nenum-head := enum-key enum-head-name_opt enum-base_opt\nenum-head-name := nested-name-specifier_opt IDENTIFIER\nopaque-enum-declaration := enum-key enum-head-name enum-base_opt ;\nenum-key := ENUM\nenum-key := ENUM CLASS\nenum-key := ENUM STRUCT\nenum-base := : type-specifier-seq\nenumerator-list := enumerator-definition\nenumerator-list := enumerator-list , enumerator-definition\nenumerator-definition := enumerator\nenumerator-definition := enumerator = constant-expression\nenumerator := IDENTIFIER\nusing-enum-declaration := USING elaborated-enum-specifier ;\n# basic.namespace\nnamespace-definition := named-namespace-definition\nnamespace-definition := unnamed-namespace-definition\nnamespace-definition := nested-namespace-definition\nnamed-namespace-definition := INLINE_opt NAMESPACE IDENTIFIER { namespace-body_opt }\nunnamed-namespace-definition := INLINE_opt NAMESPACE { namespace-body_opt }\nnested-namespace-definition := NAMESPACE enclosing-namespace-specifier :: INLINE_opt IDENTIFIER { namespace-body }\nenclosing-namespace-specifier := IDENTIFIER\nenclosing-namespace-specifier := enclosing-namespace-specifier :: INLINE_opt IDENTIFIER\n#! Custom modification to avoid nullable namespace-body.\nnamespace-body := declaration-seq\nnamespace-alias-definition := NAMESPACE IDENTIFIER = qualified-namespace-specifier ;\nqualified-namespace-specifier := nested-name-specifier_opt namespace-name\nusing-directive := USING NAMESPACE nested-name-specifier_opt namespace-name ;\nusing-declaration := USING using-declarator-list ;\nusing-declarator-list := using-declarator ..._opt\nusing-declarator-list := using-declarator-list , using-declarator ..._opt\nusing-declarator := TYPENAME_opt nested-name-specifier unqualified-id\n# dcl.asm\nasm-declaration := ASM ( string-literal ) ;\n# dcl.link\nlinkage-specification := EXTERN string-literal { declaration-seq_opt }\nlinkage-specification := EXTERN string-literal declaration\n\n# gram.module\nmodule-declaration := export-keyword_opt module-keyword module-name module-partition_opt ;\nmodule-name := module-name-qualifier_opt IDENTIFIER\nmodule-partition := : module-name-qualifier_opt IDENTIFIER\nmodule-name-qualifier := IDENTIFIER .\nmodule-name-qualifier := module-name-qualifier IDENTIFIER .\nexport-declaration := EXPORT declaration\nexport-declaration := EXPORT { declaration-seq_opt }\nexport-declaration := export-keyword module-import-declaration\nmodule-import-declaration := import-keyword module-name ;\nmodule-import-declaration := import-keyword module-partition ;\n# FIXME: we don't have header-name in the grammar. Handle these in PP?\n# module-import-declaration := import-keyword header-name ;\nglobal-module-fragment := module-keyword ; declaration-seq_opt\nprivate-module-fragment := module-keyword : PRIVATE ; declaration-seq_opt\n\n# gram.class\nclass-specifier := class-head { member-specification_opt [recover=Brackets] }\nclass-head := class-key class-head-name class-virt-specifier_opt base-clause_opt\nclass-head := class-key base-clause_opt\nclass-head-name := nested-name-specifier_opt type-name\nclass-virt-specifier := contextual-final\nclass-key := CLASS\nclass-key := STRUCT\nclass-key := UNION\nmember-specification := member-declaration member-specification_opt\nmember-specification := access-specifier : member-specification_opt\nmember-declaration := decl-specifier-seq member-declarator-list_opt ;\nmember-declaration := member-declarator-list ;\nmember-declaration := function-definition\nmember-declaration := using-declaration\nmember-declaration := using-enum-declaration\nmember-declaration := static_assert-declaration\nmember-declaration := template-declaration\nmember-declaration := explicit-specialization\nmember-declaration := deduction-guide\nmember-declaration := alias-declaration\nmember-declaration := opaque-enum-declaration\nmember-declaration := empty-declaration\nmember-declarator-list := member-declarator\nmember-declarator-list := member-declarator-list , member-declarator\nmember-declarator := function-declarator virt-specifier-seq_opt pure-specifier_opt\nmember-declarator := function-declarator requires-clause\nmember-declarator := non-function-declarator brace-or-equal-initializer_opt\nmember-declarator := IDENTIFIER_opt : constant-expression brace-or-equal-initializer_opt\nvirt-specifier-seq := virt-specifier\nvirt-specifier-seq := virt-specifier-seq virt-specifier\nvirt-specifier := contextual-override\nvirt-specifier := contextual-final\npure-specifier := = contextual-zero\nconversion-function-id := OPERATOR conversion-type-id\nconversion-type-id := type-specifier-seq conversion-declarator_opt\nconversion-declarator := ptr-operator conversion-declarator_opt\nbase-clause := : base-specifier-list\nbase-specifier-list := base-specifier ..._opt\nbase-specifier-list := base-specifier-list , base-specifier ..._opt\nbase-specifier := class-or-decltype\nbase-specifier := VIRTUAL access-specifier_opt class-or-decltype\nbase-specifier := access-specifier VIRTUAL_opt class-or-decltype\nclass-or-decltype := nested-name-specifier_opt type-name\nclass-or-decltype := nested-name-specifier TEMPLATE simple-template-id\nclass-or-decltype := decltype-specifier\naccess-specifier := PRIVATE\naccess-specifier := PROTECTED\naccess-specifier := PUBLIC\nctor-initializer := : mem-initializer-list\nmem-initializer-list := mem-initializer ..._opt\nmem-initializer-list := mem-initializer-list , mem-initializer ..._opt\nmem-initializer := mem-initializer-id ( expression-list_opt )\nmem-initializer := mem-initializer-id braced-init-list\nmem-initializer-id := class-or-decltype\nmem-initializer-id := IDENTIFIER\n\n# gram.over\noperator-function-id := OPERATOR operator-name\noperator-name := NEW\noperator-name := DELETE\noperator-name := NEW [ ]\noperator-name := DELETE [ ]\noperator-name := CO_AWAIT\noperator-name := ( )\noperator-name := [ ]\noperator-name := ->\noperator-name := ->*\noperator-name := ~\noperator-name := !\noperator-name := +\noperator-name := -\noperator-name := *\noperator-name := /\noperator-name := %\noperator-name := ^\noperator-name := &\noperator-name := |\noperator-name := =\noperator-name := +=\noperator-name := -=\noperator-name := *=\noperator-name := /=\noperator-name := %=\noperator-name := ^=\noperator-name := &=\noperator-name := |=\noperator-name := ==\noperator-name := !=\noperator-name := <\noperator-name := >\noperator-name := <=\noperator-name := >=\noperator-name := <=>\noperator-name := ^^\noperator-name := ||\noperator-name := <<\noperator-name := greatergreater\noperator-name := <<=\noperator-name := >>=\noperator-name := ++\noperator-name := --\noperator-name := ,\nliteral-operator-id := OPERATOR string-literal IDENTIFIER\nliteral-operator-id := OPERATOR user-defined-string-literal\n\n# gram.temp\ntemplate-declaration := template-head declaration\ntemplate-declaration := template-head concept-definition\ntemplate-head := TEMPLATE < template-parameter-list > requires-clause_opt\ntemplate-parameter-list := template-parameter\ntemplate-parameter-list := template-parameter-list , template-parameter\nrequires-clause := REQUIRES constraint-logical-or-expression\nconstraint-logical-or-expression := constraint-logical-and-expression\nconstraint-logical-or-expression := constraint-logical-or-expression || constraint-logical-and-expression\nconstraint-logical-and-expression := primary-expression\nconstraint-logical-and-expression := constraint-logical-and-expression && primary-expression\ntemplate-parameter := type-parameter\ntemplate-parameter := parameter-declaration\ntype-parameter := type-parameter-key ..._opt IDENTIFIER_opt\ntype-parameter := type-parameter-key IDENTIFIER_opt = type-id\ntype-parameter := type-constraint ..._opt IDENTIFIER_opt\ntype-parameter := type-constraint IDENTIFIER_opt = type-id\ntype-parameter := template-head type-parameter-key ..._opt IDENTIFIER_opt\ntype-parameter := template-head type-parameter-key IDENTIFIER_opt = id-expression\ntype-parameter-key := CLASS\ntype-parameter-key := TYPENAME\ntype-constraint := nested-name-specifier_opt concept-name\ntype-constraint := nested-name-specifier_opt concept-name < template-argument-list_opt >\nsimple-template-id := template-name < template-argument-list_opt >\ntemplate-id := simple-template-id\ntemplate-id := operator-function-id < template-argument-list_opt >\ntemplate-id := literal-operator-id < template-argument-list_opt >\ntemplate-argument-list := template-argument ..._opt\ntemplate-argument-list := template-argument-list , template-argument ..._opt\ntemplate-argument := constant-expression\ntemplate-argument := type-id\ntemplate-argument := id-expression\nconstraint-expression := logical-or-expression\ndeduction-guide := explicit-specifier_opt template-name ( parameter-declaration-list_opt ) -> simple-template-id ;\nconcept-definition := CONCEPT concept-name = constraint-expression ;\nconcept-name := IDENTIFIER\ntypename-specifier := TYPENAME nested-name-specifier IDENTIFIER\ntypename-specifier := TYPENAME nested-name-specifier TEMPLATE_opt simple-template-id\nexplicit-instantiation := EXTERN_opt TEMPLATE declaration\nexplicit-specialization := TEMPLATE < > declaration\n\n# gram.except\ntry-block := TRY compound-statement handler-seq\nfunction-try-block := TRY ctor-initializer_opt compound-statement handler-seq\nhandler-seq := handler handler-seq_opt\nhandler := CATCH ( exception-declaration ) compound-statement\nexception-declaration := type-specifier-seq declarator\nexception-declaration := type-specifier-seq abstract-declarator_opt\nnoexcept-specifier := NOEXCEPT ( constant-expression )\nnoexcept-specifier := NOEXCEPT\n\n# gram.cpp\nidentifier-list := IDENTIFIER\nidentifier-list := identifier-list , IDENTIFIER\n\n# gram.lex\n#! As we use clang lexer, most of lexical symbols are not needed, we only add\n#! needed literals.\nliteral := integer-literal\nliteral := character-literal\nliteral := floating-point-literal\nliteral := string-literal\nliteral := boolean-literal\nliteral := pointer-literal\nliteral := user-defined-literal\ninteger-literal := NUMERIC_CONSTANT [guard]\ncharacter-literal := CHAR_CONSTANT [guard]\ncharacter-literal := WIDE_CHAR_CONSTANT [guard]\ncharacter-literal := UTF8_CHAR_CONSTANT [guard]\ncharacter-literal := UTF16_CHAR_CONSTANT [guard]\ncharacter-literal := UTF32_CHAR_CONSTANT [guard]\nfloating-point-literal := NUMERIC_CONSTANT [guard]\nstring-literal-chunk := STRING_LITERAL [guard]\nstring-literal-chunk := WIDE_STRING_LITERAL [guard]\nstring-literal-chunk := UTF8_STRING_LITERAL [guard]\nstring-literal-chunk := UTF16_STRING_LITERAL [guard]\nstring-literal-chunk := UTF32_STRING_LITERAL [guard]\n#! Technically, string concatenation happens at phase 6 which is before parsing,\n#! so it doesn't belong to the grammar. However, we extend the grammar to\n#! support it, to make the pseudoparser fully functional on practical code.\nstring-literal := string-literal-chunk\nstring-literal := string-literal string-literal-chunk\nuser-defined-literal := user-defined-integer-literal\nuser-defined-literal := user-defined-floating-point-literal\nuser-defined-literal := user-defined-string-literal\nuser-defined-literal := user-defined-character-literal\nuser-defined-integer-literal := NUMERIC_CONSTANT [guard]\nuser-defined-string-literal-chunk := STRING_LITERAL [guard]\nuser-defined-string-literal-chunk := WIDE_STRING_LITERAL [guard]\nuser-defined-string-literal-chunk := UTF8_STRING_LITERAL [guard]\nuser-defined-string-literal-chunk := UTF16_STRING_LITERAL [guard]\nuser-defined-string-literal-chunk := UTF32_STRING_LITERAL [guard]\nuser-defined-string-literal := user-defined-string-literal-chunk\nuser-defined-string-literal := string-literal-chunk user-defined-string-literal\nuser-defined-string-literal := user-defined-string-literal string-literal-chunk\nuser-defined-floating-point-literal := NUMERIC_CONSTANT [guard]\nuser-defined-character-literal := CHAR_CONSTANT [guard]\nuser-defined-character-literal := WIDE_CHAR_CONSTANT [guard]\nuser-defined-character-literal := UTF8_CHAR_CONSTANT [guard]\nuser-defined-character-literal := UTF16_CHAR_CONSTANT [guard]\nuser-defined-character-literal := UTF32_CHAR_CONSTANT [guard]\nboolean-literal := FALSE\nboolean-literal := TRUE\npointer-literal := NULLPTR\n\n#! Contextual keywords -- clang lexer always lexes them as identifier tokens.\n#! Placeholders for literal text in the grammar that lex as other things.\ncontextual-override := IDENTIFIER [guard]\ncontextual-final := IDENTIFIER [guard]\ncontextual-zero := NUMERIC_CONSTANT [guard]\nmodule-keyword := IDENTIFIER [guard]\nimport-keyword := IDENTIFIER [guard]\nexport-keyword := IDENTIFIER [guard]\n\n#! greatergreater token -- clang lexer always lexes it as a single token, we\n#! split it into two tokens to make the GLR parser aware of the nested-template\n#! case.\ngreatergreater := > >\n\n#! C++ predefined identifier, __func__ [dcl.fct.def.general] p8\n#! FIXME: add other (MSVC, GNU extension) predefined identifiers.\nprimary-expression := predefined-expression\npredefined-expression := __FUNC__\n\n"