Skip to content

Grammar railroad diagram #6742

@mingodad

Description

@mingodad

Using https://github.com/mingodad/squilu to extract the {bnf} sections from all *.tex files and convert then to an EBNF understood by https://www.bottlecaps.de/rr/ui we can have a nice navigable railroad diagram (see bellow the resulting EBNF and instructions to visualize the railroad diagram).

//
// EBNF to be viewd at https://www.bottlecaps.de/rr/ui
//
// Copy and paste this at https://www.bottlecaps.de/rr/ui in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//

//
//To facilitate start navigating
//

cplusplus ::=
	preprocessing-file? translation-unit

//== lex.tex

n-char ::=
     "{any member of the translation character set except the \unicode{007d}{right curly bracket} or new-line character}"

n-char-sequence ::=
    n-char
  | n-char-sequence n-char

named-universal-character ::=
    "\N{" n-char-sequence "}"

hex-quad ::=
    hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit

simple-hexadecimal-digit-sequence ::=
    hexadecimal-digit
  | simple-hexadecimal-digit-sequence hexadecimal-digit

universal-character-name ::=
    "\u" hex-quad
  | "\U" hex-quad hex-quad
  | "\u{" simple-hexadecimal-digit-sequence "}"
  | named-universal-character

preprocessing-token ::=
    header-name
  | "import"
  | "module"
  | "export"
  | identifier
  | pp-number
  | character-literal
  | user-defined-character-literal
  | string-literal
  | user-defined-string-literal
  | preprocessing-op-or-punc
  | "{each non-whitespace character that cannot be one of the above}"

//token ::=
//    identifier
//  | keyword
//  | literal
//  | operator-or-punctuator

header-name ::=
    "<" h-char-sequence ">"
  | '"' q-char-sequence '"'

h-char-sequence ::=
    h-char
  | h-char-sequence h-char

h-char ::=
    "{any member of the translation character set except new-line and \unicode{003e}{greater-than sign}}"

q-char-sequence ::=
    q-char
  | q-char-sequence q-char

q-char ::=
    "{any member of the translation character set except new-line and \unicode{0022}{quotation mark}}"

pp-number ::=
    digit
  | "." digit
  | pp-number identifier-continue
  | pp-number "'" digit
  | pp-number "'" nondigit
  | pp-number "e" sign
  | pp-number "E" sign
  | pp-number "p" sign
  | pp-number "P" sign
  | pp-number "."

identifier ::=
    identifier-start
  | identifier identifier-continue

identifier-start ::=
    nondigit
  | "{an element of the translation character set with the Unicode property XID_Start}"

identifier-continue ::=
    digit
  | nondigit
  | "{an element of the translation character set with the Unicode property XID_Continue}"

nondigit ::=
    "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
  | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
  | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M"
  | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "_"

digit ::=
    "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

keyword ::=
    "{any identifier listed in lex.key}"
  | "import"
  | "module"
  | "export"

preprocessing-op-or-punc ::=
    preprocessing-operator
  | operator-or-punctuator

preprocessing-operator ::=
    "#" | "##" | "%:" | "%:%:"

operator-or-punctuator ::=
    "{" | "}" | "[" | "]" | "(" | ")"
  | "<:" | ":>" | "<%" | "%>" | ";" | ":" | "..."
  | "?" | "::" | "." | ".*" | "->" | "->*" | "~"
  | "!" | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|"
  | "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|="
  | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<=>" | "&&" | "||"
  | "<<" | ">>" | "<<=" | ">>=" | "++" | "--" | ","
  | "and" | "or" | "xor" | "not" | "bitand" | "bitor" | "compl"
  | "and_eq" | "or_eq" | "xor_eq" | "not_eq"

literal ::=
    integer-literal
  | character-literal
  | floating-point-literal
  | string-literal
  | boolean-literal
  | pointer-literal
  | user-defined-literal

integer-literal ::=
    binary-literal integer-suffix?
  | octal-literal integer-suffix?
  | decimal-literal integer-suffix?
  | hexadecimal-literal integer-suffix?

binary-literal ::=
    "0b" binary-digit
  | "0B" binary-digit
  | binary-literal "'"? binary-digit

octal-literal ::=
    "0"
  | octal-literal "'"? octal-digit

decimal-literal ::=
    nonzero-digit
  | decimal-literal "'"? digit

hexadecimal-literal ::=
    hexadecimal-prefix hexadecimal-digit-sequence

binary-digit ::=
    "0" | "1"

octal-digit ::=
    "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7"

nonzero-digit ::=
    "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

hexadecimal-prefix ::=
    "0x" | "0X"

hexadecimal-digit-sequence ::=
    hexadecimal-digit
  | hexadecimal-digit-sequence "'"? hexadecimal-digit

hexadecimal-digit ::=
    "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  | "a" | "b" | "c" | "d" | "e" | "f"
  | "A" | "B" | "C" | "D" | "E" | "F"

integer-suffix ::=
    unsigned-suffix long-suffix?
  | unsigned-suffix long-long-suffix?
  | unsigned-suffix size-suffix?
  | long-suffix unsigned-suffix?
  | long-long-suffix unsigned-suffix?
  | size-suffix unsigned-suffix?

unsigned-suffix ::=
    "u" | "U"

long-suffix ::=
    "l" | "L"

long-long-suffix ::=
    "ll" | "LL"

size-suffix ::=
   "z" | "Z"

character-literal ::=
    encoding-prefix? "'" c-char-sequence "'"

encoding-prefix ::=
    "u8" | "u" | "U" | "L"

c-char-sequence ::=
    c-char
  | c-char-sequence c-char

c-char ::=
    basic-c-char
  | escape-sequence
  | universal-character-name

basic-c-char ::=
    "{any member of the translation character set except the \unicode{0027}{apostrophe},}"
        "{\unicode{005c}{reverse solidus}, or new-line character}"

escape-sequence ::=
    simple-escape-sequence
  | numeric-escape-sequence
  | conditional-escape-sequence

simple-escape-sequence ::=
    "\" simple-escape-sequence-char

simple-escape-sequence-char ::=
    "'" | '"' | "?" | "\" | "a" | "b" | "f" | "n" | "r" | "t" | "v"

numeric-escape-sequence ::=
    octal-escape-sequence
  | hexadecimal-escape-sequence

simple-octal-digit-sequence ::=
    octal-digit
  | simple-octal-digit-sequence octal-digit

octal-escape-sequence ::=
    "\" octal-digit
  | "\" octal-digit octal-digit
  | "\" octal-digit octal-digit octal-digit
  | "\o{" simple-octal-digit-sequence "}"

hexadecimal-escape-sequence ::=
    "\x" simple-hexadecimal-digit-sequence
  | "\x{" simple-hexadecimal-digit-sequence "}"

conditional-escape-sequence ::=
    "\" conditional-escape-sequence-char

conditional-escape-sequence-char ::=
    '{any member of the basic character set that is not an octal-digit, a simple-escape-sequence-char, or the characters "N", "o", "u", "U", or "x"}'

floating-point-literal ::=
    decimal-floating-point-literal
  | hexadecimal-floating-point-literal

decimal-floating-point-literal ::=
    fractional-constant exponent-part? floating-point-suffix?
  | digit-sequence exponent-part floating-point-suffix?

hexadecimal-floating-point-literal ::=
    hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part floating-point-suffix?
  | hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part floating-point-suffix?

fractional-constant ::=
    digit-sequence? "." digit-sequence
  | digit-sequence "."

hexadecimal-fractional-constant ::=
    hexadecimal-digit-sequence? "." hexadecimal-digit-sequence
  | hexadecimal-digit-sequence "."

exponent-part ::=
    "e" sign? digit-sequence
  | "E" sign? digit-sequence

binary-exponent-part ::=
    "p" sign? digit-sequence
  | "P" sign? digit-sequence

sign ::=
    "+" | "-"

digit-sequence ::=
    digit
  | digit-sequence "'"? digit

floating-point-suffix ::=
    "f" | "l" | "f16" | "f32" | "f64" | "f128" | "bf16" | "F" | "L" | "F16" | "F32" | "F64" | "F128" | "BF16"

string-literal ::=
    encoding-prefix? '"' s-char-sequence? '"'
  | encoding-prefix? "R" raw-string

s-char-sequence ::=
    s-char
  | s-char-sequence s-char

s-char ::=
    basic-s-char
  | escape-sequence
  | universal-character-name

basic-s-char ::=
    "{any member of the translation character set except the \unicode{0022}{quotation mark},}"
        "{\unicode{005c}{reverse solidus}, or new-line character}"

raw-string ::=
    '"' d-char-sequence? "(" r-char-sequence? ")" d-char-sequence? '"'

r-char-sequence ::=
    r-char
  | r-char-sequence r-char

r-char ::=
    "{any member of the translation character set, except a \unicode{0029}{right parenthesis} followed by}"
        "{the initial d-char-sequence (which may be empty) followed by a \unicode{0022}{quotation mark}}"

d-char-sequence ::=
    d-char
  | d-char-sequence d-char

d-char ::=
    "{any member of the basic character set except:}"
        "{\unicode{0020}{space}, \unicode{0028}{left parenthesis}, \unicode{0029}{right parenthesis}, \unicode{005c}{reverse solidus},}"
        "{\unicode{0009}{character tabulation}, \unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line}"

unevaluated-string ::=
    string-literal

boolean-literal ::=
    "false"
  | "true"

pointer-literal ::=
    "nullptr"

user-defined-literal ::=
    user-defined-integer-literal
  | user-defined-floating-point-literal
  | user-defined-string-literal
  | user-defined-character-literal

user-defined-integer-literal ::=
    decimal-literal ud-suffix
  | octal-literal ud-suffix
  | hexadecimal-literal ud-suffix
  | binary-literal ud-suffix

user-defined-floating-point-literal ::=
    fractional-constant exponent-part? ud-suffix
  | digit-sequence exponent-part ud-suffix
  | hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part ud-suffix
  | hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part ud-suffix

user-defined-string-literal ::=
    string-literal ud-suffix

user-defined-character-literal ::=
    character-literal ud-suffix

ud-suffix ::=
    identifier

//== basic.tex

translation-unit ::=
    declaration-seq?
  | global-module-fragment? module-declaration declaration-seq? private-module-fragment?

//== expressions.tex

primary-expression ::=
    literal
  | "this"
  | "(" expression ")"
  | id-expression
  | lambda-expression
  | fold-expression
  | requires-expression

id-expression ::=
    unqualified-id
  | qualified-id
  | pack-index-expression

unqualified-id ::=
    identifier
  | operator-function-id
  | conversion-function-id
  | literal-operator-id
  | "~" type-name
  | "~" computed-type-specifier
  | template-id

qualified-id ::=
    nested-name-specifier "template"? unqualified-id

nested-name-specifier ::=
    "::"
  | type-name "::"
  | namespace-name "::"
  | computed-type-specifier "::"
  | nested-name-specifier identifier "::"
  | nested-name-specifier "template"? simple-template-id "::"

pack-index-expression ::=
    id-expression "..." "[" constant-expression "]"

lambda-expression ::=
    lambda-introducer attribute-specifier-seq? lambda-declarator compound-statement
  | lambda-introducer "<" template-parameter-list ">" requires-clause? attribute-specifier-seq?
         lambda-declarator compound-statement

lambda-introducer ::=
    "[" lambda-capture? "]"

lambda-declarator ::=
    lambda-specifier-seq noexcept-specifier? attribute-specifier-seq? trailing-return-type?
  | noexcept-specifier attribute-specifier-seq? trailing-return-type?
  | trailing-return-type?
  | "(" parameter-declaration-clause ")" lambda-specifier-seq? noexcept-specifier? attribute-specifier-seq?
         trailing-return-type? requires-clause?

lambda-specifier ::=
    "consteval"
  | "constexpr"
  | "mutable"
  | "static"

lambda-specifier-seq ::=
    lambda-specifier
  | lambda-specifier lambda-specifier-seq

lambda-capture ::=
    capture-default
  | capture-list
  | capture-default "," capture-list

capture-default ::=
    "&"
  | "="

capture-list ::=
    capture
  | capture-list "," capture

capture ::=
    simple-capture
  | init-capture

simple-capture ::=
    identifier "..."?
  | "&" identifier "..."?
  | "this"
  | "*" "this"

init-capture ::=
    "..."? identifier initializer
  | "&" "..."? identifier initializer

fold-expression ::=
    "(" cast-expression fold-operator "..." ")"
  | "(" "..." fold-operator cast-expression ")"
  | "(" cast-expression fold-operator "..." fold-operator cast-expression ")"

fold-operator ::=
    "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "<<" | ">>"
  | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<=" | ">>=" | "="
  | "==" | "!=" | "<" | ">" | "<=" | ">=" | "&&" | "||" | "," | ".*" | "->*"

requires-expression ::=
    "requires" requirement-parameter-list? requirement-body

requirement-parameter-list ::=
    "(" parameter-declaration-clause ")"

requirement-body ::=
    "{" requirement-seq "}"

requirement-seq ::=
    requirement
  | requirement requirement-seq

requirement ::=
    simple-requirement
  | type-requirement
  | compound-requirement
  | nested-requirement

simple-requirement ::=
    expression ";"

type-requirement ::=
    "typename" nested-name-specifier? type-name ";"

compound-requirement ::=
    "{" expression "}" "noexcept"? return-type-requirement? ";"

return-type-requirement ::=
    "->" type-constraint

nested-requirement ::=
    "requires" constraint-expression ";"

postfix-expression ::=
    primary-expression
  | postfix-expression "[" expression-list? "]"
  | postfix-expression "(" expression-list? ")"
  | simple-type-specifier "(" expression-list? ")"
  | typename-specifier "(" expression-list? ")"
  | simple-type-specifier braced-init-list
  | typename-specifier braced-init-list
  | postfix-expression "." "template"? id-expression
  | postfix-expression "->" "template"? id-expression
  | postfix-expression "++"
  | postfix-expression "--"
  | "dynamic_cast" "<" type-id ">" "(" expression ")"
  | "static_cast" "<" type-id ">" "(" expression ")"
  | "reinterpret_cast" "<" type-id ">" "(" expression ")"
  | "const_cast" "<" type-id ">" "(" expression ")"
  | "typeid" "(" expression ")"
  | "typeid" "(" type-id ")"

expression-list ::=
    initializer-list

unary-expression ::=
    postfix-expression
  | unary-operator cast-expression
  | "++" cast-expression
  | "--" cast-expression
  | await-expression
  | "sizeof" unary-expression
  | "sizeof" "(" type-id ")"
  | "sizeof" "..." "(" identifier ")"
  | "alignof" "(" type-id ")"
  | noexcept-expression
  | new-expression
  | delete-expression

unary-operator ::=
    "*" | "&" | "+" | "-" | "!" | "~"

await-expression ::=
    "co_await" cast-expression

noexcept-expression ::=
  "noexcept" "(" expression ")"

new-expression ::=
    "::"? "new" new-placement? new-type-id new-initializer?
  | "::"? "new" new-placement? "(" type-id ")" new-initializer?

new-placement ::=
    "(" expression-list ")"

new-type-id ::=
    type-specifier-seq new-declarator?

new-declarator ::=
    ptr-operator new-declarator?
  | noptr-new-declarator

noptr-new-declarator ::=
    "[" expression? "]" attribute-specifier-seq?
  | noptr-new-declarator "[" constant-expression "]" attribute-specifier-seq?

new-initializer ::=
    "(" expression-list? ")"
  | braced-init-list

delete-expression ::=
    "::"? "delete" cast-expression
  | "::"? "delete" "[" "]" cast-expression

cast-expression ::=
    unary-expression
  | "(" type-id ")" cast-expression

pm-expression ::=
    cast-expression
  | pm-expression ".*" cast-expression
  | pm-expression "->*" cast-expression

multiplicative-expression ::=
    pm-expression
  | multiplicative-expression "*" 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 "<<" additive-expression
  | shift-expression ">>" additive-expression

compare-expression ::=
    shift-expression
  | compare-expression "<=>" shift-expression

relational-expression ::=
    compare-expression
  | relational-expression "<" compare-expression
  | relational-expression ">" compare-expression
  | relational-expression "<=" compare-expression
  | relational-expression ">=" compare-expression

equality-expression ::=
    relational-expression
  | equality-expression "==" relational-expression
  | equality-expression "!=" 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 "&&" inclusive-or-expression

logical-or-expression ::=
    logical-and-expression
  | logical-or-expression "||" logical-and-expression

conditional-expression ::=
    logical-or-expression
  | logical-or-expression "?" expression ":" assignment-expression

  yield-expression ::=
  "co_yield" assignment-expression
  | "co_yield" braced-init-list

throw-expression ::=
    "throw"  assignment-expression?

assignment-expression ::=
    conditional-expression
  | yield-expression
  | throw-expression
  | logical-or-expression assignment-operator initializer-clause

assignment-operator ::=
    "=" | "*=" | "/=" | "%=" | "+=" | "-=" | ">>=" | "<<=" | "&=" | "^=" | "|="

expression ::=
    assignment-expression
  | expression "," assignment-expression

constant-expression ::=
    conditional-expression

//== statements.tex

statement ::=
    labeled-statement
  | attribute-specifier-seq? expression-statement
  | attribute-specifier-seq? compound-statement
  | attribute-specifier-seq? selection-statement
  | attribute-specifier-seq? iteration-statement
  | attribute-specifier-seq? jump-statement
  | declaration-statement
  | attribute-specifier-seq? try-block

init-statement ::=
    expression-statement
  | simple-declaration
  | alias-declaration

condition ::=
    expression
  | attribute-specifier-seq? decl-specifier-seq declarator brace-or-equal-initializer

label ::=
    attribute-specifier-seq? identifier ":"
  | attribute-specifier-seq? "case" constant-expression ":"
  | attribute-specifier-seq? "default" ":"

labeled-statement ::=
    label statement

expression-statement ::=
    expression? ";"

compound-statement ::=
    "{" statement-seq? label-seq? "}"

statement-seq ::=
    statement
  | statement-seq statement

label-seq ::=
    label
  | label-seq label

selection-statement ::=
    "if" "constexpr"? "(" init-statement? condition ")" statement
  | "if" "constexpr"? "(" init-statement? condition ")" statement "else" statement
  | "if" "!"? "consteval" compound-statement
  | "if" "!"? "consteval" compound-statement "else" statement
  | "switch" "(" init-statement? condition ")" statement

iteration-statement ::=
    "while" "(" condition ")" statement
  | "do" statement "while" "(" expression ")" ";"
  | "for" "(" init-statement condition? ";" expression? ")" statement
  | "for" "(" init-statement? for-range-declaration ":" for-range-initializer ")" statement

for-range-declaration ::=
    attribute-specifier-seq? decl-specifier-seq declarator
  | attribute-specifier-seq? decl-specifier-seq ref-qualifier? "[" identifier-list "]"

for-range-initializer ::=
    expr-or-braced-init-list

jump-statement ::=
    "break" ";"
  | "continue" ";"
  | "return" expr-or-braced-init-list? ";"
  | coroutine-return-statement
  | "goto" identifier ";"

coroutine-return-statement ::=
    "co_return" expr-or-braced-init-list? ";"

declaration-statement ::=
    block-declaration

//== declarations.tex

declaration-seq ::=
    declaration
  | declaration-seq declaration

declaration ::=
    name-declaration
  | special-declaration

name-declaration ::=
    block-declaration
  | nodeclspec-function-declaration
  | function-definition
  | template-declaration
  | deduction-guide
  | linkage-specification
  | namespace-definition
  | empty-declaration
  | attribute-declaration
  | module-import-declaration

special-declaration ::=
    explicit-instantiation
  | explicit-specialization
  | export-declaration

block-declaration ::=
    simple-declaration
  | asm-declaration
  | namespace-alias-definition
  | using-declaration
  | using-enum-declaration
  | using-directive
  | static_assert-declaration
  | alias-declaration
  | opaque-enum-declaration

nodeclspec-function-declaration ::=
    attribute-specifier-seq? declarator ";"

alias-declaration ::=
    "using" identifier attribute-specifier-seq? "=" defining-type-id ";"

simple-declaration ::=
    decl-specifier-seq init-declarator-list? ";"
  | attribute-specifier-seq decl-specifier-seq init-declarator-list ";"
  | attribute-specifier-seq? decl-specifier-seq ref-qualifier? "[" identifier-list "]" initializer ";"

static_assert-message ::=
  unevaluated-string
  | constant-expression

static_assert-declaration ::=
  "static_assert" "(" constant-expression ")" ";"
  | "static_assert" "(" constant-expression "," static_assert-message ")" ";"

empty-declaration ::=
    ";"

attribute-declaration ::=
    attribute-specifier-seq ";"

decl-specifier ::=
    storage-class-specifier
  | defining-type-specifier
  | function-specifier
  | "friend"
  | "typedef"
  | "constexpr"
  | "consteval"
  | "constinit"
  | "inline"

decl-specifier-seq ::=
    decl-specifier attribute-specifier-seq?
  | decl-specifier decl-specifier-seq

storage-class-specifier ::=
    "static"
  | "thread_local"
  | "extern"
  | "mutable"

function-specifier ::=
    "virtual"
  | explicit-specifier

explicit-specifier ::=
    "explicit" "(" constant-expression ")"
  | "explicit"

typedef-name ::=
    identifier
  | simple-template-id

type-specifier ::=
  simple-type-specifier
  | elaborated-type-specifier
  | typename-specifier
  | cv-qualifier

type-specifier-seq ::=
    type-specifier attribute-specifier-seq?
  | type-specifier type-specifier-seq

defining-type-specifier ::=
    type-specifier
  | class-specifier
  | enum-specifier

defining-type-specifier-seq ::=
  defining-type-specifier attribute-specifier-seq?
  | defining-type-specifier defining-type-specifier-seq

simple-type-specifier ::=
    nested-name-specifier? type-name
  | nested-name-specifier "template" simple-template-id
  | computed-type-specifier
  | placeholder-type-specifier
  | nested-name-specifier? template-name
  | "char"
  | "char8_t"
  | "char16_t"
  | "char32_t"
  | "wchar_t"
  | "bool"
  | "short"
  | "int"
  | "long"
  | "signed"
  | "unsigned"
  | "float"
  | "double"
  | "void"

type-name ::=
    class-name
  | enum-name
  | typedef-name

computed-type-specifier ::=
    decltype-specifier
  | pack-index-specifier

pack-index-specifier ::=
    typedef-name "..." "[" constant-expression "]"

elaborated-type-specifier ::=
    class-key attribute-specifier-seq? nested-name-specifier? identifier
  | class-key simple-template-id
  | class-key nested-name-specifier "template"? simple-template-id
  | "enum" nested-name-specifier? identifier

decltype-specifier ::=
  "decltype" "(" expression ")"

placeholder-type-specifier ::=
  type-constraint? "auto"
  | type-constraint? "decltype" "(" "auto" ")"

init-declarator-list ::=
    init-declarator
  | init-declarator-list "," init-declarator

init-declarator ::=
    declarator initializer?
  | declarator requires-clause

declarator ::=
    ptr-declarator
  | noptr-declarator parameters-and-qualifiers trailing-return-type

ptr-declarator ::=
    noptr-declarator
  | ptr-operator ptr-declarator

noptr-declarator ::=
    declarator-id attribute-specifier-seq?
  | noptr-declarator parameters-and-qualifiers
  | noptr-declarator "[" constant-expression? "]" attribute-specifier-seq?
  | "(" ptr-declarator ")"

parameters-and-qualifiers ::=
    "(" parameter-declaration-clause ")" cv-qualifier-seq?
        ref-qualifier? noexcept-specifier? attribute-specifier-seq?

trailing-return-type ::=
    "->" type-id

ptr-operator ::=
    "*" attribute-specifier-seq? cv-qualifier-seq?
  | "&" attribute-specifier-seq?
  | "&&" attribute-specifier-seq?
  | nested-name-specifier "*" attribute-specifier-seq? cv-qualifier-seq?

cv-qualifier-seq ::=
    cv-qualifier cv-qualifier-seq?

cv-qualifier ::=
    "const"
  | "volatile"

ref-qualifier ::=
    "&"
  | "&&"

declarator-id ::=
    "..."? id-expression

type-id ::=
    type-specifier-seq abstract-declarator?

defining-type-id ::=
    defining-type-specifier-seq abstract-declarator?

abstract-declarator ::=
    ptr-abstract-declarator
  | noptr-abstract-declarator? parameters-and-qualifiers trailing-return-type
  | abstract-pack-declarator

ptr-abstract-declarator ::=
    noptr-abstract-declarator
  | ptr-operator ptr-abstract-declarator?

noptr-abstract-declarator ::=
    noptr-abstract-declarator? parameters-and-qualifiers
  | noptr-abstract-declarator? "[" constant-expression? "]" attribute-specifier-seq?
  | "(" ptr-abstract-declarator ")"

abstract-pack-declarator ::=
    noptr-abstract-pack-declarator
  | ptr-operator abstract-pack-declarator

noptr-abstract-pack-declarator ::=
    noptr-abstract-pack-declarator parameters-and-qualifiers
  | "..."

parameter-declaration-clause ::=
    parameter-declaration-list? "..."?
  | parameter-declaration-list "," "..."

parameter-declaration-list ::=
    parameter-declaration
  | parameter-declaration-list "," parameter-declaration

parameter-declaration ::=
    attribute-specifier-seq? "this"? decl-specifier-seq declarator
  | attribute-specifier-seq? decl-specifier-seq declarator "=" initializer-clause
  | attribute-specifier-seq? "this"? decl-specifier-seq abstract-declarator?
  | attribute-specifier-seq? decl-specifier-seq abstract-declarator? "=" initializer-clause

initializer ::=
    brace-or-equal-initializer
  | "(" expression-list ")"

brace-or-equal-initializer ::=
    "=" initializer-clause
  | braced-init-list

initializer-clause ::=
    assignment-expression
  | braced-init-list

braced-init-list ::=
    "{" initializer-list ","? "}"
  | "{" designated-initializer-list ","? "}"
  | "{" "}"

initializer-list ::=
    initializer-clause "..."?
  | initializer-list "," initializer-clause "..."?

designated-initializer-list ::=
    designated-initializer-clause
  | designated-initializer-list "," designated-initializer-clause

designated-initializer-clause ::=
    designator brace-or-equal-initializer

designator ::=
    "." identifier

expr-or-braced-init-list ::=
    expression
  | braced-init-list

function-definition ::=
    attribute-specifier-seq? decl-specifier-seq? declarator virt-specifier-seq? function-body
  | attribute-specifier-seq? decl-specifier-seq? declarator requires-clause function-body

function-body ::=
    ctor-initializer? compound-statement
  | function-try-block
  | "=" "default" ";"
  | "=" "delete" ";"

enum-name ::=
    identifier

enum-specifier ::=
    enum-head "{" enumerator-list? "}"
  | enum-head "{" enumerator-list "," "}"

enum-head ::=
    enum-key attribute-specifier-seq? enum-head-name? enum-base?

enum-head-name ::=
    nested-name-specifier? identifier

opaque-enum-declaration ::=
    enum-key attribute-specifier-seq? enum-head-name enum-base? ";"

enum-key ::=
    "enum"
  | "enum" "class"
  | "enum" "struct"

enum-base ::=
    ":" type-specifier-seq

enumerator-list ::=
    enumerator-definition
  | enumerator-list "," enumerator-definition

enumerator-definition ::=
    enumerator
  | enumerator "=" constant-expression

enumerator ::=
    identifier attribute-specifier-seq?

using-enum-declaration ::=
    "using" "enum" using-enum-declarator ";"

using-enum-declarator ::=
    nested-name-specifier? identifier
  | nested-name-specifier? simple-template-id

namespace-name ::=
        identifier
  | namespace-alias

namespace-definition ::=
        named-namespace-definition
  | unnamed-namespace-definition
  | nested-namespace-definition

named-namespace-definition ::=
        "inline"? "namespace" attribute-specifier-seq? identifier "{" namespace-body "}"

unnamed-namespace-definition ::=
        "inline"? "namespace" attribute-specifier-seq? "{" namespace-body "}"

nested-namespace-definition ::=
        "namespace" enclosing-namespace-specifier "::" "inline"? identifier "{" namespace-body "}"

enclosing-namespace-specifier ::=
        identifier
  | enclosing-namespace-specifier "::" "inline"? identifier

namespace-body ::=
        declaration-seq?

namespace-alias ::=
        identifier

namespace-alias-definition ::=
        "namespace" identifier "=" qualified-namespace-specifier ";"

qualified-namespace-specifier ::=
    nested-name-specifier? namespace-name

using-directive ::=
    attribute-specifier-seq? "using" "namespace" nested-name-specifier? namespace-name ";"

using-declaration ::=
    "using" using-declarator-list ";"

using-declarator-list ::=
    using-declarator "..."?
  | using-declarator-list "," using-declarator "..."?

using-declarator ::=
    "typename"? nested-name-specifier unqualified-id

asm-declaration ::=
    attribute-specifier-seq? "asm" "(" balanced-token-seq ")" ";"

linkage-specification ::=
    "extern" unevaluated-string "{" declaration-seq? "}"
  | "extern" unevaluated-string name-declaration

attribute-specifier-seq ::=
  attribute-specifier-seq? attribute-specifier

attribute-specifier ::=
  "[" "[" attribute-using-prefix? attribute-list "]" "]"
  | alignment-specifier

alignment-specifier ::=
  "alignas" "(" type-id "..."? ")"
  | "alignas" "(" constant-expression "..."? ")"

attribute-using-prefix ::=
  "using" attribute-namespace ":"

attribute-list ::=
  attribute?
  | attribute-list "," attribute?
  | attribute "..."
  | attribute-list "," attribute "..."

attribute ::=
    attribute-token attribute-argument-clause?

attribute-token ::=
    identifier
  | attribute-scoped-token

attribute-scoped-token ::=
    attribute-namespace "::" identifier

attribute-namespace ::=
    identifier

attribute-argument-clause ::=
    "(" balanced-token-seq? ")"

balanced-token-seq ::=
    balanced-token
  | balanced-token-seq balanced-token

balanced-token ::=
    "(" balanced-token-seq? ")"
  | "[" balanced-token-seq? "]"
  | "{" balanced-token-seq? "}"
  | "{any token other than a parenthesis, a bracket, or a brace}"

//== modules.tex

module-declaration ::=
    "export"? "module" module-name module-partition? attribute-specifier-seq? ";"

module-name ::=
    module-name-qualifier? identifier

module-partition ::=
    ":" module-name-qualifier? identifier

module-name-qualifier ::=
    identifier "."
  | module-name-qualifier identifier "."

export-declaration ::=
    "export" name-declaration
  | "export" "{" declaration-seq? "}"
  | "export" module-import-declaration

module-import-declaration ::=
    "import" module-name attribute-specifier-seq? ";"
  | "import" module-partition attribute-specifier-seq? ";"
  | "import" header-name attribute-specifier-seq? ";"

global-module-fragment ::=
    "module" ";" declaration-seq?

private-module-fragment ::=
    "module" ":" "private" ";" declaration-seq?

//== classes.tex

class-name ::=
    identifier
  | simple-template-id

class-specifier ::=
    class-head "{" member-specification? "}"

class-head ::=
    class-key attribute-specifier-seq? class-head-name class-virt-specifier? base-clause?
  | class-key attribute-specifier-seq? base-clause?

class-head-name ::=
    nested-name-specifier? class-name

class-virt-specifier ::=
    "final"

class-key ::=
    "class"
  | "struct"
  | "union"

member-specification ::=
    member-declaration member-specification?
  | access-specifier ":" member-specification?

member-declaration ::=
    attribute-specifier-seq? decl-specifier-seq? member-declarator-list? ";"
  | function-definition
  | using-declaration
  | using-enum-declaration
  | static_assert-declaration
  | template-declaration
  | explicit-specialization
  | deduction-guide
  | alias-declaration
  | opaque-enum-declaration
  | empty-declaration

member-declarator-list ::=
    member-declarator
  | member-declarator-list "," member-declarator

member-declarator ::=
    declarator virt-specifier-seq? pure-specifier?
  | declarator requires-clause
  | declarator brace-or-equal-initializer?
  | identifier? attribute-specifier-seq? ":" constant-expression brace-or-equal-initializer?

virt-specifier-seq ::=
    virt-specifier
  | virt-specifier-seq virt-specifier

virt-specifier ::=
    "override"
  | "final"

pure-specifier ::=
    "=" "0"

conversion-function-id ::=
    "operator" conversion-type-id

conversion-type-id ::=
    type-specifier-seq conversion-declarator?

conversion-declarator ::=
    ptr-operator conversion-declarator?

base-clause ::=
    ":" base-specifier-list

base-specifier-list ::=
    base-specifier "..."?
  | base-specifier-list "," base-specifier "..."?

base-specifier ::=
    attribute-specifier-seq? class-or-decltype
  | attribute-specifier-seq? "virtual" access-specifier? class-or-decltype
  | attribute-specifier-seq? access-specifier "virtual"? class-or-decltype

class-or-decltype ::=
    nested-name-specifier? type-name
  | nested-name-specifier "template" simple-template-id
  | decltype-specifier

access-specifier ::=
    "private"
  | "protected"
  | "public"

ctor-initializer ::=
    ":" mem-initializer-list

mem-initializer-list ::=
    mem-initializer "..."?
  | mem-initializer-list "," mem-initializer "..."?

mem-initializer ::=
    mem-initializer-id "(" expression-list? ")"
  | mem-initializer-id braced-init-list

mem-initializer-id ::=
    class-or-decltype
  | identifier

//== overloading.tex

operator-function-id ::=
    "operator" operator

operator ::=
    "new" | "delete" | "new[]" | "delete[]" | "co_await" | "()" | "[]" | "->" | "->*"
  | "~" | "!" | "+" | "-" | "*" | "/" | "%" | "^" | "&"
  | "|" | "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&="
  | "|=" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<=>" | "&&"
  | "||" | "<<" | ">>" | "<<=" | ">>=" | "++" | "--" | ","

literal-operator-id ::=
    "operator" unevaluated-string identifier
  | "operator" user-defined-string-literal

//== templates.tex

template-declaration ::=
  template-head declaration
  | template-head concept-definition

template-head ::=
  "template" "<" template-parameter-list ">" requires-clause?

template-parameter-list ::=
  template-parameter
  | template-parameter-list "," template-parameter

requires-clause ::=
  "requires" constraint-logical-or-expression

constraint-logical-or-expression ::=
  constraint-logical-and-expression
  | constraint-logical-or-expression "||" constraint-logical-and-expression

constraint-logical-and-expression ::=
  primary-expression
  | constraint-logical-and-expression "&&" primary-expression

template-parameter ::=
  type-parameter
  | parameter-declaration

type-parameter ::=
  type-parameter-key "..."? identifier?
  | type-parameter-key identifier? "=" type-id
  | type-constraint "..."? identifier?
  | type-constraint identifier? "=" type-id
  | template-head type-parameter-key "..."? identifier?
  | template-head type-parameter-key identifier? "=" id-expression

type-parameter-key ::=
  "class"
  | "typename"

type-constraint ::=
  nested-name-specifier? concept-name
  | nested-name-specifier? concept-name "<" template-argument-list? ">"

simple-template-id ::=
  template-name "<" template-argument-list? ">"

template-id ::=
  simple-template-id
  | operator-function-id "<" template-argument-list? ">"
  | literal-operator-id "<" template-argument-list? ">"

template-name ::=
  identifier

template-argument-list ::=
  template-argument "..."?
  | template-argument-list "," template-argument "..."?

template-argument ::=
  constant-expression
  | type-id
  | id-expression
  | braced-init-list

constraint-expression ::=
    logical-or-expression

deduction-guide ::=
    explicit-specifier? template-name "(" parameter-declaration-clause ")" "->" simple-template-id ";"

concept-definition ::=
  "concept" concept-name attribute-specifier-seq? "=" constraint-expression ";"

concept-name ::=
  identifier

typename-specifier ::=
  "typename" nested-name-specifier identifier
  | "typename" nested-name-specifier "template"? simple-template-id

explicit-instantiation ::=
  "extern"? "template" declaration

explicit-specialization ::=
  "template" "<" ">" declaration

//== exceptions.tex

try-block ::=
    "try" compound-statement handler-seq

function-try-block ::=
    "try" ctor-initializer? compound-statement handler-seq

handler-seq ::=
    handler handler-seq?

handler ::=
    "catch" "(" exception-declaration ")" compound-statement

exception-declaration ::=
    attribute-specifier-seq? type-specifier-seq declarator
  | attribute-specifier-seq? type-specifier-seq abstract-declarator?
  | "..."

noexcept-specifier ::=
    "noexcept" "(" constant-expression ")"
  | "noexcept"

//== preprocessor.tex

preprocessing-file ::=
    group?
  | module-file

module-file ::=
    pp-global-module-fragment? pp-module group? pp-private-module-fragment?

pp-global-module-fragment ::=
    "module" ";" new-line group?

pp-private-module-fragment ::=
    "module" ":" "private" ";" new-line group?

group ::=
    group-part
  | group group-part

group-part ::=
    control-line
  | if-section
  | text-line
  | "#" conditionally-supported-directive

control-line ::=
    "#" "include" pp-tokens new-line
  | pp-import
  | "#" "define" identifier replacement-list new-line
  | "#" "define" identifier lparen identifier-list? ")" replacement-list new-line
  | "#" "define" identifier lparen "..." ")" replacement-list new-line
  | "#" "define" identifier lparen identifier-list "," "..." ")" replacement-list new-line
  | "#" "undef" identifier new-line
  | "#" "line" pp-tokens new-line
  | "#" "error" pp-tokens? new-line
  | "#" "warning" pp-tokens? new-line
  | "#" "pragma" pp-tokens? new-line
  | "#" new-line

if-section ::=
    if-group elif-groups? else-group? endif-line

if-group ::=
    "#" "if" constant-expression new-line group?
  | "#" "ifdef" identifier new-line group?
  | "#" "ifndef" identifier new-line group?

elif-groups ::=
    elif-group
  | elif-groups elif-group

elif-group ::=
    "#" "elif" constant-expression new-line group?
  | "#" "elifdef" identifier new-line group?
  | "#" "elifndef" identifier new-line group?

else-group ::=
    "#" "else" new-line group?

endif-line ::=
    "#" "endif" new-line

text-line ::=
    pp-tokens? new-line

conditionally-supported-directive ::=
    pp-tokens new-line

lparen ::=
    '{a "(" character not immediately preceded by whitespace}'

identifier-list ::=
    identifier
  | identifier-list "," identifier

replacement-list ::=
    pp-tokens?

pp-tokens ::=
    preprocessing-token
  | pp-tokens preprocessing-token

new-line ::=
    "{the new-line character}"

defined-macro-expression ::=
    "defined" identifier
  | "defined" "(" identifier ")"

h-preprocessing-token ::=
    '{any preprocessing-token other than ">"}'

h-pp-tokens ::=
    h-preprocessing-token
  | h-pp-tokens h-preprocessing-token

header-name-tokens ::=
    string-literal
  | "<" h-pp-tokens ">"

has-include-expression ::=
    "has_include" "(" header-name ")"
  | "has_include" "(" header-name-tokens ")"

has-attribute-expression ::=
    "has_cpp_attribute" "(" pp-tokens ")"

pp-module ::=
    "export"? "module" pp-tokens? ";" new-line

pp-import ::=
    "export"? "import" header-name pp-tokens? ";" new-line
  | "export"? "import" header-name-tokens pp-tokens? ";" new-line
  | "export"? "import" pp-tokens ";" new-line

va-opt-replacement ::=
    "VA_OPT" "(" pp-tokens? ")"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions