Anglr Syntax Rules for C# Language


Introduction

This paragraph introduces C# syntax rules written in Anglr. C# parser, which is made using these rules, translates most C# programs. The exception are programs that contain n-tuples. At C# it is impressive how rich a range of characters can be used for variable names and how few rules are needed to form lexical analyzers.

[ CompilationInfo ClassName='CsharpDeclarations' NameSpace='Csharp.Declarations' Access='public' TokenPrefix='token_' Hover='true' ]
%declarations csharpDecls
%{
    %terminal
    {
        namespace identifier extern alias using float double sbyte byte short ushort int uint
        long ulong char decimal bool ref out object string base this nameof unmanaged
        new typeof void await checked default unchecked delegate async from in group by join
        on equals into let orderby ascending descending is as select where break continue do
        while finally for foreach catch goto case if else const var lock return switch throw
        try yield class partial public protected internal private abstract sealed static struct
        readonly volatile virtual override get params set add event remove operator implicit
        explicit true false interface enum unsafe fixed stackalloc dynamic sizeof null
        when
        Interpolated-Regular-String-Element
        Interpolated-Verbatim-String-Element
    }

    %terminal
    {
        keyword
        boolean-literal
        integer-literal
        real-literal
        character-literal
        string-literal
        null-literal
    }

    %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 '?'
    }

    %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='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        ({decimal-integer-literal})|({hexadecimal-integer-literal})
        decimal-integer-literal      ({decimal-digits})({integer-type-suffix})?
        decimal-digits        ({decimal-digit})+
        decimal-digit        [0-9]
        integer-type-suffix       U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu
        hexadecimal-integer-literal     0(x|X)({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
    }

    [ Description Text='Operators and punctuators' Hover='true' ]
    %regex
    {
        operator-or-punctuator \{|\}|\[|\]|\(|\)|\.|\,|\:|\;|\+|\-|\*|\/|\%|\&|\||\^|\!|\~|\=|\<|\>|\?|\?\?|\:\:|\+\+|\-\-|\&\&|\|\||\-\>|\=\=|\!\=|\<\=|\>\=|\+\=|\-\=|\*\=|\/\=|\%\=|\&\=|\|\=|\^\=|\<\<|\<\<\=
        right-shift    \>\>
        right-shift-assignment \>\>\=
    }

    [ Description
        Text='Pre-processing directives'

        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
    {
    }
%}

[ RegexCompilationInfo ClassName='CsharpCommentRegex' Namespace='Csharp.RegexLib' Public='true' ]
[ CompilationInfo ClassName='CommentRegex' NameSpace='Csharp.RegexLib' Access='public' Hover='true' ]
%scanner commentScanner
%{
\*+/
    pop
{delimited-comment-section}
    skip
{new-line}
    skip
%}

[ RegexCompilationInfo ClassName='CsharpLangRegex' Namespace='Csharp.RegexLib' Public='true' ]
[ 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
{identifier}
    event identifier
{cs-ops}
    event cs-ops
[ \t]
    skip
[\n\f\r\v]
    skip
.
    skip
%}

[ Description Text='Lexer for c# file' Hover='true' ]
[
    UseScanner
        ScannerId='commentScanner'
        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
%{

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
    ;

namespace-or-type-name
    : identifier type-argument-list ?
    | namespace-or-type-name '.' identifier type-argument-list ?
    | 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 ',' tuple-type-element + [ ',' ] ')'
    ;

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' ]
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
    : ':' Interpolated-Regular-String-Elements
    ;

Interpolated-Regular-String-Elements
    : Interpolated-Regular-String-Element +
    ;

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
    : ':' Interpolated-Verbatim-String-Elements
    ;

Interpolated-Verbatim-String-Elements
    : Interpolated-Verbatim-String-Element +
    ;

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 ',' tuple-element + [ ',' ] ')'
    | deconstruction-expression
    ;

tuple-element
    : (identifier ':')? expression
    ;

deconstruction-expression
    : var deconstruction-tuple
    ;

deconstruction-tuple
    : '(' deconstruction-element ',' deconstruction-element + [ ',' ] ')'
    ;

deconstruction-element
    : deconstruction-tuple
    | identifier
    ;

member-access
    : ( primary-expression | predefined-type  | qualified-alias-member ) '?' ? '.' identifier type-argument-list ?
    ;

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 '?' '.' identifier type-argument-list ? dependent-access *
    ;

dependent-access
    : '.' identifier type-argument-list ?
    | '[' argument-list ']'
    | '(' argument-list ? ')'
    ;

null-conditional-projection-initializer
    : primary-expression '?' '.' identifier type-argument-list ?
    ;

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 *
    ;

expression-list
    : expression + [ ',' ]
    ;

this-access
    : this
    ;

base-access
    : base '.' identifier type-argument-list ?
    | 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 ? '}'
    | '{' member-initializer-list ',' '}'
    ;

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 '}'
    | '{' element-initializer-list ',' '}'
    ;

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 ? '}'
    | '{' member-declarator-list ',' '}'
    ;

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
    : ( identifier | identifier '::' identifier | unbound-type-name '.' identifier ) generic-dimension-specifier ?
    ;

generic-dimension-specifier
    : '<' commas ? '>'
    ;

commas
    : ','
    | commas ','
    ;

sizeof-expression
    : sizeof '(' unmanaged-type ')'
    ;

checked-expression
    : checked '(' expression ')'
    ;

unchecked-expression
    : unchecked '(' expression ')'
    ;

default-value-expression
    : default ( '(' 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 + [ ',' ] ',' ?
    ;

stackalloc-element-initializer
    : expression
    ;

nameof-expression
    : nameof '(' named-entity ')'
    ;

named-entity
    : named-entity-target ( '.' identifier type-argument-list ? ) *
    ;

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-modifier * ( ref readonly ? ) ? return-type identifier type-parameter-list ? ( formal-parameter-list ? ) type-parameter-constraints-clauses ?
    ;

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 ? using-directives ? global-attributes ? namespace-member-declarations ?
    ;

namespace-declaration
    : namespace qualified-identifier namespace-body ';' ?
    ;

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 '::' identifier type-argument-list ?
    ;

}

[ 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 ';' ?
    ;

class-modifiers
    : class-modifier +
    ;

class-modifier
    : new
    | public
    | protected
    | internal
    | private
    | abstract
    | sealed
    | static
    | unsafe-modifier
    ;

type-parameter-list
    : '<' type-parameters '>'
    ;

type-parameters
    : ( 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
    : ( 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
    ;

remove-accessor-declaration
    : attributes ? remove block
    ;

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 ';' ?
    ;

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 ? '}'
    | '{' variable-initializer-list ',' '}'
    ;

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 ';' ?
    ;

interface-modifiers
    : interface-modifier +
    ;

interface-modifier
    : new
    | public
    | protected
    | internal
    | private
    | unsafe-modifier
    ;

variant-type-parameter-list
    : '<' variant-type-parameters '>'
    ;

variant-type-parameters
    : ( 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 ';' ?
    ;

enum-base
    : ':' integral-type
    | ':' integral-type-name
    ;

integral-type-name
    : type-name
    ;

enum-body
    : '{' enum-member-declarations ? '}'
    | '{' enum-member-declarations ',' '}'
    ;

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 ']'
    | '[' global-attribute-target-specifier attribute-list ',' ']'
    ;

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 ']'
    | '[' attribute-target-specifier ? attribute-list ',' ']'
    ;

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 '->' identifier type-argument-list ?
    ;

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 ']'
    ;

}

%}