robertoraggi / cplusplus

A compiler front end for the C++ language
https://robertoraggi.github.io/cplusplus/
MIT License
121 stars 12 forks source link

Changing "specs/grammar.txt" to an EBNF understood by https://www.bottlecaps.de/rr/ui #281

Open mingodad opened 9 months ago

mingodad commented 9 months ago

If we change "specs/grammar.txt" to an EBNF understood by https://www.bottlecaps.de/rr/ui we can get a nice navigable railroad diagram representation of it that can help document/develop/debug this project grammar, follow the instructions shown bellow:

//
// 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? ")"
mingodad commented 9 months ago

Using the EBNF syntax to also give a high level view for the actual parser (not finished):

//
// 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.
//

parse_translation_unit ::=
    parse_module_unit
    | parse_top_level_declaration_seq

parse_module_unit ::=
    parse_module_head parse_global_module_fragment
        parse_module_declaration parse_declaration_seq parse_private_module_fragment

parse_top_level_declaration_seq ::=
    parse_declaration+

parse_declaration_seq ::=
    parse_maybe_module
    | parse_declaration+

parse_declaration ::=
    parse_empty_declaration
    | parse_explicit_instantiation
    | parse_template_declaration
    | parse_linkage_specification
    | parse_namespace_definition
    | parse_deduction_guide
    | parse_export_declaration
    | parse_module_import_declaration
    | parse_attribute_declaration
    | parse_block_declaration

parse_empty_declaration ::=
    T_SEMICOLON

parse_explicit_instantiation ::=
    T_EXTERN T_TEMPLATE parse_declaration

parse_template_declaration ::=
    T_TEMPLATE T_LESS parse_template_parameter_list T_GREATER
        parse_requires_clause parse_template_declaration?
        parse_concept_definition?
        parse_template_declaration_body

parse_linkage_specification ::=
    T_EXTERN parse_optional_attribute_specifier_seq T_STRING_LITERAL
        (T_LBRACE parse_declaration_seq T_RBRACE | parse_declaration )

parse_namespace_definition ::=
    T_INLINE? T_NAMESPACE parse_optional_attribute_specifier_seq T_IDENTIFIER T_COLON_COLON
        parse_namespace_body

parse_deduction_guide ::=
    parse_explicit_specifier T_IDENTIFIER T_LPAREN parse_parameter_declaration_clause T_RPAREN
        parse_simple_template_id T_SEMICOLON

parse_export_declaration ::=
    T_EXPORT (T_LBRACE parse_declaration_seq T_RBRACE | parse_module_import_declaration? parse_declaration )

parse_module_import_declaration ::=
    parse_import_keyword parse_import_name parse_optional_attribute_specifier_seq T_SEMICOLON

parse_attribute_declaration ::=
    parse_attribute_specifier_seq T_SEMICOLON

parse_block_declaration ::=
    parse_asm_declaration
    | parse_namespace_alias_definition
    | parse_static_assert_declaration
    | parse_opaque_enum_declaration
    | parse_using_enum_declaration
    | parse_using_directive
    | parse_alias_declaration
    | parse_using_declaration
    | parse_simple_declaration

parse_asm_declaration ::=
    T_ASM AsmQualifier* T_LPAREN T_STRING_LITERAL
        AsmOutputOperandList? AsmInpputOperandList?
        T_RPAREN T_SEMICOLON

AsmQualifier ::=
    T_INLINE
    | T_VOLATILE
    | T_GOTO

AsmOutputOperandList ::=
    AsmInOutOperandList

AsmInpputOperandList ::=
    AsmInOutOperandList

AsmInOutOperandList ::=
    T_COLON parse_asm_operand (T_COMMA parse_asm_operand)*

parse_namespace_alias_definition ::=
    T_NAMESPACE T_IDENTIFIER T_EQUAL parse_qualified_namespace_specifier T_SEMICOLON

parse_static_assert_declaration ::=
    T_STATIC_ASSERT T_LPAREN parse_constant_expression (T_COMMA T_STRING_LITERAL)? T_RPAREN T_SEMICOLON

parse_opaque_enum_declaration ::=
    parse_optional_attribute_specifier_seq parse_enum_key parse_enum_head_name parse_enum_base T_SEMICOLON

parse_using_enum_declaration ::=
    T_USING parse_elaborated_enum_specifier T_SEMICOLON

parse_using_directive ::=
    T_USING T_NAMESPACE parse_optional_nested_name_specifier parse_name_id T_SEMICOLON

parse_alias_declaration ::=
    T_USING T_IDENTIFIER parse_optional_attribute_specifier_seq T_EQUAL parse_defining_type_id T_SEMICOLON

parse_using_declaration ::=
    T_USING parse_using_declarator_list T_SEMICOLON

parse_simple_declaration ::=
    parse_one_simple_declaration+

parse_one_simple_declaration ::=
    T___EXTENSION__? parse_optional_attribute_specifier_seq
        (
        T_SEMICOLON
        | parse_template_class_declaration
        | parse_empty_or_attribute_declaration
        | parse_notypespec_function_definition
        | parse_decl_specifier_seq
        | parse_type_or_forward_declaration
        | parse_structured_binding
        )

parse_module_head ::=
    T_EXPORT parse_id

parse_global_module_fragment ::=
    parse_module_keyword T_SEMICOLON parse_declaration_seq

parse_module_declaration ::=
    parse_export_keyword parse_module_keyword parse_module_name parse_module_partition
        parse_optional_attribute_specifier_seq T_SEMICOLON

parse_private_module_fragment ::=
    parse_module_keyword T_COLON T_PRIVATE T_SEMICOLON parse_declaration_seq

parse_block_declaration ::=
    parse_class_specifier parse_attribute_specifier_seq T_SEMICOLON

parse_class_specifier ::=
    parse_class_head T_LBRACE parse_class_body T_RBRACE

parse_class_head ::=
    (T_CLASS | T_STRUCT | T_UNION) parse_optional_attribute_specifier_seq
        parse_class_head_name parse_class_virt_specifier parse_base_clause

parse_class_head_name ::=
    parse_optional_nested_name_specifier check_type_traits parse_type_name

parse_class_virt_specifier ::=
    parse_final

parse_base_clause ::=
    T_COLON parse_base_specifier_list

parse_base_specifier_list ::=
    parse_base_specifier T_DOT_DOT_DOT ( T_COMMA parse_base_specifier T_DOT_DOT_DOT)*

parse_base_specifier ::=
    parse_optional_attribute_specifier_seq
        (T_VIRTUAL parse_access_specifier | parse_access_specifier T_VIRTUAL)?
        parse_class_or_decltype

parse_class_body ::=
    parse_member_specification*

parse_member_specification ::=
    parse_member_declaration

parse_member_declaration ::=
    parse_access_specifier T_COLON
    | parse_empty_declaration
    | parse_using_enum_declaration
    | parse_alias_declaration
    | parse_using_declaration
    | parse_static_assert_declaration
    | parse_deduction_guide
    | parse_opaque_enum_declaration
    | parse_template_declaration
    | parse_member_declaration_helper

parse_member_declaration_helper ::=
    T___EXTENSION__? parse_optional_attribute_specifier_seq parse_decl_specifier_seq_no_typespecs
        (parse_notypespec_function_definition | parse_decl_specifier_seq T_SEMICOLON )

parse_notypespec_function_definition ::=
    parse_declarator_id parse_function_declarator parse_requires_clause parse_virt_specifier_seq
        parse_optional_attribute_specifier_seq parse_pure_specifier (T_SEMICOLON | parse_function_body)

parse_function_body ::=
    parse_function_try_block
    | T_EQUAL T_DEFAULT T_SEMICOLON
    | T_EQUAL T_DELETE T_SEMICOLON
    | parse_ctor_initializer parse_compound_statement

parse_compound_statement ::=
    T_LBRACE finish_compound_statement? T_RBRACE

finish_compound_statement ::=
    ( parse_maybe_statement | parse_skip_statement )+

parse_maybe_statement ::=
    T___EXTENSION__? (
        parse_case_statement
        | parse_default_statement
        | parse_while_statement
        | parse_do_statement
        | parse_for_statement
        | parse_if_statement
        | parse_switch_statement
        | parse_break_statement
        | parse_continue_statement
        | parse_return_statement
        | parse_goto_statement
        | parse_coroutine_return_statement
        | parse_try_block
        | parse_maybe_compound_statement
        | parse_labeled_statement
        | parse_declaration_statement
        | parse_expression_statement
    )

parse_case_statement ::=
    T_CASE parse_constant_expression T_COLON

parse_default_statement ::=
    T_DEFAULT T_COLON

parse_while_statement ::=
    T_WHILE T_LPAREN parse_condition T_RPAREN

parse_do_statement ::=
    T_DO parse_statement T_WHILE T_LPAREN parse_expression T_RPAREN T_SEMICOLON

parse_for_statement ::=
    parse_for_range_statement
    | T_FOR T_LPAREN parse_init_statement T_SEMICOLON parse_condition T_SEMICOLON parse_expression T_RPAREN
        parse_statement

parse_for_range_statement ::=
    T_FOR T_LPAREN parse_init_statement parse_for_range_declaration T_COLON parse_for_range_initializer T_RPAREN
        parse_statement

parse_init_statement ::=
    parse_simple_declaration parse_maybe_expression

parse_for_range_declaration ::=
    parse_decl_specifier_seq ( parse_structured_binding | parse_declarator )

parse_for_range_initializer ::=
    parse_expr_or_braced_init_list

parse_if_statement ::=
    T_IF (
        T_EXCLAIM  T_CONSTEVAL parse_compound_statement (T_ELSE parse_statement)?
        | T_CONSTEXPR? T_LPAREN parse_init_statement parse_condition T_RPAREN parse_statement (T_ELSE parse_statement)?
        )

parse_switch_statement ::=
    T_SWITCH T_LPAREN parse_init_statement parse_condition T_RPAREN parse_statement

parse_break_statement ::=
    T_BREAK T_SEMICOLON

parse_continue_statement ::=
    T_CONTINUE T_SEMICOLON

parse_return_statement ::=
    T_RETURN parse_expr_or_braced_init_list? T_SEMICOLON

parse_goto_statement ::=
    T_GOTO T_IDENTIFIER T_SEMICOLON

parse_coroutine_return_statement ::=
    T_CO_RETURN parse_expr_or_braced_init_list? T_SEMICOLON

parse_try_block ::=
    T_TRY parse_compound_statement parse_handler_seq

parse_handler_seq ::=
    T_CATCH parse_handler

parse_maybe_compound_statement ::=
    parse_compound_statement?

parse_labeled_statement ::=
    T_IDENTIFIER T_COLON

parse_declaration_statement ::=
    parse_block_declaration

parse_expression_statement ::=
    T_SEMICOLON
    | parse_maybe_expression T_SEMICOLON

parse_final ::=
    parse_id

parse_optional_attribute_specifier_seq ::=
    parse_attribute_specifier*

parse_attribute_specifier ::=
    parse_cxx_attribute_specifier
    | parse_gcc_attribute
    | parse_alignment_specifier
    | parse_asm_specifier

parse_cxx_attribute_specifier ::=
    T_LBRACKET T_LBRACKET parse_attribute_using_prefix parse_attribute_list T_RBRACKET T_RBRACKET

parse_gcc_attribute ::=
    T___ATTRIBUTE__ T_LPAREN parse_skip_balanced T_RPAREN

parse_alignment_specifier ::=
    T_ALIGNAS T_LPAREN parse_type_id T_DOT_DOT_DOT T_RPAREN

parse_asm_specifier ::=
    T_ASM T_LPAREN T_STRING_LITERAL T_RPAREN

//
//Tokens
//

T_SEMICOLON ::= ';'
T_EXTERN ::= "extern"
T_TEMPLATE ::= "template"
T_LESS ::= '<'
T_GREATER ::= '>'
T_LBRACE ::= '{'
T_RBRACE ::= '}'
T_LPAREN ::= '('
T_RPAREN ::= ')'
T_LBRACKET ::= '['
T_RBRACKET ::= ']'
T_COLON ::= ':'
T_COMMA ::= ','
T_EQUAL ::= '='
T_EXCLAIM ::= '!'
T_COLON_COLON ::= "::"
T_NAMESPACE ::= "namespace"
T_INLINE ::= "inline"
T_EXPORT ::= "export"
T_ASM ::= "asm"
T_VOLATILE ::= "volatile"
T_GOTO ::= "goto"
T_STATIC_ASSERT ::= "static_assert"
T_USING ::= "using"
T___EXTENSION__ ::= "__extension__"
T_PRIVATE ::= "private"
T___ATTRIBUTE__ ::= "__attribute__"
T_ALIGNAS ::= "allignas"
T_DOT_DOT_DOT ::= "..."
T_VIRTUAL ::= "virtual"
T_CASE ::= "case"
T_DEFAULT ::= "default"
T_WHILE ::= "while"
T_IF ::= "if"
T_ELSE ::= "else"
T_CONSTEVAL ::= "consteval"
T_SWITCH ::= "switch"
T_BREAK ::= "break"
T_RETURN ::= "return"
T_CO_RETURN ::= "co_return"
T_TRY ::= "try"
T_CATCH ::= "catch"
T_FOR ::= "for"
T_CLASS ::= "class"
T_STRUCT ::= "struct"
T_UNION ::= "union"
T_DELETE ::= "delete"
T_DO ::= "do"
T_CONSTEXPR ::= "constexpr"
T_CONTINUE ::= "continue"

T_STRING_LITERAL ::= '"' ('\' . | [^"\\n\\r\\])* '"'
T_IDENTIFIER ::= [A-Za-z_][A-Za-z0-9_]*
mingodad commented 9 months ago

I figured out that the content on specs/grammar.txt come from https://github.com/cplusplus/draft so I made a script to scrap/convert it to an EBNF understood by https://www.bottlecaps.de/rr/ui see the result here https://github.com/cplusplus/draft/issues/6742 .

robertoraggi commented 8 months ago

Thanks for your suggestion but I'm not sure it is a good idea to diverge too much from the official C++ grammar, the C++ language is still evolving. In the past I had a C++ grammar in BNF for pgen, a simple generalized parser generator that I wrote, but it was way too much work to maintain.

https://github.com/robertoraggi/pgen https://github.com/robertoraggi/cplusplus/blob/554e41b4c07b88f7cf51787e37d6b21dcf7481ef/src/cxx/parser.pgen

mingodad commented 8 months ago

Not at all ! This one is mechanically extracted from the files at https://github.com/cplusplus/draft/

mingodad commented 8 months ago

I've just added the C++11, C++14, C++117, C++20, C++23-draft converted to the EBNF understood by https://www.bottlecaps.de/rr/ui and the navigable railroad diagrams read to view here https://mingodad.github.io/cpp-grammars/ .

mingodad commented 7 months ago

Maybe you'll also be interested in https://github.com/thradams/cake and it's playground http://thradams.com/cake/playground.html it has an interesting borrow checker extension.

robertoraggi commented 7 months ago

@mingodad Thanks for the suggestion, it looks like an interesting project to follow. Once I’m done with core language, I plan to implement a few extensions for C++, with reflection and memory safety being on top of my list.

mingodad commented 4 months ago

Today I found this project https://github.com/srcML/srcML and they have a wasm playground here http://www.srcml.org/doc/playground.html that is very interesting and I think that it can be interesting to you too.