@willbooster/tree-sitter-c-sharp 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/grammar.js CHANGED
@@ -6,9 +6,13 @@
6
6
  * @license MIT
7
7
  */
8
8
 
9
- /// <reference types="tree-sitter-cli/dsl" />
10
9
  // @ts-check
11
10
 
11
+ const { alias, choice, field, grammar, optional, prec, repeat, repeat1, seq, sym, token } =
12
+ /** @type {typeof globalThis & import('@willbooster/web-tree-sitter/dsl').DSL} */ (globalThis);
13
+
14
+ /** @typedef {'_preproc_expression' | '_top_level_item_no_statement' | 'attribute_list' | 'declaration' | 'enum_member_declaration' | 'expression' | 'method_signature' | 'statement'} PreprocContentRule */
15
+
12
16
  const PREC = {
13
17
  GENERIC: 19,
14
18
  DOT: 18,
@@ -49,27 +53,140 @@ module.exports = grammar({
49
53
  name: 'c_sharp',
50
54
 
51
55
  conflicts: ($) => [
52
- [$._assignment_pointer_cast, $._lvalue_cast_expression],
53
- [$._assignment_pointer_expression, $._pointer_indirection_expression],
56
+ [$.list_pattern],
57
+ [$._conditional_binding_receiver, $._binding_generic_suppression_expression],
58
+ [$._member_conditional_binding_receiver, $._member_binding_generic_suppression_expression],
59
+ [$._binding_invocation_expression, $._binding_generic_suppression_expression],
60
+ [$._member_binding_invocation_expression, $._member_binding_generic_suppression_expression],
61
+ [$._simple_name, $._generic_alias_qualified_name],
62
+ [$._simple_name, $._generic_invocation_simple_name],
63
+ [$._pattern_declaration_type, $._assignment_target_await_expression, $.await_expression],
64
+ [$.recursive_pattern],
65
+ [$.type, $._pattern_type, $.recursive_pattern],
66
+ [$.implicit_type, $._pattern_identifier, $.var_pattern, $._reserved_identifier],
67
+ [$._pattern_primary_expression, $._pattern_non_name_primary_expression],
68
+ [$._pattern_type, $._pattern_array_type],
69
+ [$._pattern_type, $.recursive_pattern],
70
+ [$._pattern_type, $._pattern_array_type, $._array_base_type],
71
+ [$._pattern_identifier, $.var_pattern, $._reserved_identifier],
72
+ [
73
+ $._pattern_primary_expression,
74
+ $._pattern_non_name_primary_expression,
75
+ $._primary_no_conditional_access_expression,
76
+ ],
77
+ [
78
+ $._pattern_primary_expression,
79
+ $._primary_no_conditional_access_expression,
80
+ $.conditional_access_expression,
81
+ $._conditional_assignment_expression,
82
+ ],
83
+ [$._pattern_primary_expression, $.conditional_access_expression, $._conditional_assignment_expression],
84
+ [
85
+ $._primary_no_conditional_access_expression,
86
+ $.conditional_access_expression,
87
+ $._conditional_assignment_expression,
88
+ ],
89
+ [$._pattern_array_type, $._array_base_type],
90
+ [$._definite_cast_type, $._range_cast_type],
91
+ [$.type, $._definite_cast_type, $._range_cast_type],
92
+ [$._pattern_type, $._definite_cast_type, $._range_cast_type],
93
+ [$._definite_cast_name, $._range_cast_type],
94
+ [$._name, $._definite_cast_name, $._range_cast_type],
95
+ [$.array_rank_specifier, $._omitted_array_rank_specifier],
96
+ [$._pattern_parenthesized_expression, $.constant_pattern, $.expression],
97
+ [$._pattern_parenthesized_expression, $.constant_pattern],
98
+ [$._simple_name, $._pattern_simple_identifier_name, $._ambiguous_cast_qualified_name],
99
+ [$._simple_name, $._ambiguous_cast_qualified_name],
100
+ [$._simple_name, $._definite_cast_qualified_name],
101
+ [$.positional_pattern_clause, $._untyped_positional_pattern_clause],
102
+ [$._parenthesized_pattern_with_designation, $.subpattern],
103
+ [$._pattern_type, $._definite_cast_type],
104
+ [$.type, $._definite_cast_type],
105
+ [$.parameter, $._simple_name, $._ambiguous_cast_name],
106
+ [$._simple_name, $._ambiguous_cast_name],
107
+ [$._simple_name, $._definite_cast_name],
108
+ [$._name, $._definite_cast_name],
109
+ [$._object_initializer_expression, $.initializer_expression],
110
+ [
111
+ $._pattern_primary_expression,
112
+ $._primary_no_conditional_access_expression,
113
+ $._definite_conditional_access_receiver,
114
+ ],
115
+ [$._pattern_primary_expression, $._definite_conditional_access_receiver],
116
+ [$._primary_no_conditional_access_expression, $._definite_conditional_access_receiver],
117
+ [$._pattern_unary_expression, $._nonconditional_unary_expression],
118
+ [$._pattern_primary_expression, $._nonconditional_unary_expression],
119
+ [$._pattern_primary_expression, $._primary_no_conditional_access_expression, $._conditional_access_receiver],
120
+ [$.parameter, $._pattern_non_name_primary_expression, $._primary_no_conditional_access_expression],
121
+ [$._named_subpattern, $.subpattern],
122
+ [$.parameter_list, $._untyped_positional_pattern_clause],
123
+ [$.pattern, $._nonconstant_pattern],
124
+ [$.attribute, $._pattern_type],
125
+ [$.type, $._pattern_type],
126
+ [$.type, $._pattern_declaration_type],
127
+ [$._pattern_type, $._pattern_declaration_type],
128
+ [$._pattern_type, $.nullable_type],
129
+ [$._pattern_type, $._pattern_nullable_type, $.nullable_type],
130
+ [$._pattern_type, $._pattern_nullable_type],
131
+ [$._pattern_nullable_type, $.nullable_type],
132
+ [$._pattern_type, $._pointer_base_type],
133
+ [$._pattern_member_access_expression, $._pattern_generic_member_expression],
134
+ [$._simple_name, $._pattern_simple_generic_name],
135
+ [$._simple_name, $.generic_name, $._pattern_simple_identifier_name],
136
+ [$._simple_name, $._pattern_simple_identifier_name],
137
+ [$.generic_name, $._pattern_simple_identifier_name],
138
+ [$._pattern_non_name_member_access_expression, $.member_access_expression],
139
+ [$._pattern_unary_expression, $._unary_expression],
140
+ [$._pattern_primary_expression, $._primary_expression],
141
+ [$._pattern_primary_expression, $._primary_no_conditional_access_expression],
142
+ [$._pattern_identifier, $.from_clause, $._reserved_identifier],
143
+ [$.scoped_type, $._pattern_identifier, $._reserved_identifier],
144
+ [$._pattern_identifier, $._lambda_expression_init, $.anonymous_method_expression, $._reserved_identifier],
145
+ [$._pattern_identifier, $.identifier],
146
+ [$.implicit_type, $._pattern_identifier, $._reserved_identifier],
147
+ [$._pattern_primary_expression, $._conditional_access_receiver],
148
+ [$._pattern_non_name_primary_expression, $._primary_no_conditional_access_expression],
149
+ [$._pattern_identifier, $._reserved_identifier],
150
+ [$.var_pattern, $._reserved_identifier],
151
+ [$.anonymous_method_expression, $._reserved_identifier],
152
+ [$.attribute, $.type, $.recursive_pattern],
153
+ [$._initialized_stackalloc_expression, $.stackalloc_expression],
154
+ [$._member_conditional_binding_expression, $._member_conditional_binding_receiver],
155
+ [$.array_creation_expression, $._initialized_array_creation_expression],
156
+ [$.type, $.array_creation_expression, $._initialized_array_creation_expression],
157
+ [$._name, $._primary_no_conditional_access_expression, $._conditional_access_receiver],
158
+ [$._primary_no_conditional_access_expression, $._conditional_access_receiver],
159
+ [$._name, $._conditional_access_receiver],
160
+ [$.constant_pattern, $._nonconditional_unary_expression],
161
+ [$._unary_expression, $._nonconditional_unary_expression],
162
+ [$._primary_expression, $._nonconditional_unary_expression],
163
+ [$.constant_pattern, $._primary_no_conditional_access_expression],
164
+ [$._name, $.constant_pattern, $._primary_no_conditional_access_expression],
165
+ [$._conditional_binding_expression, $._conditional_binding_receiver],
166
+ [$.parameter, $._primary_no_conditional_access_expression],
167
+ [$._primary_expression, $.conditional_access_expression],
168
+ [$._name, $._primary_no_conditional_access_expression],
169
+ [$.constant_pattern, $._primary_expression],
170
+ [$._name, $.constant_pattern, $._primary_expression],
171
+ [$.parameter, $._primary_expression],
172
+ [$._unary_expression, $.conditional_access_expression],
173
+ [$._name, $._primary_expression],
174
+ [$.constant_pattern, $._unary_expression],
175
+ [$.constant_pattern, $.expression],
176
+ [$.tuple_element, $.declaration_expression],
177
+ [$.nullable_type, $.array_creation_expression],
178
+ [$._array_base_type, $.array_creation_expression],
179
+ [$.modifier, $.anonymous_method_expression, $._reserved_identifier],
180
+ [$.modifier, $.anonymous_method_expression],
54
181
  [$.modifier, $._constructor_declaration_initializer, $._reserved_identifier],
55
182
  [$._simple_name, $.generic_name],
56
183
  [$._simple_name, $.type_parameter],
57
184
  [$._simple_name, $.subpattern],
58
-
59
185
  [$.tuple_element, $.type_pattern],
60
186
  [$.type_pattern, $.declaration_pattern],
61
187
  [$.tuple_element, $.using_variable_declarator],
62
-
63
188
  [$.tuple_pattern, $.parameter],
64
189
  [$.tuple_pattern, $._simple_name],
65
-
66
- [$.lvalue_expression, $._name],
67
- [$.parameter, $.lvalue_expression],
68
- // C# 14 null-conditional assignment: `obj?.x = v` requires
69
- // `conditional_access_expression` to appear in both lvalue and
70
- // non-lvalue contexts. Tree-sitter needs GLR for the decision.
71
- [$.lvalue_expression, $.non_lvalue_expression],
72
-
73
190
  [$.type, $.attribute],
74
191
  [$.type, $.nullable_type],
75
192
  [$.type, $.nullable_type, $.array_creation_expression],
@@ -77,28 +194,18 @@ module.exports = grammar({
77
194
  [$.type, $._array_base_type, $.array_creation_expression],
78
195
  [$.type, $.array_creation_expression],
79
196
  [$.type, $._pointer_base_type],
80
-
81
197
  [$.qualified_name, $.member_access_expression],
82
198
  [$.qualified_name, $.explicit_interface_specifier],
83
-
84
199
  [$._array_base_type, $.stackalloc_expression],
85
-
86
- [$.constant_pattern, $.non_lvalue_expression],
87
200
  [$.constant_pattern, $._expression_statement_expression],
88
- [$.constant_pattern, $.lvalue_expression],
89
201
  [$.constant_pattern, $._name],
90
- [$.constant_pattern, $.lvalue_expression, $._name],
91
-
92
202
  [$.type, $._name_invocation_pattern, $.recursive_pattern],
93
203
  [$.type, $.recursive_pattern],
94
204
  [$.attribute, $.type, $._name_invocation_pattern, $.recursive_pattern],
95
-
96
205
  [$.parenthesized_pattern, $._parenthesized_pattern_with_designation],
97
-
98
206
  [$.expression_element, $.argument],
99
207
  [$.spread_element, $.range_expression],
100
208
  [$.collection_expression, $.list_pattern],
101
-
102
209
  [$._reserved_identifier, $.modifier],
103
210
  [$._reserved_identifier],
104
211
  [$._lambda_expression_init, $.anonymous_method_expression, $._reserved_identifier],
@@ -118,52 +225,67 @@ module.exports = grammar({
118
225
  [$.tuple_element, $.parameter, $.declaration_expression],
119
226
  [$.parameter, $.declaration_expression],
120
227
  [$.parameter, $.tuple_element],
121
-
122
228
  [$.event_declaration, $.variable_declarator],
123
-
124
229
  [$.base_list],
125
230
  [$.using_directive, $.modifier],
126
231
  [$.using_directive],
127
-
128
232
  [$._constructor_declaration_initializer, $._simple_name],
129
-
130
- // For C# 14 extension declarations: `extension(scoped X x)` —
131
- // `scoped` can be a parameter modifier, a scoped_type, or a
132
- // reserved identifier (when there's no further type). Keep all
133
- // three alive until later tokens disambiguate.
134
233
  [$.receiver_parameter, $.scoped_type, $._reserved_identifier],
135
234
  ],
136
235
 
137
- externals: ($) => [
138
- $._optional_semi,
139
- $.interpolation_regular_start,
140
- $.interpolation_verbatim_start,
141
- $.interpolation_raw_start,
142
- $.interpolation_start_quote,
143
- $.interpolation_end_quote,
144
- $.interpolation_open_brace,
145
- $.interpolation_close_brace,
146
- $.interpolation_string_content,
147
- $.raw_string_start,
148
- $.raw_string_end,
149
- $.raw_string_content,
236
+ externals: () => [
237
+ sym('_optional_semi'),
238
+ sym('interpolation_regular_start'),
239
+ sym('interpolation_verbatim_start'),
240
+ sym('interpolation_raw_start'),
241
+ sym('interpolation_start_quote'),
242
+ sym('interpolation_end_quote'),
243
+ sym('interpolation_open_brace'),
244
+ sym('interpolation_close_brace'),
245
+ sym('interpolation_string_content'),
246
+ sym('raw_string_start'),
247
+ sym('raw_string_end'),
248
+ sym('raw_string_content'),
150
249
  // C# 14: emitted by the scanner at '(' when forward-scanning shows a
151
250
  // simple-lambda parameter list (at least one element has a parameter
152
251
  // modifier) closed by ')=>'.
153
- $._lambda_paren_open,
154
- $._end_of_input,
155
- $._directive_newline,
156
- $._file_directive_preproc_arg,
157
- $._file_directive_sdk,
158
- $._file_directive_package,
159
- $._file_directive_property,
160
- $._file_directive_project,
161
- $._file_directive_ref,
162
- $._file_directive_include,
163
- $._file_directive_exclude,
164
- $.file_directive_kind,
165
- $._file_directive_literal_context,
166
- $._file_directive_newline,
252
+ sym('_lambda_paren_open'),
253
+ sym('_end_of_input'),
254
+ sym('_directive_newline'),
255
+ sym('_file_directive_preproc_arg'),
256
+ sym('_file_directive_sdk'),
257
+ sym('_file_directive_package'),
258
+ sym('_file_directive_property'),
259
+ sym('_file_directive_project'),
260
+ sym('_file_directive_ref'),
261
+ sym('_file_directive_include'),
262
+ sym('_file_directive_exclude'),
263
+ sym('file_directive_kind'),
264
+ sym('_file_directive_literal_context'),
265
+ sym('_file_directive_newline'),
266
+ sym('_question_unknown'),
267
+ sym('_question_ternary'),
268
+ sym('_question_member_access'),
269
+ sym('_question_element_access'),
270
+ sym('_question_nullable'),
271
+ sym('_case_label_colon'),
272
+ sym('_type_context_is'),
273
+ sym('_type_context_as'),
274
+ sym('_question_definite_access'),
275
+ sym('_object_index_start'),
276
+ sym('_slice_pattern_start'),
277
+ sym('_ambiguous_cast_operand_start'),
278
+ sym('_ambiguous_cast_type_end'),
279
+ sym('_definite_cast_type_end'),
280
+ sym('_range_cast_type_end'),
281
+ sym('_nonprimary_expression_end'),
282
+ sym('_pattern_paren_end'),
283
+ sym('_pattern_bracket_end'),
284
+ sym('_bang_operator'),
285
+ sym('_conditional_alternative_start'),
286
+ sym('_statement_end'),
287
+ sym('_block_end'),
288
+ sym('_ampersand_operator'),
167
289
  ],
168
290
 
169
291
  extras: ($) => [
@@ -182,6 +304,7 @@ module.exports = grammar({
182
304
  ],
183
305
 
184
306
  inline: ($) => [
307
+ $._postfix_receiver,
185
308
  $._namespace_member_declaration,
186
309
  $._object_creation_type,
187
310
  $._nullable_base_type,
@@ -197,13 +320,16 @@ module.exports = grammar({
197
320
  supertypes: ($) => [
198
321
  $.declaration,
199
322
  $.expression,
200
- $.non_lvalue_expression,
201
- $.lvalue_expression,
202
323
  $.literal,
203
324
  $.statement,
204
325
  $.type,
205
326
  $.type_declaration,
206
327
  $.pattern,
328
+ $._ambiguous_cast_type,
329
+ $._definite_cast_type,
330
+ $._range_cast_type,
331
+ $._is_pattern,
332
+ $._nonconstant_pattern,
207
333
  ],
208
334
 
209
335
  word: ($) => $._identifier_token,
@@ -218,14 +344,14 @@ module.exports = grammar({
218
344
  $.extern_alias_directive,
219
345
  $.using_directive,
220
346
  $.global_attribute,
221
- alias($.preproc_if_in_top_level, $.preproc_if),
347
+ alias(sym('preproc_if_in_top_level'), sym('preproc_if')),
222
348
  $._namespace_member_declaration,
223
349
  $.file_scoped_namespace_declaration
224
350
  ),
225
351
 
226
352
  global_statement: ($) => prec(1, $.statement),
227
353
 
228
- extern_alias_directive: ($) => seq('extern', 'alias', field('name', $.identifier), ';'),
354
+ extern_alias_directive: ($) => seq('extern', 'alias', field('name', $.identifier), statementEnd()),
229
355
 
230
356
  using_directive: ($) =>
231
357
  seq(
@@ -235,7 +361,7 @@ module.exports = grammar({
235
361
  seq(optional('unsafe'), field('name', $.identifier), '=', $.type),
236
362
  seq(repeat(choice('static', 'unsafe')), $._name)
237
363
  ),
238
- ';'
364
+ statementEnd()
239
365
  ),
240
366
 
241
367
  global_attribute: ($) => seq('[', choice('assembly', 'module'), ':', commaSep1($.attribute), optional(','), ']'),
@@ -249,7 +375,7 @@ module.exports = grammar({
249
375
 
250
376
  attribute_list: ($) => seq('[', optional($.attribute_target_specifier), commaSep1($.attribute), optional(','), ']'),
251
377
 
252
- _attribute_list: ($) => choice($.attribute_list, $.preproc_if_in_attribute_list),
378
+ _attribute_list: ($) => choice($.attribute_list, sym('preproc_if_in_attribute_list')),
253
379
 
254
380
  // Higher precedence than `_reserved_identifier`: when both interpretations
255
381
  // are valid (e.g. `[field :` could be `_reserved_identifier` followed by
@@ -262,9 +388,9 @@ module.exports = grammar({
262
388
  _namespace_member_declaration: ($) => choice($.namespace_declaration, $.type_declaration),
263
389
 
264
390
  namespace_declaration: ($) =>
265
- seq('namespace', field('name', $._name), field('body', $.declaration_list), $._optional_semi),
391
+ seq('namespace', field('name', $._name), field('body', $.declaration_list), sym('_optional_semi')),
266
392
 
267
- file_scoped_namespace_declaration: ($) => seq('namespace', field('name', $._name), ';'),
393
+ file_scoped_namespace_declaration: ($) => seq('namespace', field('name', $._name), statementEnd()),
268
394
 
269
395
  type_declaration: ($) =>
270
396
  choice(
@@ -304,7 +430,7 @@ module.exports = grammar({
304
430
  enum_declaration: ($) =>
305
431
  seq(
306
432
  $._enum_declaration_initializer,
307
- choice(seq(field('body', $.enum_member_declaration_list), $._optional_semi), ';')
433
+ choice(seq(field('body', $.enum_member_declaration_list), sym('_optional_semi')), statementEnd())
308
434
  ),
309
435
 
310
436
  _enum_declaration_initializer: ($) =>
@@ -313,7 +439,9 @@ module.exports = grammar({
313
439
  enum_member_declaration_list: ($) =>
314
440
  seq(
315
441
  '{',
316
- commaSep(choice($.enum_member_declaration, alias($.preproc_if_in_enum_member_declaration, $.preproc_if))),
442
+ commaSep(
443
+ choice($.enum_member_declaration, alias(sym('preproc_if_in_enum_member_declaration'), sym('preproc_if')))
444
+ ),
317
445
  optional(','),
318
446
  '}'
319
447
  ),
@@ -335,7 +463,7 @@ module.exports = grammar({
335
463
  ),
336
464
 
337
465
  delegate_declaration: ($) =>
338
- seq($._delegate_declaration_initializer, repeat($.type_parameter_constraints_clause), ';'),
466
+ seq($._delegate_declaration_initializer, repeat($.type_parameter_constraints_clause), statementEnd()),
339
467
 
340
468
  _delegate_declaration_initializer: ($) =>
341
469
  seq(
@@ -368,7 +496,8 @@ module.exports = grammar({
368
496
  seq(':', $.primary_constructor_base_type, optional(seq(',', commaSep1($._name))))
369
497
  ),
370
498
 
371
- _declaration_list_body: ($) => choice(seq(field('body', $.declaration_list), $._optional_semi), ';'),
499
+ _declaration_list_body: ($) =>
500
+ choice(seq(field('body', $.declaration_list), sym('_optional_semi')), statementEnd()),
372
501
 
373
502
  primary_constructor_base_type: ($) => seq(field('type', $._name), $.argument_list),
374
503
 
@@ -410,7 +539,7 @@ module.exports = grammar({
410
539
 
411
540
  type_parameter_constraint: ($) =>
412
541
  choice(
413
- seq('class', optional('?')),
542
+ seq('class', optional(nullableQuestion())),
414
543
  'struct',
415
544
  'notnull',
416
545
  'unmanaged',
@@ -431,7 +560,7 @@ module.exports = grammar({
431
560
  field(
432
561
  'operator',
433
562
  choice(
434
- '!',
563
+ bangOperator(),
435
564
  '~',
436
565
  '++',
437
566
  '--',
@@ -444,7 +573,7 @@ module.exports = grammar({
444
573
  '%',
445
574
  '^',
446
575
  '|',
447
- '&',
576
+ ampersandOperator(),
448
577
  '<<',
449
578
  '>>',
450
579
  '>>>',
@@ -476,20 +605,13 @@ module.exports = grammar({
476
605
  repeat($._attribute_list),
477
606
  repeat($.modifier),
478
607
  choice('implicit', 'explicit'),
479
- repeat1(
480
- choice(
481
- // Intentionally structured this way for grammar size
482
- $.explicit_interface_specifier,
483
- 'operator',
484
- 'checked'
485
- )
486
- ),
608
+ repeat1(choice($.explicit_interface_specifier, 'operator', 'checked')),
487
609
  field('type', $.type),
488
610
  field('parameters', $.parameter_list),
489
611
  $._function_body
490
612
  ),
491
613
 
492
- declaration_list: ($) => seq('{', repeat($.declaration), '}'),
614
+ declaration_list: ($) => seq('{', repeat($.declaration), blockEnd()),
493
615
 
494
616
  declaration: ($) =>
495
617
  choice(
@@ -512,7 +634,7 @@ module.exports = grammar({
512
634
  $.conversion_operator_declaration,
513
635
  $.property_declaration,
514
636
  $.using_directive,
515
- $.preproc_if,
637
+ sym('preproc_if'),
516
638
  $.extension_declaration
517
639
  ),
518
640
 
@@ -543,12 +665,13 @@ module.exports = grammar({
543
665
  receiver_parameter: ($) =>
544
666
  prec(1, seq(repeat($._attribute_list), $._parameter_type_with_modifiers, optional(field('name', $.identifier)))),
545
667
 
546
- extension_body: ($) => seq('{', repeat($._extension_member_declaration), '}', optional(';')),
668
+ extension_body: ($) => seq('{', repeat($._extension_member_declaration), '}', optional(statementEnd())),
547
669
 
548
670
  _extension_member_declaration: ($) =>
549
671
  choice($.method_declaration, $.conditional_method_declaration, $.property_declaration, $.operator_declaration),
550
672
 
551
- field_declaration: ($) => seq(repeat($._attribute_list), repeat($.modifier), $.variable_declaration, ';'),
673
+ field_declaration: ($) =>
674
+ seq(repeat($._attribute_list), repeat($.modifier), $.variable_declaration, statementEnd()),
552
675
 
553
676
  constructor_declaration: ($) => seq($._constructor_declaration_initializer, $._function_body),
554
677
 
@@ -576,7 +699,8 @@ module.exports = grammar({
576
699
 
577
700
  method_declaration: ($) => seq($._method_signature, $._function_body),
578
701
 
579
- conditional_method_declaration: ($) => seq(alias($.preproc_if_in_method_signature, $.preproc_if), $._function_body),
702
+ conditional_method_declaration: ($) =>
703
+ seq(alias(sym('preproc_if_in_method_signature'), sym('preproc_if')), $._function_body),
580
704
 
581
705
  method_signature: ($) => $._method_signature,
582
706
 
@@ -600,11 +724,14 @@ module.exports = grammar({
600
724
  field('type', $.type),
601
725
  optional($.explicit_interface_specifier),
602
726
  field('name', $.identifier),
603
- choice(field('accessors', $.accessor_list), ';')
727
+ choice(field('accessors', $.accessor_list), statementEnd())
604
728
  ),
605
729
 
606
730
  event_field_declaration: ($) =>
607
- prec.dynamic(1, seq(repeat($._attribute_list), repeat($.modifier), 'event', $.variable_declaration, ';')),
731
+ prec.dynamic(
732
+ 1,
733
+ seq(repeat($._attribute_list), repeat($.modifier), 'event', $.variable_declaration, statementEnd())
734
+ ),
608
735
 
609
736
  accessor_list: ($) => seq('{', repeat($.accessor_declaration), '}'),
610
737
 
@@ -624,7 +751,7 @@ module.exports = grammar({
624
751
  optional($.explicit_interface_specifier),
625
752
  'this',
626
753
  field('parameters', $.bracketed_parameter_list),
627
- choice(field('accessors', $.accessor_list), seq(field('value', $.arrow_expression_clause), ';'))
754
+ choice(field('accessors', $.accessor_list), seq(field('value', $.arrow_expression_clause), statementEnd()))
628
755
  ),
629
756
 
630
757
  bracketed_parameter_list: ($) => seq('[', sep(choice($.parameter, $._parameter_array), ','), ']'),
@@ -637,8 +764,8 @@ module.exports = grammar({
637
764
  optional($.explicit_interface_specifier),
638
765
  field('name', $.identifier),
639
766
  choice(
640
- seq(field('accessors', $.accessor_list), optional(seq('=', field('value', $.expression), ';'))),
641
- seq(field('value', $.arrow_expression_clause), ';')
767
+ seq(field('accessors', $.accessor_list), optional(seq('=', field('value', $.expression), statementEnd()))),
768
+ seq(field('value', $.arrow_expression_clause), statementEnd())
642
769
  )
643
770
  ),
644
771
 
@@ -687,11 +814,12 @@ module.exports = grammar({
687
814
  )
688
815
  ),
689
816
 
690
- block: ($) => seq('{', repeat($.statement), '}'),
817
+ block: ($) => seq('{', repeat($.statement), blockEnd()),
691
818
 
692
819
  arrow_expression_clause: ($) => seq('=>', $.expression),
693
820
 
694
- _function_body: ($) => choice(field('body', $.block), seq(field('body', $.arrow_expression_clause), ';'), ';'),
821
+ _function_body: ($) =>
822
+ choice(field('body', $.block), seq(field('body', $.arrow_expression_clause), statementEnd()), statementEnd()),
695
823
 
696
824
  variable_declaration: ($) => seq(field('type', $.type), commaSep1($.variable_declarator)),
697
825
 
@@ -700,14 +828,14 @@ module.exports = grammar({
700
828
 
701
829
  variable_declarator: ($) =>
702
830
  seq(
703
- choice(field('name', $.identifier), $.tuple_pattern),
831
+ choice(field('name', $.identifier), prec.dynamic(-1, $.tuple_pattern)),
704
832
  optional($.bracketed_argument_list),
705
833
  optional(seq('=', $.expression))
706
834
  ),
707
835
 
708
836
  using_variable_declarator: ($) => seq(field('name', $.identifier), optional(seq('=', $.expression))),
709
837
 
710
- bracketed_argument_list: ($) => seq('[', commaSep1($.argument), optional(','), ']'),
838
+ bracketed_argument_list: ($) => bracketedArgumentList($, '['),
711
839
 
712
840
  qualified_identifier: ($) => sep1($.identifier, '.'),
713
841
 
@@ -723,16 +851,51 @@ module.exports = grammar({
723
851
 
724
852
  type_argument_list: ($) => seq('<', choice(repeat(','), commaSep1($.type)), '>'),
725
853
 
726
- type: ($) =>
854
+ type: ($) => typeAlternatives($),
855
+
856
+ _pattern_type: ($) =>
857
+ choice(
858
+ prec.dynamic(2, alias($._pattern_array_type, $.array_type)),
859
+ $._name,
860
+ alias($._pattern_nullable_type, $.nullable_type),
861
+ $.function_pointer_type,
862
+ $.predefined_type,
863
+ $.ref_type,
864
+ $.scoped_type
865
+ ),
866
+
867
+ _pattern_array_type: ($) =>
868
+ seq(
869
+ field(
870
+ 'type',
871
+ choice(
872
+ alias($._pattern_array_type, $.array_type),
873
+ $._name,
874
+ alias($._pattern_nullable_type, $.nullable_type),
875
+ $.pointer_type,
876
+ $.function_pointer_type,
877
+ $.predefined_type,
878
+ $.tuple_type
879
+ )
880
+ ),
881
+ field('rank', $.array_rank_specifier)
882
+ ),
883
+
884
+ _pattern_nullable_type: ($) =>
885
+ seq(
886
+ field('type', choice(alias($._pattern_array_type, $.array_type), $._name, $.predefined_type)),
887
+ nullableQuestion()
888
+ ),
889
+
890
+ _pattern_declaration_type: ($) =>
727
891
  choice(
728
892
  $.implicit_type,
729
- $.array_type,
893
+ prec(PREC.UNARY, alias('await', $.identifier)),
894
+ alias($._pattern_array_type, $.array_type),
730
895
  $._name,
731
- $.nullable_type,
732
- $.pointer_type,
896
+ alias($._pattern_nullable_type, $.nullable_type),
733
897
  $.function_pointer_type,
734
898
  $.predefined_type,
735
- $.tuple_type,
736
899
  $.ref_type,
737
900
  $.scoped_type
738
901
  ),
@@ -754,7 +917,7 @@ module.exports = grammar({
754
917
 
755
918
  array_rank_specifier: ($) => seq('[', commaSep(optional($.expression)), ']'),
756
919
 
757
- nullable_type: ($) => seq(field('type', $._nullable_base_type), '?'),
920
+ nullable_type: ($) => seq(field('type', $._nullable_base_type), nullableQuestion()),
758
921
 
759
922
  _nullable_base_type: ($) => choice($.array_type, $._name, $.predefined_type, $.tuple_type),
760
923
 
@@ -803,8 +966,6 @@ module.exports = grammar({
803
966
  'uint',
804
967
  'ulong',
805
968
  'ushort',
806
- 'nint',
807
- 'nuint',
808
969
  'void'
809
970
  )
810
971
  ),
@@ -860,22 +1021,22 @@ module.exports = grammar({
860
1021
  $.while_statement,
861
1022
  $.local_declaration_statement,
862
1023
  $.local_function_statement,
863
- alias($.preproc_if_in_top_level, $.preproc_if)
1024
+ alias(sym('preproc_if_in_top_level'), sym('preproc_if'))
864
1025
  )
865
1026
  ),
866
1027
 
867
- break_statement: () => seq('break', ';'),
1028
+ break_statement: () => seq('break', statementEnd()),
868
1029
 
869
1030
  checked_statement: ($) => seq(choice('checked', 'unchecked'), $.block),
870
1031
 
871
- continue_statement: () => seq('continue', ';'),
1032
+ continue_statement: () => seq('continue', statementEnd()),
872
1033
 
873
1034
  do_statement: ($) =>
874
- seq('do', field('body', $.statement), 'while', '(', field('condition', $.expression), ')', ';'),
1035
+ seq('do', field('body', $.statement), 'while', '(', field('condition', $.expression), ')', statementEnd()),
875
1036
 
876
- empty_statement: () => ';',
1037
+ empty_statement: () => statementEnd(),
877
1038
 
878
- expression_statement: ($) => seq($._expression_statement_expression, ';'),
1039
+ expression_statement: ($) => seq($._expression_statement_expression, statementEnd()),
879
1040
 
880
1041
  fixed_statement: ($) => seq('fixed', '(', $.variable_declaration, ')', $.statement),
881
1042
 
@@ -885,18 +1046,18 @@ module.exports = grammar({
885
1046
  seq(
886
1047
  '(',
887
1048
  field('initializer', optional(choice($.variable_declaration, commaSep1($.expression)))),
888
- ';',
1049
+ statementEnd(),
889
1050
  field('condition', optional($.expression)),
890
- ';',
1051
+ statementEnd(),
891
1052
  field('update', optional(commaSep1($.expression))),
892
1053
  ')'
893
1054
  ),
894
1055
 
895
- return_statement: ($) => seq('return', optional($.expression), ';'),
1056
+ return_statement: ($) => seq('return', optional($.expression), statementEnd()),
896
1057
 
897
1058
  lock_statement: ($) => seq('lock', '(', $.expression, ')', $.statement),
898
1059
 
899
- yield_statement: ($) => seq('yield', choice(seq('return', $.expression), 'break'), ';'),
1060
+ yield_statement: ($) => seq('yield', choice(seq('return', $.expression), 'break'), statementEnd()),
900
1061
 
901
1062
  switch_statement: ($) =>
902
1063
  seq(
@@ -905,18 +1066,18 @@ module.exports = grammar({
905
1066
  field('body', $.switch_body)
906
1067
  ),
907
1068
 
908
- switch_body: ($) => seq('{', repeat($.switch_section), '}'),
1069
+ switch_body: ($) => seq('{', repeat($.switch_section), blockEnd()),
909
1070
 
910
1071
  switch_section: ($) =>
911
1072
  prec.left(
912
1073
  seq(
913
1074
  choice(seq('case', choice($.expression, seq($.pattern, optional($.when_clause)))), 'default'),
914
- ':',
1075
+ alias(sym('_case_label_colon'), ':'),
915
1076
  repeat($.statement)
916
1077
  )
917
1078
  ),
918
1079
 
919
- throw_statement: ($) => seq('throw', optional($.expression), ';'),
1080
+ throw_statement: ($) => seq('throw', optional($.expression), statementEnd()),
920
1081
 
921
1082
  try_statement: ($) => seq('try', field('body', $.block), repeat($.catch_clause), optional($.finally_clause)),
922
1083
 
@@ -957,7 +1118,7 @@ module.exports = grammar({
957
1118
  ')'
958
1119
  ),
959
1120
 
960
- goto_statement: ($) => seq('goto', optional(choice('case', 'default')), optional($.expression), ';'),
1121
+ goto_statement: ($) => seq('goto', optional(choice('case', 'default')), optional($.expression), statementEnd()),
961
1122
 
962
1123
  labeled_statement: ($) => seq($.identifier, ':', $.statement),
963
1124
 
@@ -976,7 +1137,7 @@ module.exports = grammar({
976
1137
  while_statement: ($) => seq('while', '(', field('condition', $.expression), ')', field('body', $.statement)),
977
1138
 
978
1139
  local_declaration_statement: ($) =>
979
- seq(optional('await'), optional('using'), repeat($.modifier), $.variable_declaration, ';'),
1140
+ seq(optional('await'), optional('using'), repeat($.modifier), $.variable_declaration, statementEnd()),
980
1141
 
981
1142
  local_function_statement: ($) =>
982
1143
  seq($._local_function_declaration, repeat($.type_parameter_constraints_clause), $._function_body),
@@ -991,50 +1152,195 @@ module.exports = grammar({
991
1152
  field('parameters', $.parameter_list)
992
1153
  ),
993
1154
 
994
- pattern: ($) =>
1155
+ _is_pattern: ($) =>
995
1156
  choice(
996
- $.constant_pattern,
1157
+ alias($._is_constant_pattern, $.constant_pattern),
997
1158
  $.declaration_pattern,
998
1159
  $.discard,
999
1160
  $.recursive_pattern,
1000
1161
  $.var_pattern,
1001
- $.negated_pattern,
1002
- // This must come before plain parenthesized_pattern to create GLR conflict
1003
- prec.dynamic(1, alias($._parenthesized_pattern_with_designation, $.recursive_pattern)),
1162
+ alias($._is_negated_pattern, $.negated_pattern),
1163
+ alias($._parenthesized_pattern_with_designation, $.recursive_pattern),
1004
1164
  $.parenthesized_pattern,
1005
1165
  $.relational_pattern,
1006
- $.or_pattern,
1007
- $.and_pattern,
1166
+ alias($._is_or_pattern, $.or_pattern),
1167
+ alias($._is_and_pattern, $.and_pattern),
1008
1168
  $.list_pattern,
1169
+ $.slice_pattern,
1009
1170
  $.type_pattern
1010
1171
  ),
1011
1172
 
1012
- // Uses '(' pattern ')' to create direct conflict with parenthesized_pattern
1013
- _parenthesized_pattern_with_designation: ($) => seq('(', $.pattern, ')', $._simple_designation),
1173
+ _is_constant_pattern: ($) => prec(PREC.REL, choice(...constantExpressionRoots($))),
1014
1174
 
1015
- constant_pattern: ($) =>
1175
+ _is_negated_pattern: ($) => seq('not', alias($._is_pattern, $.pattern)),
1176
+
1177
+ _is_or_pattern: ($) =>
1178
+ prec.dynamic(
1179
+ 2,
1180
+ prec.left(
1181
+ PREC.OR,
1182
+ seq(
1183
+ field('left', alias($._is_pattern, $.pattern)),
1184
+ field('operator', 'or'),
1185
+ field('right', alias($._is_pattern, $.pattern))
1186
+ )
1187
+ )
1188
+ ),
1189
+
1190
+ _is_and_pattern: ($) =>
1191
+ prec.dynamic(
1192
+ 2,
1193
+ prec.left(
1194
+ PREC.AND,
1195
+ seq(
1196
+ field('left', alias($._is_pattern, $.pattern)),
1197
+ field('operator', 'and'),
1198
+ field('right', alias($._is_pattern, $.pattern))
1199
+ )
1200
+ )
1201
+ ),
1202
+
1203
+ _pattern_unary_expression: ($) =>
1204
+ choice($._pattern_primary_expression, $.prefix_unary_expression, $.cast_expression),
1205
+
1206
+ _pattern_parenthesized_expression: ($) =>
1207
+ seq('(', choice(...nestedConstantExpressionRoots($)), choice(')', alias(sym('_pattern_paren_end'), ')'))),
1208
+
1209
+ _pattern_primary_expression: ($) =>
1016
1210
  choice(
1017
- $.binary_expression,
1018
- $.default_expression,
1019
- $.interpolated_string_expression,
1020
- $.parenthesized_expression,
1021
- $.postfix_unary_expression,
1022
- $.prefix_unary_expression,
1023
- $.sizeof_expression,
1024
- $.tuple_expression,
1025
- $.typeof_expression,
1026
- $.member_access_expression,
1027
- alias($._name_invocation_pattern, $.invocation_expression),
1028
- alias($._complex_invocation_expression, $.invocation_expression),
1029
- $.cast_expression,
1030
- $._simple_name,
1031
- $.literal
1032
- ),
1033
-
1034
- // Invocation with name - creates conflict with recursive_pattern's Name(positional_pattern_clause)
1211
+ primaryAtoms($, {
1212
+ name: alias($._pattern_identifier, $.identifier),
1213
+ member: alias($._pattern_member_access_expression, $.member_access_expression),
1214
+ collection: false,
1215
+ element: alias($._pattern_element_access_expression, $.element_access_expression),
1216
+ invocation: alias($._pattern_invocation_expression, $.invocation_expression),
1217
+ tuple: false,
1218
+ parenthesized: alias($._pattern_parenthesized_expression, $.parenthesized_expression),
1219
+ }),
1220
+ $.conditional_access_expression,
1221
+ alias($._conditional_suppression_expression, $.postfix_unary_expression)
1222
+ ),
1223
+
1224
+ _pattern_identifier: ($) => choice($._identifier_token, ...reservedIdentifiers().slice(1)),
1225
+
1226
+ _pattern_simple_identifier_name: ($) => $.identifier,
1227
+
1228
+ _pattern_simple_generic_name: ($) => $.generic_name,
1229
+
1230
+ _pattern_member_access_expression: ($) =>
1231
+ choice(
1232
+ memberAccessExpression(
1233
+ $,
1234
+ choice($._primary_no_conditional_access_expression, $.predefined_type, $._name),
1235
+ $._pattern_simple_identifier_name
1236
+ ),
1237
+ memberAccessExpression(
1238
+ $,
1239
+ choice($._pattern_non_name_primary_expression, $.predefined_type),
1240
+ $._pattern_simple_generic_name,
1241
+ '.'
1242
+ ),
1243
+ memberAccessExpression(
1244
+ $,
1245
+ choice($._primary_no_conditional_access_expression, $.predefined_type, $._name),
1246
+ $._pattern_simple_generic_name,
1247
+ '->'
1248
+ )
1249
+ ),
1250
+
1251
+ _pattern_non_name_primary_expression: ($) =>
1252
+ choice(
1253
+ primaryAtoms($, {
1254
+ member: alias($._pattern_non_name_member_access_expression, $.member_access_expression),
1255
+ collection: true,
1256
+ parenthesized: alias($._pattern_parenthesized_expression, $.parenthesized_expression),
1257
+ })
1258
+ ),
1259
+
1260
+ _pattern_non_name_member_access_expression: ($) =>
1261
+ choice(
1262
+ memberAccessExpression(
1263
+ $,
1264
+ choice($._pattern_non_name_primary_expression, $.predefined_type),
1265
+ $._simple_name,
1266
+ '.'
1267
+ ),
1268
+ memberAccessExpression(
1269
+ $,
1270
+ choice($._primary_no_conditional_access_expression, $.predefined_type, $._name),
1271
+ $._simple_name,
1272
+ '->'
1273
+ )
1274
+ ),
1275
+
1276
+ _pattern_element_access_expression: ($) => elementAccessExpression($, $._pattern_non_name_primary_expression),
1277
+
1278
+ _pattern_invocation_expression: ($) => invocationExpression($, $._pattern_non_name_primary_expression),
1279
+
1280
+ _nameof_expression: ($) => invocationExpression($, alias('nameof', $.identifier)),
1281
+
1282
+ _pattern_generic_member_expression: ($) =>
1283
+ memberAccessExpression(
1284
+ $,
1285
+ choice($._primary_no_conditional_access_expression, $.predefined_type, $._name),
1286
+ $._pattern_simple_generic_name
1287
+ ),
1288
+
1289
+ _is_arithmetic_start_expression: ($) =>
1290
+ prec(
1291
+ PREC.SHIFT,
1292
+ choice(
1293
+ ...constantExpressionRoots($),
1294
+ $.generic_name,
1295
+ $.element_access_expression,
1296
+ alias($._pattern_generic_member_expression, $.member_access_expression)
1297
+ )
1298
+ ),
1299
+
1300
+ _is_arithmetic_expression: ($) =>
1301
+ prec(
1302
+ PREC.SHIFT,
1303
+ choice(
1304
+ $._unary_expression,
1305
+ alias($._is_arithmetic_operand_binary_expression, $.binary_expression),
1306
+ alias($._is_operand_range_expression, $.range_expression),
1307
+ alias($._is_operand_switch_expression, $.switch_expression),
1308
+ alias($._is_operand_with_expression, $.with_expression)
1309
+ )
1310
+ ),
1311
+
1312
+ _is_constant_receiver_expression: ($) => prec(PREC.SHIFT, choice(...constantExpressionRoots($))),
1313
+
1314
+ _is_range_expression: ($) => rangeExpression($._is_arithmetic_start_expression, $._is_arithmetic_expression, false),
1315
+
1316
+ _is_operand_range_expression: ($) => rangeExpression($._is_arithmetic_expression, $._is_arithmetic_expression),
1317
+
1318
+ _is_switch_expression: ($) => switchExpression($, $._is_constant_receiver_expression),
1319
+
1320
+ _is_operand_switch_expression: ($) => switchExpression($, $._is_arithmetic_expression),
1321
+
1322
+ _is_with_expression: ($) => withExpression($, $._is_constant_receiver_expression),
1323
+
1324
+ _is_operand_with_expression: ($) => withExpression($, $._is_arithmetic_expression),
1325
+
1326
+ _is_arithmetic_binary_expression: ($) =>
1327
+ arithmeticBinaryExpression($._is_arithmetic_start_expression, $._is_arithmetic_expression, true),
1328
+
1329
+ _is_arithmetic_operand_binary_expression: ($) =>
1330
+ arithmeticBinaryExpression($._is_arithmetic_expression, $._is_arithmetic_expression),
1331
+
1332
+ pattern: ($) => choice($.constant_pattern, nonconstantPatterns($)),
1333
+
1334
+ _nonconstant_pattern: ($) => nonconstantPatterns($),
1335
+
1336
+ // Uses '(' pattern ')' to create direct conflict with parenthesized_pattern
1337
+ _parenthesized_pattern_with_designation: ($) =>
1338
+ seq('(', $.pattern, choice(')', alias(sym('_pattern_paren_end'), ')')), $._simple_designation),
1339
+
1340
+ constant_pattern: ($) => choice(...nestedConstantExpressionRoots($)),
1341
+
1035
1342
  _name_invocation_pattern: ($) => seq(field('function', $._name), field('arguments', $.argument_list)),
1036
1343
 
1037
- // One above `invocation_expression`, which reads the same tokens where both fit.
1038
1344
  _complex_invocation_expression: ($) =>
1039
1345
  prec(
1040
1346
  PREC.INVOCATION + 1,
@@ -1056,11 +1362,10 @@ module.exports = grammar({
1056
1362
 
1057
1363
  discard: () => '_',
1058
1364
 
1059
- parenthesized_pattern: ($) => seq('(', $.pattern, ')'),
1365
+ parenthesized_pattern: ($) =>
1366
+ seq('(', alias($._nonconstant_pattern, $.pattern), choice(')', alias(sym('_pattern_paren_end'), ')'))),
1060
1367
 
1061
- // `var x` parses as a declaration_pattern with an implicit_type. `var (x, y)` also reads as a positional pattern
1062
- // of type `var` or, after `is`, as an invocation of `o is var`; each of those carries the implicit_type's dynamic
1063
- // precedence of 1, so this needs more.
1368
+ // The implicit_type reading of `var` contributes dynamic precedence 1; its parenthesized designation needs more.
1064
1369
  var_pattern: ($) => prec.dynamic(2, seq('var', $.parenthesized_variable_designation)),
1065
1370
 
1066
1371
  // No associativity: tree-sitter 0.27 resolves a precedence tie with a right-associative reduce as a shift, which
@@ -1068,63 +1373,80 @@ module.exports = grammar({
1068
1373
  // A name such as `A.B` in `R(A.B or C)` also parses as a constant pattern. Without the negative dynamic
1069
1374
  // precedence, the reading depends on the other GLR stack versions alive at that point, so an incremental
1070
1375
  // reparse can switch it without reporting a changed range.
1071
- type_pattern: ($) => prec.dynamic(-1, field('type', $.type)),
1376
+ type_pattern: ($) => prec.dynamic(-1, field('type', $._pattern_type)),
1072
1377
 
1073
- // Left-associative so that a contextual keyword after `]` (`when` in a switch arm or section, `select` in a query)
1074
- // ends the pattern instead of becoming its designation.
1075
1378
  list_pattern: ($) =>
1076
- prec.left(
1077
- seq(
1078
- '[',
1079
- optional(seq(commaSep1(choice($.pattern, $.slice_pattern)), optional(','))),
1080
- ']',
1081
- optional($._simple_designation)
1082
- )
1379
+ seq(
1380
+ '[',
1381
+ optional(seq(commaSep1($.pattern), optional(','))),
1382
+ choice(']', alias(sym('_pattern_bracket_end'), ']')),
1383
+ optional($._simple_designation)
1083
1384
  ),
1084
1385
 
1085
- slice_pattern: ($) => prec.right(seq('..', optional($.pattern))),
1386
+ slice_pattern: ($) => prec.right(seq(alias(sym('_slice_pattern_start'), '..'), optional($.pattern))),
1086
1387
 
1087
1388
  recursive_pattern: ($) =>
1088
- prec.left(
1089
- choice(
1090
- prec.dynamic(
1091
- 1,
1092
- seq(
1093
- field('type', $._name),
1094
- $.positional_pattern_clause,
1095
- optional($.property_pattern_clause),
1096
- $._simple_designation
1097
- )
1098
- ),
1099
- prec.dynamic(
1100
- -1,
1101
- seq(field('type', $._name), $.positional_pattern_clause, optional($.property_pattern_clause))
1102
- ),
1103
- prec.dynamic(1, seq($.positional_pattern_clause, $._simple_designation)),
1104
- $.positional_pattern_clause,
1105
- seq(field('type', $.type), $.property_pattern_clause, optional($._simple_designation)),
1106
- // A positional clause follows only a name (above), a predefined type, or an array type. Letting any type take
1107
- // one reads `Name(A.B)` once more, through `type`; after a syntax error, the extra GLR versions then exceed
1108
- // the runtime's limit, and which reading survives depends on the versions alive, not on dynamic precedence.
1389
+ choice(
1390
+ prec.dynamic(
1391
+ 2,
1109
1392
  seq(
1110
- field('type', choice($.predefined_type, $.array_type)),
1393
+ field('type', $._name),
1111
1394
  $.positional_pattern_clause,
1112
1395
  optional($.property_pattern_clause),
1113
- optional($._simple_designation)
1114
- ),
1115
- // no type, just pattern clauses (no variable designation to avoid conflict with above)
1116
- seq(
1117
- choice(seq($.positional_pattern_clause, $.property_pattern_clause), $.property_pattern_clause),
1118
- optional($._simple_designation)
1396
+ $._simple_designation
1119
1397
  )
1398
+ ),
1399
+ prec.dynamic(2, seq(field('type', $._name), $.positional_pattern_clause, optional($.property_pattern_clause))),
1400
+ prec.dynamic(1, seq($.positional_pattern_clause, $._simple_designation)),
1401
+ alias($._untyped_positional_pattern_clause, $.positional_pattern_clause),
1402
+ seq(
1403
+ field('type', typeAlternatives($, true, true, false)),
1404
+ $.property_pattern_clause,
1405
+ optional($._simple_designation)
1406
+ ),
1407
+ // Names already use the branch above. Admitting them again through type duplicates Name(A.B)
1408
+ // and can evict viable GLR versions during recovery.
1409
+ seq(
1410
+ field(
1411
+ 'type',
1412
+ choice(
1413
+ $.predefined_type,
1414
+ $.function_pointer_type,
1415
+ prec.dynamic(1, alias($._pattern_array_type, $.array_type))
1416
+ )
1417
+ ),
1418
+ $.positional_pattern_clause,
1419
+ optional($.property_pattern_clause),
1420
+ optional($._simple_designation)
1421
+ ),
1422
+ seq(
1423
+ choice(seq($.positional_pattern_clause, $.property_pattern_clause), $.property_pattern_clause),
1424
+ optional($._simple_designation)
1425
+ )
1426
+ ),
1427
+
1428
+ positional_pattern_clause: ($) =>
1429
+ prec(1, seq('(', optional(commaSep($.subpattern)), choice(')', alias(sym('_pattern_paren_end'), ')')))),
1430
+
1431
+ _untyped_positional_pattern_clause: ($) =>
1432
+ prec(
1433
+ 1,
1434
+ seq(
1435
+ '(',
1436
+ optional(choice(commaSep2($.subpattern), alias($._named_subpattern, $.subpattern))),
1437
+ choice(')', alias(sym('_pattern_paren_end'), ')'))
1120
1438
  )
1121
1439
  ),
1122
1440
 
1123
- positional_pattern_clause: ($) => prec(1, seq('(', optional(commaSep($.subpattern)), ')')),
1441
+ _named_subpattern: ($) => subpattern($, true),
1124
1442
 
1125
- property_pattern_clause: ($) => prec(1, seq('{', commaSep($.subpattern), optional(','), '}')),
1443
+ property_pattern_clause: ($) =>
1444
+ prec(
1445
+ 1,
1446
+ seq('{', commaSep($.subpattern), optional(','), choice('}', alias(sym('_nonprimary_expression_end'), '}')))
1447
+ ),
1126
1448
 
1127
- subpattern: ($) => prec.right(seq(optional(choice(seq($.expression, ':'), seq($.identifier, ':'))), $.pattern)),
1449
+ subpattern: ($) => subpattern($),
1128
1450
 
1129
1451
  relational_pattern: ($) =>
1130
1452
  choice(seq('<', $.expression), seq('<=', $.expression), seq('>', $.expression), seq('>=', $.expression)),
@@ -1132,187 +1454,148 @@ module.exports = grammar({
1132
1454
  negated_pattern: ($) => seq('not', $.pattern),
1133
1455
 
1134
1456
  and_pattern: ($) =>
1135
- prec.left(PREC.AND, seq(field('left', $.pattern), field('operator', 'and'), field('right', $.pattern))),
1457
+ prec.dynamic(
1458
+ 2,
1459
+ prec.left(PREC.AND, seq(field('left', $.pattern), field('operator', 'and'), field('right', $.pattern)))
1460
+ ),
1136
1461
 
1137
1462
  or_pattern: ($) =>
1138
- prec.left(PREC.OR, seq(field('left', $.pattern), field('operator', 'or'), field('right', $.pattern))),
1463
+ prec.dynamic(
1464
+ 2,
1465
+ prec.left(PREC.OR, seq(field('left', $.pattern), field('operator', 'or'), field('right', $.pattern)))
1466
+ ),
1139
1467
 
1140
- declaration_pattern: ($) => seq(field('type', $.type), $._simple_designation),
1468
+ declaration_pattern: ($) => seq(field('type', $._pattern_declaration_type), $._simple_designation),
1141
1469
 
1142
1470
  _variable_designation: ($) => choice($._simple_designation, $.parenthesized_variable_designation),
1143
1471
 
1144
1472
  // C# admits a parenthesized designation in a pattern only after `var`; elsewhere `T (x)` and `nameof(x)` are
1145
1473
  // positional patterns or invocations.
1146
- _simple_designation: ($) => prec(1, choice($.discard, field('name', $.identifier))),
1474
+ _simple_designation: ($) =>
1475
+ prec(
1476
+ 1,
1477
+ choice(
1478
+ $.discard,
1479
+ field('name', $.identifier),
1480
+ prec.dynamic(-2, field('name', alias(choice('and', 'or'), $.identifier)))
1481
+ )
1482
+ ),
1147
1483
 
1148
1484
  parenthesized_variable_designation: ($) => seq('(', commaSep($._variable_designation), ')'),
1149
1485
 
1150
- expression: ($) => choice($.non_lvalue_expression, $.lvalue_expression),
1151
-
1152
- non_lvalue_expression: ($) =>
1486
+ expression: ($) =>
1153
1487
  choice(
1154
- 'base',
1488
+ $._unary_expression,
1489
+ $.assignment_expression,
1155
1490
  $.binary_expression,
1156
- $.interpolated_string_expression,
1157
1491
  $.conditional_expression,
1158
- $.conditional_access_expression,
1159
- $.literal,
1160
- $._expression_statement_expression,
1161
- $.is_expression,
1162
1492
  $.is_pattern_expression,
1163
1493
  $.as_expression,
1164
- $.cast_expression,
1165
- $.checked_expression,
1166
- $.collection_expression,
1167
1494
  $.switch_expression,
1168
1495
  $.throw_expression,
1169
- $.default_expression,
1170
1496
  $.lambda_expression,
1171
1497
  $.with_expression,
1172
- $.sizeof_expression,
1173
- $.typeof_expression,
1174
- $.makeref_expression,
1175
1498
  $.ref_expression,
1176
- alias($._address_of_expression, $.prefix_unary_expression),
1177
- alias($._value_indirection_expression, $.prefix_unary_expression),
1178
- $.reftype_expression,
1179
- $.refvalue_expression,
1180
- $.stackalloc_expression,
1181
1499
  $.range_expression,
1182
- $.array_creation_expression,
1183
- $.anonymous_method_expression,
1184
- $.anonymous_object_creation_expression,
1185
- $.implicit_array_creation_expression,
1186
- $.implicit_object_creation_expression,
1187
- $.implicit_stackalloc_expression,
1188
1500
  $.initializer_expression,
1189
- $.query_expression,
1190
- alias($.preproc_if_in_expression, $.preproc_if)
1501
+ $.query_expression
1191
1502
  ),
1192
1503
 
1193
- lvalue_expression: ($) =>
1194
- choice(
1195
- 'this',
1196
- $.member_access_expression,
1197
- $.tuple_expression,
1198
- $._simple_name,
1199
- $.element_access_expression,
1200
- alias($.bracketed_argument_list, $.element_binding_expression),
1201
- alias($._pointer_indirection_expression, $.prefix_unary_expression),
1202
- alias($._parenthesized_lvalue_expression, $.parenthesized_expression),
1203
- // C# 14 null-conditional assignment: `obj?.x = v`, `obj?[i] = v`.
1204
- // https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#null-conditional-assignment
1205
- $.conditional_access_expression
1206
- ),
1207
-
1208
- // Covers error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
1209
- _expression_statement_expression: ($) =>
1504
+ _unary_expression: ($) =>
1505
+ choice($._primary_expression, $.prefix_unary_expression, $.cast_expression, $.await_expression),
1506
+
1507
+ _primary_expression: ($) =>
1210
1508
  choice(
1211
- $.assignment_expression,
1212
- $.invocation_expression,
1213
- $.postfix_unary_expression,
1214
- $.prefix_unary_expression,
1215
- $.await_expression,
1216
- $.object_creation_expression,
1217
- $.parenthesized_expression
1509
+ $._primary_no_conditional_access_expression,
1510
+ $.conditional_access_expression,
1511
+ alias($._conditional_suppression_expression, $.postfix_unary_expression)
1218
1512
  ),
1219
1513
 
1220
- assignment_expression: ($) =>
1221
- seq(
1222
- // An invocation can return a reference (`Unsafe.Add(ref x, i) = v`). It ends with `)`, so `=` after it adds few
1223
- // parse states, unlike making any expression assignable.
1224
- field(
1225
- 'left',
1226
- choice(
1227
- $.lvalue_expression,
1228
- $.invocation_expression,
1229
- alias($._assignment_pointer_expression, $.prefix_unary_expression)
1230
- )
1231
- ),
1232
- field('operator', choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '<<=', '>>=', '>>>=', '??=')),
1233
- field('right', $.expression)
1514
+ _nonconditional_unary_expression: ($) =>
1515
+ choice(
1516
+ $._primary_no_conditional_access_expression,
1517
+ alias($._assignment_target_prefix_unary_expression, $.prefix_unary_expression),
1518
+ alias($._assignment_target_cast_expression, $.cast_expression),
1519
+ alias($._assignment_target_await_expression, $.await_expression)
1234
1520
  ),
1235
1521
 
1236
- // Keep this alternative confined to assignment targets: sharing it with ordinary dereferences changes hidden
1237
- // expression-supertype captures in nested reads. -3 prefers the existing lvalue path (-2) when both fit.
1238
- _assignment_pointer_expression: ($) =>
1239
- prec.dynamic(
1240
- -3,
1241
- prec.right(
1242
- PREC.UNARY,
1243
- seq(
1244
- '*',
1245
- choice(
1246
- $.lvalue_expression,
1247
- $.parenthesized_expression,
1248
- $.invocation_expression,
1249
- $.postfix_unary_expression,
1250
- alias($._assignment_pointer_expression, $.prefix_unary_expression),
1251
- alias($._pointer_prefix_update, $.prefix_unary_expression),
1252
- alias($._assignment_pointer_cast, $.cast_expression)
1253
- )
1254
- )
1255
- )
1522
+ _assignment_target_unary_operand: ($) =>
1523
+ choice(
1524
+ $._nonconditional_unary_expression,
1525
+ alias($._assignment_target_prefix_range_expression, $.range_expression)
1256
1526
  ),
1257
1527
 
1258
- _pointer_prefix_update: ($) =>
1259
- prec(
1260
- PREC.UNARY,
1261
- seq(choice('++', '--'), choice($.lvalue_expression, $.invocation_expression, $.parenthesized_expression))
1528
+ _assignment_target_prefix_unary_expression: ($) => prefixUnaryExpression($._assignment_target_unary_operand),
1529
+
1530
+ _assignment_target_cast_expression: ($) =>
1531
+ castExpression(
1532
+ $,
1533
+ $._nonconditional_unary_expression,
1534
+ alias($._assignment_target_prefix_range_expression, $.range_expression)
1262
1535
  ),
1263
1536
 
1264
- _assignment_pointer_cast: ($) =>
1265
- prec(
1266
- PREC.CAST,
1267
- seq(
1268
- '(',
1269
- field('type', $.type),
1270
- ')',
1271
- field(
1272
- 'value',
1273
- choice(
1274
- $.lvalue_expression,
1275
- $.parenthesized_expression,
1276
- $.invocation_expression,
1277
- $.postfix_unary_expression,
1278
- alias($._assignment_pointer_expression, $.prefix_unary_expression),
1279
- alias($._pointer_prefix_update, $.prefix_unary_expression)
1280
- )
1281
- )
1282
- )
1537
+ _assignment_target_prefix_range_expression: ($) => prefixRangeExpression($._assignment_target_unary_operand),
1538
+
1539
+ _assignment_target_await_expression: ($) =>
1540
+ prec.right(PREC.UNARY, seq('await', $._assignment_target_unary_operand)),
1541
+
1542
+ _conditional_suppression_expression: ($) =>
1543
+ postfixExpression(
1544
+ choice(
1545
+ $.conditional_access_expression,
1546
+ alias($._conditional_suppression_expression, $.postfix_unary_expression)
1547
+ ),
1548
+ bangOperator()
1283
1549
  ),
1284
1550
 
1551
+ _conditional_update_expression: ($) =>
1552
+ postfixExpression(
1553
+ choice(
1554
+ $.conditional_access_expression,
1555
+ alias($._conditional_suppression_expression, $.postfix_unary_expression)
1556
+ ),
1557
+ choice('++', '--')
1558
+ ),
1559
+
1560
+ _primary_no_conditional_access_expression: ($) =>
1561
+ primaryAtoms($, { name: $._simple_name, member: $.member_access_expression, collection: true }),
1562
+
1563
+ _conditional_access_receiver: ($) =>
1564
+ primaryAtoms($, {
1565
+ name: $._simple_name,
1566
+ member: $.member_access_expression,
1567
+ collection: true,
1568
+ element: $.element_access_expression,
1569
+ invocation: $.invocation_expression,
1570
+ tuple: true,
1571
+ array: alias($._initialized_array_creation_expression, $.array_creation_expression),
1572
+ stackalloc: alias($._initialized_stackalloc_expression, $.stackalloc_expression),
1573
+ definite: false,
1574
+ }),
1575
+
1576
+ _definite_conditional_access_receiver: ($) =>
1577
+ primaryAtoms($, {
1578
+ name: $._simple_name,
1579
+ member: $.member_access_expression,
1580
+ collection: true,
1581
+ element: $.element_access_expression,
1582
+ invocation: $.invocation_expression,
1583
+ tuple: true,
1584
+ array: alias($._initialized_array_creation_expression, $.array_creation_expression),
1585
+ stackalloc: alias($._initialized_stackalloc_expression, $.stackalloc_expression),
1586
+ definite: true,
1587
+ }),
1588
+
1589
+ _expression_statement_expression: ($) => choice($._unary_expression, $.assignment_expression),
1590
+
1591
+ assignment_expression: ($) => assignmentExpression($, $._nonconditional_unary_expression),
1592
+
1285
1593
  binary_expression: ($) =>
1286
1594
  choice(
1287
- ...[
1288
- ['&&', PREC.LOGICAL_AND],
1289
- ['||', PREC.LOGICAL_OR],
1290
- ['>>', PREC.SHIFT],
1291
- ['>>>', PREC.SHIFT],
1292
- ['<<', PREC.SHIFT],
1293
- ['&', PREC.AND],
1294
- ['^', PREC.XOR],
1295
- ['|', PREC.OR],
1296
- ['+', PREC.ADD],
1297
- ['-', PREC.ADD],
1298
- ['*', PREC.MULT],
1299
- ['/', PREC.MULT],
1300
- ['%', PREC.MULT],
1301
- ['<', PREC.REL],
1302
- ['<=', PREC.REL],
1303
- ['==', PREC.EQUAL],
1304
- ['!=', PREC.EQUAL],
1305
- ['>=', PREC.REL],
1306
- ['>', PREC.REL],
1307
- ].map(([operator, precedence]) =>
1595
+ ...binaryOperators().map(([operator, precedence]) =>
1308
1596
  prec.left(
1309
1597
  precedence,
1310
- seq(
1311
- field('left', $.expression),
1312
- // @ts-ignore
1313
- field('operator', operator),
1314
- field('right', $.expression)
1315
- )
1598
+ seq(field('left', $.expression), field('operator', operator), field('right', $.expression))
1316
1599
  )
1317
1600
  ),
1318
1601
  prec.right(
@@ -1321,80 +1604,13 @@ module.exports = grammar({
1321
1604
  )
1322
1605
  ),
1323
1606
 
1324
- postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq(postfixOperand($), choice('++', '--', '!'))),
1325
-
1326
- // `&` and `*` have rules of their own (`_address_of_expression`, `_pointer_indirection_expression`, and
1327
- // `_value_indirection_expression`), aliased to this node. The dynamic precedence of `+`, `-`, and `^` is explained
1328
- // at `_pointer_indirection_expression`.
1329
- prefix_unary_expression: ($) =>
1330
- prec(
1331
- PREC.UNARY,
1332
- choice(
1333
- seq(choice('++', '--', '!', '~'), $.expression),
1334
- prec.dynamic(-2, seq(choice('+', '-', '^'), $.expression))
1335
- )
1336
- ),
1337
-
1338
- // Keep the lvalue operand set restricted: a general expression also permits assignment after every operand,
1339
- // substantially increasing parser states. Additional call and prefix-update operands use the assignment-only
1340
- // `_assignment_pointer_expression` path to preserve the shared read derivations and their query captures.
1341
- // Dynamic precedences: an assignable dereference -2, a read-only one -4, a read-only cast +1, an assignable cast -1,
1342
- // and a unary `+`, `-`, `^`, or `&` -2. C# reads a parenthesized name as a cast only when the token after `)` is
1343
- // `~`, `!`, `(`, an identifier, a literal, or a keyword (C# spec §12.9.8 Cast expressions), and these values keep
1344
- // that reading: `(a) * b`, `(a) - b`, and `(a) & b` are binary expressions (0), not casts of `*b`, `-b`, or `&b`
1345
- // (+1 - 2); `*(p) + 1` and `*(p) & x` apply to a dereference of `(p)` (-2), not to a dereference of a cast of `+1`
1346
- // or `&x` (-5); `*(b)[0]` dereferences an element access (-2), not a cast of `[0]` (-3). Where both casts fit, they
1347
- // give the same tree.
1348
- _pointer_indirection_expression: ($) =>
1349
- prec.dynamic(
1350
- -2,
1351
- prec.right(
1352
- PREC.UNARY,
1353
- seq(
1354
- '*',
1355
- choice(
1356
- $.lvalue_expression,
1357
- $.parenthesized_expression,
1358
- alias($._address_of_expression, $.prefix_unary_expression),
1359
- alias($._lvalue_cast_expression, $.cast_expression),
1360
- $.postfix_unary_expression
1361
- )
1362
- )
1363
- )
1364
- ),
1365
-
1366
- _lvalue_cast_expression: ($) =>
1367
- prec(
1368
- PREC.CAST,
1369
- prec.dynamic(
1370
- -1,
1371
- seq(
1372
- '(',
1373
- field('type', $.type),
1374
- ')',
1375
- field(
1376
- 'value',
1377
- choice(
1378
- $.lvalue_expression,
1379
- $.parenthesized_expression,
1380
- alias($._address_of_expression, $.prefix_unary_expression),
1381
- $.postfix_unary_expression,
1382
- $.invocation_expression
1383
- )
1384
- )
1385
- )
1386
- )
1607
+ postfix_unary_expression: ($) =>
1608
+ choice(
1609
+ postfixExpression($._primary_no_conditional_access_expression, choice('++', '--', bangOperator())),
1610
+ $._generic_invocation_suppression_expression
1387
1611
  ),
1388
1612
 
1389
- _value_indirection_expression: ($) => prec.dynamic(-4, prec.right(PREC.UNARY, seq('*', $.non_lvalue_expression))),
1390
-
1391
- // Address-of is split out from `prefix_unary_expression` and takes only a variable: an lvalue, or an invocation,
1392
- // which can return a reference (`&span.GetPinnableReference()`). If a cast could take `&` before any expression,
1393
- // the lexer would split `&&` into two `&` tokens and `(a) && (b > 0)` would read as a cast of `&(&(b > 0))`; as
1394
- // `(b > 0)` is not a variable, that reading fails and `&&` stays one token. The dynamic precedence is explained at
1395
- // `_pointer_indirection_expression`.
1396
- _address_of_expression: ($) =>
1397
- prec.dynamic(-2, prec.right(PREC.UNARY, seq('&', choice($.lvalue_expression, $.invocation_expression)))),
1613
+ prefix_unary_expression: ($) => prefixUnaryExpression($._unary_operand),
1398
1614
 
1399
1615
  query_expression: ($) => seq($.from_clause, $._query_body),
1400
1616
 
@@ -1432,139 +1648,422 @@ module.exports = grammar({
1432
1648
  PREC.CONDITIONAL,
1433
1649
  seq(
1434
1650
  field('condition', $.expression),
1435
- '?',
1651
+ ternaryQuestion(),
1436
1652
  field('consequence', $.expression),
1437
1653
  ':',
1654
+ sym('_conditional_alternative_start'),
1438
1655
  field('alternative', $.expression)
1439
1656
  )
1440
1657
  ),
1441
1658
 
1442
1659
  conditional_access_expression: ($) =>
1443
- prec.right(
1444
- PREC.CONDITIONAL,
1660
+ choice(
1661
+ $._conditional_assignment_expression,
1662
+ conditionalAccessExpression($, $._conditional_access_receiver),
1445
1663
  seq(
1446
- field('condition', $.expression),
1447
- '?',
1448
- choice($.member_binding_expression, alias($.bracketed_argument_list, $.element_binding_expression))
1664
+ field('condition', $._definite_conditional_access_receiver),
1665
+ definiteAccessQuestion(),
1666
+ field('consequence', $._conditional_access_consequence)
1667
+ ),
1668
+ seq(
1669
+ field('condition', $.array_creation_expression),
1670
+ memberAccessQuestion(),
1671
+ field('consequence', $._member_conditional_access_consequence)
1449
1672
  )
1450
1673
  ),
1451
1674
 
1452
- as_expression: ($) =>
1453
- prec(PREC.REL, seq(field('left', $.expression), field('operator', 'as'), field('right', $.type))),
1675
+ _member_conditional_access_consequence: ($) => $._member_conditional_binding_expression,
1454
1676
 
1455
- is_expression: ($) =>
1456
- prec(PREC.REL, seq(field('left', $.expression), field('operator', 'is'), field('right', $.type))),
1677
+ _member_conditional_binding_expression: ($) =>
1678
+ choice(
1679
+ $._member_nonconditional_binding_expression,
1680
+ alias($._member_binding_conditional_access_expression, $.conditional_access_expression)
1681
+ ),
1457
1682
 
1458
- is_pattern_expression: ($) =>
1459
- prec(PREC.REL, seq(field('expression', $.expression), 'is', field('pattern', $.pattern))),
1683
+ _member_nonconditional_binding_expression: ($) =>
1684
+ choice(
1685
+ $.member_binding_expression,
1686
+ alias($._member_binding_member_access_expression, $.member_access_expression),
1687
+ alias($._member_binding_element_access_expression, $.element_access_expression),
1688
+ alias($._member_binding_invocation_expression, $.invocation_expression)
1689
+ ),
1460
1690
 
1461
- cast_expression: ($) =>
1462
- prec(
1463
- PREC.CAST,
1691
+ _member_conditional_binding_receiver: ($) =>
1692
+ choice(
1693
+ $._member_nonconditional_binding_expression,
1694
+ alias($._member_binding_suppression_expression, $.postfix_unary_expression),
1695
+ alias($._member_binding_generic_suppression_expression, $.postfix_unary_expression)
1696
+ ),
1697
+
1698
+ _member_binding_suppression_expression: ($) =>
1699
+ postfixExpression($._member_conditional_binding_receiver, bangOperator()),
1700
+
1701
+ _member_binding_member_access_expression: ($) => memberAccessExpression($, $._member_conditional_binding_receiver),
1702
+
1703
+ _member_binding_element_access_expression: ($) =>
1704
+ elementAccessExpression($, $._member_conditional_binding_receiver),
1705
+
1706
+ _member_binding_invocation_expression: ($) =>
1707
+ choice(
1708
+ invocationExpression($, $._member_conditional_binding_receiver),
1709
+ $._member_binding_generic_invocation_expression
1710
+ ),
1711
+
1712
+ _member_binding_generic_invocation_expression: ($) =>
1713
+ genericInvocationExpression(
1714
+ $,
1715
+ choice(
1716
+ alias($._generic_member_binding_expression, $.member_binding_expression),
1717
+ alias($._member_binding_generic_member_expression, $.member_access_expression)
1718
+ ),
1719
+ $._member_binding_generic_invocation_expression,
1720
+ $._member_binding_generic_suppression_expression
1721
+ ),
1722
+
1723
+ _member_binding_generic_member_expression: ($) =>
1724
+ memberAccessExpression($, $._member_conditional_binding_receiver, $._generic_invocation_simple_name),
1725
+
1726
+ _member_binding_generic_suppression_expression: ($) =>
1727
+ seq(
1728
+ genericInvocationReceiver(
1729
+ $,
1730
+ $._member_binding_generic_invocation_expression,
1731
+ $._member_binding_generic_suppression_expression
1732
+ ),
1733
+ bangOperator()
1734
+ ),
1735
+
1736
+ _member_binding_conditional_access_expression: ($) =>
1737
+ conditionalAccessExpression($, $._member_conditional_binding_receiver),
1738
+
1739
+ _member_conditional_binding_assignment_expression: ($) =>
1740
+ assignmentExpression($, $._member_conditional_binding_receiver),
1741
+
1742
+ _conditional_access_consequence: ($) => $._conditional_binding_expression,
1743
+
1744
+ _conditional_binding_expression: ($) =>
1745
+ choice(
1746
+ $._nonconditional_binding_expression,
1747
+ alias($._binding_conditional_access_expression, $.conditional_access_expression)
1748
+ ),
1749
+
1750
+ _nonconditional_binding_expression: ($) =>
1751
+ choice(
1752
+ $.member_binding_expression,
1753
+ alias($.bracketed_argument_list, sym('element_binding_expression')),
1754
+ alias($._binding_member_access_expression, $.member_access_expression),
1755
+ alias($._binding_element_access_expression, $.element_access_expression),
1756
+ alias($._binding_invocation_expression, $.invocation_expression)
1757
+ ),
1758
+
1759
+ _conditional_binding_receiver: ($) =>
1760
+ choice(
1761
+ $._nonconditional_binding_expression,
1762
+ alias($._binding_suppression_expression, $.postfix_unary_expression),
1763
+ alias($._binding_generic_suppression_expression, $.postfix_unary_expression)
1764
+ ),
1765
+
1766
+ _binding_suppression_expression: ($) => postfixExpression($._conditional_binding_receiver, bangOperator()),
1767
+
1768
+ _binding_member_access_expression: ($) => memberAccessExpression($, $._conditional_binding_receiver),
1769
+
1770
+ _binding_element_access_expression: ($) => elementAccessExpression($, $._conditional_binding_receiver),
1771
+
1772
+ _binding_invocation_expression: ($) =>
1773
+ choice(invocationExpression($, $._conditional_binding_receiver), $._binding_generic_invocation_expression),
1774
+
1775
+ _binding_generic_invocation_expression: ($) =>
1776
+ genericInvocationExpression(
1777
+ $,
1778
+ choice(
1779
+ alias($._generic_member_binding_expression, $.member_binding_expression),
1780
+ alias($._binding_generic_member_expression, $.member_access_expression)
1781
+ ),
1782
+ $._binding_generic_invocation_expression,
1783
+ $._binding_generic_suppression_expression
1784
+ ),
1785
+
1786
+ _binding_generic_member_expression: ($) =>
1787
+ memberAccessExpression($, $._conditional_binding_receiver, $._generic_invocation_simple_name),
1788
+
1789
+ _binding_generic_suppression_expression: ($) =>
1790
+ seq(
1791
+ genericInvocationReceiver(
1792
+ $,
1793
+ $._binding_generic_invocation_expression,
1794
+ $._binding_generic_suppression_expression
1795
+ ),
1796
+ bangOperator()
1797
+ ),
1798
+
1799
+ _binding_conditional_access_expression: ($) => conditionalAccessExpression($, $._conditional_binding_receiver),
1800
+
1801
+ _conditional_binding_assignment_expression: ($) => assignmentExpression($, $._conditional_binding_receiver),
1802
+
1803
+ _conditional_assignment_expression: ($) =>
1804
+ choice(
1805
+ seq(
1806
+ field('condition', $._conditional_access_receiver),
1807
+ accessQuestion(),
1808
+ field('consequence', $._conditional_assignment_consequence)
1809
+ ),
1810
+ seq(
1811
+ field('condition', $._definite_conditional_access_receiver),
1812
+ definiteAccessQuestion(),
1813
+ field('consequence', $._conditional_assignment_consequence)
1814
+ ),
1815
+ seq(
1816
+ field('condition', $.array_creation_expression),
1817
+ memberAccessQuestion(),
1818
+ field('consequence', $._member_conditional_assignment_consequence)
1819
+ )
1820
+ ),
1821
+
1822
+ _conditional_assignment_consequence: ($) =>
1823
+ choice(
1824
+ alias($._conditional_binding_assignment_expression, $.assignment_expression),
1825
+ alias($._binding_conditional_assignment_expression, $.conditional_access_expression)
1826
+ ),
1827
+
1828
+ _member_conditional_assignment_consequence: ($) =>
1829
+ choice(
1830
+ alias($._member_conditional_binding_assignment_expression, $.assignment_expression),
1831
+ alias($._member_binding_conditional_assignment_expression, $.conditional_access_expression)
1832
+ ),
1833
+
1834
+ _binding_conditional_assignment_expression: ($) =>
1835
+ seq(
1836
+ field('condition', $._conditional_binding_receiver),
1837
+ accessQuestion(),
1838
+ field('consequence', $._conditional_assignment_consequence)
1839
+ ),
1840
+
1841
+ _member_binding_conditional_assignment_expression: ($) =>
1842
+ seq(
1843
+ field('condition', $._member_conditional_binding_receiver),
1844
+ accessQuestion(),
1845
+ field('consequence', $._conditional_assignment_consequence)
1846
+ ),
1847
+
1848
+ _postfix_receiver: ($) =>
1849
+ choice(
1850
+ $._primary_no_conditional_access_expression,
1851
+ alias($._conditional_assignment_expression, $.conditional_access_expression)
1852
+ ),
1853
+
1854
+ _conditional_assignment_suppression_expression: ($) =>
1855
+ postfixExpression(
1856
+ choice(
1857
+ alias($._conditional_assignment_expression, $.conditional_access_expression),
1858
+ alias($._conditional_assignment_suppression_expression, $.postfix_unary_expression)
1859
+ ),
1860
+ bangOperator()
1861
+ ),
1862
+
1863
+ as_expression: ($) =>
1864
+ prec(
1865
+ PREC.REL,
1866
+ seq(
1867
+ field('left', $.expression),
1868
+ field('operator', alias(sym('_type_context_as'), 'as')),
1869
+ field('right', $.type)
1870
+ )
1871
+ ),
1872
+
1873
+ is_pattern_expression: ($) =>
1874
+ prec(
1875
+ PREC.REL,
1876
+ seq(
1877
+ field('expression', $.expression),
1878
+ alias(sym('_type_context_is'), 'is'),
1879
+ field('pattern', alias($._is_pattern, $.pattern))
1880
+ )
1881
+ ),
1882
+
1883
+ // C# treats a non-generic terminal name followed by a nonempty collection as parenthesized indexing.
1884
+ cast_expression: ($) =>
1885
+ castExpression($, $._non_range_unary_operand, alias($._prefix_range_expression, $.range_expression)),
1886
+
1887
+ _non_range_unary_operand: ($) => choice($._unary_expression, $.query_expression),
1888
+
1889
+ _unary_operand: ($) => choice($._non_range_unary_operand, alias($._prefix_range_expression, $.range_expression)),
1890
+
1891
+ _prefix_range_expression: ($) => prefixRangeExpression($._unary_operand),
1892
+
1893
+ _range_cast_type: ($) =>
1894
+ choice(
1895
+ typeAlternatives($, false, true, false, false, $.alias_qualified_name),
1896
+ alias($._omitted_cast_array_type, $.array_type)
1897
+ ),
1898
+
1899
+ _omitted_cast_array_type: ($) =>
1900
+ seq(
1901
+ field('type', $._array_base_type),
1902
+ field('rank', alias($._omitted_array_rank_specifier, $.array_rank_specifier))
1903
+ ),
1904
+
1905
+ _omitted_array_rank_specifier: () => seq('[', repeat(','), ']'),
1906
+
1907
+ _ambiguous_cast_type: ($) => $._ambiguous_cast_name,
1908
+
1909
+ _definite_cast_type: ($) =>
1910
+ choice(
1911
+ typeAlternatives($, false, true, true, false, $._definite_cast_name),
1912
+ alias($._omitted_cast_array_type, $.array_type)
1913
+ ),
1914
+
1915
+ _preferred_cast_head: ($) =>
1916
+ choice(
1464
1917
  prec.dynamic(
1465
- 1,
1918
+ 2,
1919
+ seq('(', field('type', alias($._ambiguous_cast_type, $.type)), alias(sym('_ambiguous_cast_type_end'), ')'))
1920
+ ),
1921
+ prec.dynamic(
1922
+ 3,
1466
1923
  seq(
1467
- // higher than invocation, lower than binary
1468
1924
  '(',
1469
- field('type', $.type),
1470
- ')',
1471
- field('value', $.expression)
1925
+ field('type', alias($._omitted_cast_array_type, $.array_type)),
1926
+ alias(sym('_definite_cast_type_end'), ')')
1472
1927
  )
1473
1928
  )
1474
1929
  ),
1475
1930
 
1931
+ _preferred_range_cast_head: ($) =>
1932
+ prec.dynamic(
1933
+ 3,
1934
+ seq(
1935
+ '(',
1936
+ field('type', alias($._omitted_cast_array_type, $.array_type)),
1937
+ alias(sym('_range_cast_type_end'), ')')
1938
+ )
1939
+ ),
1940
+
1941
+ _ambiguous_cast_name: ($) => choice($.identifier, alias($._ambiguous_cast_qualified_name, $.qualified_name)),
1942
+
1943
+ _ambiguous_cast_qualified_name: ($) => seq(field('qualifier', $._name), '.', field('name', $.identifier)),
1944
+
1945
+ _definite_cast_name: ($) =>
1946
+ choice($.generic_name, $.alias_qualified_name, alias($._definite_cast_qualified_name, $.qualified_name)),
1947
+
1948
+ _definite_cast_qualified_name: ($) => seq(field('qualifier', $._name), '.', field('name', $.generic_name)),
1949
+
1476
1950
  checked_expression: ($) => seq(choice('checked', 'unchecked'), '(', $.expression, ')'),
1477
1951
 
1478
1952
  invocation_expression: ($) =>
1479
- prec(PREC.INVOCATION, seq(field('function', postfixOperand($)), field('arguments', $.argument_list))),
1953
+ choice(invocationExpression($, $._postfix_receiver), $._generic_invocation_expression),
1954
+
1955
+ _generic_invocation_expression: ($) =>
1956
+ genericInvocationExpression(
1957
+ $,
1958
+ choice(
1959
+ $._generic_invocation_simple_name,
1960
+ alias($._pattern_generic_member_expression, $.member_access_expression),
1961
+ alias($._generic_alias_qualified_name, $.alias_qualified_name)
1962
+ ),
1963
+ $._generic_invocation_expression,
1964
+ $._generic_invocation_suppression_expression
1965
+ ),
1480
1966
 
1481
- switch_expression: ($) => prec(PREC.SWITCH, seq($.expression, 'switch', $._switch_expression_body)),
1482
- _switch_expression_body: ($) => seq('{', commaSep($.switch_expression_arm), optional(','), '}'),
1967
+ _generic_member_binding_expression: ($) => seq('.', field('name', $._generic_invocation_simple_name)),
1968
+
1969
+ _generic_invocation_simple_name: ($) => $.generic_name,
1970
+
1971
+ _generic_alias_qualified_name: ($) => seq(field('alias', $.identifier), '::', field('name', $.generic_name)),
1972
+
1973
+ _generic_invocation_suppression_expression: ($) =>
1974
+ postfixExpression(
1975
+ genericInvocationReceiver($, $._generic_invocation_expression, $._generic_invocation_suppression_expression),
1976
+ bangOperator()
1977
+ ),
1978
+
1979
+ switch_expression: ($) => switchExpression($, $.expression),
1980
+ _switch_expression_body: ($) =>
1981
+ seq(
1982
+ '{',
1983
+ commaSep($.switch_expression_arm),
1984
+ optional(','),
1985
+ choice('}', alias(sym('_nonprimary_expression_end'), '}'))
1986
+ ),
1483
1987
 
1484
1988
  switch_expression_arm: ($) => seq($.pattern, optional($.when_clause), '=>', $.expression),
1485
1989
 
1486
1990
  when_clause: ($) => seq('when', $.expression),
1487
1991
 
1488
- await_expression: ($) => prec.right(PREC.UNARY, seq('await', $.expression)),
1992
+ await_expression: ($) => prec.right(PREC.UNARY, seq('await', $._unary_operand)),
1489
1993
 
1490
1994
  throw_expression: ($) => seq('throw', $.expression),
1491
1995
 
1492
- element_access_expression: ($) =>
1493
- prec(PREC.POSTFIX, seq(field('expression', postfixOperand($)), field('subscript', $.bracketed_argument_list))),
1996
+ element_access_expression: ($) => elementAccessExpression($, $._postfix_receiver),
1494
1997
 
1495
1998
  interpolated_string_expression: ($) =>
1496
1999
  choice(
1497
2000
  seq(
1498
- alias($.interpolation_regular_start, $.interpolation_start),
1499
- alias($.interpolation_start_quote, '"'),
2001
+ alias(sym('interpolation_regular_start'), sym('interpolation_start')),
2002
+ alias(sym('interpolation_start_quote'), '"'),
1500
2003
  repeat($._interpolated_string_content),
1501
- alias($.interpolation_end_quote, '"')
2004
+ alias(sym('interpolation_end_quote'), '"')
1502
2005
  ),
1503
2006
  seq(
1504
- alias($.interpolation_verbatim_start, $.interpolation_start),
1505
- alias($.interpolation_start_quote, '"'),
2007
+ alias(sym('interpolation_verbatim_start'), sym('interpolation_start')),
2008
+ alias(sym('interpolation_start_quote'), '"'),
1506
2009
  repeat($._interpolated_verbatim_string_content),
1507
- alias($.interpolation_end_quote, '"')
2010
+ alias(sym('interpolation_end_quote'), '"')
1508
2011
  ),
1509
2012
  seq(
1510
- alias($.interpolation_raw_start, $.interpolation_start),
1511
- alias($.interpolation_start_quote, $.interpolation_quote),
2013
+ alias(sym('interpolation_raw_start'), sym('interpolation_start')),
2014
+ alias(sym('interpolation_start_quote'), sym('interpolation_quote')),
1512
2015
  repeat($._interpolated_raw_string_content),
1513
- alias($.interpolation_end_quote, $.interpolation_quote)
2016
+ alias(sym('interpolation_end_quote'), sym('interpolation_quote'))
1514
2017
  )
1515
2018
  ),
1516
2019
 
1517
2020
  _interpolated_string_content: ($) =>
1518
- choice(alias($.interpolation_string_content, $.string_content), $.escape_sequence, $.interpolation),
2021
+ choice(alias(sym('interpolation_string_content'), sym('string_content')), $.escape_sequence, $.interpolation),
1519
2022
 
1520
2023
  _interpolated_verbatim_string_content: ($) =>
1521
2024
  choice(
1522
- alias($.interpolation_string_content, $.string_content),
2025
+ alias(sym('interpolation_string_content'), sym('string_content')),
1523
2026
  alias($._multiline_interpolation, $.interpolation)
1524
2027
  ),
1525
2028
 
1526
2029
  _interpolated_raw_string_content: ($) =>
1527
2030
  choice(
1528
- alias($.interpolation_string_content, $.string_content),
2031
+ alias(sym('interpolation_string_content'), sym('string_content')),
1529
2032
  alias($._multiline_interpolation, $.interpolation)
1530
2033
  ),
1531
2034
 
1532
2035
  interpolation: ($) =>
1533
2036
  seq(
1534
- alias($.interpolation_open_brace, $.interpolation_brace),
2037
+ alias(sym('interpolation_open_brace'), sym('interpolation_brace')),
1535
2038
  $.expression,
1536
2039
  optional($.interpolation_alignment_clause),
1537
2040
  choice(
1538
- alias($.interpolation_close_brace, $.interpolation_brace),
1539
- seq($.interpolation_format_clause, alias(token.immediate('}'), $.interpolation_brace))
2041
+ alias(sym('interpolation_close_brace'), sym('interpolation_brace')),
2042
+ seq($.interpolation_format_clause, alias(token.immediate('}'), sym('interpolation_brace')))
1540
2043
  )
1541
2044
  ),
1542
2045
 
1543
2046
  interpolation_alignment_clause: ($) => seq(',', $.expression),
1544
2047
 
1545
- interpolation_format_clause: ($) =>
1546
- seq(':', optional($._file_directive_literal_context), token.immediate(/[^}"\n\r\u0085\u2028\u2029]+/)),
2048
+ interpolation_format_clause: () =>
2049
+ prec.dynamic(
2050
+ 1,
2051
+ seq(':', optional(sym('_file_directive_literal_context')), token.immediate(/[^}"\n\r\u0085\u2028\u2029]+/))
2052
+ ),
1547
2053
 
1548
2054
  _multiline_interpolation: ($) =>
1549
2055
  seq(
1550
- alias($.interpolation_open_brace, $.interpolation_brace),
2056
+ alias(sym('interpolation_open_brace'), sym('interpolation_brace')),
1551
2057
  $.expression,
1552
2058
  optional($.interpolation_alignment_clause),
1553
2059
  optional(alias($._multiline_interpolation_format_clause, $.interpolation_format_clause)),
1554
- alias($.interpolation_close_brace, $.interpolation_brace)
2060
+ alias(sym('interpolation_close_brace'), sym('interpolation_brace'))
1555
2061
  ),
1556
2062
 
1557
- _multiline_interpolation_format_clause: ($) => seq(':', optional($._file_directive_literal_context), /[^}"]+/),
2063
+ _multiline_interpolation_format_clause: () =>
2064
+ prec.dynamic(1, seq(':', optional(sym('_file_directive_literal_context')), /[^}"]+/)),
1558
2065
 
1559
- member_access_expression: ($) =>
1560
- prec(
1561
- PREC.DOT,
1562
- seq(
1563
- field('expression', choice(postfixOperand($), $.predefined_type, $._name)),
1564
- choice('.', '->'),
1565
- field('name', $._simple_name)
1566
- )
1567
- ),
2066
+ member_access_expression: ($) => memberAccessExpression($, choice($._postfix_receiver, $.predefined_type, $._name)),
1568
2067
 
1569
2068
  member_binding_expression: ($) => seq('.', field('name', $._simple_name)),
1570
2069
 
@@ -1572,17 +2071,20 @@ module.exports = grammar({
1572
2071
  prec.right(
1573
2072
  seq(
1574
2073
  'new',
1575
- field('type', $.type),
1576
- field('arguments', optional($.argument_list)),
1577
- field('initializer', optional($.initializer_expression))
2074
+ field('type', $._object_creation_type),
2075
+ choice(
2076
+ seq(
2077
+ field('arguments', $.argument_list),
2078
+ field('initializer', optional(alias($._object_initializer_expression, $.initializer_expression)))
2079
+ ),
2080
+ field('initializer', alias($._object_initializer_expression, $.initializer_expression))
2081
+ )
1578
2082
  )
1579
2083
  ),
1580
2084
 
1581
- _object_creation_type: ($) => choice($._name, $.nullable_type, $.predefined_type),
1582
-
1583
- parenthesized_expression: ($) => seq('(', $.non_lvalue_expression, ')'),
2085
+ _object_creation_type: ($) => typeAlternatives($, true, true, true, false),
1584
2086
 
1585
- _parenthesized_lvalue_expression: ($) => seq('(', $.lvalue_expression, ')'),
2087
+ parenthesized_expression: ($) => seq('(', $.expression, ')'),
1586
2088
 
1587
2089
  lambda_expression: ($) =>
1588
2090
  prec(-1, seq($._lambda_expression_init, '=>', field('body', choice($.block, $.expression)))),
@@ -1594,7 +2096,7 @@ module.exports = grammar({
1594
2096
  repeat($._attribute_list),
1595
2097
  repeat(prec.dynamic(1, alias(choice('static', 'async'), $.modifier))),
1596
2098
  choice(
1597
- field('parameters', prec(-1, alias($.identifier, $.implicit_parameter))),
2099
+ field('parameters', prec(-1, alias($.identifier, sym('implicit_parameter')))),
1598
2100
  seq(optional(field('type', $.type)), field('parameters', $._lambda_parameters))
1599
2101
  )
1600
2102
  )
@@ -1619,21 +2121,24 @@ module.exports = grammar({
1619
2121
  // external _lambda_paren_open; the closing ')' is the regular literal.
1620
2122
  _implicit_parameter_list_with_modifiers: ($) =>
1621
2123
  seq(
1622
- $._lambda_paren_open,
2124
+ sym('_lambda_paren_open'),
1623
2125
  commaSep1(
1624
2126
  choice(
1625
2127
  seq(
1626
2128
  repeat1(alias(choice('scoped', 'ref', 'out', 'in', 'readonly'), $.modifier)),
1627
- alias($.identifier, $.implicit_parameter)
2129
+ alias($.identifier, sym('implicit_parameter'))
1628
2130
  ),
1629
- alias($.identifier, $.implicit_parameter)
2131
+ alias($.identifier, sym('implicit_parameter'))
1630
2132
  )
1631
2133
  ),
1632
2134
  ')'
1633
2135
  ),
1634
2136
 
1635
- array_creation_expression: ($) =>
1636
- prec.dynamic(PREC.UNARY, seq('new', field('type', $.array_type), optional($.initializer_expression))),
2137
+ array_creation_expression: ($) => arrayCreationExpression($, optional($.initializer_expression)),
2138
+
2139
+ _initialized_array_creation_expression: ($) => arrayCreationExpression($, $.initializer_expression),
2140
+
2141
+ _initialized_stackalloc_expression: ($) => stackallocExpression($, $.initializer_expression),
1637
2142
 
1638
2143
  anonymous_method_expression: ($) =>
1639
2144
  seq(
@@ -1651,7 +2156,9 @@ module.exports = grammar({
1651
2156
  implicit_array_creation_expression: ($) => seq('new', '[', repeat(','), ']', $.initializer_expression),
1652
2157
 
1653
2158
  implicit_object_creation_expression: ($) =>
1654
- prec.right(seq('new', $.argument_list, optional($.initializer_expression))),
2159
+ prec.right(
2160
+ seq('new', $.argument_list, optional(alias($._object_initializer_expression, $.initializer_expression)))
2161
+ ),
1655
2162
 
1656
2163
  implicit_stackalloc_expression: ($) => seq('stackalloc', '[', ']', $.initializer_expression),
1657
2164
 
@@ -1663,14 +2170,44 @@ module.exports = grammar({
1663
2170
 
1664
2171
  spread_element: ($) => prec.dynamic(1, prec(PREC.RANGE, seq('..', $.expression))),
1665
2172
 
2173
+ _object_initializer_expression: ($) =>
2174
+ seq(
2175
+ '{',
2176
+ commaSep(
2177
+ choice(
2178
+ alias($._object_index_initializer, $.assignment_expression),
2179
+ alias($._object_member_initializer, $.assignment_expression),
2180
+ $.expression
2181
+ )
2182
+ ),
2183
+ optional(','),
2184
+ '}'
2185
+ ),
2186
+
2187
+ _object_initializer_value: ($) =>
2188
+ choice($.expression, alias($._object_initializer_expression, $.initializer_expression)),
2189
+
2190
+ _object_index_initializer: ($) =>
2191
+ assignmentExpression(
2192
+ $,
2193
+ alias($._object_index_target, sym('element_binding_expression')),
2194
+ '=',
2195
+ $._object_initializer_value
2196
+ ),
2197
+
2198
+ _object_index_target: ($) => bracketedArgumentList($, alias(sym('_object_index_start'), '[')),
2199
+
2200
+ _object_member_initializer: ($) => assignmentExpression($, $.identifier, '=', $._object_initializer_value),
2201
+
1666
2202
  initializer_expression: ($) => seq('{', commaSep($.expression), optional(','), '}'),
1667
2203
 
1668
2204
  declaration_expression: ($) => prec.dynamic(1, seq(field('type', $.type), field('name', $.identifier))),
1669
2205
 
1670
2206
  default_expression: ($) => prec.right(seq('default', optional(seq('(', field('type', $.type), ')')))),
1671
2207
 
1672
- with_expression: ($) => prec.left(PREC.WITH, seq($.expression, 'with', $._with_body)),
1673
- _with_body: ($) => seq('{', commaSep($.with_initializer), optional(','), '}'),
2208
+ with_expression: ($) => withExpression($, $.expression),
2209
+ _with_body: ($) =>
2210
+ seq('{', commaSep($.with_initializer), optional(','), choice('}', alias(sym('_nonprimary_expression_end'), '}'))),
1674
2211
 
1675
2212
  with_initializer: ($) => seq($.identifier, '=', $.expression),
1676
2213
 
@@ -1686,10 +2223,9 @@ module.exports = grammar({
1686
2223
 
1687
2224
  refvalue_expression: ($) => seq('__refvalue', '(', field('value', $.expression), ',', field('type', $.type), ')'),
1688
2225
 
1689
- stackalloc_expression: ($) =>
1690
- prec.left(seq('stackalloc', field('type', $.array_type), optional($.initializer_expression))),
2226
+ stackalloc_expression: ($) => stackallocExpression($, optional($.initializer_expression)),
1691
2227
 
1692
- range_expression: ($) => prec.right(PREC.RANGE, seq(optional($.expression), '..', optional($.expression))),
2228
+ range_expression: ($) => rangeExpression($.expression, $.expression),
1693
2229
 
1694
2230
  tuple_expression: ($) => seq('(', commaSep2(alias($._tuple_argument, $.argument)), ')'),
1695
2231
 
@@ -1749,7 +2285,7 @@ module.exports = grammar({
1749
2285
  string_literal: ($) =>
1750
2286
  seq(
1751
2287
  '"',
1752
- repeat(choice($.string_literal_content, $.escape_sequence, $._file_directive_literal_context)),
2288
+ repeat(choice($.string_literal_content, $.escape_sequence, sym('_file_directive_literal_context'))),
1753
2289
  token.immediate('"'),
1754
2290
  optional($.string_literal_encoding)
1755
2291
  ),
@@ -1763,8 +2299,8 @@ module.exports = grammar({
1763
2299
 
1764
2300
  verbatim_string_literal: () => token(seq('@"', repeat(choice(/[^"]/, '""')), '"', optional(stringEncoding))),
1765
2301
 
1766
- raw_string_literal: ($) =>
1767
- seq($.raw_string_start, $.raw_string_content, $.raw_string_end, optional(stringEncoding)),
2302
+ raw_string_literal: () =>
2303
+ seq(sym('raw_string_start'), sym('raw_string_content'), sym('raw_string_end'), optional(stringEncoding)),
1768
2304
 
1769
2305
  boolean_literal: () => choice('true', 'false'),
1770
2306
 
@@ -1777,51 +2313,11 @@ module.exports = grammar({
1777
2313
  ),
1778
2314
  identifier: ($) => choice($._identifier_token, $._reserved_identifier),
1779
2315
 
1780
- _reserved_identifier: () =>
1781
- choice(
1782
- prec(-1, '_'),
1783
- 'alias',
1784
- 'async',
1785
- 'ascending',
1786
- 'by',
1787
- 'descending',
1788
- 'equals',
1789
- // attribute_target_specifier keywords — contextual only when followed
1790
- // by `:` in `[target: Attr]` position. Anywhere else they're
1791
- // identifiers. Without listing them here the LR table preferred the
1792
- // literal-keyword interpretation, breaking `[type]`, `[field]`, etc.
1793
- // as collection_expression elements. Excludes `'event'` and `'return'`
1794
- // from the attribute_target_specifier choice — those are real C#
1795
- // keywords and must not be accepted as identifiers anywhere else.
1796
- 'field',
1797
- 'file',
1798
- 'from',
1799
- 'global',
1800
- 'group',
1801
- 'into',
1802
- 'join',
1803
- 'let',
1804
- 'method',
1805
- 'notnull',
1806
- 'on',
1807
- 'orderby',
1808
- 'param',
1809
- 'partial',
1810
- 'property',
1811
- 'scoped',
1812
- 'select',
1813
- 'type',
1814
- 'typevar',
1815
- 'unmanaged',
1816
- 'var',
1817
- 'when',
1818
- 'where',
1819
- 'yield'
1820
- ),
2316
+ _reserved_identifier: () => choice(...reservedIdentifiers()),
1821
2317
 
1822
2318
  ...preprocIf(
1823
2319
  '_in_method_signature',
1824
- ($) => choice($.method_signature, alias($.preproc_if_in_method_signature, $.preproc_if)),
2320
+ ($) => choice($.method_signature, alias(sym('preproc_if_in_method_signature'), sym('preproc_if'))),
1825
2321
  0,
1826
2322
  false,
1827
2323
  true
@@ -1837,7 +2333,7 @@ module.exports = grammar({
1837
2333
  token(prec(-1, /[^\s\u0085\u2028\u2029]([^/\r\n\u0085\u2028\u2029]|\/[^*\r\n\u0085\u2028\u2029])*/)),
1838
2334
  optional($._preproc_arg_slash)
1839
2335
  ),
1840
- _file_directive_argument: ($) => seq($._file_directive_preproc_arg, optional($._preproc_arg_slash)),
2336
+ _file_directive_argument: ($) => seq(sym('_file_directive_preproc_arg'), optional($._preproc_arg_slash)),
1841
2337
  _preproc_arg_slash: () => token.immediate(/\//),
1842
2338
  preproc_directive: () => /#[ \t]*[a-zA-Z0-9]\w*/,
1843
2339
 
@@ -1847,7 +2343,7 @@ module.exports = grammar({
1847
2343
  $.boolean_literal,
1848
2344
  $.integer_literal,
1849
2345
  $.character_literal,
1850
- alias($.preproc_unary_expression, $.unary_expression),
2346
+ alias($.preproc_unary_expression, sym('unary_expression')),
1851
2347
  alias($.preproc_binary_expression, $.binary_expression),
1852
2348
  alias($.preproc_parenthesized_expression, $.parenthesized_expression)
1853
2349
  ),
@@ -1855,9 +2351,10 @@ module.exports = grammar({
1855
2351
  preproc_parenthesized_expression: ($) => seq('(', $._preproc_expression, ')'),
1856
2352
 
1857
2353
  preproc_unary_expression: ($) =>
1858
- prec.left(PREC.UNARY, seq(field('operator', '!'), field('argument', $._preproc_expression))),
2354
+ prec.left(PREC.UNARY, seq(field('operator', bangOperator()), field('argument', $._preproc_expression))),
1859
2355
 
1860
2356
  preproc_binary_expression: ($) => {
2357
+ /** @type {[string, number][]} */
1861
2358
  const table = [
1862
2359
  ['||', PREC.LOGICAL_OR],
1863
2360
  ['&&', PREC.LOGICAL_AND],
@@ -1871,7 +2368,6 @@ module.exports = grammar({
1871
2368
  precedence,
1872
2369
  seq(
1873
2370
  field('left', $._preproc_expression),
1874
- // @ts-ignore
1875
2371
  field('operator', operator),
1876
2372
  field('right', $._preproc_expression)
1877
2373
  )
@@ -1884,14 +2380,14 @@ module.exports = grammar({
1884
2380
  seq(
1885
2381
  preprocessor('region'),
1886
2382
  optional(field('content', choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)))),
1887
- directiveEnd($)
2383
+ directiveEnd()
1888
2384
  ),
1889
2385
 
1890
2386
  preproc_endregion: ($) =>
1891
2387
  seq(
1892
2388
  preprocessor('endregion'),
1893
2389
  optional(field('content', choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)))),
1894
- directiveEnd($)
2390
+ directiveEnd()
1895
2391
  ),
1896
2392
 
1897
2393
  preproc_line: ($) =>
@@ -1917,7 +2413,7 @@ module.exports = grammar({
1917
2413
  alias($._preproc_filename, $.string_literal)
1918
2414
  )
1919
2415
  ),
1920
- directiveEnd($)
2416
+ directiveEnd()
1921
2417
  ),
1922
2418
 
1923
2419
  _preproc_filename: ($) =>
@@ -1926,7 +2422,7 @@ module.exports = grammar({
1926
2422
  repeat(
1927
2423
  choice(
1928
2424
  $.string_literal_content,
1929
- $._file_directive_literal_context,
2425
+ sym('_file_directive_literal_context'),
1930
2426
  alias(token.immediate(prec(-1, '\\')), $.string_literal_content),
1931
2427
  alias(
1932
2428
  token.immediate(
@@ -1946,43 +2442,43 @@ module.exports = grammar({
1946
2442
  seq('warning', choice('disable', 'restore'), commaSep(choice($.identifier, $.integer_literal))),
1947
2443
  seq('checksum', alias($._preproc_filename, $.string_literal), $.string_literal, $.string_literal)
1948
2444
  ),
1949
- directiveEnd($)
2445
+ directiveEnd()
1950
2446
  ),
1951
2447
 
1952
- preproc_nullable: ($) =>
2448
+ preproc_nullable: () =>
1953
2449
  seq(
1954
2450
  preprocessor('nullable'),
1955
2451
  choice('enable', 'disable', 'restore'),
1956
2452
  optional(choice('annotations', 'warnings')),
1957
- directiveEnd($)
2453
+ directiveEnd()
1958
2454
  ),
1959
2455
 
1960
2456
  preproc_error: ($) =>
1961
2457
  seq(
1962
2458
  preprocessor('error'),
1963
2459
  choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)),
1964
- directiveEnd($)
2460
+ directiveEnd()
1965
2461
  ),
1966
2462
 
1967
2463
  preproc_warning: ($) =>
1968
2464
  seq(
1969
2465
  preprocessor('warning'),
1970
2466
  choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)),
1971
- directiveEnd($)
2467
+ directiveEnd()
1972
2468
  ),
1973
2469
 
1974
2470
  preproc_define: ($) =>
1975
2471
  seq(
1976
2472
  preprocessor('define'),
1977
2473
  choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)),
1978
- directiveEnd($)
2474
+ directiveEnd()
1979
2475
  ),
1980
2476
 
1981
2477
  preproc_undef: ($) =>
1982
2478
  seq(
1983
2479
  preprocessor('undef'),
1984
2480
  choice($.preproc_arg, alias($._file_directive_argument, $.preproc_arg)),
1985
- directiveEnd($)
2481
+ directiveEnd()
1986
2482
  ),
1987
2483
 
1988
2484
  file_directive: ($) =>
@@ -1990,27 +2486,27 @@ module.exports = grammar({
1990
2486
  choice(
1991
2487
  fileDirectiveArguments(
1992
2488
  $,
1993
- choice(alias($._file_directive_sdk, '#:sdk'), alias($._file_directive_package, '#:package')),
2489
+ choice(alias(sym('_file_directive_sdk'), '#:sdk'), alias(sym('_file_directive_package'), '#:package')),
1994
2490
  '@',
1995
2491
  'metadata'
1996
2492
  ),
1997
- fileDirectiveArguments($, alias($._file_directive_property, '#:property'), '=', 'value'),
2493
+ fileDirectiveArguments($, alias(sym('_file_directive_property'), '#:property'), '=', 'value'),
1998
2494
  seq(
1999
2495
  choice(
2000
- alias($._file_directive_project, '#:project'),
2001
- alias($._file_directive_ref, '#:ref'),
2002
- alias($._file_directive_include, '#:include'),
2003
- alias($._file_directive_exclude, '#:exclude')
2496
+ alias(sym('_file_directive_project'), '#:project'),
2497
+ alias(sym('_file_directive_ref'), '#:ref'),
2498
+ alias(sym('_file_directive_include'), '#:include'),
2499
+ alias(sym('_file_directive_exclude'), '#:exclude')
2004
2500
  ),
2005
2501
  optional(seq($._file_directive_spacing, field('value', $.file_directive_value)))
2006
2502
  ),
2007
2503
  seq(
2008
- $.file_directive_kind,
2504
+ sym('file_directive_kind'),
2009
2505
  optional(seq($._file_directive_spacing, optional(field('value', $.file_directive_value))))
2010
2506
  )
2011
2507
  ),
2012
2508
  optional($._file_directive_spacing),
2013
- choice($._file_directive_newline, $._end_of_input)
2509
+ choice(sym('_file_directive_newline'), sym('_end_of_input'))
2014
2510
  ),
2015
2511
 
2016
2512
  _file_directive_spacing: () => token.immediate(prec(1, new RegExp(`[${directiveHorizontal}]+`))),
@@ -2041,11 +2537,11 @@ module.exports = grammar({
2041
2537
  });
2042
2538
 
2043
2539
  /**
2044
- * @param {GrammarSymbols<string>} $
2045
- * @param {Rule} kind
2540
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_file_directive_spacing' | 'file_directive_name' | 'file_directive_value'>} $
2541
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} kind
2046
2542
  * @param {string} separator
2047
2543
  * @param {string} extraField
2048
- * @returns {SeqRule}
2544
+ * @returns {import('@willbooster/web-tree-sitter/dsl').SeqRule}
2049
2545
  */
2050
2546
  function fileDirectiveArguments($, kind, separator, extraField) {
2051
2547
  return seq(
@@ -2079,23 +2575,20 @@ function fileDirectiveArguments($, kind, separator, extraField) {
2079
2575
  * Ends a directive that opens no conditional section: at a line break, or at the end of the input, which a file may
2080
2576
  * reach without a final line break.
2081
2577
  *
2082
- * @param {GrammarSymbols<string>} $
2083
- *
2084
- * @returns {ChoiceRule}
2578
+ * @returns {import('@willbooster/web-tree-sitter/dsl').ChoiceRule}
2085
2579
  */
2086
- function directiveEnd($) {
2087
- return choice(directiveNewLine($), $._end_of_input);
2580
+ function directiveEnd() {
2581
+ return choice(directiveNewLine(), sym('_end_of_input'));
2088
2582
  }
2089
2583
 
2090
- /** @param {GrammarSymbols<string>} $ */
2091
- function directiveNewLine($) {
2092
- return $._directive_newline;
2584
+ function directiveNewLine() {
2585
+ return sym('_directive_newline');
2093
2586
  }
2094
2587
 
2095
2588
  /**
2096
2589
  * @param {string} command
2097
2590
  *
2098
- * @returns {AliasRule}
2591
+ * @returns {import('@willbooster/web-tree-sitter/dsl').AliasRule}
2099
2592
  */
2100
2593
  function preprocessor(command) {
2101
2594
  return alias(new RegExp('#[ \t]*' + command), '#' + command);
@@ -2105,7 +2598,7 @@ function preprocessor(command) {
2105
2598
  *
2106
2599
  * @param {string} suffix
2107
2600
  *
2108
- * @param {RuleBuilder<string>} content
2601
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleBuilder<PreprocContentRule>} content
2109
2602
  *
2110
2603
  * @param {number} precedence
2111
2604
  *
@@ -2113,19 +2606,23 @@ function preprocessor(command) {
2113
2606
  *
2114
2607
  * @param {boolean} required
2115
2608
  *
2116
- * @returns {RuleBuilders<string, string>}
2609
+ * @returns {Record<string, import('@willbooster/web-tree-sitter/dsl').RuleBuilder<PreprocContentRule>>}
2117
2610
  */
2118
2611
  function preprocIf(suffix, content, precedence = 0, rep = true, required = false) {
2612
+ /** @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<PreprocContentRule>} $ */
2613
+ function contentRule($) {
2614
+ const rule = content($);
2615
+ return rep ? repeat(rule) : required ? rule : optional(rule);
2616
+ }
2617
+
2119
2618
  /**
2120
2619
  *
2121
- * @param {GrammarSymbols<string>} $
2122
- *
2123
- * @returns {ChoiceRule}
2620
+ * @returns {import('@willbooster/web-tree-sitter/dsl').ChoiceRule}
2124
2621
  */
2125
- function alternativeBlock($) {
2622
+ function alternativeBlock() {
2126
2623
  return choice(
2127
- suffix ? alias($['preproc_else' + suffix], $.preproc_else) : $.preproc_else,
2128
- suffix ? alias($['preproc_elif' + suffix], $.preproc_elif) : $.preproc_elif
2624
+ suffix ? alias(sym('preproc_else' + suffix), sym('preproc_else')) : sym('preproc_else'),
2625
+ suffix ? alias(sym('preproc_elif' + suffix), sym('preproc_elif')) : sym('preproc_elif')
2129
2626
  );
2130
2627
  }
2131
2628
 
@@ -2136,18 +2633,14 @@ function preprocIf(suffix, content, precedence = 0, rep = true, required = false
2136
2633
  seq(
2137
2634
  preprocessor('if'),
2138
2635
  field('condition', $._preproc_expression),
2139
- directiveNewLine($),
2140
- rep ? repeat(content($)) : required ? content($) : optional(content($)),
2141
- field('alternative', optional(alternativeBlock($))),
2636
+ directiveNewLine(),
2637
+ contentRule($),
2638
+ field('alternative', optional(alternativeBlock())),
2142
2639
  preprocessor('endif')
2143
2640
  )
2144
2641
  ),
2145
2642
 
2146
- ['preproc_else' + suffix]: ($) =>
2147
- prec(
2148
- precedence,
2149
- seq(preprocessor('else'), rep ? repeat(content($)) : required ? content($) : optional(content($)))
2150
- ),
2643
+ ['preproc_else' + suffix]: ($) => prec(precedence, seq(preprocessor('else'), contentRule($))),
2151
2644
 
2152
2645
  ['preproc_elif' + suffix]: ($) =>
2153
2646
  prec(
@@ -2155,79 +2648,519 @@ function preprocIf(suffix, content, precedence = 0, rep = true, required = false
2155
2648
  seq(
2156
2649
  preprocessor('elif'),
2157
2650
  field('condition', $._preproc_expression),
2158
- directiveNewLine($),
2159
- rep ? repeat(content($)) : required ? content($) : optional(content($)),
2160
- field('alternative', optional(alternativeBlock($)))
2651
+ directiveNewLine(),
2652
+ contentRule($),
2653
+ field('alternative', optional(alternativeBlock()))
2161
2654
  )
2162
2655
  ),
2163
2656
  };
2164
2657
  }
2165
2658
 
2166
2659
  /**
2167
- * The operand of a postfix operator, an invocation, an element access, or a member access. Besides `expression`, it
2168
- * lists the forms that are operands of `&`, of the assignable `*`, or of the assignable cast: reaching them only
2169
- * through `expression` would reduce the unary operator or the cast (precedence UNARY or CAST) before `expression`
2170
- * (precedence 0) lets the postfix operator apply, reading `&a[0]` as `(&a)[0]` and `*(T*)f()[0]` as `(*(T*)f())[0]`.
2171
- *
2172
- * @param {GrammarSymbols<string>} $
2173
- *
2174
- * @returns {ChoiceRule}
2660
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_simple_name'>} $
2661
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2662
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} [name]
2663
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} [operator]
2664
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2175
2665
  */
2176
- function postfixOperand($) {
2666
+ function memberAccessExpression($, receiver, name = $._simple_name, operator = choice('.', '->')) {
2667
+ return prec(PREC.DOT, seq(field('expression', receiver), operator, field('name', name)));
2668
+ }
2669
+
2670
+ /**
2671
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'bracketed_argument_list'>} $
2672
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2673
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2674
+ */
2675
+ function elementAccessExpression($, receiver) {
2676
+ return prec(PREC.DOT, seq(field('expression', receiver), field('subscript', $.bracketed_argument_list)));
2677
+ }
2678
+
2679
+ /**
2680
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'argument_list'>} $
2681
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2682
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2683
+ */
2684
+ function invocationExpression($, receiver) {
2685
+ return prec(PREC.INVOCATION, seq(field('function', receiver), field('arguments', $.argument_list)));
2686
+ }
2687
+
2688
+ /**
2689
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'argument_list' | 'invocation_expression' | 'postfix_unary_expression'>} $
2690
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} first
2691
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} call
2692
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} suppression
2693
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2694
+ */
2695
+ function genericInvocationExpression($, first, call, suppression) {
2177
2696
  return choice(
2178
- $.expression,
2179
- $.lvalue_expression,
2180
- $.invocation_expression,
2181
- $.postfix_unary_expression,
2182
- $.parenthesized_expression
2697
+ prec.dynamic(1, invocationExpression($, first)),
2698
+ prec.dynamic(3, invocationExpression($, genericInvocationReceiver($, call, suppression)))
2699
+ );
2700
+ }
2701
+
2702
+ /**
2703
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'invocation_expression' | 'postfix_unary_expression'>} $
2704
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} call
2705
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} suppression
2706
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2707
+ */
2708
+ function genericInvocationReceiver($, call, suppression) {
2709
+ return choice(alias(call, $.invocation_expression), alias(suppression, $.postfix_unary_expression));
2710
+ }
2711
+
2712
+ /**
2713
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} operand
2714
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2715
+ */
2716
+ function prefixUnaryExpression(operand) {
2717
+ return prec.right(
2718
+ PREC.UNARY,
2719
+ choice(
2720
+ seq(choice('++', '--', bangOperator(), '~'), operand),
2721
+ prec.dynamic(-2, seq(choice('+', '-', '^', '*', ampersandOperator()), operand))
2722
+ )
2723
+ );
2724
+ }
2725
+
2726
+ /**
2727
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_ambiguous_cast_type' | '_definite_cast_type' | '_preferred_cast_head' | '_preferred_range_cast_head' | '_range_cast_type' | 'type'>} $
2728
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} operand
2729
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} [rangeOperand]
2730
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2731
+ */
2732
+ function castExpression($, operand, rangeOperand) {
2733
+ return prec(
2734
+ PREC.CAST,
2735
+ prec.dynamic(
2736
+ 1,
2737
+ choice(
2738
+ seq(
2739
+ '(',
2740
+ field('type', alias($._ambiguous_cast_type, $.type)),
2741
+ ')',
2742
+ sym('_ambiguous_cast_operand_start'),
2743
+ field('value', operand)
2744
+ ),
2745
+ seq('(', field('type', alias($._definite_cast_type, $.type)), ')', field('value', operand)),
2746
+ seq($._preferred_cast_head, field('value', operand)),
2747
+ ...(rangeOperand
2748
+ ? [
2749
+ seq('(', field('type', alias($._range_cast_type, $.type)), ')', field('value', rangeOperand)),
2750
+ seq($._preferred_range_cast_head, field('value', rangeOperand)),
2751
+ ]
2752
+ : [])
2753
+ )
2754
+ )
2755
+ );
2756
+ }
2757
+
2758
+ /**
2759
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_conditional_access_consequence'>} $
2760
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2761
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2762
+ */
2763
+ function conditionalAccessExpression($, receiver) {
2764
+ return seq(field('condition', receiver), accessQuestion(), field('consequence', $._conditional_access_consequence));
2765
+ }
2766
+
2767
+ /**
2768
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2769
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} operator
2770
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2771
+ */
2772
+ function postfixExpression(receiver, operator) {
2773
+ return prec(PREC.POSTFIX, seq(receiver, operator));
2774
+ }
2775
+
2776
+ /**
2777
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'expression'>} $
2778
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
2779
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} [operator]
2780
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} [value]
2781
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2782
+ */
2783
+ function assignmentExpression(
2784
+ $,
2785
+ receiver,
2786
+ operator = choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '<<=', '>>=', '>>>=', '??='),
2787
+ value = $.expression
2788
+ ) {
2789
+ return prec.right(PREC.ASSIGN, seq(field('left', receiver), field('operator', operator), field('right', value)));
2790
+ }
2791
+
2792
+ /**
2793
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'array_type'>} $
2794
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} initializer
2795
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2796
+ */
2797
+ function arrayCreationExpression($, initializer) {
2798
+ return prec.dynamic(PREC.UNARY, seq('new', field('type', $.array_type), initializer));
2799
+ }
2800
+
2801
+ /**
2802
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'type'>} $
2803
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} initializer
2804
+ * @returns {import('@willbooster/web-tree-sitter/dsl').Rule}
2805
+ */
2806
+ function stackallocExpression($, initializer) {
2807
+ return prec.left(seq('stackalloc', field('type', $.type), initializer));
2808
+ }
2809
+
2810
+ /**
2811
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'argument'>} $
2812
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} opener
2813
+ */
2814
+ function bracketedArgumentList($, opener) {
2815
+ return seq(opener, commaSep1($.argument), optional(','), ']');
2816
+ }
2817
+
2818
+ function bangOperator() {
2819
+ return alias(sym('_bang_operator'), '!');
2820
+ }
2821
+
2822
+ function definiteAccessQuestion() {
2823
+ return choice(alias(sym('_question_definite_access'), '?'), alias(sym('_question_unknown'), '?'));
2824
+ }
2825
+
2826
+ function accessQuestion() {
2827
+ return choice(
2828
+ alias(sym('_question_member_access'), '?'),
2829
+ alias(sym('_question_element_access'), '?'),
2830
+ alias(sym('_question_unknown'), '?')
2183
2831
  );
2184
2832
  }
2185
2833
 
2834
+ function memberAccessQuestion() {
2835
+ return choice(alias(sym('_question_member_access'), '?'), alias(sym('_question_unknown'), '?'));
2836
+ }
2837
+
2838
+ function ternaryQuestion() {
2839
+ return choice(alias(sym('_question_ternary'), '?'), alias(sym('_question_unknown'), '?'));
2840
+ }
2841
+
2842
+ function nullableQuestion() {
2843
+ return choice(alias(sym('_question_nullable'), '?'), alias(sym('_question_unknown'), '?'));
2844
+ }
2845
+
2186
2846
  /**
2187
- * @param {Rule} rule
2847
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} rule
2188
2848
  *
2189
- * @returns {SeqRule}
2849
+ * @returns {import('@willbooster/web-tree-sitter/dsl').SeqRule}
2190
2850
  */
2191
2851
  function commaSep1(rule) {
2192
2852
  return seq(rule, repeat(seq(',', rule)));
2193
2853
  }
2194
2854
 
2195
2855
  /**
2196
- * @param {Rule} rule
2856
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} rule
2197
2857
  *
2198
- * @returns {SeqRule}
2858
+ * @returns {import('@willbooster/web-tree-sitter/dsl').SeqRule}
2199
2859
  */
2200
2860
  function commaSep2(rule) {
2201
2861
  return seq(rule, repeat1(seq(',', rule)));
2202
2862
  }
2203
2863
 
2204
2864
  /**
2205
- * @param {Rule} rule
2865
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} rule
2206
2866
  *
2207
- * @returns {ChoiceRule}
2867
+ * @returns {import('@willbooster/web-tree-sitter/dsl').ChoiceRule}
2208
2868
  */
2209
2869
  function commaSep(rule) {
2210
2870
  return optional(commaSep1(rule));
2211
2871
  }
2212
2872
 
2213
2873
  /**
2214
- * @param {RuleOrLiteral} rule
2874
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} rule
2215
2875
  *
2216
- * @param {RuleOrLiteral} separator
2876
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} separator
2217
2877
  *
2218
- * @returns {SeqRule}
2878
+ * @returns {import('@willbooster/web-tree-sitter/dsl').SeqRule}
2219
2879
  */
2220
2880
  function sep1(rule, separator) {
2221
2881
  return seq(rule, repeat(seq(separator, rule)));
2222
2882
  }
2223
2883
 
2224
2884
  /**
2225
- * @param {RuleOrLiteral} rule
2885
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} rule
2226
2886
  *
2227
- * @param {RuleOrLiteral} separator
2887
+ * @param {import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral} separator
2228
2888
  *
2229
- * @returns {ChoiceRule}
2889
+ * @returns {import('@willbooster/web-tree-sitter/dsl').ChoiceRule}
2230
2890
  */
2231
2891
  function sep(rule, separator) {
2232
2892
  return optional(sep1(rule, separator));
2233
2893
  }
2894
+
2895
+ function binaryOperators() {
2896
+ /** @type {[import('@willbooster/web-tree-sitter/dsl').RuleOrLiteral, number][]} */
2897
+ const operators = [
2898
+ ['&&', PREC.LOGICAL_AND],
2899
+ ['||', PREC.LOGICAL_OR],
2900
+ ['>>', PREC.SHIFT],
2901
+ ['>>>', PREC.SHIFT],
2902
+ ['<<', PREC.SHIFT],
2903
+ [ampersandOperator(), PREC.AND],
2904
+ ['^', PREC.XOR],
2905
+ ['|', PREC.OR],
2906
+ ['+', PREC.ADD],
2907
+ ['-', PREC.ADD],
2908
+ ['*', PREC.MULT],
2909
+ ['/', PREC.MULT],
2910
+ ['%', PREC.MULT],
2911
+ ['<', PREC.REL],
2912
+ ['<=', PREC.REL],
2913
+ ['==', PREC.EQUAL],
2914
+ ['!=', PREC.EQUAL],
2915
+ ['>=', PREC.REL],
2916
+ ['>', PREC.REL],
2917
+ ];
2918
+ return operators;
2919
+ }
2920
+
2921
+ /**
2922
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_conditional_assignment_suppression_expression' | '_conditional_update_expression' | '_nameof_expression' | 'anonymous_method_expression' | 'anonymous_object_creation_expression' | 'array_creation_expression' | 'checked_expression' | 'collection_expression' | 'default_expression' | 'element_access_expression' | 'implicit_array_creation_expression' | 'implicit_object_creation_expression' | 'implicit_stackalloc_expression' | 'interpolated_string_expression' | 'invocation_expression' | 'literal' | 'makeref_expression' | 'object_creation_expression' | 'parenthesized_expression' | 'postfix_unary_expression' | 'reftype_expression' | 'refvalue_expression' | 'sizeof_expression' | 'stackalloc_expression' | 'tuple_expression' | 'typeof_expression'>} $
2923
+ * @param {{name?: import('@willbooster/web-tree-sitter/dsl').Rule, member: import('@willbooster/web-tree-sitter/dsl').Rule, collection: boolean, element?: import('@willbooster/web-tree-sitter/dsl').Rule, invocation?: import('@willbooster/web-tree-sitter/dsl').Rule, parenthesized?: import('@willbooster/web-tree-sitter/dsl').Rule, tuple?: boolean, array?: import('@willbooster/web-tree-sitter/dsl').Rule, stackalloc?: import('@willbooster/web-tree-sitter/dsl').Rule, definite?: boolean}} options
2924
+ */
2925
+ function primaryAtoms(
2926
+ $,
2927
+ {
2928
+ name,
2929
+ member,
2930
+ collection,
2931
+ element = $.element_access_expression,
2932
+ invocation = $.invocation_expression,
2933
+ parenthesized = $.parenthesized_expression,
2934
+ tuple = true,
2935
+ array = $.array_creation_expression,
2936
+ stackalloc = $.stackalloc_expression,
2937
+ definite,
2938
+ }
2939
+ ) {
2940
+ const uncertain = [
2941
+ ...(name ? [name] : []),
2942
+ member,
2943
+ element,
2944
+ invocation,
2945
+ ...(tuple ? [$.tuple_expression] : []),
2946
+ parenthesized,
2947
+ ...(collection ? [$.collection_expression] : []),
2948
+ alias(sym('preproc_if_in_expression'), sym('preproc_if')),
2949
+ ];
2950
+ const completed = [
2951
+ alias($._nameof_expression, $.invocation_expression),
2952
+ alias($._conditional_update_expression, $.postfix_unary_expression),
2953
+ alias($._conditional_assignment_suppression_expression, $.postfix_unary_expression),
2954
+ 'this',
2955
+ 'base',
2956
+ $.postfix_unary_expression,
2957
+ $.literal,
2958
+ $.interpolated_string_expression,
2959
+ $.checked_expression,
2960
+ $.default_expression,
2961
+ $.sizeof_expression,
2962
+ $.typeof_expression,
2963
+ $.makeref_expression,
2964
+ $.reftype_expression,
2965
+ $.refvalue_expression,
2966
+ stackalloc,
2967
+ array,
2968
+ $.object_creation_expression,
2969
+ $.anonymous_method_expression,
2970
+ $.anonymous_object_creation_expression,
2971
+ $.implicit_array_creation_expression,
2972
+ $.implicit_object_creation_expression,
2973
+ $.implicit_stackalloc_expression,
2974
+ ];
2975
+ return choice(...(definite === true ? [] : uncertain), ...(definite === false ? [] : completed));
2976
+ }
2977
+
2978
+ function reservedIdentifiers() {
2979
+ return [
2980
+ prec(-1, '_'),
2981
+ 'alias',
2982
+ 'async',
2983
+ 'ascending',
2984
+ 'by',
2985
+ 'descending',
2986
+ 'equals',
2987
+ // attribute_target_specifier keywords — contextual only when followed
2988
+ // by `:` in `[target: Attr]` position. Anywhere else they're
2989
+ // identifiers. Without listing them here the LR table preferred the
2990
+ // literal-keyword interpretation, breaking `[type]`, `[field]`, etc.
2991
+ // as collection_expression elements. Excludes `'event'` and `'return'`
2992
+ // from the attribute_target_specifier choice — those are real C#
2993
+ // keywords and must not be accepted as identifiers anywhere else.
2994
+ 'field',
2995
+ 'file',
2996
+ 'from',
2997
+ 'global',
2998
+ 'group',
2999
+ 'into',
3000
+ 'join',
3001
+ 'let',
3002
+ 'method',
3003
+ 'nameof',
3004
+ 'nint',
3005
+ 'nuint',
3006
+ 'notnull',
3007
+ 'on',
3008
+ 'orderby',
3009
+ 'param',
3010
+ 'partial',
3011
+ 'property',
3012
+ 'scoped',
3013
+ 'select',
3014
+ 'type',
3015
+ 'typevar',
3016
+ 'unmanaged',
3017
+ 'var',
3018
+ 'when',
3019
+ 'where',
3020
+ 'yield',
3021
+ ];
3022
+ }
3023
+
3024
+ /**
3025
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} left
3026
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} right
3027
+ * @param {boolean} [preferArithmetic]
3028
+ */
3029
+ function arithmeticBinaryExpression(left, right, preferArithmetic = false) {
3030
+ return choice(
3031
+ ...binaryOperators()
3032
+ .filter(([, precedence]) => precedence >= PREC.SHIFT)
3033
+ .map(([operator, precedence]) => {
3034
+ const rule = prec.left(
3035
+ precedence,
3036
+ seq(field('left', left), field('operator', operator), field('right', right))
3037
+ );
3038
+ return preferArithmetic && operator !== '>>' && operator !== '>>>' ? prec.dynamic(2, rule) : rule;
3039
+ })
3040
+ );
3041
+ }
3042
+
3043
+ /**
3044
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_name' | 'array_type' | 'function_pointer_type' | 'implicit_type' | 'nullable_type' | 'pointer_type' | 'predefined_type' | 'ref_type' | 'scoped_type' | 'tuple_type'>} $
3045
+ * @param {boolean} [implicit]
3046
+ * @param {boolean} [pointer]
3047
+ * @param {boolean} [tuple]
3048
+ * @param {boolean} [array]
3049
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} [name]
3050
+ */
3051
+ function typeAlternatives($, implicit = true, pointer = true, tuple = true, array = true, name = $._name) {
3052
+ return choice(
3053
+ ...(implicit ? [$.implicit_type] : []),
3054
+ ...(array ? [$.array_type] : []),
3055
+ name,
3056
+ $.nullable_type,
3057
+ ...(pointer ? [$.pointer_type] : []),
3058
+ $.function_pointer_type,
3059
+ $.predefined_type,
3060
+ ...(tuple ? [$.tuple_type] : []),
3061
+ $.ref_type,
3062
+ $.scoped_type
3063
+ );
3064
+ }
3065
+
3066
+ /**
3067
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_parenthesized_pattern_with_designation' | 'and_pattern' | 'declaration_pattern' | 'discard' | 'list_pattern' | 'negated_pattern' | 'or_pattern' | 'parenthesized_pattern' | 'recursive_pattern' | 'relational_pattern' | 'slice_pattern' | 'type_pattern' | 'var_pattern'>} $
3068
+ */
3069
+ function nonconstantPatterns($) {
3070
+ return choice(
3071
+ $.declaration_pattern,
3072
+ $.discard,
3073
+ $.recursive_pattern,
3074
+ $.var_pattern,
3075
+ $.negated_pattern,
3076
+ prec.dynamic(1, alias($._parenthesized_pattern_with_designation, $.recursive_pattern)),
3077
+ $.parenthesized_pattern,
3078
+ $.relational_pattern,
3079
+ $.or_pattern,
3080
+ $.and_pattern,
3081
+ $.list_pattern,
3082
+ $.slice_pattern,
3083
+ $.type_pattern
3084
+ );
3085
+ }
3086
+
3087
+ /**
3088
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'expression' | 'identifier' | 'pattern'>} $
3089
+ * @param {boolean} [named]
3090
+ */
3091
+ function subpattern($, named = false) {
3092
+ const name = choice(seq($.expression, ':'), seq($.identifier, ':'));
3093
+ return seq(named ? name : optional(name), $.pattern);
3094
+ }
3095
+
3096
+ /**
3097
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_pattern_unary_expression' | 'binary_expression' | 'conditional_expression' | 'is_pattern_expression' | 'as_expression' | 'switch_expression' | 'throw_expression' | 'range_expression' | 'with_expression'>} $
3098
+ */
3099
+ function nestedConstantExpressionRoots($) {
3100
+ return [
3101
+ $._pattern_unary_expression,
3102
+ $.binary_expression,
3103
+ $.conditional_expression,
3104
+ $.is_pattern_expression,
3105
+ $.as_expression,
3106
+ $.switch_expression,
3107
+ $.throw_expression,
3108
+ $.range_expression,
3109
+ $.with_expression,
3110
+ ];
3111
+ }
3112
+
3113
+ /**
3114
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_is_arithmetic_binary_expression' | '_is_range_expression' | '_is_switch_expression' | '_is_with_expression' | '_pattern_unary_expression' | 'binary_expression' | 'range_expression' | 'switch_expression' | 'with_expression'>} $
3115
+ */
3116
+ function constantExpressionRoots($) {
3117
+ return [
3118
+ $._pattern_unary_expression,
3119
+ alias($._is_arithmetic_binary_expression, $.binary_expression),
3120
+ alias($._is_range_expression, $.range_expression),
3121
+ alias($._is_switch_expression, $.switch_expression),
3122
+ alias($._is_with_expression, $.with_expression),
3123
+ ];
3124
+ }
3125
+
3126
+ /**
3127
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_switch_expression_body'>} $
3128
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
3129
+ */
3130
+ function switchExpression($, receiver) {
3131
+ return prec(PREC.SWITCH, seq(receiver, 'switch', $._switch_expression_body));
3132
+ }
3133
+
3134
+ /**
3135
+ * @param {import('@willbooster/web-tree-sitter/dsl').GrammarSymbols<'_with_body'>} $
3136
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} receiver
3137
+ */
3138
+ function withExpression($, receiver) {
3139
+ return prec.left(PREC.WITH, seq(receiver, 'with', $._with_body));
3140
+ }
3141
+
3142
+ /**
3143
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} left
3144
+ * @param {import('@willbooster/web-tree-sitter/dsl').Rule} right
3145
+ * @param {boolean} [prefix]
3146
+ */
3147
+ function rangeExpression(left, right, prefix = true) {
3148
+ return prec.right(PREC.RANGE, seq(prefix ? optional(left) : left, '..', optional(right)));
3149
+ }
3150
+
3151
+ /** @param {import('@willbooster/web-tree-sitter/dsl').Rule} operand */
3152
+ function prefixRangeExpression(operand) {
3153
+ return prec.right(PREC.RANGE, seq('..', optional(operand)));
3154
+ }
3155
+
3156
+ function statementEnd() {
3157
+ return choice(';', alias(sym('_statement_end'), ';'));
3158
+ }
3159
+
3160
+ function blockEnd() {
3161
+ return choice('}', alias(sym('_block_end'), '}'));
3162
+ }
3163
+
3164
+ function ampersandOperator() {
3165
+ return alias(sym('_ampersand_operator'), '&');
3166
+ }