### ----------------------------------------------------
### -- App::nm2perl6
### -- Licenses: Artistic-2.0
### -- Authors: Jeffrey Goff
### -- File: spec.txt
### ----------------------------------------------------
### -- Chunk 1 of 2
#`{ Try it in Perl6?

token mangled-name {
|	'_Z' <encoding>
|	'_Z' <encoding> '.' <vendor-specific-suffix>
}

token encoding {
|	<function-name> <bare-function-type>
|	<data-name>
|	<special-name>
}

token name {
|	<nested-name>
|	<unscoped-name>
|	<unscoped-template-name> <template-args>
|	<local-name> # see Scope Encoding
}

token unscoped-name {
|	<unqualified-name>
|	'St' <unqualified-name> # ::std::
}

token unscoped-template-name {
|	<unscoped-name>
|	<substitution>
}

token nested-name {
|	'N' <CV-Qualifiers>? <ref-qualifier>? <prefix> <unqualified-name> 'E'
|	'N' <CV-Qualifiers>? <ref-qualifier>? <template-prefix> <template-args> 'E'
}

token prefix {
|	<unqualified-name>			# global class or namespace
|	<prefix> <unqualified-name>		# nested class or namespace
|	<template-prefix> <template-args>	# class template specialization
|	<template-param>			# template type parameter
|	<decltype>				# decltype qualifier
|	<prefix> <data-member-prefix>		# initializer of a data member
|	<substitution>
}

token template-prefix {
|	<template-unqualified-name>		# global template
|	<prefix> <template unqualified-name>	# nested template
|	<template-param>			# tempalte template parameter
|	<substitution>
}

token unqualified-name {
|	<operator-name> <abi-tags>?
|	<ctor-dtor-name>
|	<source-name>
|	<unnamed-type-name>
|	'DC' <sourc-name>+ 'E'	# Structured binding declaration
}

token source-name { <positive-length-number> <identifier> }

token identifier { <unqualified-source-code-identifier> }

token abi-tags> { <abi-tag> <abi-tags>?  }

token abi-tag { 'B' <source-name> }

token number { <[ 1 .. 9 ]> <[ 0 .. 9 ]>* }

token seq-id { <[ 0 .. 9 A .. Z ]>+ }

token operator-name {
|	'nw'	# new           
|	'na'	# new[]
|	'dl'	# delete        
|	'da'	# delete[]      
|	'ps'        # + (unary)
|	'ng'	# - (unary)     
|	'ad'	# & (unary)     
|	'de'	# * (unary)     
|	'co'	# ~             
|	'pl'	# +             
|	'mi'	# -             
|	'ml'	# *             
|	'dv'	# /             
|	'rm'	# %             
|	'an'	# &             
|	'or'	# |             
|	'eo'	# ^             
|	'aS'	# =             
|	'pL'	# +=            
|	'mI'	# -=            
|	'mL'	# *=            
|	'dV'	# /=            
|	'rM'	# %=            
|	'aN'	# &=            
|	'oR'	# |=            
|	'eO'	# ^=            
|	'ls'	# <<            
|	'rs'	# >>            
|	'lS'	# <<=           
|	'rS'	# >>=           
|	'eq'	# ==            
|	'ne'	# !=            
|	'lt'	# <             
|	'gt'	# >             
|	'le'	# <=            
|	'ge'	# >=            
|	'ss'	# <=>           
|	'nt'	# !             
|	'aa'	# &&            
|	'oo'	# ||            
|	'pp'	# ++ (postfix in <expression> context)
|	'mm'	# -- (postfix in <expression> context)           
|	'cm'	# ,             
|	'pm'	# ->*           
|	'pt'	# ->            
|	'cl'	# ()            
|	'ix'	# []            
|	'qu'	# ?             
|	'cv' <type>			# (cast)
|	'li' <source-name>		# operator ""
|	'v' <digit> <source-name>	# vendor extended operator
}

token special-name {
|	'TV' <type>	# Virtual table
|	'TT' <type>	# VTT structure (construction vtable index)
|	'TI' <type>	# typeinfo structure
|	'TS' <type>	# typeinfo name (null-terminated)
}

# base is the nominal target function of thunk
token special-name { 'T' <call-offset> <base-encoding> }

token call-offset {
|	'h' <nv-offset> '_'
|	'v' <v-offset> '_'
}

# non-virtual base override
token nv-offset { <offset-number> }

# virtual base override, with vcall offset
token v-offset { <offset-number> '_' <virtual-offset-number> }

token special-name {
	'Tc' <call-offset> <call-offset> <base-encoding>
		# base is the nominal target function of thunk
		# first call-offset is 'this' adjustment
		# second call-offset is result adjustment
}

token ctor-dtor-name {
|	'C1'	# complete object constructor
|	'C2'	# base object constructor
|	'C3'	# complete object allocating constructor
|	'D0'	# deleting destructor
|	'D1'	# complete object destructor
|	'D2'	# base object destructor
}

# Guard variable for one-time initialization
# No <type>
token special-name { 'GV' <object-name> }

token special-name {
|	'GR' <object-name> '_'		# First temporary
|	'GR' <object-name> <seq-id> '_'	# Subsequent temporaries
}

token type {
|	<builtin-type>
|	<qualified-type>
|	<function-type>
|	<class-enum-type>
|	<array-type>
|	<pointer-to-member-type>
|	<template-param>
|	<template-template-param> <template-args>
|	<decltype>
|	'P' <type>	# pointer
|	'R' <type>	# l-value reference
|	'O' <type>	# r-value reference (C++11)
|	'C' <type>	# complex pair (C99)
|	'G' <type>	# imaginary (C99)
|	<substitution>	# See Compression below
}

token qualified-type { <qualifier> <type> }

token qualifiers { <extended-qualifier>* <CV-qualifiers> }

token extended-qualifier {
	'U' <source-name> <template-args>? # vendor extended type qualifier
}

# restrict (C99), volatile, const
token CV-qualifiers { 'r'? 'V'? 'K'? }

token req-qualifier { 'R' }	# & ref-qualifier
token ref-qualifier { 'O' }	# && ref-qualifier

token builtin-type {
|	'v'	# void
|	'w'	# wchar_t
|	'b'	# bool
|	'c'	# char
|	'a'	# signed char
|	'h'	# unsigned char
|	's'	# short
|	't'	# unsigned short
|	'i'	# int
|	'j'	# unsigned int
|	'l'	# long
|	'm'	# unsigned long
|	'x'	# long long, __int64
|	'y'	# unsigned long long, __int64
|	'n'	# __int128
|	'o'	# unsigned __int128
|	'f'	# float
|	'd'	# double
|	'e'	# long double, __float80
|	'g'	# __float128
|	'z'	# ellipsis
|	'Dd'	# IEEE 754r decimal floating point (64 bits)
|	'De'	# IEEE 754r decimal floating point (128 bits)
|	'Df'	# IEEE 754r decimal floating point (32 bits)
|	'Dh'	# IEEE 754r half-precision floating point (16 bits)
|	'DF' <number> '_' # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)
|	'Di'	# char32_t
|	'Ds'	# char16_t
|	'Da'	# auto
|	'Dc'	# decltype(auto)
|	'Dn'	# std::nullptr_t (i.e., decltype(nullptr))
|	'u' <source-name>	# vendor extended type
}

token function-type {
	<CV-qualifiers>? <exception-spec>? 'Dx'? 'F' 'Y'? <bare-function-type> <ref-qualifier>? 'E'
}

# types are possible return type, then parameter types
token bare-function-type { <signature type>+ }

token exception-spec {
|	'Do'			# non-throwing exception-specification (e.g., noexcept, throw())
|	'DO' <expression> 'E'	# computed (instantiation-dependent) noexcept
|	'Dw' <type>+ 'E'	# dynamic exception specification with instantiation-dependent types
}

token decltype {
|	'Dt' <expression> 'E'	# decltype of an id-expression or class member access (C++0x)
|	'DT' <expression> 'E'	# decltype of an expression (C++0x)
}

token class-enum-type {
|	<name>     # non-dependent type name, dependent type name, or dependent typename-specifier
|	'Ts' <name>  # dependent elaborated type specifier using 'struct' or 'class'
|	'Tu' <name>  # dependent elaborated type specifier using 'union'
|	'Te' <name>  # dependent elaborated type specifier using 'enum'
}

token unnamed-type-name { 'Ut' <nonnegative number>? '_' }

token array-type {
|	'A' <positive-dimension-number> '_' <element type>
|	'A' <dimension expression>? '_' <element type>
}

token pointer-to-member-type { 'M' <class-type> <member-type> }

token template-param {
|	'T_'	# first template parameter
|	'T' <parameter-2-non-negative number> '_'
}

token template-template-param {
|	<template-param>
|	<substitution>
}

token function-param {
|	'fp' <top-level-CV-qualifiers> '_'            # L == 0, first parameter
|	'fp' <top-level-CV-qualifiers> <parameter-2-non-negative number> '_' # L == 0, second and later parameters
|	'fL' <L-1-non-negative number> 'p' <top-level-CV-qualifiers> '_' # L > 0, first parameter
|	'fL' <L-1-non-negative number> 'p' <top-level CV-qualifiers>
                                                    <parameter-2-non-negative-number> '_'   # L > 0, second and later parameters
}

token template-args { 'I' <template-arg>+ 'E' }

token template-arg {
|	<type>			# type or template
|	'X' <expression> 'E'	# expression
|	<expr-primary>		# simple expressions
|	'J' <template-arg>* 'E'	# argument pack
}

token expression {
|	<unary operator-name> <expression>
|	<binary operator-name> <expression> <expression>
|	<ternary operator-name> <expression> <expression> <expression>
|	'pp_' <expression>                                # prefix ++
|	'mm_' <expression>                                # prefix --
|	'cl' <expression>+ 'E'                            # expression (expr-list), call
|	'cv' <type> <expression>                          # type (expression), conversion with one argument
|	'cv' <type> _ <expression>* E                     # type (expr-list), conversion with other than one argument
|	'tl' <type> <braced-expression>* E                # type {expr-list}, conversion with braced-init-list argument
|	'il' <braced-expression>* E                       # {expr-list}, braced-init-list in any other context
|	'gs'? 'nw' <expression>* '_' <type> 'E'           # new (expr-list) type
|	'gs'? 'nw' <expression>* '_' <type> <initializer> # new (expr-list) type (init)
|	'gs'? 'na' <expression>* '_' <type> 'E'           # new[] (expr-list) type
|	'gs'? 'na' <expression>* '_' <type> <initializer> # new[] (expr-list) type (init)
|	'gs'? 'dl' <expression>                           # delete expression
|	'gs'? 'da' <expression>                           # delete[] expression
|	'dc' <type> <expression>                          # dynamic_cast<type> (expression)
|	'sc' <type> <expression>                          # static_cast<type> (expression)
|	'cc' <type> <expression>                          # const_cast<type> (expression)
|	'rc' <type> <expression>                          # reinterpret_cast<type> (expression)
|	'ti' <type>                                       # typeid (type)
|	'te' <expression>                                 # typeid (expression)
|	'st' <type>                                       # sizeof (type)
|	'sz' <expression>                                 # sizeof (expression)
|	'at' <type>                                       # alignof (type)
|	'az' <expression>                                 # alignof (expression)
|	'nx' <expression>                                 # noexcept (expression)
|	<template-param>
|	<function-param>
|	'dt' <expression> <unresolved-name>               # expr.name
|	'pt' <expression> <unresolved-name>               # expr->name
|	'ds' <expression> <expression>                    # expr.*expr
|	'sZ' <template-param>                             # sizeof...(T), size of a template parameter pack
|	'sZ' <function-param>                             # sizeof...(parameter), size of a function parameter pack
|	'sP' <template-arg>* 'E'                          # sizeof...(T), size of a captured template parameter pack from an alias template
|	'sp' <expression>                                 # expression..., pack expansion
|	'tw' <expression>                                 # throw expression
|	'tr'                                              # throw with no operand (rethrow)
|	<unresolved-name>                                 # f(p), N::f(p), ::f(p),
 	                                                  # freestanding dependent name (e.g., T::x),
 	                                                  # objectless nonstatic member reference
|	<expr-primary>
}

token unresolved-name {
|	'gs'? <base-unresolved-name>                     # x or (with "gs") ::x
|	'sr' <unresolved-type> <base-unresolved-name>    # T::x / decltype(p)::x
|	'srN' <unresolved-type> <unresolved-qualifier-level>+ 'E'
	<base-unresolved-name>
|	                                                # T::N::x /decltype(p)::N::x
|	'gs'? 'sr' <unresolved-qualifier-level>+ 'E' <base-unresolved-name>  
|	                                                # A::x, N::y, A<T>::z; "gs" means leading "::"
|	
|	<template-param> <template-args>?            # T:: or T<X,Y>::
|	<decltype>                                      # decltype(p)::
|	<substitution>
}

token unresolved-qualifier-level { <simple-id> }

token simple-id { <source-name> <template-args>? }

token base-unresolved-name {
|	<simple-id>                          # unresolved name
|	'on' <operator-name>                 # unresolved operator-function-id
|	'on' <operator-name> <template-args> # unresolved operator template-id
|	'dn' <destructor-name>               # destructor or pseudo-destructor;
                                             # e.g. ~X or ~X<N-1>
}

token destructor-name {
|	<unresolved-type> # e.g., ~T or ~decltype(f())
|	<simple-id>       # e.g., ~A<2*N>
}

token expr-primary {
|	'L' <type> <value number> 'E' # integer literal
|	'L' <type> <value float> 'E'  # floating literal
|	'L' <string type> 'E'         # string literal
|	'L' <nullptr type> 'E'        # nullptr literal (i.e., "LDnE")
|	'L' <pointer type> 0 'E'      # null pointer template argument
|	'L' <type> <real-part float>  # complex floating point literal (C 2000)
|	'L' _Z <encoding> 'E'         # external name
}

token braced-expression {
|	<expression>
|	'di' <field-source-name> <braced-expression>    # .name = expr
|	'dx' <index-expression> <braced-expression>     # [expr] = expr
|	'dX' <range-begin expression> <range-end-expression>
			<braced-expression>		# [expr ... expr] = expr
}

token initializer { 'pi' <expression>* 'E' } # parenthesized initialization

token local-name {
|	'Z' <function encoding> 'E' <entity name> <discriminator>?
|	'Z' <function encoding> 'E' 's' <discriminator>?
}

token discriminator {
|	'_' <non-negative number>      # when number < 10
|	'__' <non-negative number> '_' # when number >= 10
}

token unnamed-type-name {
|	'Ut' <nonnegative-number>? '_'
|	<closure-type-name>
}

token closure-type-name { 'Ul' <lambda-sig> 'E' <nonnegative-number>? '_' }

token lambda-sig {
	<parameter-type>+  # Parameter types or "v" if the lambda has no parameters
}

token local-name {
	'Z' <function-encoding> 'Ed' <parameter-number>? '_' <entity-name>
}

token data-member-prefix { <member-source-name> <template-args>? 'M' }

token substitution {
|	'S' <seq-id> '_'
|	'S_'
|	'St' # ::std::
|	'Sa' # ::std::allocator
|	'Sb' # ::std::basic_string
|	'Ss' # ::std::basic_string < char,
	     #   		 ::std::char_traits<char>,
 	     #   		 ::std::allocator<char> >
|	'Si' # ::std::basic_istream<char,  std::char_traits<char> >
|	'So' # ::std::basic_ostream<char,  std::char_traits<char> >
|	'Sd' # ::std::basic_iostream<char, std::char_traits<char> >
}

token name { 'St' <unqualified-name> } # ::std::

}

#`{

<mangled-name> ::= _Z <encoding>
               ::= _Z <encoding> . <vendor-specific suffix>

<encoding>     ::= <function name> <bare-function-type>
               ::= <data name>
               ::= <special-name>

<name>         ::= <nested-name>
	       ::= <unscoped-name>
	       ::= <unscoped-template-name> <template-args>
	       ::= <local-name>	# See Scope Encoding below

    <unscoped-name> ::= <unqualified-name>
		    ::= St <unqualified-name>   # ::std::

    <unscoped-template-name> ::= <unscoped-name>
			     ::= <substitution>

    <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
		  ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E

    <prefix> ::= <unqualified-name>                 # global class or namespace
             ::= <prefix> <unqualified-name>        # nested class or namespace
	     ::= <template-prefix> <template-args>  # class template specialization
             ::= <template-param>                   # template type parameter
             ::= <decltype>                         # decltype qualifier
             ::= <prefix> <data-member-prefix>      # initializer of a data member
	     ::= <substitution>

    <template-prefix> ::= <template unqualified-name>           # global template
                      ::= <prefix> <template unqualified-name>  # nested template
                      ::= <template-param>                      # template template parameter
                      ::= <substitution>

    <unqualified-name> ::= <operator-name> [<abi-tags>]
                       ::= <ctor-dtor-name>  
                       ::= <source-name>   
                       ::= <unnamed-type-name>   
                       ::= DC <source-name>+ E      # structured binding declaration

    <source-name> ::= <positive length number> <identifier>
    <identifier> ::= <unqualified source code identifier>



    <abi-tags> ::= <abi-tag> [<abi-tags>]
    <abi-tag> ::= B <source-name>


    <number> ::= [n] <non-negative decimal integer>


    <seq-id> ::= <0-9A-Z>+


  <operator-name> ::= nw	# new           
		  ::= na	# new[]
		  ::= dl	# delete        
		  ::= da	# delete[]      
		  ::= ps        # + (unary)
		  ::= ng	# - (unary)     
		  ::= ad	# & (unary)     
		  ::= de	# * (unary)     
		  ::= co	# ~             
		  ::= pl	# +             
		  ::= mi	# -             
		  ::= ml	# *             
		  ::= dv	# /             
		  ::= rm	# %             
		  ::= an	# &             
		  ::= or	# |             
		  ::= eo	# ^             
		  ::= aS	# =             
		  ::= pL	# +=            
		  ::= mI	# -=            
		  ::= mL	# *=            
		  ::= dV	# /=            
		  ::= rM	# %=            
		  ::= aN	# &=            
		  ::= oR	# |=            
		  ::= eO	# ^=            
		  ::= ls	# <<            
		  ::= rs	# >>            
		  ::= lS	# <<=           
		  ::= rS	# >>=           
		  ::= eq	# ==            
		  ::= ne	# !=            
		  ::= lt	# <             
		  ::= gt	# >             
		  ::= le	# <=            
		  ::= ge	# >=            
		  ::= ss	# <=>           
		  ::= nt	# !             
		  ::= aa	# &&            
		  ::= oo	# ||            
		  ::= pp	# ++ (postfix in <expression> context)
		  ::= mm	# -- (postfix in <expression> context)           
		  ::= cm	# ,             
		  ::= pm	# ->*           
		  ::= pt	# ->            
		  ::= cl	# ()            
		  ::= ix	# []            
		  ::= qu	# ?             
		  ::= cv <type>	# (cast)
                  ::= li <source-name>          # operator ""
		  ::= v <digit> <source-name>	# vendor extended operator



  <special-name> ::= TV <type>	# virtual table
		 ::= TT <type>	# VTT structure (construction vtable index)
		 ::= TI <type>	# typeinfo structure
		 ::= TS <type>	# typeinfo name (null-terminated byte string)


  <special-name> ::= T <call-offset> <base encoding>
		      # base is the nominal target function of thunk
  <call-offset> ::= h <nv-offset> _
		::= v <v-offset> _
  <nv-offset> ::= <offset number>
		      # non-virtual base override
  <v-offset>  ::= <offset number> _ <virtual offset number>
		      # virtual base override, with vcall offset



  <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
		      # base is the nominal target function of thunk
		      # first call-offset is 'this' adjustment
		      # second call-offset is result adjustment


  <ctor-dtor-name> ::= C1	# complete object constructor
		   ::= C2	# base object constructor
		   ::= C3	# complete object allocating constructor
		   ::= D0	# deleting destructor
		   ::= D1	# complete object destructor
		   ::= D2	# base object destructor



  <special-name> ::= GV <object name>	# Guard variable for one-time initialization
			# No <type>



  <special-name> ::= GR <object name> _             # First temporary
  <special-name> ::= GR <object name> <seq-id> _    # Subsequent temporaries


  <type> ::= <builtin-type>
         ::= <qualified-type>
         ::= <function-type>
         ::= <class-enum-type>
         ::= <array-type>
         ::= <pointer-to-member-type>
         ::= <template-param>
         ::= <template-template-param> <template-args>
         ::= <decltype>
         ::= P <type>        # pointer
         ::= R <type>        # l-value reference
         ::= O <type>        # r-value reference (C++11)
         ::= C <type>        # complex pair (C99)
         ::= G <type>        # imaginary (C99)
         ::= <substitution>  # See Compression below



  <qualified-type>     ::= <qualifiers> <type>

  <qualifiers>         ::= <extended-qualifier>* <CV-qualifiers>
  <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
  <CV-qualifiers>      ::= [r] [V] [K] 	  # restrict (C99), volatile, const

  <ref-qualifier>      ::= R              # & ref-qualifier
  <ref-qualifier>      ::= O              # && ref-qualifier



  <builtin-type> ::= v	# void
		 ::= w	# wchar_t
		 ::= b	# bool
		 ::= c	# char
		 ::= a	# signed char
		 ::= h	# unsigned char
		 ::= s	# short
		 ::= t	# unsigned short
		 ::= i	# int
		 ::= j	# unsigned int
		 ::= l	# long
		 ::= m	# unsigned long
		 ::= x	# long long, __int64
		 ::= y	# unsigned long long, __int64
		 ::= n	# __int128
		 ::= o	# unsigned __int128
		 ::= f	# float
		 ::= d	# double
		 ::= e	# long double, __float80
		 ::= g	# __float128
		 ::= z	# ellipsis
                 ::= Dd # IEEE 754r decimal floating point (64 bits)
                 ::= De # IEEE 754r decimal floating point (128 bits)
                 ::= Df # IEEE 754r decimal floating point (32 bits)
                 ::= Dh # IEEE 754r half-precision floating point (16 bits)
                 ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)
                 ::= Di # char32_t
                 ::= Ds # char16_t
                 ::= Da # auto
                 ::= Dc # decltype(auto)
                 ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
		 ::= u <source-name>	# vendor extended type



  <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
  <bare-function-type> ::= <signature type>+
	# types are possible return type, then parameter types
  <exception-spec> ::= Do                # non-throwing exception-specification (e.g., noexcept, throw())
                   ::= DO <expression> E # computed (instantiation-dependent) noexcept
                   ::= Dw <type>+ E      # dynamic exception specification with instantiation-dependent types


 <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class member access (C++0x)
             ::= DT <expression> E  # decltype of an expression (C++0x)




  <class-enum-type> ::= <name>     # non-dependent type name, dependent type name, or dependent typename-specifier
                    ::= Ts <name>  # dependent elaborated type specifier using 'struct' or 'class'
                    ::= Tu <name>  # dependent elaborated type specifier using 'union'
                    ::= Te <name>  # dependent elaborated type specifier using 'enum'


  <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ 




  <array-type> ::= A <positive dimension number> _ <element type>
	       ::= A [<dimension expression>] _ <element type>



  <pointer-to-member-type> ::= M <class type> <member type>




  <template-param> ::= T_	# first template parameter
		   ::= T <parameter-2 non-negative number> _
  <template-template-param> ::= <template-param>
			    ::= <substitution>



  <function-param> ::= fp <top-level CV-qualifiers> _                                     # L == 0, first parameter
		   ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _   # L == 0, second and later parameters
		   ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _         # L > 0, first parameter
		   ::= fL <L-1 non-negative number> p <top-level CV-qualifiers>
                                                    <parameter-2 non-negative number> _   # L > 0, second and later parameters




  <template-args> ::= I <template-arg>+ E

  <template-arg> ::= <type>                                             # type or template
                 ::= X <expression> E                                   # expression
                 ::= <expr-primary>                                     # simple expressions
                 ::= J <template-arg>* E                                # argument pack





 <expression> ::= <unary operator-name> <expression>
               ::= <binary operator-name> <expression> <expression>
               ::= <ternary operator-name> <expression> <expression> <expression>
               ::= pp_ <expression>                                     # prefix ++
               ::= mm_ <expression>                                     # prefix --
               ::= cl <expression>+ E                                   # expression (expr-list), call
               ::= cv <type> <expression>                               # type (expression), conversion with one argument
               ::= cv <type> _ <expression>* E                          # type (expr-list), conversion with other than one argument
               ::= tl <type> <braced-expression>* E                     # type {expr-list}, conversion with braced-init-list argument
               ::= il <braced-expression>* E                            # {expr-list}, braced-init-list in any other context
               ::= [gs] nw <expression>* _ <type> E                     # new (expr-list) type
               ::= [gs] nw <expression>* _ <type> <initializer>         # new (expr-list) type (init)
               ::= [gs] na <expression>* _ <type> E                     # new[] (expr-list) type
               ::= [gs] na <expression>* _ <type> <initializer>         # new[] (expr-list) type (init)
               ::= [gs] dl <expression>                                 # delete expression
               ::= [gs] da <expression>                                 # delete[] expression
               ::= dc <type> <expression>                               # dynamic_cast<type> (expression)
               ::= sc <type> <expression>                               # static_cast<type> (expression)
               ::= cc <type> <expression>                               # const_cast<type> (expression)
               ::= rc <type> <expression>                               # reinterpret_cast<type> (expression)
               ::= ti <type>                                            # typeid (type)
               ::= te <expression>                                      # typeid (expression)
               ::= st <type>                                            # sizeof (type)
               ::= sz <expression>                                      # sizeof (expression)
               ::= at <type>                                            # alignof (type)
               ::= az <expression>                                      # alignof (expression)
               ::= nx <expression>                                      # noexcept (expression)
               ::= <template-param>
               ::= <function-param>
               ::= dt <expression> <unresolved-name>                    # expr.name
               ::= pt <expression> <unresolved-name>                    # expr->name
               ::= ds <expression> <expression>                         # expr.*expr
               ::= sZ <template-param>                                  # sizeof...(T), size of a template parameter pack
               ::= sZ <function-param>                                  # sizeof...(parameter), size of a function parameter pack
               ::= sP <template-arg>* E                                 # sizeof...(T), size of a captured template parameter pack from an alias template
               ::= sp <expression>                                      # expression..., pack expansion
               ::= tw <expression>                                      # throw expression
               ::= tr                                                   # throw with no operand (rethrow)
               ::= <unresolved-name>                                    # f(p), N::f(p), ::f(p),
                                                                        # freestanding dependent name (e.g., T::x),
                                                                        # objectless nonstatic member reference
               ::= <expr-primary>

  <unresolved-name> ::= [gs] <base-unresolved-name>                     # x or (with "gs") ::x
                    ::= sr <unresolved-type> <base-unresolved-name>     # T::x / decltype(p)::x
                    ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
                                                                        # T::N::x /decltype(p)::N::x
                    ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>  
                                                                        # A::x, N::y, A<T>::z; "gs" means leading "::"

  <unresolved-type> ::= <template-param> [ <template-args> ]            # T:: or T<X,Y>::
                    ::= <decltype>                                      # decltype(p)::
                    ::= <substitution>

  <unresolved-qualifier-level> ::= <simple-id>

  <simple-id> ::= <source-name> [ <template-args> ]

  <base-unresolved-name> ::= <simple-id>                                # unresolved name
                         ::= on <operator-name>                         # unresolved operator-function-id
                         ::= on <operator-name> <template-args>         # unresolved operator template-id
                         ::= dn <destructor-name>                       # destructor or pseudo-destructor;
                                                                        # e.g. ~X or ~X<N-1>

  <destructor-name> ::= <unresolved-type>                               # e.g., ~T or ~decltype(f())
                    ::= <simple-id>                                     # e.g., ~A<2*N>

  <expr-primary> ::= L <type> <value number> E                          # integer literal
                 ::= L <type> <value float> E                           # floating literal
                 ::= L <string type> E                                  # string literal
                 ::= L <nullptr type> E                                 # nullptr literal (i.e., "LDnE")
                 ::= L <pointer type> 0 E                               # null pointer template argument
		 ::= L <type> <real-part float> _ <imag-part float> E   # complex floating point literal (C 2000)
                 ::= L _Z <encoding> E                                  # external name

  <braced-expression> ::= <expression>
                      ::= di <field source-name> <braced-expression>    # .name = expr
                      ::= dx <index expression> <braced-expression>     # [expr] = expr
                      ::= dX <range begin expression> <range end expression> <braced-expression>
                                                                        # [expr ... expr] = expr

  <initializer> ::= pi <expression>* E                                  # parenthesized initialization





  <local-name> ::= Z <function encoding> E <entity name> [<discriminator>]
               ::= Z <function encoding> E s [<discriminator>]

  <discriminator> ::= _ <non-negative number>      # when number < 1