Anglr Syntax Rules for C# Language
Introduction
This paragraph introduces complete set of Anglr syntax rules for C# 8 programming language. C# parser, which is made using these rules, can be used to produce concrete syntax tree for any C# source code file. C# program following these syntax rules, should be used to parse single C# source file or the whole directory of C# source code files. The result is a list of concrete syntax trees. For every source file parsed without syntax errors there is exactly one syntax tree in the list.
[ Description Text='In this file are represented Anglr declarations for C# programming language.' Text='All grammar and lexical definitions are actually copied from the Microsoft' Text='specifications of C# programming language defined in' Text='https://learn.microsoft.com/en-us/dotnet/csharp/specification/overview' Text='The notations of some syntax rules are slightly modified, however, because' Text='they can be written more compactly in Anglr. For example: syntax rule' Text=' expression ( "," expression ) * ' Text='can be writen like' Text=' expression + [ "," ] ' Text='which means: positive number of expressions separated with commas.' ] [ CompilationInfo ClassName='CsharpDeclarations' NameSpace='Csharp.Declarations' Access='public' TokenPrefix='token_' Hover='true' ] %declarations csharpDecls %{ [ Description Text='character representation of an identifier as returned by the lexical analyzer' ] %terminal { raw-identifier } [ Description Text='terminal symbols associated with C# keywords' ] %terminal { abstract add alias as ascending async await base bool break by byte case catch char checked class const continue decimal default delegate descending do double dynamic else enum equals event explicit extern false finally fixed float for foreach from get global using goto group if implicit in int interface internal into is join let lock long nameof namespace new null object on operator orderby out override params partial private protected public readonly ref remove return sbyte sealed select set short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unmanaged unsafe ushort var virtual void volatile when where while yield } [ Description Text='terminal symbols representing C# literals' ] %terminal { keyword boolean-literal integer-literal real-literal character-literal string-literal null-literal } [ Description Text='Terminal symbols representing C# arithmetic operators.' Text='They are listed with their textual representations.' Text='But be carefull: exact textual representations are defined' Text='with regular expression cs-ops and should differ from the' Text='textual representations stated in the following %terminal block.' ] %terminal { lshequ-op '<<=' nullc-op '??' member-op '::' uinc-op '++' udec-op '--' land-op '&&' lor-op '||' ptr-op '->' eq-op '==' neq-op '!=' lteq-op '<=' gteq-op '>=' adde-op '+=' sube-op '-=' mule-op '*=' dive-op '/=' mode-op '%=' ande-op '&=' ore-op '|=' xore-op '^=' lsh-op '<<' lambda-op '=>' lcb '{' rcb '}' lab '[' rab ']' lrb '(' rrb ')' dot '.' comma ',' colon ':' semicolon ';' add-op '+' sub-op '-' mul-op '*' div-op '/' mod-op '%' and-op '&' or-op '|' xor-op '^' not-op '!' inv-op '~' equ-op '=' lt-op '<' gt-op '>' aif-op '?' } [ Description Text='terminal symbols associated with interpolated strings' ] %terminal { interpolated-regular-string-elements interpolated-verbatim-string-elements irss '$"' ivss '$@"' ise '"' } [ Description Text='regular expressions associated with c# arithmetic operators' ] %regex { lshequ-op \<\<\= nullc-op \?\? member-op \:\: uinc-op \+\+ udec-op \-\- land-op \&\& lor-op \|\| ptr-op \-\> eq-op \=\= neq-op \!\= lteq-op \<\= gteq-op \>\= adde-op \+\= sube-op \-\= mule-op \*\= dive-op \/\= mode-op \%\= ande-op \&\= ore-op \|\= xore-op \^\= lsh-op \<\< lambda-op \=\> lcb \{ rcb \} lab \[ rab \] lrb \( rrb \) dot \. comma \, colon \: semicolon \; add-op \+ sub-op \- mul-op \* div-op \/ mod-op \% and-op \& or-op \| xor-op \^ not-op \! inv-op \~ equ-op \= lt-op \< gt-op \> aif-op \? cs-ops ({lshequ-op}|{nullc-op}|{member-op}|{uinc-op}|{udec-op}|{land-op}|{lor-op}|{ptr-op}|{eq-op}|{neq-op}|{lteq-op}|{gteq-op}|{adde-op}|{sube-op}|{mule-op}|{dive-op}|{mode-op}|{ande-op}|{ore-op}|{xore-op}|{lsh-op}|{lambda-op}|{lcb}|{rcb}|{lab}|{rab}|{lrb}|{rrb}|{dot}|{comma}|{colon}|{semicolon}|{add-op}|{sub-op}|{mul-op}|{div-op}|{mod-op}|{and-op}|{or-op}|{xor-op}|{not-op}|{inv-op}|{equ-op}|{lt-op}|{gt-op}|{aif-op}) } [ Description Text='regular expressions associated with beginning of interpolated strings' ] %regex { irss \$\" ivss \$\@\"|\@\$\" } [ Description Text='Lexical grammar' Hover='true' ] %regex { input ({input-section})? input-section ({input-section-part})+ input-section-part ({input-elements})?({new-line})|({pp-directive}) input-elements ({input-element})+ input-element ({whitespace})|({comment})|({token}) } [ Description Text='Line terminators' Hover='true' ] %regex { new-line \u000D|\u000A|\u000D\u000A|\u0085|\u2028|\u2029 } [ Description Text='White space' Hover='true' ] %regex { whitespace ({whitespace-character})+ whitespace-character \p{Zs}|\u0009|\u000B|\u000C } [ Description Text='Comments' Hover='true' ] %regex { comment ({single-line-comment})|({delimited-comment}) single-line-comment \/\/({input-characters})? input-characters ({input-character})+ input-character [^{new-line-character}] new-line-character \u000D\u000A\u0085\u2028\u2029 delimited-comment \/\*({delimited-comment-text})?({asterisks})\/ delimited-comment-text ({delimited-comment-section})+ delimited-comment-section \/|({asterisks})?({not-slash-or-asterisk}) asterisks \*+ not-slash-or-asterisk [^\/\*] } [ Description Text='Tokens' Hover='true' ] %regex { token ({identifier})|({keyword})|({integer-literal})|({real-literal})|({character-literal})|({string-literal})|({operator-or-punctuator}) } [ Description Text='Unicode character escape sequences' Hover='true' ] %regex { unicode-escape-sequence \\u({hex-digit}){4}|\\u({hex-digit}){8} } [ Description Text='Identifiers' Hover='true' ] %regex { identifier ({available-identifier})|\@({identifier-or-keyword}) available-identifier {identifier-or-keyword} identifier-or-keyword ({identifier-start-character})({identifier-part-characters})? identifier-start-character ({letter-character})|({underscore-character}) underscore-character _|\u005F identifier-part-characters ({identifier-part-character})+ identifier-part-character ({letter-character})|({decimal-digit-character})|({connecting-character})|({combining-character})|({formatting-character}) letter-character \p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl} combining-character \p{Mn}|\p{Mc} decimal-digit-character \p{Nd} connecting-character \p{Pc} formatting-character \p{Cf} } [ Description Text='Keywords' Hover='true' ] %regex { keyword abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while } [ Description Text='Literals' Hover='true' ] %regex { literal ({boolean-literal})|({integer-literal})|({real-literal})|({character-literal})|({string-literal})|({null-literal}) boolean-literal true|false integer-literal ({hexadecimal-integer-literal})|{decimal-integer-literal} decimal-integer-literal ({decimal-digits})({integer-type-suffix})? decimal-digits ({decimal-digit})+ decimal-digit [0-9] integer-type-suffix [uUlL]+ hexadecimal-integer-literal (0(x|X)({hex-digits})({integer-type-suffix})?)|((x|X)0({hex-digits})({integer-type-suffix})?) hex-digits ({hex-digit})+ hex-digit [0-9A-Fa-f] real-literal ({decimal-digits})\.({decimal-digits})({exponent-part})?({real-type-suffix})?|\.({decimal-digits})({exponent-part})?({real-type-suffix})?|({decimal-digits})({exponent-part})({real-type-suffix})?|({decimal-digits})({real-type-suffix}) exponent-part (e|E)({sign})?({decimal-digits}) sign \+|\- real-type-suffix F|f|D|d|M|m character-literal '({character})' character ({single-character})|({simple-escape-sequence})|({hexadecimal-escape-sequence})|({unicode-escape-sequence}) single-character [^'\\{new-line-character}] simple-escape-sequence \\\'|\\\"|\\\\|\\0|\\a|\\b|\\f|\\n|\\r|\\t|\\v hexadecimal-escape-sequence \\x({hex-digit}){1,4} string-literal ({regular-string-literal})|({verbatim-string-literal}) regular-string-literal "({regular-string-literal-characters})?" regular-string-literal-characters ({regular-string-literal-character})+ regular-string-literal-character ({single-regular-string-literal-character})|({simple-escape-sequence})|({hexadecimal-escape-sequence})|({unicode-escape-sequence}) single-regular-string-literal-character [^"\\{new-line-character}] verbatim-string-literal @"({verbatim-string-literal-characters})?" verbatim-string-literal-characters ({verbatim-string-literal-character})+ verbatim-string-literal-character ({single-verbatim-string-literal-character})|({quote-escape-sequence}) single-verbatim-string-literal-character [^"] quote-escape-sequence "" null-literal null interpolated-regular-string-elements ({interpolated-regular-string-element})+ interpolated-regular-string-element {interpolated-regular-string-character}|{simple-escape-sequence}|{hexadecimal-escape-sequence}|{unicode-escape-sequence}|{open-brace-escape-sequence}|{close-brace-escape-sequence} interpolated-regular-string-character [^"\\{}\u000D\u000A\u0085\u2028\u2029] open-brace-escape-sequence \u007b\u007b close-brace-escape-sequence \u007d\u007d interpolated-verbatim-string-elements ({interpolated-verbatim-string-element})+ interpolated-verbatim-string-element {interpolated-verbatim-string-character}|{quote-escape-sequence}|{open-brace-escape-sequence}|{close-brace-escape-sequence} interpolated-verbatim-string-character [^"{}] } [ Description Text='Operators and punctuators' Hover='true' ] %regex { operator-or-punctuator \{|\}|\[|\]|\(|\)|\.|\,|\:|\;|\+|\-|\*|\/|\%|\&|\||\^|\!|\~|\=|\<|\>|\?|\?\?|\:\:|\+\+|\-\-|\&\&|\|\||\-\>|\=\=|\!\=|\<\=|\>\=|\+\=|\-\=|\*\=|\/\=|\%\=|\&\=|\|\=|\^\=|\<\<|\<\<\= right-shift \>\> right-shift-assignment \>\>\= } [ Description Text='Pre-processing directives. They are not handled by lexical analyzer. Instead they' Text='are handled by event pp-directive. See csharpScanner %scanner section for details' Text='and https://angstlr.com for additional information about Anglr events.' Text='%regex' Text='{' Text=' pp-directive::' Text=' pp-declaration' Text=' pp-conditional' Text=' pp-line ' Text=' pp-diagnostic' Text=' pp-region' Text=' pp-pragma' Text=' conditional-symbol::' Text=' Any identifier-or-keyword except true or false' Text=' pp-expression::' Text=' whitespace ? pp-or-expression whitespace ?' Text=' pp-or-expression::' Text=' pp-and-expression' Text=' pp-or-expression whitespace ? || whitespace ? pp-and-expression' Text=' pp-and-expression::' Text=' pp-equality-expression' Text=' pp-and-expression whitespace ? && whitespace ? pp-equality-expression' Text=' pp-equality-expression::' Text=' pp-unary-expression' Text=' pp-equality-expression whitespace ? == whitespace ? pp-unary-expression' Text=' pp-equality-expression whitespace ? != whitespace ? pp-unary-expression' Text=' pp-unary-expression::' Text=' pp-primary-expression' Text=' ! whitespace ? pp-unary-expression' Text=' pp-primary-expression::' Text=' true' Text=' false' Text=' conditional-symbol' Text=' ( whitespace ? pp-expression whitespace ? )' Text=' pp-declaration::' Text=' whitespace ? # whitespace ? define whitespace conditional-symbol pp-new-line' Text=' whitespace ? # whitespace ? undef whitespace conditional-symbol pp-new-line' Text=' pp-new-line::' Text=' whitespace ? single-line-comment ? new-line' Text=' pp-conditional::' Text=' pp-if-section pp-elif-sections ? pp-else-section ? pp-endif' Text=' pp-if-section::' Text=' whitespace ? # whitespace ? if whitespace pp-expression pp-new-line conditional-section ?' Text=' pp-elif-sections::' Text=' pp-elif-section' Text=' pp-elif-sections pp-elif-section' Text=' pp-elif-section::' Text=' whitespace ? # whitespace ? elif whitespace pp-expression pp-new-line conditional-section ?' Text=' pp-else-section::' Text=' whitespace ? # whitespace ? else pp-new-line conditional-section ?' Text=' pp-endif::' Text=' whitespace ? # whitespace ? endif pp-new-line' Text=' conditional-section::' Text=' input-section' Text=' skipped-section' Text=' skipped-section::' Text=' skipped-section-part +' Text=' skipped-section-part::' Text=' skipped-characters ? new-line' Text=' pp-directive' Text=' skipped-characters::' Text=' whitespace ? not-number-sign input-characters ?' Text=' not-number-sign::' Text=' Any input-character except #' Text=' pp-line::' Text=' whitespace ? # whitespace ? line whitespace line-indicator pp-new-line' Text=' line-indicator::' Text=' decimal-digits whitespace file-name' Text=' decimal-digits' Text=' default' Text=' hidden' Text=' file-name::' Text=' " file-name-characters "' Text=' file-name-characters::' Text=' file-name-character +' Text=' file-name-character::' Text=' Any input-character except " (U+0022), and new-line-character' Text=' pp-diagnostic::' Text=' whitespace ? # whitespace ? error pp-message' Text=' whitespace ? # whitespace ? warning pp-message' Text=' pp-message::' Text=' new-line' Text=' whitespace input-characters ? new-line' Text=' pp-region::' Text=' pp-start-region conditional-section ? pp-end-region' Text=' pp-start-region::' Text=' whitespace ? # whitespace ? region pp-message' Text=' pp-end-region::' Text=' whitespace ? # whitespace ? endregion pp-message' Text=' pp-pragma::' Text=' whitespace ? # whitespace ? pragma pp-pragma-text' Text=' pp-pragma-text::' Text=' new-line' Text=' whitespace input-characters ? new-line' Text='}' ] %regex { pp-directive ({whitespace})?#({whitespace})?({identifier}).* } %} [ Declarations Id='csharpDecls' Hover='true' ] [ CompilationInfo ClassName='CommentRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ] %scanner commentScanner %{ \*+/ pop {delimited-comment-section} skip {new-line} skip %} [ Declarations Id='csharpDecls' Hover='true' ] [ CompilationInfo ClassName='InterpolatedRegularStringRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ] %scanner interpolatedRegularStringScanner %{ \" pop terminal ise {interpolated-regular-string-elements} terminal interpolated-regular-string-elements {lcb} push interpolatedScanner terminal lcb %} [ Declarations Id='csharpDecls' Hover='true' ] [ CompilationInfo ClassName='InterpolatedVerbatimStringRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ] %scanner interpolatedVerbatimStringScanner %{ \" pop terminal ise {interpolated-verbatim-string-elements} terminal interpolated-verbatim-string-elements {lcb} push interpolatedScanner terminal lcb %} [ Description Hover='true' Text='In the definition of the following scanner there are two lexical rules' Text='which are correlated in some way, namely:' Text='- {rcb}' Text='- {cs-ops}' Text='Lexical rule {cs-ops} must be preceeded by lexical rule {rcb} since it' Text='contains its definition. Otherwise the lexical rule {rcb} will have no' Text='effect since its definition would be hidden by the lexical rule {cs-ops}.' Text='Otherwise (if the lexical rule {rcb} follows the definition of the lexical' Text='rule {cs-ops} or if the lexical rule {rcb} would be omited), the event' Text='handler for the lexical rule {cs-ops} should implement the funcionality' Text='of the lexical rule {rcb}. It should invoke pop action and return terminal' Text='symbol rcb. But such implementation is not clean since some push and/or pop' Text='actions are executed by lexical analyzer itself and the other with event' Text='handlers and is hard to identify their pairing.' Text='' Text='Also, there is another event handler: event identifier. This event handler' Text='should distinguish between keywords and other identifiers found in C# source' Text='code. Since it is important for a lexical analyzer to contain as few items as' Text='possible, all identifiers are treated in the source code, which separates' Text='them into names of the variables and keywords. There are other aspects that' Text='need to be taken into account, e.g. the use of keywords instead of' Text='variable names. All this can only be done in the source code and that is what' Text='this event handler should do: it should take into account the duality of' Text='keywords. Some keywords should be treated as keywords and variable names at' Text='the same time. Syntax analyzer should later decide what is right depending' Text='of the context in which this identifier is found.' Text='' Text='The same arguments apply to the definition of the next scanner, except that' Text='there is no need to handle the lexical rule {rcb} separately from the' Text='lexical rule {cs-ops} since {rcb} need not to pop the scanner but just' Text='return the token code which is returned by {cs-ops} too.' ] [ Declarations Id='csharpDecls' Hover='true' ] [ CompilationInfo ClassName='InterpolatedScannerRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ] %scanner interpolatedScanner %{ \/\/.* skip \/\* push commentScanner {integer-literal} terminal integer-literal {real-literal} terminal real-literal {character-literal} terminal character-literal {string-literal} terminal string-literal {irss} push interpolatedRegularStringScanner terminal irss {ivss} push interpolatedVerbatimStringScanner terminal ivss {identifier} event identifier {rcb} pop terminal rcb {cs-ops} event cs-ops {whitespace} skip [\n\f\r\v] pop . pop %} [ Declarations Id='csharpDecls' Hover='true' ] [ CompilationInfo ClassName='ScannerRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ] %scanner csharpScanner %{ \/\/.* skip \/\* push commentScanner {integer-literal} terminal integer-literal {real-literal} terminal real-literal {character-literal} terminal character-literal {string-literal} terminal string-literal {irss} push interpolatedRegularStringScanner terminal irss {ivss} push interpolatedVerbatimStringScanner terminal ivss {identifier} event identifier {cs-ops} event cs-ops {pp-directive} event pp-directive {whitespace} skip [\n\f\r\v] skip . skip %} [ Description Text='Lexer for c# file' Hover='true' ] [ UseScanner ScannerId='commentScanner' ScannerId='interpolatedRegularStringScanner' ScannerId='interpolatedVerbatimStringScanner' ScannerId='interpolatedScanner' InitialScanner='csharpScanner' Hover='true' ] [ CompilationInfo ClassName='CsharpLexer' NameSpace='Csharp.Lexer' Access='public' Hover='true' ] %lexer csharpLexer %{ %} [ Declarations Id='csharpDecls' Hover='true' ] [ Lexer Id='csharpLexer' Hover='true' ] [ CompilationInfo ClassName='CsharpParser' NameSpace='Csharp.Parser' Access='public' Hover='true' ] %parser csharpParser %{ [ Description Text='Helpers' ] [ Description Text='The following syntax rules are introduced only to prevent creation' ] [ Description Text='of generated rules of the form <generated rule n>' ] Helpers { identifier : raw-identifier ; coma-sign : ',' ; semicolon-sign : ';' ; aif-op-sign : '?' ; ref-readonly : ref readonly ? ; right-shift : '>' '>' ; right-shift-assignment : '>' '>' '=' ; } [ Description Text='A.3 Syntactic grammar' ] [ Description Text='A.3.1 Basic concepts' ] Basic-concepts { namespace-name : namespace-or-type-name ; type-name : namespace-or-type-name ; [ Iterator Text='This attribute is processed by Anglr compiler.' Text='Therefore, the transition of the node belonging' Text='to the syntax rule namespace-or-type-name turns' Text='into an iteration. You can also remove this' Text='attribute because namespace names are usually not' Text='long. Therefore, recursive node transitions cannot' Text='be a problem either.' ] namespace-or-type-name : simple-name | namespace-or-type-name '.' simple-name | qualified-alias-member ; } [ Description Text='A.3.2 Types' ] Types { type : reference-type | value-type | type-parameter | nullable-type | pointer-type ; reference-type : class-type | interface-type | array-type | delegate-type | dynamic ; class-type : type-name | object | string ; interface-type : type-name ; array-type : non-array-type rank-specifiers ; non-array-type : value-type | class-type | interface-type | delegate-type | dynamic | type-parameter | pointer-type ; rank-specifiers : rank-specifier + ; rank-specifier : '[' dim-separators ? ']' ; dim-separators : ',' + ; delegate-type : type-name ; value-type : non-nullable-value-type | nullable-value-type ; non-nullable-value-type : struct-type | enum-type ; struct-type : type-name | simple-type | tuple-type ; simple-type : numeric-type | bool ; numeric-type : integral-type | floating-point-type | decimal ; integral-type : sbyte | byte | short | ushort | int | uint | long | ulong | char ; nullable-type : non-nullable-value-type '?' ; floating-point-type : float | double ; tuple-type : '(' tuple-type-element { 2, } [ ',' ] ')' ; tuple-type-element : type identifier ? ; enum-type : type-name ; nullable-value-type : non-nullable-value-type '?' ; type-argument-list : '<' type-arguments '>' ; type-arguments : type-argument + [ ',' ] ; type-argument : type ; type-parameter : identifier ; unmanaged-type : value-type ; } [ Description Text='A.3.3 Variables' ] Variables { variable-reference : expression ; } [ Description Text='Source: ?11.2 Pattern Forms' ] Patterns { pattern : declaration-pattern | constant-pattern | var-pattern ; [ Description Text='Source: ?11.2.1 Declaration pattern' ] declaration-pattern : type simple-designation ; simple-designation : single-variable-designation ; single-variable-designation : identifier ; [ Description Text='Source: ?11.2.2 Constant pattern' ] constant-pattern : constant-expression ; [ Description Text='Source: ?11.2.3 Var pattern' ] var-pattern : var designation ; designation : simple-designation ; } [ Description Text='A.3.4 Expressions' ] Expressions { argument-list : argument + [ ',' ] ; argument : argument-name ? argument-value ; argument-name : identifier ':' ; argument-value : expression | in variable-reference | ref variable-reference | out variable-reference ; primary-expression : primary-no-array-creation-expression | array-creation-expression ; primary-no-array-creation-expression : literal | interpolated-string-expression | simple-name | parenthesized-expression | tuple-expression | member-access | null-conditional-member-access | invocation-expression | element-access | null-conditional-element-access | this-access | base-access | post-increment-expression | post-decrement-expression | object-creation-expression | delegate-creation-expression | anonymous-object-creation-expression | typeof-expression | sizeof-expression | checked-expression | unchecked-expression | default-value-expression | nameof-expression | anonymous-method-expression | pointer-member-access | pointer-element-access | stackalloc-expression ; interpolated-string-expression : interpolated-regular-string-expression | interpolated-verbatim-string-expression ; interpolated-regular-string-expression : Interpolated-Regular-String-Start Interpolated-Regular-String-Mid ? + [ '{' regular-interpolation '}' ] Interpolated_Regular_String_End ; interpolation-minimum-width : ',' constant-expression ; regular-interpolation : expression interpolation-minimum-width ? Regular-Interpolation-Format ? ; Interpolated-Regular-String-Start : '$"' ; Interpolated-Regular-String-Mid : interpolated-regular-string-elements ; Regular-Interpolation-Format : ':' ( :Regular-Interpolation-Format-body: interpolated-regular-string-elements | literal | identifier ) ; Interpolated_Regular_String_End : '"' ; interpolated-verbatim-string-expression : Interpolated-Verbatim-String-Start Interpolated-Verbatim-String-Mid ? + [ '{' verbatim_interpolation '}' ] Interpolated-Verbatim-String-End ; verbatim_interpolation : expression interpolation-minimum-width ? Verbatim-Interpolation-Format ? ; Interpolated-Verbatim-String-Start : '$@"' ; Interpolated-Verbatim-String-Mid : interpolated-verbatim-string-elements ; Verbatim-Interpolation-Format : ':' ( :Verbatim-Interpolation-Format-body: interpolated-verbatim-string-elements | literal | identifier ) ; Interpolated-Verbatim-String-End : '"' ; literal : boolean-literal | integer-literal | real-literal | character-literal | string-literal | null-literal ; simple-name : identifier type-argument-list ? ; parenthesized-expression : '(' expression ')' ; tuple-expression : '(' tuple-element { 2, } [ ',' ] ')' | deconstruction-expression ; tuple-element : ( :tuple-element-ref: identifier ':' ) ? expression ; deconstruction-expression : var deconstruction-tuple ; deconstruction-tuple : '(' deconstruction-element { 2, } [ ',' ] ')' ; deconstruction-element : deconstruction-tuple | identifier ; member-access : ( :member-access-head: primary-expression | predefined-type | qualified-alias-member ) aif-op-sign ? '.' simple-name ; predefined-type : bool | byte | char | decimal | double | float | int | long | object | sbyte | short | string | uint | ulong | ushort ; [ Description Text = "?12.8.8 Null Conditional Member Access" ] null-conditional-member-access : primary-expression '?' '.' simple-name dependent-access-list ? ; dependent-access-list : dependent-access + ; dependent-access : '.' simple-name | '[' argument-list ']' | '(' argument-list ? ')' ; null-conditional-projection-initializer : primary-expression '?' '.' simple-name ; invocation-expression : primary-expression '(' argument-list ? ')' ; null-conditional-invocation-expression : null-conditional-member-access '(' argument-list ? ')' | null-conditional-element-access '(' argument-list ? ')' ; element-access : primary-no-array-creation-expression '[' argument-list ']' ; null-conditional-element-access : primary-no-array-creation-expression '?' '[' argument-list ']' dependent-access-list ? ; expression-list : expression + [ ',' ] ; this-access : this ; base-access : base '.' simple-name | base '[' argument-list ']' ; post-increment-expression : primary-expression '++' ; post-decrement-expression : primary-expression '--' ; object-creation-expression : new type '(' argument-list ? ')' object-or-collection-initializer ? | new type object-or-collection-initializer ; object-or-collection-initializer : object-initializer | collection-initializer ; object-initializer : '{' member-initializer-list ? coma-sign ? '}' ; member-initializer-list : member-initializer + [ ',' ] ; member-initializer : initializer-target '=' initializer-value ; initializer-target : identifier | '[' argument-list ']' ; initializer-value : expression | object-or-collection-initializer ; collection-initializer : '{' element-initializer-list ? coma-sign ? '}' ; element-initializer-list : element-initializer + [ ',' ] ; element-initializer : non-assignment-expression | '{' expression-list '}' ; array-creation-expression : new non-array-type '[' expression-list ']' rank-specifiers ? array-initializer ? | new array-type array-initializer | new rank-specifier array-initializer ; delegate-creation-expression : new delegate-type '(' expression ')' ; anonymous-object-creation-expression : new anonymous-object-initializer ; anonymous-object-initializer : '{' member-declarator-list ? coma-sign ? '}' ; member-declarator-list : member-declarator + [ ',' ] ; member-declarator : simple-name | member-access | null-conditional-projection-initializer | base-access | identifier '=' expression ; typeof-expression : typeof '(' type ')' | typeof '(' unbound-type-name ')' | typeof '(' void ')' ; unbound-type-name : ( :unbound-type-name-head: identifier | identifier '::' identifier | unbound-type-name '.' identifier ) generic-dimension-specifier ? ; generic-dimension-specifier : '<' commas ? '>' ; commas : ',' + ; sizeof-expression : sizeof '(' unmanaged-type ')' ; checked-expression : checked '(' expression ')' ; unchecked-expression : unchecked '(' expression ')' ; default-value-expression : default ( :default-value-expression-body: '(' type ')' ) ? ; stackalloc-expression : stackalloc unmanaged-type '[' expression ']' | stackalloc unmanaged-type ? '[' expression ? ']' stackalloc-initializer ; stackalloc-initializer : '{' stackalloc-initializer-element-list '}' ; stackalloc-initializer-element-list : stackalloc-element-initializer + [ ',' ] coma-sign ? ; stackalloc-element-initializer : expression ; nameof-expression : nameof '(' named-entity ')' ; named-entity : named-entity-target named-entity-part-list ? ; named-entity-part-list : '.' simple-name + [ '.' ] ; named-entity-target : simple-name | this | base | predefined-type | qualified-alias-member ; unary-expression : primary-expression | '+' unary-expression | '-' unary-expression | '!' unary-expression | '~' unary-expression | pre-increment-expression | pre-decrement-expression | cast-expression | await-expression | pointer-indirection-expression | addressof-expression ; pre-increment-expression : '++' unary-expression ; pre-decrement-expression : '--' unary-expression ; cast-expression : '(' type ')' unary-expression ; await-expression : await unary-expression ; multiplicative-expression : unary-expression | multiplicative-expression '*' unary-expression | multiplicative-expression '/' unary-expression | multiplicative-expression '%' unary-expression ; additive-expression : multiplicative-expression | additive-expression '+' multiplicative-expression | additive-expression '-' multiplicative-expression ; shift-expression : additive-expression | shift-expression '<<' additive-expression | shift-expression right-shift additive-expression ; relational-expression : shift-expression | relational-expression '<' shift-expression | relational-expression '>' shift-expression | relational-expression '<=' shift-expression | relational-expression '>=' shift-expression | relational-expression is type | relational-expression is pattern | relational-expression is null-literal | relational-expression as type ; 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 ; conditional-and-expression : inclusive-or-expression | conditional-and-expression '&&' inclusive-or-expression ; conditional-or-expression : conditional-and-expression | conditional-or-expression '||' conditional-and-expression ; null-coalescing-expression : conditional-or-expression | conditional-or-expression '??' null-coalescing-expression | throw-expression ; throw-expression : throw null-coalescing-expression ; declaration-expression : local-variable-type identifier ; conditional-expression : null-coalescing-expression | null-coalescing-expression '?' expression ':' expression | null-coalescing-expression '?' ref variable-reference ':' ref variable-reference ; lambda-expression : async ? anonymous-function-signature '=>' anonymous-function-body ; anonymous-method-expression : async ? delegate explicit-anonymous-function-signature ? block ; anonymous-function-signature : explicit-anonymous-function-signature | implicit-anonymous-function-signature ; explicit-anonymous-function-signature : '(' explicit-anonymous-function-parameter-list ? ')' ; explicit-anonymous-function-parameter-list : explicit-anonymous-function-parameter + [ ',' ] ; explicit-anonymous-function-parameter : anonymous-function-parameter-modifier ? type identifier ; anonymous-function-parameter-modifier : ref | out | in ; implicit-anonymous-function-signature : '(' implicit-anonymous-function-parameter-list ? ')' | implicit-anonymous-function-parameter ; implicit-anonymous-function-parameter-list : implicit-anonymous-function-parameter + [ ',' ] ; implicit-anonymous-function-parameter : identifier ; anonymous-function-body : null-conditional-invocation-expression | expression | ref variable-reference | block ; query-expression : from-clause query-body ; from-clause : from type ? identifier in expression ; query-body : query-body-clauses ? select-or-group-clause query-continuation ? ; query-body-clauses : query-body-clause + ; query-body-clause : from-clause | let-clause | where-clause | join-clause | join-into-clause | orderby-clause ; let-clause : let identifier '=' expression ; where-clause : where boolean-expression ; join-clause : join type ? identifier in expression on expression equals expression ; join-into-clause : join type ? identifier in expression on expression equals expression into identifier ; orderby-clause : orderby orderings ; orderings : ordering + [ ',' ] ; ordering : expression ordering-direction ? ; ordering-direction : ascending | descending ; select-or-group-clause : select-clause | group-clause ; select-clause : select expression ; group-clause : group expression by expression ; query-continuation : into identifier query-body ; assignment : unary-expression assignment-operator expression ; assignment-operator : '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | right-shift-assignment ; expression : non-assignment-expression | assignment ; non-assignment-expression : declaration-expression | conditional-expression | lambda-expression | query-expression ; constant-expression : expression ; boolean-expression : expression ; } [ Description Text='A.3.5 Statements' ] Statements { statement : labeled-statement | declaration-statement | embedded-statement ; embedded-statement : block | empty-statement | expression-statement | selection-statement | iteration-statement | jump-statement | try-statement | checked-statement | unchecked-statement | lock-statement | using-statement | yield-statement | unsafe-statement | fixed-statement ; block : '{' statement-list ? '}' ; statement-list : statement + ; empty-statement : ';' ; labeled-statement : identifier ':' statement ; declaration-statement : local-variable-declaration ';' | local-constant-declaration ';' | local-function-declaration ; local-variable-declaration : ref-readonly ? local-variable-type local-variable-declarators ; local-variable-type : type | var ; local-variable-declarators : local-variable-declarator + [ ',' ] ; local-variable-declarator : identifier | identifier '=' local-variable-initializer ; local-variable-initializer : expression | ref variable-reference | array-initializer ; local-constant-declaration : const type constant-declarators ; constant-declarators : constant-declarator + [ ',' ] ; constant-declarator : identifier '=' constant-expression ; local-function-declaration : local-function-header local-function-body ; local-function-header : local-function-modifiers ? ref-readonly ? return-type identifier type-parameter-list ? '(' formal-parameter-list ? ')' type-parameter-constraints-clauses ? ; local-function-modifiers : local-function-modifier + ; local-function-modifier : async | unsafe ; local-function-body : block | '=>' null-conditional-invocation-expression ';' | '=>' expression ';' ; expression-statement : statement-expression ';' ; statement-expression : null-conditional-invocation-expression | invocation-expression | object-creation-expression | assignment | post-increment-expression | post-decrement-expression | pre-increment-expression | pre-decrement-expression | await-expression ; selection-statement : if-statement | switch-statement ; if-statement : if '(' boolean-expression ')' embedded-statement | if '(' boolean-expression ')' embedded-statement else embedded-statement ; switch-statement : switch '(' expression ')' switch-block ; switch-block : '{' switch-sections ? '}' ; switch-sections : switch-section + ; switch-section : switch-labels statement-list ; switch-labels : switch-label + ; switch-label : case pattern case-guard ? ':' | default ':' ; case-guard : when expression ; iteration-statement : while-statement | do-statement | for-statement | foreach-statement ; while-statement : while '(' boolean-expression ')' embedded-statement ; do-statement : do embedded-statement while '(' boolean-expression ')' ';' ; for-statement : for '(' for-initializer ? ';' for-condition ? ';' for-iterator ? ')' embedded-statement ; for-initializer : local-variable-declaration | statement-expression-list ; for-condition : boolean-expression ; for-iterator : statement-expression-list ; statement-expression-list : statement-expression + [ ',' ] ; foreach-statement : foreach '(' ref-readonly ? local-variable-type identifier ? in expression ')' embedded-statement ; jump-statement : break-statement | continue-statement | goto-statement | return-statement | throw-statement ; break-statement : break ';' ; continue-statement : continue ';' ; goto-statement : goto identifier ';' | goto case constant-expression ';' | goto default ';' ; return-statement : return ';' | return expression ';' | return ref variable-reference ';' ; throw-statement : throw expression ? ';' ; try-statement : try block catch-clauses | try block catch-clauses ? finally-clause ; catch-clauses : specific-catch-clauses | specific-catch-clauses ? general-catch-clause ; specific-catch-clauses : specific-catch-clause + ; specific-catch-clause : catch exception-specifier exception-filter ? block | catch exception-filter block ; exception-specifier : '(' type identifier ? ')' ; exception-filter : when '(' boolean-expression ')' ; general-catch-clause : catch block ; finally-clause : finally block ; checked-statement : checked block ; unchecked-statement : unchecked block ; lock-statement : lock '(' expression ')' embedded-statement ; using-statement : using '(' resource-acquisition ')' embedded-statement ; resource-acquisition : local-variable-declaration | expression ; yield-statement : yield return expression ';' | yield break ';' ; } [ Description Text='A.3.6 Namespaces' ] Namespaces { [ Start ] compilation-unit : extern-alias-directives ? global-using-directives ? using-directives ? global-attributes ? namespace-member-declarations ? ; global-using-directives : global-using-directive + ; global-using-directive : global-using-alias-directive | global-using-namespace-directive | global-using-static-directive ; global-using-alias-directive : global using identifier '=' namespace-or-type-name ';' ; global-using-namespace-directive : global using namespace-name ';' ; global-using-static-directive : global using static type-name ';' ; namespace-declaration : namespace qualified-identifier namespace-body semicolon-sign ? ; qualified-identifier : identifier + [ '.' ] ; namespace-body : '{' extern-alias-directives ? using-directives ? namespace-member-declarations ? '}' ; extern-alias-directives : extern-alias-directive + ; extern-alias-directive : extern alias identifier ';' ; using-directives : using-directive + ; using-directive : using-alias-directive | using-namespace-directive | using-static-directive ; using-alias-directive : using identifier '=' namespace-or-type-name ';' ; using-namespace-directive : using namespace-name ';' ; using-static-directive : using static type-name ';' ; namespace-member-declarations : namespace-member-declaration + ; namespace-member-declaration : namespace-declaration | type-declaration ; type-declaration : class-declaration | struct-declaration | interface-declaration | enum-declaration | delegate-declaration ; qualified-alias-member : identifier '::' simple-name ; } [ Description Text='A.3.7 Classes' ] Classes { class-declaration : attributes ? class-modifiers ? partial ? class identifier type-parameter-list ? class-base ? type-parameter-constraints-clauses ? class-body semicolon-sign ? ; class-modifiers : class-modifier + ; class-modifier : new | public | protected | internal | private | abstract | sealed | static | unsafe-modifier ; type-parameter-list : '<' type-parameters '>' ; type-parameters : ( :type-parameters-body: attributes ? type-parameter ) + [ ',' ] ; class-base : ':' class-type | ':' interface-type-list | ':' class-type ',' interface-type-list ; interface-type-list : interface-type + [ ',' ] ; type-parameter-constraints-clauses : type-parameter-constraints-clause + ; type-parameter-constraints-clause : where type-parameter ':' type-parameter-constraints ; type-parameter-constraints : primary-constraint | secondary-constraints | constructor-constraint | primary-constraint ',' secondary-constraints | primary-constraint ',' constructor-constraint | secondary-constraints ',' constructor-constraint | primary-constraint ',' secondary-constraints ',' constructor-constraint ; primary-constraint : class-type | class | struct | unmanaged ; secondary-constraints : ( :secondary-constraints-body: interface-type | type-parameter ) + [ ',' ] ; constructor-constraint : new '(' ')' ; class-body : '{' class-member-declarations ? '}' ; class-member-declarations : class-member-declaration + ; class-member-declaration : constant-declaration | field-declaration | method-declaration | property-declaration | event-declaration | indexer-declaration | operator-declaration | constructor-declaration | finalizer-declaration | static-constructor-declaration | type-declaration ; constant-declaration : attributes ? constant-modifiers ? const type constant-declarators ';' ; constant-modifiers : constant-modifier + ; constant-modifier : new | public | protected | internal | private ; field-declaration : attributes ? field-modifiers ? type variable-declarators ';' ; field-modifiers : field-modifier + ; field-modifier : new | public | protected | internal | private | static | readonly | volatile | unsafe-modifier ; variable-declarators : variable-declarator + [ ',' ] ; variable-declarator : identifier | identifier '=' variable-initializer ; method-declaration : method-header method-body ; method-header : attributes ? method-modifiers ? partial ? ref-readonly ? return-type member-name type-parameter-list ? '(' formal-parameter-list ? ')' type-parameter-constraints-clauses ? ; method-modifiers : method-modifier + ; method-modifier : new | public | protected | internal | private | static | virtual | sealed | override | abstract | extern | async | unsafe-modifier ; return-type : type | void ; member-name : identifier | interface-type '.' identifier ; method-body : block | '=>' null-conditional-invocation-expression ';' | '=>' expression ';' | ';' ; formal-parameter-list : fixed-parameters | fixed-parameters ',' parameter-array | parameter-array ; fixed-parameters : fixed-parameter + [ ',' ] ; fixed-parameter : attributes ? parameter-modifier ? type identifier default-argument ? ; default-argument : '=' expression ; parameter-modifier : parameter-mode-modifier | this ; parameter-mode-modifier : ref | out | in ; parameter-array : attributes ? params array-type identifier ; property-declaration : attributes ? property-modifiers ? ref-readonly ? type member-name property-body ; property-modifiers : property-modifier + ; property-modifier : new | public | protected | internal | private | static | virtual | sealed | override | abstract | extern | unsafe-modifier ; property-body : '{' accessor-declarations '}' property-initializer ? | '=>' expression ';' ; property-initializer : '=' variable-initializer ';' ; accessor-declarations : get-accessor-declaration set-accessor-declaration ? | set-accessor-declaration get-accessor-declaration ? ; get-accessor-declaration : attributes ? accessor-modifier ? get accessor-body ; set-accessor-declaration : attributes ? accessor-modifier ? set accessor-body ; accessor-modifier : protected | internal | private | protected internal | internal protected | protected private | private protected ; accessor-body : block | '=>' expression ';' | ';' ; event-declaration : attributes ? event-modifiers ? event type variable-declarators ';' | attributes ? event-modifiers ? event type member-name '{' event-accessor-declarations '}' ; event-modifiers : event-modifier + ; event-modifier : new | public | protected | internal | private | static | virtual | sealed | override | abstract | extern | unsafe-modifier ; event-accessor-declarations : add-accessor-declaration remove-accessor-declaration | remove-accessor-declaration add-accessor-declaration ; add-accessor-declaration : attributes ? add block | attributes ? add '=>' expression ';' ; remove-accessor-declaration : attributes ? remove block | attributes ? remove '=>' expression ';' ; indexer-declaration : attributes ? indexer-modifiers ? indexer-declarator indexer-body ; indexer-modifiers : indexer-modifier + ; indexer-modifier : new | public | protected | internal | private | virtual | sealed | override | abstract | extern | unsafe-modifier ; indexer-declarator : ref-readonly ? type this '[' formal-parameter-list ']' | ref-readonly ? type interface-type '.' this '[' formal-parameter-list ']' ; indexer-body : '{' accessor-declarations '}' | '=>' expression ';' ; operator-declaration : attributes ? operator-modifiers operator-declarator operator-body ; operator-modifiers : operator-modifier + ; operator-modifier : public | static | extern | unsafe-modifier ; operator-declarator : unary-operator-declarator | binary-operator-declarator | conversion-operator-declarator ; unary-operator-declarator : type operator overloadable-unary-operator '(' fixed-parameter ')' ; overloadable-unary-operator : '+' | '-' | '!' | '~' | '++' | '--' | true | false ; binary-operator-declarator : type operator overloadable-binary-operator '(' fixed-parameter ',' fixed-parameter ')' ; overloadable-binary-operator : '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<' | right-shift | '==' | '!=' | '>' | '<' | '>=' | '<=' ; conversion-operator-declarator : implicit operator type '(' fixed-parameter ')' | explicit operator type '(' fixed-parameter ')' ; operator-body : block | '=>' expression ';' | ';' ; constructor-declaration : attributes ? constructor-modifiers ? constructor-declarator constructor-body ; constructor-modifiers : constructor-modifier + ; constructor-modifier : public | protected | internal | private | extern | unsafe-modifier ; constructor-declarator : identifier '(' formal-parameter-list ? ')' constructor-initializer ? ; constructor-initializer : ':' base '(' argument-list ? ')' | ':' this '(' argument-list ? ')' ; constructor-body : block | '=>' expression ';' | ';' ; static-constructor-declaration : attributes ? static-constructor-modifiers identifier '(' ')' static-constructor-body ; static-constructor-modifiers : static | static extern unsafe-modifier ? | static unsafe-modifier extern ? | extern static unsafe-modifier ? | extern unsafe-modifier static | unsafe-modifier static extern ? | unsafe-modifier extern static ; static-constructor-body : block | '=>' expression ';' | ';' ; finalizer-declaration : attributes ? '~' identifier '(' ')' finalizer-body | attributes ? extern unsafe-modifier ? '~' identifier '(' ')' finalizer-body | attributes ? unsafe-modifier extern ? '~' identifier '(' ')' finalizer-body ; finalizer-body : block | '=>' expression ';' | ';' ; } [ Description Text='A.3.8 Structs' ] Structs { struct-declaration : attributes ? struct-modifiers ? ref ? partial ? struct identifier type-parameter-list ? struct-interfaces ? type-parameter-constraints-clauses ? struct-body semicolon-sign ? ; struct-modifiers : struct-modifier + ; struct-modifier : new | public | protected | internal | private | readonly | unsafe-modifier ; struct-interfaces : ':' interface-type-list ; struct-body : '{' struct-member-declarations ? '}' ; struct-member-declarations : struct-member-declaration + ; struct-member-declaration : constant-declaration | field-declaration | method-declaration | property-declaration | event-declaration | indexer-declaration | operator-declaration | constructor-declaration | static-constructor-declaration | type-declaration | fixed-size-buffer-declaration ; } [ Description Text='A.3.9 Arrays' ] Arrays { array-initializer : '{' variable-initializer-list ? coma-sign ? '}' ; variable-initializer-list : variable-initializer + [ ',' ] ; variable-initializer : expression | array-initializer ; } [ Description Text='A.3.10 Interfaces' ] Interfaces { interface-declaration : attributes ? interface-modifiers ? partial ? interface identifier variant-type-parameter-list ? interface-base ? type-parameter-constraints-clauses ? interface-body semicolon-sign ? ; interface-modifiers : interface-modifier + ; interface-modifier : new | public | protected | internal | private | unsafe-modifier ; variant-type-parameter-list : '<' variant-type-parameters '>' ; variant-type-parameters : ( :variant-type-parameter: attributes ? variance-annotation ? type-parameter ) + [ ',' ] ; variance-annotation : in | out ; interface-base : ':' interface-type-list ; interface-body : '{' interface-member-declarations ? '}' ; interface-member-declarations : interface-member-declaration + ; interface-member-declaration : interface-method-declaration | interface-property-declaration | interface-event-declaration | interface-indexer-declaration ; interface-method-declaration : attributes ? new ? return-type identifier type-parameter-list ? '(' formal-parameter-list ? ')' type-parameter-constraints-clauses ? ';' ; interface-property-declaration : attributes ? new ? type identifier '{' interface-accessors '}' ; interface-accessors : attributes ? get ';' | attributes ? set ';' | attributes ? get ';' attributes ? set ';' | attributes ? set ';' attributes ? get ';' ; interface-event-declaration : attributes ? new ? event type identifier ';' ; interface-indexer-declaration : attributes ? new ? type this '[' formal-parameter-list ']' '{' interface-accessors '}' ; } [ Description Text='A.3.11 Enums' ] Enums { enum-declaration : attributes ? enum-modifiers ? enum identifier enum-base ? enum-body semicolon-sign ? ; enum-base : ':' integral-type | ':' integral-type-name ; integral-type-name : type-name ; enum-body : '{' enum-member-declarations ? coma-sign ? '}' ; enum-modifiers : enum-modifier + ; enum-modifier : new | public | protected | internal | private ; enum-member-declarations : enum-member-declaration + [ ',' ] ; enum-member-declaration : attributes ? identifier | attributes ? identifier '=' constant-expression ; } [ Description Text='A.3.12 Delegates' ] Delegates { delegate-declaration : attributes ? delegate-modifiers ? delegate ref-readonly ? return-type identifier variant-type-parameter-list ? '(' formal-parameter-list ? ')' type-parameter-constraints-clauses ? ';' ; delegate-modifiers : delegate-modifier + ; delegate-modifier : new | public | protected | internal | private | unsafe-modifier ; } [ Description Text='A.3.13 Attributes' ] Attributes { global-attributes : global-attribute-sections ; global-attribute-sections : global-attribute-section + ; global-attribute-section : '[' global-attribute-target-specifier attribute-list coma-sign ? ']' ; global-attribute-target-specifier : global-attribute-target ':' ; global-attribute-target : identifier ; attributes : attribute-sections ; attribute-sections : attribute-section + ; attribute-section : '[' attribute-target-specifier ? attribute-list coma-sign ? ']' ; attribute-target-specifier : attribute-target ':' ; attribute-target : identifier | keyword ; attribute-list : attribute + [ ',' ] ; attribute : attribute-name attribute-arguments ? ; attribute-name : type-name ; attribute-arguments : '(' positional-argument-list ? ')' | '(' positional-argument-list ',' named-argument-list ')' | '(' named-argument-list ')' ; positional-argument-list : positional-argument + [ ',' ] ; positional-argument : argument-name ? attribute-argument-expression ; named-argument-list : named-argument + [ ',' ] ; named-argument : identifier '=' attribute-argument-expression ; attribute-argument-expression : expression ; } [ Description Text='A.4 Grammar extensions for unsafe code' ] Grammar-extensions-for-unsafe-code { unsafe-modifier : unsafe ; unsafe-statement : unsafe block ; pointer-type : unmanaged-type '*' | void '*' ; pointer-indirection-expression : '*' unary-expression ; pointer-member-access : primary-expression '->' simple-name ; pointer-element-access : primary-no-array-creation-expression '[' expression ']' ; addressof-expression : '&' unary-expression ; fixed-statement : fixed '(' pointer-type fixed-pointer-declarators ')' embedded-statement ; fixed-pointer-declarators : fixed-pointer-declarator + [ ',' ] ; fixed-pointer-declarator : identifier '=' fixed-pointer-initializer ; fixed-pointer-initializer : '&' variable-reference | expression ; fixed-size-buffer-declaration : attributes ? fixed-size-buffer-modifiers ? fixed buffer-element-type fixed-size-buffer-declarators ';' ; [ Description Text='ATTENTION: right recursion' ] fixed-size-buffer-modifiers : fixed-size-buffer-modifier - ; fixed-size-buffer-modifier : new | public | protected | internal | private | unsafe ; buffer-element-type : type ; [ Description Text='ATTENTION: right recursion' ] fixed-size-buffer-declarators : fixed-size-buffer-declarator - [ ',' ] ; fixed-size-buffer-declarator : identifier '[' constant-expression ']' ; } %}