alx71hub / hcb

Hyperlinked C++ BNF Grammar
GNU General Public License v3.0
41 stars 7 forks source link

Grammar railroad diagram #11

Open mingodad opened 2 years ago

mingodad commented 2 years ago

Viewing https://alx71hub.github.io/hcb/ in a browser and selecting all and copying and pasting on an editor and manually fixing it to be an EBNF understood by https://www.bottlecaps.de/rr/ui we can have a nice navigable railroad diagram.

Copy and paste the EBNF (manually incomplete translated) shown bellow on https://www.bottlecaps.de/rr/ui on the tab Edit Grammar the click on the tab View Diagram to see/download a navigable railroad diagram.

/*
Hyperlinked C++ BNF Grammar
By Alessio Marchetti

Version 3.6

Last updated: 10-Aug-2021

Purpose of this document
If you are a C++ developer then you sometimes need to have a look at the C++ BNF grammar. At least I do.

But reading a set of BNF rules is difficult since you have to jump from one rule to the next one, maybe pages away from it.

With this document I tried to make it easier to navigate among the BNF rules of the C++ language grammar; you can find here a hyperlinked graph whose nodes are the BNF productions of the C++ language grammar.

If you find errors or inconsistencies, please log an issue.

The BNF non-terminal for a C++ translation unit (translation-unit) is defined here.
The BNF non-terminal for a C++ preprocessing file (preprocessing-file) is defined here.
BNF Grammar Rules
*/

start_here ::= translation-unit // for easy navigation purpose

//lex.charset
hex-quad ::=
    hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit
universal-character-name ::=
    "\u" hex-quad
    | "\U" hex-quad hex-quad

//lex.pptoken
preprocessing-token ::=
    header-name
    | identifier
    | pp-number
    | character-literal
    | user-defined-character-literal     // C++0x
    | string-literal
    | user-defined-string-literal     // C++0x
    | preprocessing-op-or-punc
    //each non-white-space character that cannot be one of the above

//lex.token
token ::=
    identifier
    | keyword
    | literal
    | operator-token // See C++ Standard Core Language Issue n. 189
    | punctuator // See C++ Standard Core Language Issue n. 189

//lex.header
header-name ::=
    '<' h-char-sequence '>'
    | '"' q-char-sequence '"'
h-char-sequence ::=
    h-char
    | h-char-sequence h-char
h-char ::=
    //any member of the source character set except new-line and >
    [^\n>]
q-char-sequence ::=
    q-char
    | q-char-sequence q-char
q-char ::=
    //any member of the source character set except new-line and "
    [^\n"]

//lex.ppnumber
pp-number ::=
    digit
    | '.' digit
    | pp-number digit
    | pp-number identifier-nondigit
    | pp-number 'e' sign
    | pp-number 'E' sign
    | pp-number '.'

//lex.name
identifier ::=
    identifier-nondigit     // C++0x
    | identifier identifier-nondigit     // C++0x
    | identifier digit
identifier-nondigit ::=
    nondigit     // C++0x
    | universal-character-name     // C++0x
    // other implementation-defined characters     // C++0x
nondigit ::=
    universal-character-name     // Removed in C++0x
    [a-zA-Z_]
    // _     (underscore)
digit ::=
    [0-9]

//lex.key
keyword ::=
     "alignas"     // C++0x
    | "alignof"     // C++0x
    | "asm"
    | "auto"
    | "bool"
    | "break"
    | "case"
    | "catch"
    | "char"
    | "char16_t"     // C++0x
    | "char32_t"     // C++0x
    | "class"
    | "const"
    | "constexpr"     // C++0x
    | "const_cast"
    | "continue"
    | "decltype"     // C++0x
    | "default"
    | "delete"
    | "do"
    | "double"
    | "dynamic_cast"
    | "else"
    | "enum"
    | "explicit"
    | "export"     // C++0x - Reserved for future use
    | "extern"
    | "false"
    | "float"
    | "for"
    | "friend"
    | "goto"
    | "if"
    | "inline"
    | "int"
    | "long"
    | "mutable"
    | "namespace"
    | "new"
    | "noexcept"     // C++0x
    | "nullptr"     // C++0x
    | "operator"
    | "private"
    | "protected"
    | "public"
    | "register"
    | "reinterpret_cast"
    | "return"
    | "short"
    | "signed"
    | "sizeof"
    | "static"
    | "static_assert"     // C++0x
    | "static_cast"
    | "struct"
    | "switch"
    | "template"
    | "this"
    | "thread_local"     // C++0x
    | "throw"
    | "true"
    | "try"
    | "typedef"
    | "typeid"
    | "typename"
    | "union"
    | "unsigned"
    | "using"
    | "virtual"
    | "void"
    | "volatile"
    | "wchar_t"
    | "while"

//lex.operators
operator-token ::=
    //Look at preprocessing-op-or-punc below // See C++ Standard Core Language Issue n. 189
punctuator ::=
    //Look at preprocessing-op-or-punc below // See C++ Standard Core Language Issue n. 189
preprocessing-op-or-punc ::=
     "{"
    | "}"
    | "["
    | "]"
    | "#"
    | "##"
    | "("
    | ")"
    | "<:"
    | ":>"
    | "<%"
    | "%>"
    | "%:"
    | "%:%:"
    | ";"
    | ":"
    | "..."
    | "new"
    | "delete"
    | "?"
    | "::"
    | "."
    | ".*"
    | "+"
    | "-"
    | "*"
    | "/"
    | "%"
    | "^"
    | "&"
    | "|"
    | "~"
    | "!"
    | "="
    | "<"
    | ">"
    | "+="
    | "-="
    | "*="
    | "/="
    | "%="
    | "^="
    | "&="
    | "|="
    | "<<"
    | ">>"
    | "<<="
    | ">>="
    | "=="
    | "!="
    | "<="
    | ">="
    | "&&"
    | "||"
    | "++"
    | "--"
    | ","
    | "->*"
    | "->"
    | "and"
    | "and_eq"
    | "bitand"
    | "bitor"
    | "compl"
    | "not"
    | "not_eq"
    | "or"
    | "or_eq"
    | "xor"
    | "xor_eq"

//lex.literal.kinds
literal ::=
    integer-literal
    | character-literal
    | floating-literal
    | string-literal
    | boolean-literal
    | pointer-literal     // C++0x
    | user-defined-literal     // C++0x

//lex.icon
integer-literal ::=
    decimal-literal integer-suffix?
    | octal-literal integer-suffix?
    | hexadecimal-literal integer-suffix?
decimal-literal ::=
    nonzero-digit
    | decimal-literal digit
octal-literal ::=
    '0'
    | octal-literal octal-digit
hexadecimal-literal ::=
    '0x' hexadecimal-digit
    | '0X' hexadecimal-digit
    | hexadecimal-literal hexadecimal-digit
nonzero-digit ::=
    [1-9]
octal-digit ::=
    [0-7]
hexadecimal-digit ::=
    [0-9a-fA-F]
integer-suffix ::=
    unsigned-suffix long-suffix?
    | unsigned-suffix long-long-suffix?     // C++0x
    | long-suffix unsigned-suffix?
    | long-long-suffix unsigned-suffix?     // C++0x
unsigned-suffix ::=
    'u'
    | 'U'
long-suffix ::=
    'l'
    | 'L'
long-long-suffix ::=
    'll'     // C++0x
    | 'LL'     // C++0x

//lex.ccon
character-literal ::=
    "'" c-char-sequence "'"
    | "u'" c-char-sequence "'"     // C++0x
    | "U'" c-char-sequence "'"     // C++0x
    | "L'" c-char-sequence "'"
c-char-sequence ::=
    c-char
    | c-char-sequence c-char
c-char ::=
    //any member of the source character set except the single quote ', backslash \, or new-line character
    escape-sequence
    | universal-character-name
escape-sequence ::=
    simple-escape-sequence
    | octal-escape-sequence
    | hexadecimal-escape-sequence
simple-escape-sequence ::=
     "\'"
    | '\"'
    | "\?"
    | "\\"
    | "\a"
    | "\b"
    | "\f"
    | "\n"
    | "\r"
    | "\t"
    | "\v"
octal-escape-sequence ::=
     "\" octal-digit
    | "\" octal-digit octal-digit
    | "\" octal-digit octal-digit octal-digit
hexadecimal-escape-sequence ::=
    "\x" hexadecimal-digit
    | hexadecimal-escape-sequence hexadecimal-digit

//lex.fcon
floating-literal ::=
    fractional-constant exponent-part? floating-suffix?
    | digit-sequence exponent-part floating-suffix?
fractional-constant ::=
    digit-sequence? '.' digit-sequence
    | digit-sequence .
exponent-part ::=
    'e' sign? digit-sequence
    | 'E' sign? digit-sequence
sign ::=
    '+'
    | '-'
digit-sequence ::=
    digit
    | digit-sequence digit
floating-suffix ::=
     "f"
    | "l"
    | "F"
    | "L"

//lex.string
string-literal ::=
    encoding-prefix? '"' s-char-sequence? '"'     // C++0x
    | encoding-prefix? 'R' raw-string     // C++0x
encoding-prefix ::=
     "u8"     // C++0x
    | "u"    // C++0x
    | "U"     // C++0x
    | "L"    // C++0x
s-char-sequence ::=
    s-char
    | s-char-sequence s-char
s-char ::=
    //any member of the source character set except the double-quote ", backslash \, or new-line character
    escape-sequence
    | universal-character-name
raw-string ::=
    '"' d-char-sequence? '(' r-char-sequence? ')' d-char-sequence? '"'     // C++0x
r-char-sequence ::=
    r-char     // C++0x
    | r-char-sequence r-char     // C++0x
r-char ::=
    //any member of the source character set, except a right parenthesis ) followed by the initial d-char-sequence (which may be empty) followed by a double quote ".     // C++0x

d-char-sequence ::=
    d-char     // C++0x
    | d-char-sequence d-char     // C++0x
d-char ::=
    //any member of the basic source character set, except: space, the left parenthesis (, the right parenthesis ), the backslash \, and the control characters representing horizontal tab, vertical tab, form feed, and newline.     // C++0x

//lex.bool
boolean-literal ::=
     "false"
    | "true"

//lex.nullptr
pointer-literal ::=
    "nullptr"     // C++0x

//lex.ext
user-defined-literal ::=
    user-defined-integer-literal     // C++0x
    | user-defined-floating-literal     // C++0x
    | user-defined-string-literal     // C++0x
    | user-defined-character-literal     // C++0x
user-defined-integer-literal ::=
    decimal-literal ud-suffix     // C++0x
    | octal-literal ud-suffix     // C++0x
    | hexadecimal-literal ud-suffix     // C++0x
user-defined-floating-literal ::=
    fractional-constant exponent-part? ud-suffix     // C++0x
    | digit-sequence exponent-part ud-suffix     // C++0x
user-defined-string-literal ::=
    string-literal ud-suffix     // C++0x
user-defined-character-literal ::=
    character-literal ud-suffix     // C++0x
ud-suffix ::=
    identifier     // C++0x

//basic.link
translation-unit ::=
    declaration-seq?

//expr.prim.general
primary-expression ::=
    literal
    | "this"
    | '(' expression ')'
    | id-expression
    | lambda-expression     // C++0x
id-expression ::=
    unqualified-id
    | qualified-id
unqualified-id ::=
    identifier
    | operator-function-id
    | conversion-function-id
    | literal-operator-id     // C++0x
    | '~' class-name
    | '~' decltype-specifier     // C++0x
    | template-id
qualified-id ::=
    | "::"? nested-name-specifier template? unqualified-id
    | "::" identifier
    | "::" operator-function-id
    | "::" literal-operator-id     // C++0x
    | "::" template-id
nested-name-specifier ::=
    type-name "::"
    | namespace-name "::"
    | decltype-specifier "::"     // C++0x
    | nested-name-specifier identifier "::"
    | nested-name-specifier template? simple-template-id "::"

//expr.prim.lambda
lambda-expression ::=
    lambda-introducer lambda-declarator? compound-statement     // C++0x
lambda-introducer ::=
    '[' lambda-capture? ']'     // C++0x
lambda-capture ::=
    capture-default     // C++0x
    | capture-list     // C++0x
    | capture-default ',' capture-list     // C++0x
capture-default ::=
     '&'     // C++0x
    | '='     // C++0x
capture-list ::=
    capture "..."?     // C++0x
    | capture-list ',' capture "..."?     // C++0x
capture ::=
    identifier     // C++0x
    | '&' identifier     // C++0x
    | "this"     // C++0x
lambda-declarator ::=
    '(' parameter-declaration-clause ')' mutable? exception-specification? attribute-specifier-seq? trailing-return-type?     // C++0x

//expr.post
postfix-expression ::=
    primary-expression
    | postfix-expression '[' expression ']'
    | postfix-expression '[' braced-init-list? ']'     // C++0x
    | postfix-expression '(' expression-list? ')'
    | simple-type-specifier '(' expression-list? ')'
    | typename-specifier '(' expression-list? ')'
    | simple-type-specifier braced-init-list     // C++0x
    | typename-specifier braced-init-list     // C++0x
    | postfix-expression '.' template? id-expression
    | postfix-expression "->" template? id-expression
    | postfix-expression '.' pseudo-destructor-name
    | postfix-expression "->" pseudo-destructor-name
    | 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
pseudo-destructor-name ::=
     "::"? nested-name-specifier? type-name "::" '~' type-name
    | "::"? nested-name-specifier template simple-template-id "::" '~' type-name     // C++0x
    | "::"? nested-name-specifier? '~' type-name
    | "~" decltype-specifier     // C++0x

//expr.unary
unary-expression ::=
    postfix-expression
    | "++" cast-expression
    | "--" cast-expression
    | unary-operator cast-expression
    | "sizeof" unary-expression
    | "sizeof" '(' type-id ')'
    | "sizeof" "..." '(' identifier ')'     // C++0x
    | "alignof" '(' type-id ')'     // C++0x
    | noexcept-expression     // C++0x
    | new-expression
    | delete-expression
unary-operator ::=
     '*'
    | '&'
    | '+'
    | '-'
    | '!'
    | '~'

//expr.new
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     // C++0x
noptr-new-declarator ::=
    '[' expression ']' attribute-specifier-seq?     // C++0x
    | noptr-new-declarator '[' constant-expression ']' attribute-specifier-seq?     // C++0x
new-initializer ::=
    '(' expression-list? ')'
    | braced-init-list     // C++0x

//expr.delete
delete-expression ::=
     "::"? "delete" cast-expression
    | "::"? "delete" '[' ']' cast-expression

//expr.unary.noexcept
noexcept-expression ::=
    "noexcept" '(' expression ')'     // C++0x

//expr.cast
cast-expression ::=
    unary-expression
    | '(' type-id ')' cast-expression

//expr.mptr.oper
pm-expression ::=
    cast-expression
    | pm-expression ".*" cast-expression
    | pm-expression "->*" cast-expression

//expr.mul
multiplicative-expression ::=
    pm-expression
    | multiplicative-expression '*' pm-expression
    | multiplicative-expression '/' pm-expression
    | multiplicative-expression '%' pm-expression

//expr.add
additive-expression ::=
    multiplicative-expression
    | additive-expression '+' multiplicative-expression
    | additive-expression '-' multiplicative-expression

//expr.shift
shift-expression ::=
    additive-expression
    | shift-expression '<<' additive-expression
    | shift-expression '>>' additive-expression

//expr.rel
relational-expression ::=
    shift-expression
    | relational-expression "<" shift-expression
    | relational-expression ">" shift-expression
    | relational-expression "<=" shift-expression
    | relational-expression ">=" shift-expression

//expr.eq
equality-expression ::=
    relational-expression
    | equality-expression "==" relational-expression
    | equality-expression "!=" relational-expression

//expr.bit.and
and-expression ::=
    equality-expression
    | and-expression '&' equality-expression

//expr.xor
exclusive-or-expression ::=
    and-expression
    | exclusive-or-expression '^' and-expression

//expr.or
inclusive-or-expression ::=
    exclusive-or-expression
    | inclusive-or-expression '|' exclusive-or-expression

//expr.log.and
logical-and-expression ::=
    inclusive-or-expression
    | logical-and-expression "&&" inclusive-or-expression

//expr.log.or
logical-or-expression ::=
    logical-and-expression
    | logical-or-expression "||" logical-and-expression

//expr.cond
conditional-expression ::=
    logical-or-expression
    | logical-or-expression '?' expression ':' assignment-expression

//expr.ass
assignment-expression ::=
    conditional-expression
    | logical-or-expression assignment-operator initializer-clause     // C++0x
    | throw-expression
assignment-operator ::=
     "="
    | "*="
    | "/="
    | "%="
    | "+="
    | "-="
    | ">>="
    | "<<="
    | "&="
    | "^="
    | "|="

//expr.comma
expression ::=
    assignment-expression
    | expression ',' assignment-expression

//expr.const
constant-expression ::=
    conditional-expression

//stmt.stmt
statement ::=
    labeled-statement
    | attribute-specifier-seq? expression-statement     // C++0x
    | attribute-specifier-seq? compound-statement     // C++0x
    | attribute-specifier-seq? selection-statement     // C++0x
    | attribute-specifier-seq? iteration-statement     // C++0x
    | attribute-specifier-seq? jump-statement     // C++0x
    | declaration-statement
    | attribute-specifier-seq? try-block

//stmt.label
labeled-statement ::=
    attribute-specifier-seq? identifier ':' statement
    | attribute-specifier-seq? "case" constant-expression ':' statement
    | attribute-specifier-seq? "default" ':' statement

//stmt.expr
expression-statement ::=
    expression? ';'

//stmt.block
compound-statement ::=
    '{' statement-seq? '}'
statement-seq ::=
    statement
    | statement-seq statement

//stmt.select
selection-statement ::=
     "if" '(' condition ')' statement
    | "if" '(' condition ')' statement else statement
    | "switch" '(' condition ')' statement
condition ::=
    expression
    | attribute-specifier-seq? decl-specifier-seq declarator '=' initializer-clause     // C++0x
    | attribute-specifier-seq? decl-specifier-seq declarator braced-init-list     // C++0x

//stmt.iter
iteration-statement ::=
     "while" '(' condition ')' statement
    | "do" statement "while" '(' expression ')' ';'
    | "for" '(' for-init-statement condition? ';' expression? ')' statement
    | "for" '(' for-range-declaration ':' for-range-initializer ')' statement     // C++0x
for-init-statement ::=
    expression-statement
    | simple-declaration
for-range-declaration ::=
    attribute-specifier-seq? type-specifier-seq declarator     // C++0x
for-range-initializer ::=
    expression
    | braced-init-list

//stmt.jump
jump-statement ::=
     "break" ';'
    | "continue" ';'
    | "return" expression? ';'
    | "return" braced-init-list? ';'     // C++0x
    | "goto" identifier ';'

//stmt.dcl
declaration-statement ::=
    block-declaration

//dcl.dcl
declaration-seq ::=
    declaration
    | declaration-seq declaration
declaration ::=
    block-declaration
    | function-definition
    | template-declaration
    | explicit-instantiation
    | explicit-specialization
    | linkage-specification
    | namespace-definition
    | empty-declaration     // C++0x
    | attribute-declaration     // C++0x
block-declaration ::=
    simple-declaration
    | asm-definition
    | namespace-alias-definition
    | using-declaration
    | using-directive
    | static_assert-declaration     // C++0x
    | alias-declaration     // C++0x
    | opaque-enum-declaration     // C++0x
alias-declaration ::=
    using identifier '=' type-id ';'     // C++0x
simple-declaration ::=
    attribute-specifier-seq? decl-specifier-seq? init-declarator-list? ';'     // C++0x
static_assert-declaration ::=
    "static_assert" '(' constant-expression ',' string-literal ')' ';'     // C++0x
empty-declaration ::=
    ';'     // C++0x
attribute-declaration ::=
    attribute-specifier-seq ';'     // C++0x

//dcl.spec
decl-specifier ::=
    storage-class-specifier
    | type-specifier
    | function-specifier
    | "friend"
    | "typedef"
    | "constexpr"     // C++0x
decl-specifier-seq ::=
    decl-specifier attribute-specifier-seq?     // C++0x
    | decl-specifier decl-specifier-seq     // C++0x

//dcl.stc
storage-class-specifier ::=
     "auto"     // Removed in C++0x
    | "register"
    | "static"
    | "thread_local"     // C++0x
    | "extern"
    | "mutable"

//dcl.fct.spec
function-specifier ::=
     "inline"
    | "virtual"
    | "explicit"

//dcl.typedef
typedef-name ::=
    identifier

//dcl.type
type-specifier ::=
    trailing-type-specifier
    | class-specifier
    | enum-specifier
trailing-type-specifier ::=
    simple-type-specifier
    | elaborated-type-specifier
    | typename-specifier
    | cv-qualifier
type-specifier-seq ::=
    type-specifier attribute-specifier-seq?     // C++0x
    | type-specifier type-specifier-seq
trailing-type-specifier-seq ::=
    trailing-type-specifier attribute-specifier-seq?     // C++0x
    | trailing-type-specifier trailing-type-specifier-seq     // C++0x

dct.type.simple
simple-type-specifier ::=
     "::"? nested-name-specifier? type-name
    | "::"? nested-name-specifier template simple-template-id
    | "char"
    | "char16_t"     // C++0x
    | "char32_t"     // C++0x
    | "wchar_t"
    | "bool"
    | "short"
    | "int"
    | "long"
    | "signed"
    | "unsigned"
    | "float"
    | "double"
    | "void"
    | "auto"     // C++0x
    | decltype-specifier     // C++0x
type-name ::=
    class-name
    | enum-name
    | typedef-name
    | simple-template-id     // C++0x
decltype-specifier ::=
    decltype '(' expression ')'     // C++0x

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

//dcl.enum
enum-name ::=
    identifier
enum-specifier ::=
    enum-head '{' enumerator-list? '}'     // C++0x
    | enum-head '{' enumerator-list ',' '}'     // C++0x
enum-head ::=
    enum-key attribute-specifier-seq? identifier? enum-base?     // C++0x
    | enum-key attribute-specifier-seq? nested-name-specifier identifier enum-base?     // C++0x
opaque-enum-declaration ::=
    enum-key attribute-specifier-seq? identifier enum-base? ';'     // C++0x
enum-key ::=
     "enum"     // C++0x
    | "enum" "class"     // C++0x
    | "enum" "struct"     // C++0x
enum-base ::=
    ':' type-specifier-seq     // C++0x
enumerator-list ::=
    enumerator-definition     // C++0x
    | enumerator-list ',' enumerator-definition     // C++0x
enumerator-definition ::=
    enumerator
    | enumerator '=' constant-expression
enumerator ::=
    identifier

//namespace.def
namespace-name ::=
    original-namespace-name
    | namespace-alias
original-namespace-name ::=
    identifier
namespace-definition ::=
    named-namespace-definition
    | unnamed-namespace-definition
named-namespace-definition ::=
    original-namespace-definition
    | extension-namespace-definition
original-namespace-definition ::=
    inline? namespace identifier '{' namespace-body '}'     // C++0x
extension-namespace-definition ::=
    inline? namespace original-namespace-name '{' namespace-body '}'     // C++0x
unnamed-namespace-definition ::=
    inline? namespace '{' namespace-body '}'
namespace-body ::=
    declaration-seq?

//namespace.alias
namespace-alias ::=
    identifier
namespace-alias-definition ::=
    namespace identifier '=' qualified-namespace-specifier ';'
qualified-namespace-specifier ::=
    "::"? nested-name-specifier? namespace-name

//namespace.udecl
using-declaration ::=
    "using" "typename"? "::"? nested-name-specifier unqualified-id ';'
    | "using" "::" unqualified-id ';'

//namespace.udir
using-directive ::=
    attribute-specifier-seq? "using" "namespace" "::"? nested-name-specifier? namespace-name ';'

//dcl.asm
asm-definition ::=
    "asm" '(' string-literal ')' ';'

//dcl.link
linkage-specification ::=
    "extern" string-literal '{' declaration-seq? '}'
    | "extern" string-literal declaration

//dcl.attr.grammar
attribute-specifier-seq ::=
    attribute-specifier     // C++0x
    | attribute-specifier-seq attribute-specifier     // C++0x
attribute-specifier ::=
    '[' '[' attribute-list ']' ']'     // C++0x
    | alignment-specifier     // C++0x
alignment-specifier ::=
     "alignas" '(' type-id "..."? ')'     // C++0x
    | "alignas" '(' assignment-expression "..."? ')'     // C++0x
attribute-list ::=
    attribute?     // C++0x
    | attribute-list ',' attribute?     // C++0x
    | attribute "..."     // C++0x
    | attribute-list ',' attribute "..."     // C++0x
attribute ::=
    attribute-token attribute-argument-clause?     // C++0x
attribute-token ::=
    identifier     // C++0x
    | attribute-scoped-token     // C++0x
attribute-scoped-token ::=
    attribute-namespace "::" identifier     // C++0x
attribute-namespace ::=
    identifier     // C++0x
attribute-argument-clause ::=
    '(' balanced-token-seq ')'     // C++0x
balanced-token-seq ::=
    balanced-token     // C++0x
    | balanced-token-seq balanced-token     // C++0x
balanced-token ::=
     '(' balanced-token-seq ')'     // C++0x
    | '[' balanced-token-seq ']'     // C++0x
    | '{' balanced-token-seq '}'     // C++0x
    | token     // C++0x - except a parenthesis, a bracket, or a brace

//dcl.decl
init-declarator-list ::=
    init-declarator
    | init-declarator-list ',' init-declarator
init-declarator ::=
    declarator initializer?
declarator ::=
    ptr-declarator     // C++0x
    | noptr-declarator parameters-and-qualifiers trailing-return-type     // C++0x
ptr-declarator ::=
    noptr-declarator     // C++0x
    | ptr-operator ptr-declarator     // C++0x
noptr-declarator ::=
    declarator-id attribute-specifier-seq?     // C++0x
    | noptr-declarator parameters-and-qualifiers     // C++0x
    | noptr-declarator '[' constant-expression? ']' attribute-specifier-seq?     // C++0x
    | '(' ptr-declarator ')'     // C++0x
parameters-and-qualifiers ::=
    '(' parameter-declaration-clause ')' attribute-specifier-seq? cv-qualifier-seq? ref-qualifier? exception-specification?     // C++0x
trailing-return-type ::=
    "->" trailing-type-specifier-seq abstract-declarator?     // C++0x
ptr-operator ::=
     "*" attribute-specifier-seq? cv-qualifier-seq?     // C++0x
    | "&" attribute-specifier-seq?     // C++0x
    | "&&" attribute-specifier-seq?     // C++0x
    | "::"? nested-name-specifier "*" attribute-specifier-seq? cv-qualifier-seq?     // C++0x
cv-qualifier-seq ::=
    cv-qualifier
    | cv-qualifier cv-qualifier-seq
cv-qualifier ::=
     "const"
    | "volatile"
ref-qualifier ::=
     "&"     // C++0x
    | "&&"     // C++0x
declarator-id ::=
    "..."? id-expression     // C++0x
    | "::"? nested-name-specifier? class-name     // C++0x

//dcl.name
type-id ::=
    type-specifier-seq abstract-declarator?
abstract-declarator ::=
    ptr-abstract-declarator     // C++0x
    | noptr-abstract-declarator? parameters-and-qualifiers trailing-return-type     // C++0x
    | "..."     // C++0x
ptr-abstract-declarator ::=
    noptr-abstract-declarator     // C++0x
    | ptr-operator ptr-abstract-declarator?     // C++0x
noptr-abstract-declarator ::=
    noptr-abstract-declarator? parameters-and-qualifiers     // C++0x
    | noptr-abstract-declarator? '[' constant-expression ']' attribute-specifier-seq?     // C++0x
    | '(' ptr-abstract-declarator ')'     // C++0x

//dcl.fct
parameter-declaration-clause ::=
    parameter-declaration-list? "..."?
    | parameter-declaration-list ',' "..."
parameter-declaration-list ::=
    parameter-declaration
    | parameter-declaration-list ',' parameter-declaration
parameter-declaration ::=
    attribute-specifier-seq? decl-specifier-seq declarator     // C++0x
    | attribute-specifier-seq? decl-specifier-seq declarator '=' initializer-clause     // C++0x
    | attribute-specifier-seq? decl-specifier-seq abstract-declarator?     // C++0x
    | attribute-specifier-seq? decl-specifier-seq abstract-declarator? '=' initializer-clause     // C++0x

//dcl.fct.def.general
function-definition ::=
    attribute-specifier-seq? decl-specifier-seq? declarator function-body     // C++0x
    | attribute-specifier-seq? decl-specifier-seq? declarator '=' "default" ';'     // C++0x
    | attribute-specifier-seq? decl-specifier-seq? declarator '=' "delete" ';'     // C++0x
function-body ::=
    ctor-initializer? compound-statement     // C++0x
    | function-try-block     // C++0x

//dcl.init
initializer ::=
    brace-or-equal-initializer     // C++0x
    | '(' expression-list ')'     // C++0x
brace-or-equal-initializer ::=
    '=' initializer-clause     // C++0x
    | braced-init-list     // C++0x
initializer-clause ::=
    assignment-expression     // C++0x
    | braced-init-list     // C++0x
initializer-list ::=
    initializer-clause "..."?     // C++0x
    | initializer-list ',' initializer-clause "..."?     // C++0x
braced-init-list ::=
    '{' initializer-list ','? '}'     // C++0x
    | '{' '}'     // C++0x

//class
class-name ::=
    identifier
    | simple-template-id     // C++0x
class-specifier ::=
    class-head '{' member-specification? '}'
class-head ::=
    class-key attribute-specifier-seq? class-head-name class-virt-specifier-seq? base-clause?     // C++0x
    | class-key attribute-specifier-seq? base-clause?     // C++0x
class-head-name ::=
    nested-name-specifier? class-name     // C++0x
class-virt-specifier-seq ::=
    class-virt-specifier     // C++0x
    | class-virt-specifier-seq class-virt-specifier     // C++0x
class-virt-specifier ::=
    "final"     // C++0x
class-key ::=
     "class"
    | "struct"
    | "union"

//class.mem
member-specification ::=
    member-declaration member-specification?
    | access-specifier ':' member-specification?
member-declaration ::=
    attribute-specifier-seq? decl-specifier-seq? member-declarator-list? ';'     // C++0x
    | function-definition ';'?
    | using-declaration
    | static_assert-declaration     // C++0x
    | template-declaration
    | alias-declaration     // C++0x
member-declarator-list ::=
    member-declarator
    | member-declarator-list ',' member-declarator
member-declarator ::=
    declarator virt-specifier-seq? pure-specifier?
    | declarator virt-specifier-seq? brace-or-equal-initializer?     // C++0x
    | identifier? attribute-specifier-seq? virt-specifier-seq? ':' constant-expression
virt-specifier-seq ::=
    virt-specifier
    | virt-specifier-seq virt-specifier
virt-specifier ::=
     "override"
    | "final"
    | "new"
pure-specifier ::=
    '=' '0'

//class.derived
base-clause ::=
    ':' base-specifier-list
base-specifier-list ::=
    base-specifier "..."?     // C++0x
    | base-specifier-list ',' base-specifier "..."?     // C++0x
base-specifier ::=
    attribute-specifier-seq? base-type-specifier     // C++0x
    | attribute-specifier-seq? virtual access-specifier? base-type-specifier     // C++0x
    | attribute-specifier-seq? access-specifier virtual? base-type-specifier     // C++0x
class-or-decltype ::=
    "::"? nested-name-specifier? class-name     // C++0x
    | decltype-specifier     // C++0x
base-type-specifier ::=
    class-or-decltype     // C++0x
access-specifier ::=
     "private"
    | "protected"
    | "public"

//class.conv.fct
conversion-function-id ::=
    operator conversion-type-id
conversion-type-id ::=
    type-specifier-seq conversion-declarator?
conversion-declarator ::=
    ptr-operator conversion-declarator?

//class.base.init
ctor-initializer ::=
    ':' mem-initializer-list
mem-initializer-list ::=
    mem-initializer "..."?     // C++0x
    | mem-initializer ',' mem-initializer-list "..."?     // C++0x
mem-initializer ::=
    mem-initializer-id '(' expression-list? ')'
    | mem-initializer-id braced-init-list     // C++0x
mem-initializer-id ::=
    class-or-decltype
    | identifier

//over.oper
operator-function-id ::=    // See C++ Standard Core Language Issue n. 189
    "operator" overloadable-operator
    | "operator" overloadable-operator '<' template-argument-list? '>'
overloadable-operator ::=   // See C++ Standard Core Language Issue n. 189
     "new"
    | "delete"
    | "new" '[' ']'
    | "delete" '[' ']'
    | "+"
    | "-"
    | "*"
    | "/"
    | "%"
    | "^"
    | "&"
    | "|"
    | "~"
    | "!"
    | "="
    | "<"
    | ">"
    | "+="
    | "-="
    | "*="
    | "/="
    | "%="
    | "^="
    | "&="
    | "|="
    | "<<"
    | ">>"
    | ">>="
    | "<<="
    | "=="
    | "!="
    | "<="
    | ">="
    | "&&"
    | "||"
    | "++"
    | "--"
    | ","
    | "->*"
    | "->"
    | "()"
    | "[]"

//over.literal
literal-operator-id ::=
    "operator" '""' identifier     // C++0x

//temp
template-declaration ::=
    "template" '<' template-parameter-list '>' declaration     // C++0x - The export keyword is reserved for future use
template-parameter-list ::=
    template-parameter
    | template-parameter-list ',' template-parameter

//temp.param
template-parameter ::=
    type-parameter
    | parameter-declaration
type-parameter ::=
    "class" "..."? identifier?     // C++0x
    | "class" identifier? '=' type-id
    | "typename" "..."? identifier?     // C++0x
    | "typename" identifier? '=' type-id
    | "template" '<' template-parameter-list '>' class "..."? identifier?     // C++0x
    | "template" '<' template-parameter-list '>' class identifier? '=' id-expression

//temp.names
simple-template-id ::=
    template-name '<' template-argument-list? '>'     // C++0x
template-id ::=
    simple-template-id     // C++0x
    | operator-function-id '<' template-argument-list? '>'     // C++0x
    | literal-operator-id '<' template-argument-list? '>'     // C++0x
template-name ::=
    identifier
template-argument-list ::=
    template-argument "..."?     // C++0x
    | template-argument-list ',' template-argument "..."?     // C++0x
template-argument ::=
    constant-expression     // C++0x
    | type-id     // C++0x
    | id-expression     // C++0x

//temp.res
typename-specifier ::=
     "typename" "::"? nested-name-specifier identifier     // C++0x
    | "typename" "::"? nested-name-specifier template? simple-template-id     // C++0x

//temp.explicit
explicit-instantiation ::=
    "extern"? "template" declaration     // C++0x

//temp.expl.spec
explicit-specialization ::=
    "template" '<' '>' declaration

//except
try-block ::=
    "try" compound-statement handler-seq
function-try-block ::=
    "try" ctor-initializer? compound-statement handler-seq     // C++0x
handler-seq ::=
    handler
    | handler handler-seq
handler ::=
    "catch" '(' exception-declaration ')' compound-statement
exception-declaration ::=
    attribute-specifier-seq? type-specifier-seq declarator     // C++0x
    | attribute-specifier-seq? type-specifier-seq abstract-declarator?     // C++0x
    | "..."     // C++0x
throw-expression ::=
    "throw" assignment-expression?

//except.spec
exception-specification ::=
    dynamic-exception-specification     // C++0x
    | noexcept-specification     // C++0x
dynamic-exception-specification ::=
    "throw" '(' type-id-list? ')'     // C++0x
type-id-list ::=
    type-id "..."?     // C++0x
    | type-id-list ',' type-id "..."?     // C++0x
noexcept-specification ::=
    "noexcept" '(' constant-expression ')'     // C++0x
    | "noexcept"     // C++0x

//cpp
preprocessing-file ::=
    group?
group ::=
    group-part
    | group group-part
group-part ::=
    if-section
    | control-line
    | text-line     // C++0x
    | '#' non-directive     // C++0x
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?
else-group ::=
    '#' "else" new-line group?
endif-line ::=
    '#' "endif" new-line
control-line ::=
     '#' "include" pp-tokens new-line
    | '#' "define" identifier replacement-list new-line
    | '#' "define" identifier lparen identifier-list? ')' replacement-list new-line     // C++0x
    | '#' "define" identifier lparen identifier-list ',' "..." ')' replacement-list new-line     // C++0x
    | '#' "undef" identifier new-line
    | '#' "line" pp-tokens new-line
    | '#' "error" pp-tokens? new-line
    | '#' "pragma" pp-tokens? new-line
    | '#' new-line
text-line ::=
    pp-tokens? new-line     // C++0x
non-directive ::=
    pp-tokens new-line     // C++0x
lparen ::=
    '(' // a ( character not immediately preceded by white-space
identifier-list ::=
    identifier
    | identifier-list ',' identifier
replacement-list ::=
    pp-tokens?
pp-tokens ::=
    preprocessing-token
    | pp-tokens preprocessing-token
new-line ::=
    [\n] //the new-line character
mingodad commented 2 years ago

After playing a bit with xslt I managed to create one based on html.xslt to output an EBNF understood by https://www.bottlecaps.de/rr/ui :

<?xml version='1.0'?>
<xsl:stylesheet
  version='1.0'
  xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >

<xsl:output method='html' indent='yes'/>
<xsl:strip-space elements="*"/>
<xsl:output method="text" />

<xsl:template match='bnf'>
/*
Hyperlinked C++ BNF Grammar
By Alessio Marchetti

Version 3.6

Last updated: 10-Aug-2021

Purpose of this document
If you are a C++ developer then you sometimes need to have a look at the C++ BNF grammar. At least I do.

But reading a set of BNF rules is difficult since you have to jump from one rule to the next one, maybe pages away from it.

With this document I tried to make it easier to navigate among the BNF rules of the C++ language grammar; you can find here a hyperlinked graph whose nodes are the BNF productions of the C++ language grammar.

If you find errors or inconsistencies, please log an issue.

The BNF non-terminal for a C++ translation unit (translation-unit) is defined here.
The BNF non-terminal for a C++ preprocessing file (preprocessing-file) is defined here.
BNF Grammar Rules
*/

start_here ::= translation-unit // for easy navigation purpose

<xsl:apply-templates/>

</xsl:template>

<xsl:template match='section'>
<xsl:attribute name='name'><xsl:value-of select='@id'/></xsl:attribute>
//<xsl:value-of select='@id'/>
<xsl:apply-templates/>
</xsl:template>

<xsl:template match='rule'>
<xsl:attribute name='name'><xsl:value-of select='syntax'/></xsl:attribute>
<xsl:text>&#x0A;</xsl:text><xsl:value-of select='syntax'/><xsl:text> ::=&#x0A;&#x09;</xsl:text>
    <xsl:choose>
      <xsl:when test='@issue'>
          <xsl:text>&#x09;// See </xsl:text>
            <xsl:attribute name='href'>http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html</xsl:attribute>
            <xsl:text>C++ Standard Core Language Issue</xsl:text>
          <xsl:text> n. </xsl:text>
          <xsl:value-of select='@issue'/>
      </xsl:when>
      <xsl:when test='@note and not(@issue)'>
        <xsl:text>&#x09;// </xsl:text><xsl:value-of select='@note'/>
      </xsl:when>
    </xsl:choose>
<xsl:apply-templates/>
<xsl:text>&#x0A;</xsl:text>
</xsl:template>

<xsl:template match='syntax'/>

<xsl:template match='alternative'>
    <xsl:if test="position() > 1">
    <xsl:text>&#x0A;&#x09;|</xsl:text>
    </xsl:if>
    <xsl:apply-templates/>
    <xsl:if test='@issue'>
        <xsl:text>&#x09;// See </xsl:text>
          <xsl:attribute name='href'>http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_toc.html</xsl:attribute>
          <xsl:text>C++ Standard Core Language Issue</xsl:text>
        <xsl:text> n. </xsl:text>
        <xsl:value-of select='@issue'/>
    </xsl:if>
    <xsl:if test="@note and not(@issue)">
      <xsl:text>&#09;// </xsl:text><xsl:value-of select='@note'/>
    </xsl:if>
</xsl:template>

<xsl:template match='terminal'>
   <xsl:variable name="quote">
      <xsl:choose>
        <xsl:when test="contains(., '&quot;')">
          <xsl:text>'</xsl:text>
        </xsl:when>
        <xsl:otherwise>"</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
<xsl:choose>
  <xsl:when test="@sentence='true'">
    <xsl:text> </xsl:text><xsl:value-of select="$quote"/><xsl:value-of select='.'/><xsl:value-of select="$quote"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:text> </xsl:text><xsl:value-of select="$quote"/><xsl:value-of select='.'/><xsl:value-of select="$quote"/><xsl:if test="@optional='true'">?</xsl:if>
  </xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match='non-terminal'>
    <xsl:text> </xsl:text><xsl:value-of select='.'/><xsl:if test="@optional='true'">?</xsl:if>
</xsl:template>

</xsl:stylesheet>
mingodad commented 2 years ago

Also for people looking for other related C++ grammars here are some I found:

hadrielk commented 1 year ago

Thanks @mingodad, I found the visual diagram quite useful!