Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mingodad opened this issue Dec 20, 2023 · 8 comments

Comments

@mingodad
Copy link

mingodad commented Dec 20, 2023

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
Copy link
Author

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
Copy link
Author

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 cplusplus/draft#6742 .

@robertoraggi
Copy link
Owner

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
Copy link
Author

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

@mingodad
Copy link
Author

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
Copy link
Author

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
Copy link
Owner

@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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants