Annex A (informative) Grammar summary [gram]

This summary of C++ syntax is intended to be an aid to comprehension. It is not an exact statement of the language. In particular, the grammar described here accepts a superset of valid C++ constructs. Disambiguation rules ([stmt.ambig], [dcl.spec], [class.member.lookup]) must be applied to distinguish expressions from declarations. Further, access control, ambiguity, and type rules must be used to weed out syntactically valid but meaningless constructs.

A.1 Keywords [gram.key]

New context-dependent keywords are introduced into a program by typedef ([dcl.typedef]), namespace ([namespace.def]), class (clause [class]), enumeration ([dcl.enum]), and template (clause [temp]) declarations.

typedef-name:
	identifier
namespace-name:
	original-namespace-name
	namespace-alias

original-namespace-name:
	identifier

namespace-alias:
	identifier
class-name:
	identifier
	simple-template-id
enum-name:
	identifier
template-name:
	identifier

Note that a typedef-name naming a class is also a class-name ([class.name]).

A.2 Lexical conventions [gram.lex]

hex-quad:
    hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit
universal-character-name:
    \u hex-quad
    \U hex-quad hex-quad
preprocessing-token:
    header-name
    identifier
    pp-number
    character-literal
    user-defined-character-literal
    string-literal
    user-defined-string-literal
    preprocessing-op-or-punc
    each non-white-space character that cannot be one of the above
token:
    identifier
    keyword
    literal
    operator
    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 source character set except new-line and >
q-char-sequence:
    q-char
    q-char-sequence q-char
q-char:
    any member of the source character set except new-line and "
pp-number:
    digit
    . digit
    pp-number digit
    pp-number identifier-nondigit
    pp-number e sign
    pp-number E sign
    pp-number .
identifier:
    identifier-nondigit
    identifier identifier-nondigit
    identifier digit
identifier-nondigit:
    nondigit
    universal-character-name
    other implementation-defined characters
nondigit: one of
    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: one of
    0 1 2 3 4 5 6 7 8 9
preprocessing-op-or-punc: one of
	{ 	} 	[ 	] 	# 	## 	( 	)
	<: 	:> 	<% 	%> 	%: 	%:%: 	; 	: 	...
	new 	delete 	? 	:: 	. 	.*
	+ 	- 	* 	/ 	% 	^ 	& 	| 	~
	! 	= 	< 	> 	+= 	-= 	*= 	/= 	%=
	^= 	&= 	|= 	<< 	>> 	>>= 	<<= 	== 	!=
	<= 	>= 	&& 	|| 	++ 	-- 	, 	->* 	->
	and 	and_eq 	bitand 	bitor 	compl 	not 	not_eq
	or 	or_eq 	xor 	xor_eq
literal:
    integer-literal
    character-literal
    floating-literal
    string-literal
    boolean-literal
    pointer-literal
    user-defined-literal
integer-literal:
    decimal-literal integer-suffixopt
    octal-literal integer-suffixopt
    hexadecimal-literal integer-suffixopt
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: one of
    1  2  3  4  5  6  7  8  9
octal-digit: one of
    0  1  2  3  4  5  6  7
hexadecimal-digit: one of
    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-suffixopt 
    unsigned-suffix long-long-suffixopt 
    long-suffix unsigned-suffixopt 
    long-long-suffix unsigned-suffixopt
unsigned-suffix: one of
    u  U
long-suffix: one of
    l  L
long-long-suffix: one of
    ll  LL
character-literal:
    ' c-char-sequence '
    u' c-char-sequence '
    U' c-char-sequence '
    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: one of
    \'  \"  \?  \\
    \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
floating-literal:
    fractional-constant exponent-partopt floating-suffixopt
    digit-sequence exponent-part floating-suffixopt
fractional-constant:
    digit-sequenceopt . digit-sequence
    digit-sequence .
exponent-part:
    e signopt digit-sequence
    E signopt digit-sequence
sign: one of
    +  -
digit-sequence:
    digit
    digit-sequence digit
floating-suffix: one of
    f  l  F  L
string-literal:
    encoding-prefixopt " s-char-sequenceopt "
    encoding-prefixopt R raw-string
encoding-prefix:
  u8
  u
  U
  L
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-sequenceopt ( r-char-sequenceopt ) d-char-sequenceopt "
r-char-sequence:
    r-char
    r-char-sequence r-char
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 ".
d-char-sequence:
    d-char
    d-char-sequence d-char
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.
boolean-literal:
    false
    true
pointer-literal:
    nullptr
user-defined-literal:
    user-defined-integer-literal
    user-defined-floating-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
user-defined-floating-literal:
    fractional-constant exponent-partopt ud-suffix
    digit-sequence exponent-part ud-suffix
user-defined-string-literal:
    string-literal ud-suffix
user-defined-character-literal:
    character-literal ud-suffix
ud-suffix:
    identifier

A.4 Expressions [gram.expr]

primary-expression:
    literal
    this
    ( expression )
    id-expression
    lambda-expression
id-expression:
    unqualified-id
    qualified-id
unqualified-id:
    identifier
    operator-function-id
    conversion-function-id
    literal-operator-id
    ~ class-name
    ~ decltype-specifier
    template-id
qualified-id:
    nested-name-specifier templateopt unqualified-id
    :: identifier
    :: operator-function-id
    :: literal-operator-id
    :: template-id
nested-name-specifier:
    ::opt type-name ::
    ::opt namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier templateopt simple-template-id ::
lambda-expression:
    lambda-introducer lambda-declaratoropt compound-statement
lambda-introducer:
    [ lambda-captureopt ]
lambda-capture:
    capture-default
    capture-list
    capture-default , capture-list
capture-default:
    &
    =
capture-list:
    capture ...opt
    capture-list , capture ...opt
capture:
    identifier
    & identifier
    this
lambda-declarator:
    ( parameter-declaration-clause ) mutableopt
    exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt
postfix-expression:
    primary-expression
    postfix-expression [ expression ]
    postfix-expression [ braced-init-list ]
    postfix-expression ( expression-listopt )
    simple-type-specifier ( expression-listopt )
    typename-specifier ( expression-listopt )
    simple-type-specifier braced-init-list
    typename-specifier braced-init-list
    postfix-expression . templateopt id-expression
    postfix-expression -> templateopt 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-specifieropt type-name :: ~ type-name
    nested-name-specifier template simple-template-id :: ~ type-name
    nested-name-specifieropt ~ type-name
    ~ decltype-specifier
unary-expression:
    postfix-expression
    ++ cast-expression
    -- cast-expression
    unary-operator cast-expression
    sizeof unary-expression
    sizeof ( type-id )
    sizeof ... ( identifier )
    alignof ( type-id )
    noexcept-expression
    new-expression
    delete-expression
unary-operator: one of
    *  &  +  -  !  ~
new-expression:
    ::opt new new-placementopt new-type-id new-initializeropt 
    ::opt new new-placementopt ( type-id ) new-initializeropt
new-placement:
    ( expression-list )
new-type-id:
    type-specifier-seq new-declaratoropt
new-declarator:
    ptr-operator new-declaratoropt 
    noptr-new-declarator
noptr-new-declarator:
    [ expression ] attribute-specifier-seqopt
    noptr-new-declarator [ constant-expression ] attribute-specifier-seqopt
new-initializer:
    ( expression-listopt )
    braced-init-list
delete-expression:
    ::opt delete cast-expression
    ::opt delete [ ] cast-expression
noexcept-expression:
  noexcept ( 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
relational-expression:
    shift-expression
    relational-expression < shift-expression
    relational-expression > shift-expression
    relational-expression <= shift-expression
    relational-expression >= shift-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
assignment-expression:
    conditional-expression
    logical-or-expression assignment-operator initializer-clause
    throw-expression
assignment-operator: one of
    =  *=  /=  %=   +=  -=  >>=  <<=  &=  ^=  |=
expression:
    assignment-expression
    expression , assignment-expression
constant-expression:
    conditional-expression

A.6 Declarations [gram.dcl]

declaration-seq:
    declaration
    declaration-seq declaration
declaration:
    block-declaration
    function-definition
    template-declaration
    explicit-instantiation
    explicit-specialization
    linkage-specification
    namespace-definition
    empty-declaration
    attribute-declaration
block-declaration:
    simple-declaration
    asm-definition
    namespace-alias-definition
    using-declaration
    using-directive
    static_assert-declaration
    alias-declaration
    opaque-enum-declaration
alias-declaration:
    using identifier attribute-specifier-seqopt = type-id ;
simple-declaration:
    decl-specifier-seqopt init-declarator-listopt ;
    attribute-specifier-seq decl-specifier-seqopt init-declarator-list ;
static_assert-declaration:
  static_assert ( constant-expression , string-literal ) ;
empty-declaration:
    ;
attribute-declaration:
    attribute-specifier-seq ;
decl-specifier:
    storage-class-specifier
    type-specifier
    function-specifier
    friend
    typedef
    constexpr
decl-specifier-seq:
    decl-specifier attribute-specifier-seqopt
    decl-specifier decl-specifier-seq
storage-class-specifier:
    register
    static
    thread_local
    extern
    mutable
function-specifier:
    inline
    virtual
    explicit
typedef-name:
    identifier
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-seqopt
    type-specifier type-specifier-seq
trailing-type-specifier-seq:
  trailing-type-specifier attribute-specifier-seqopt
  trailing-type-specifier trailing-type-specifier-seq
simple-type-specifier:
    nested-name-specifieropt type-name
    nested-name-specifier template simple-template-id
    char
    char16_t
    char32_t
    wchar_t
    bool
    short
    int
    long
    signed
    unsigned
    float
    double
    void
    auto
    decltype-specifier
type-name:
    class-name
    enum-name
    typedef-name
    simple-template-id
decltype-specifier:
  decltype ( expression )
elaborated-type-specifier:
    class-key attribute-specifier-seqopt nested-name-specifieropt identifier
    class-key nested-name-specifieropt templateopt simple-template-id
    enum nested-name-specifieropt identifier
enum-name:
    identifier
enum-specifier:
    enum-head { enumerator-listopt }
    enum-head { enumerator-list , }
enum-head:
    enum-key attribute-specifier-seqopt identifieropt enum-baseopt
    enum-key attribute-specifier-seqopt nested-name-specifier identifier
enum-baseopt
opaque-enum-declaration:
    enum-key attribute-specifier-seqopt identifier enum-baseopt ;
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
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:
        inlineopt namespace identifier { namespace-body }
extension-namespace-definition:
        inlineopt namespace original-namespace-name { namespace-body }
unnamed-namespace-definition:
        inlineopt namespace { namespace-body }
namespace-body:
        declaration-seqopt
namespace-alias:
        identifier
namespace-alias-definition:
        namespace identifier = qualified-namespace-specifier ;
qualified-namespace-specifier:
    nested-name-specifieropt namespace-name
using-declaration:
    using typenameopt nested-name-specifier unqualified-id ;
    using :: unqualified-id ;
using-directive:
    attribute-specifier-seqopt using  namespace nested-name-specifieropt namespace-name ;
asm-definition:
    asm ( string-literal ) ;
linkage-specification:
    extern string-literal { declaration-seqopt }
    extern string-literal declaration
attribute-specifier-seq:
  attribute-specifier-seqopt attribute-specifier
attribute-specifier:
  [ [ attribute-list ] ]
  alignment-specifier
alignment-specifier:
  alignas ( type-id ...opt )
  alignas ( alignment-expression ...opt )
attribute-list:
  attributeopt
  attribute-list , attributeopt
  attribute ...
  attribute-list , attribute ...
attribute:
    attribute-token attribute-argument-clauseopt
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-tokenopt
    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

A.7 Declarators [gram.decl]

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator
init-declarator:
    declarator initializeropt
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-seqopt
    noptr-declarator parameters-and-qualifiers
    noptr-declarator [ constant-expressionopt ] attribute-specifier-seqopt
    ( ptr-declarator )
parameters-and-qualifiers:
    ( parameter-declaration-clause ) attribute-specifier-seqopt cv-qualifier-seqopt
ref-qualifieropt exception-specificationopt
trailing-return-type:
    -> trailing-type-specifier-seq abstract-declaratoropt
ptr-operator:
    * attribute-specifier-seqopt cv-qualifier-seqopt
    & attribute-specifier-seqopt
    && attribute-specifier-seqopt
    nested-name-specifier * attribute-specifier-seqopt cv-qualifier-seqopt
cv-qualifier-seq:
    cv-qualifier cv-qualifier-seqopt
cv-qualifier:
    const
    volatile
ref-qualifier:
    &
    &&
declarator-id:
    ...opt id-expression
    nested-name-specifieropt class-name
type-id:
    type-specifier-seq abstract-declaratoropt
abstract-declarator:
    ptr-abstract-declarator
    noptr-abstract-declaratoropt parameters-and-qualifiers trailing-return-type
    abstract-pack-declarator
ptr-abstract-declarator:
    noptr-abstract-declarator
    ptr-operator ptr-abstract-declaratoropt
noptr-abstract-declarator:
    noptr-abstract-declaratoropt parameters-and-qualifiers
    noptr-abstract-declaratoropt [ constant-expressionopt ] attribute-specifier-seqopt
    ( 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
    noptr-abstract-pack-declarator [ constant-expressionopt ] attribute-specifier-seqopt
    ...
parameter-declaration-clause:
    parameter-declaration-listopt ...opt
    parameter-declaration-list , ...
parameter-declaration-list:
    parameter-declaration
    parameter-declaration-list , parameter-declaration
parameter-declaration:
    attribute-specifier-seqopt decl-specifier-seq declarator
    attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
    attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt
    attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt = initializer-clause
function-definition:
    attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body
function-body:
    ctor-initializeropt compound-statement
    function-try-block
    = default ;
    = delete ;
initializer:
    brace-or-equal-initializer
    ( expression-list )
brace-or-equal-initializer:
    = initializer-clause
    braced-init-list
initializer-clause:
    assignment-expression
    braced-init-list
initializer-list:
    initializer-clause ...opt
    initializer-list , initializer-clause ...opt
braced-init-list:
    { initializer-list ,opt }
    { }

A.11 Overloading [gram.over]

operator-function-id:
    operator operator
operator: one of
	new	delete	new[]	delete[]
	+	-	*	/	%	^	&	|	~
	!	=	<	>	+=	-=	*=	/=	%=
	^=	&=	|=	<<	>>	>>=	<<=	==	!=
	<=	>=	&&	||	++	--	,	->*	->
	( )	[ ]
literal-operator-id:
    operator "" identifier