@willbooster/tree-sitter-c-sharp 0.0.0-placeholder.0 → 1.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 ADDED
@@ -0,0 +1,1879 @@
1
+ /**
2
+ * @file C# grammar for tree-sitter
3
+ * @author Max Brunsfeld <maxbrunsfeld@gmail.com>
4
+ * @author Damien Guard <damieng@gmail.com>
5
+ * @author Amaan Qureshi <amaanq12@gmail.com>
6
+ * @license MIT
7
+ */
8
+
9
+ /// <reference types="tree-sitter-cli/dsl" />
10
+ // @ts-check
11
+
12
+ const PREC = {
13
+ GENERIC: 19,
14
+ DOT: 18,
15
+ INVOCATION: 18,
16
+ POSTFIX: 18,
17
+ PREFIX: 17,
18
+ UNARY: 17,
19
+ CAST: 17,
20
+ RANGE: 16,
21
+ SWITCH: 15,
22
+ WITH: 14,
23
+ MULT: 13,
24
+ ADD: 12,
25
+ SHIFT: 11,
26
+ REL: 10,
27
+ EQUAL: 9,
28
+ AND: 8,
29
+ XOR: 7,
30
+ OR: 6,
31
+ LOGICAL_AND: 5,
32
+ LOGICAL_OR: 4,
33
+ COALESCING: 3,
34
+ CONDITIONAL: 2,
35
+ ASSIGN: 1,
36
+ SELECT: 0,
37
+ };
38
+
39
+ const decimalDigitSequence = /([0-9][0-9_]*[0-9]|[0-9])/;
40
+
41
+ const stringEncoding = /(u|U)8/;
42
+
43
+ // oxlint-disable-next-line unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads grammar.js as CommonJS.
44
+ module.exports = grammar({
45
+ name: 'c_sharp',
46
+
47
+ conflicts: ($) => [
48
+ [$._simple_name, $.generic_name],
49
+ [$._simple_name, $.type_parameter],
50
+ [$._simple_name, $.subpattern],
51
+
52
+ [$.tuple_element, $.type_pattern],
53
+ [$.tuple_element, $.using_variable_declarator],
54
+ [$.tuple_element, $.declaration_expression],
55
+
56
+ [$.tuple_pattern, $.parameter],
57
+ [$.tuple_pattern, $._simple_name],
58
+
59
+ [$.lvalue_expression, $._name],
60
+ [$.parameter, $.lvalue_expression],
61
+ // C# 14 null-conditional assignment: `obj?.x = v` requires
62
+ // `conditional_access_expression` to appear in both lvalue and
63
+ // non-lvalue contexts. Tree-sitter needs GLR for the decision.
64
+ [$.lvalue_expression, $.non_lvalue_expression],
65
+
66
+ [$.type, $.attribute],
67
+ [$.type, $.nullable_type],
68
+ [$.type, $.nullable_type, $.array_creation_expression],
69
+ [$.type, $._array_base_type],
70
+ [$.type, $._array_base_type, $.array_creation_expression],
71
+ [$.type, $.array_creation_expression],
72
+ [$.type, $._pointer_base_type],
73
+
74
+ [$.qualified_name, $.member_access_expression],
75
+ [$.qualified_name, $.explicit_interface_specifier],
76
+
77
+ [$._array_base_type, $.stackalloc_expression],
78
+
79
+ [$.constant_pattern, $.non_lvalue_expression],
80
+ [$.constant_pattern, $._expression_statement_expression],
81
+ [$.constant_pattern, $.lvalue_expression],
82
+ [$.constant_pattern, $._name],
83
+ [$.constant_pattern, $.lvalue_expression, $._name],
84
+
85
+ [$.type, $._name_invocation_pattern, $.recursive_pattern],
86
+ [$.attribute, $.type, $._name_invocation_pattern, $.recursive_pattern],
87
+
88
+ [$.parenthesized_pattern, $._parenthesized_pattern_with_designation],
89
+
90
+ [$.expression_element, $.argument],
91
+ [$.spread_element, $.range_expression],
92
+ [$.collection_expression, $.list_pattern],
93
+
94
+ [$._reserved_identifier, $.modifier],
95
+ [$._reserved_identifier, $.scoped_type],
96
+ [$._reserved_identifier, $.implicit_type],
97
+ [$._reserved_identifier, $.from_clause],
98
+ [$._reserved_identifier, $.implicit_type, $.var_pattern],
99
+ [$._reserved_identifier, $.type_parameter_constraint],
100
+ [$._reserved_identifier, $.parameter, $.scoped_type],
101
+ [$._reserved_identifier, $.parameter],
102
+ [$._simple_name, $.parameter],
103
+ [$.tuple_element, $.parameter, $.declaration_expression],
104
+ [$.parameter, $.tuple_element],
105
+
106
+ [$.event_declaration, $.variable_declarator],
107
+
108
+ [$.base_list],
109
+ [$.using_directive, $.modifier],
110
+ [$.using_directive],
111
+
112
+ [$._constructor_declaration_initializer, $._simple_name],
113
+
114
+ // For C# 14 extension declarations: `extension(scoped X x)` —
115
+ // `scoped` can be a parameter modifier, a scoped_type, or a
116
+ // reserved identifier (when there's no further type). Keep all
117
+ // three alive until later tokens disambiguate.
118
+ [$.receiver_parameter, $.scoped_type, $._reserved_identifier],
119
+ ],
120
+
121
+ externals: ($) => [
122
+ $._optional_semi,
123
+ $.interpolation_regular_start,
124
+ $.interpolation_verbatim_start,
125
+ $.interpolation_raw_start,
126
+ $.interpolation_start_quote,
127
+ $.interpolation_end_quote,
128
+ $.interpolation_open_brace,
129
+ $.interpolation_close_brace,
130
+ $.interpolation_string_content,
131
+ $.raw_string_start,
132
+ $.raw_string_end,
133
+ $.raw_string_content,
134
+ // C# 14: emitted by the scanner at '(' when forward-scanning shows a
135
+ // simple-lambda parameter list (at least one element has a parameter
136
+ // modifier) closed by ')=>'.
137
+ $._lambda_paren_open,
138
+ ],
139
+
140
+ extras: ($) => [
141
+ /[\s\u00A0\uFEFF\u3000]+/,
142
+ $.comment,
143
+ $.preproc_region,
144
+ $.preproc_endregion,
145
+ $.preproc_line,
146
+ $.preproc_pragma,
147
+ $.preproc_nullable,
148
+ $.preproc_error,
149
+ $.preproc_warning,
150
+ $.preproc_define,
151
+ $.preproc_undef,
152
+ ],
153
+
154
+ inline: ($) => [
155
+ $._namespace_member_declaration,
156
+ $._object_creation_type,
157
+ $._nullable_base_type,
158
+ $._parameter_type_with_modifiers,
159
+ $._top_level_item_no_statement,
160
+ ],
161
+
162
+ precedences: ($) => [
163
+ [$._anonymous_object_member_declarator, $._simple_name],
164
+ [$.block, $.initializer_expression],
165
+ ],
166
+
167
+ supertypes: ($) => [
168
+ $.declaration,
169
+ $.expression,
170
+ $.non_lvalue_expression,
171
+ $.lvalue_expression,
172
+ $.literal,
173
+ $.statement,
174
+ $.type,
175
+ $.type_declaration,
176
+ $.pattern,
177
+ ],
178
+
179
+ word: ($) => $._identifier_token,
180
+
181
+ rules: {
182
+ compilation_unit: ($) => seq(optional($.shebang_directive), repeat($._top_level_item)),
183
+
184
+ _top_level_item: ($) => prec(2, choice($._top_level_item_no_statement, $.global_statement)),
185
+
186
+ _top_level_item_no_statement: ($) =>
187
+ choice(
188
+ $.extern_alias_directive,
189
+ $.using_directive,
190
+ $.global_attribute,
191
+ alias($.preproc_if_in_top_level, $.preproc_if),
192
+ $._namespace_member_declaration,
193
+ $.file_scoped_namespace_declaration
194
+ ),
195
+
196
+ global_statement: ($) => prec(1, $.statement),
197
+
198
+ extern_alias_directive: ($) => seq('extern', 'alias', field('name', $.identifier), ';'),
199
+
200
+ using_directive: ($) =>
201
+ seq(
202
+ optional('global'),
203
+ 'using',
204
+ choice(
205
+ seq(optional('unsafe'), field('name', $.identifier), '=', $.type),
206
+ seq(repeat(choice('static', 'unsafe')), $._name)
207
+ ),
208
+ ';'
209
+ ),
210
+
211
+ global_attribute: ($) => seq('[', choice('assembly', 'module'), ':', commaSep1($.attribute), optional(','), ']'),
212
+
213
+ attribute: ($) => seq(field('name', $._name), optional($.attribute_argument_list)),
214
+
215
+ attribute_argument_list: ($) => prec(-1, seq('(', commaSep($.attribute_argument), ')')),
216
+
217
+ attribute_argument: ($) =>
218
+ prec(-1, seq(optional(prec(1, seq(field('name', $.identifier), choice(':', '=')))), $.expression)),
219
+
220
+ attribute_list: ($) => seq('[', optional($.attribute_target_specifier), commaSep1($.attribute), optional(','), ']'),
221
+
222
+ _attribute_list: ($) => choice($.attribute_list, $.preproc_if_in_attribute_list),
223
+
224
+ // Higher precedence than `_reserved_identifier`: when both interpretations
225
+ // are valid (e.g. `[field :` could be `_reserved_identifier` followed by
226
+ // bogus `:`, or `attribute_target_specifier`), prefer the target-specifier
227
+ // reading. `_reserved_identifier` still wins when no `:` follows, so
228
+ // `[field]` continues to parse as collection_expression with identifier.
229
+ attribute_target_specifier: () =>
230
+ prec(1, seq(choice('field', 'event', 'method', 'param', 'property', 'return', 'type', 'typevar'), ':')),
231
+
232
+ _namespace_member_declaration: ($) => choice($.namespace_declaration, $.type_declaration),
233
+
234
+ namespace_declaration: ($) =>
235
+ seq('namespace', field('name', $._name), field('body', $.declaration_list), $._optional_semi),
236
+
237
+ file_scoped_namespace_declaration: ($) => seq('namespace', field('name', $._name), ';'),
238
+
239
+ type_declaration: ($) =>
240
+ choice(
241
+ $.class_declaration,
242
+ $.struct_declaration,
243
+ $.enum_declaration,
244
+ $.interface_declaration,
245
+ $.delegate_declaration,
246
+ $.record_declaration
247
+ ),
248
+
249
+ class_declaration: ($) => seq($._class_declaration_initializer, $._declaration_list_body),
250
+
251
+ _class_declaration_initializer: ($) =>
252
+ seq(
253
+ repeat($._attribute_list),
254
+ repeat($.modifier),
255
+ 'class',
256
+ field('name', $.identifier),
257
+ repeat(choice($.type_parameter_list, $.parameter_list, $.base_list)),
258
+ repeat($.type_parameter_constraints_clause)
259
+ ),
260
+
261
+ struct_declaration: ($) => seq($._struct_declaration_initializer, $._declaration_list_body),
262
+
263
+ _struct_declaration_initializer: ($) =>
264
+ seq(
265
+ repeat($._attribute_list),
266
+ repeat($.modifier),
267
+ optional('ref'),
268
+ 'struct',
269
+ field('name', $.identifier),
270
+ repeat(choice($.type_parameter_list, $.parameter_list, $.base_list)),
271
+ repeat($.type_parameter_constraints_clause)
272
+ ),
273
+
274
+ enum_declaration: ($) =>
275
+ seq(
276
+ $._enum_declaration_initializer,
277
+ choice(seq(field('body', $.enum_member_declaration_list), $._optional_semi), ';')
278
+ ),
279
+
280
+ _enum_declaration_initializer: ($) =>
281
+ seq(repeat($._attribute_list), repeat($.modifier), 'enum', field('name', $.identifier), optional($.base_list)),
282
+
283
+ enum_member_declaration_list: ($) =>
284
+ seq(
285
+ '{',
286
+ commaSep(choice($.enum_member_declaration, alias($.preproc_if_in_enum_member_declaration, $.preproc_if))),
287
+ optional(','),
288
+ '}'
289
+ ),
290
+
291
+ enum_member_declaration: ($) =>
292
+ seq(repeat($._attribute_list), field('name', $.identifier), optional(seq('=', field('value', $.expression)))),
293
+
294
+ interface_declaration: ($) => seq($._interface_declaration_initializer, $._declaration_list_body),
295
+
296
+ _interface_declaration_initializer: ($) =>
297
+ seq(
298
+ repeat($._attribute_list),
299
+ repeat($.modifier),
300
+ 'interface',
301
+ field('name', $.identifier),
302
+ field('type_parameters', optional($.type_parameter_list)),
303
+ optional($.base_list),
304
+ repeat($.type_parameter_constraints_clause)
305
+ ),
306
+
307
+ delegate_declaration: ($) =>
308
+ seq($._delegate_declaration_initializer, repeat($.type_parameter_constraints_clause), ';'),
309
+
310
+ _delegate_declaration_initializer: ($) =>
311
+ seq(
312
+ repeat($._attribute_list),
313
+ repeat($.modifier),
314
+ 'delegate',
315
+ field('type', $.type),
316
+ field('name', $.identifier),
317
+ field('type_parameters', optional($.type_parameter_list)),
318
+ field('parameters', $.parameter_list)
319
+ ),
320
+
321
+ record_declaration: ($) => seq($._record_declaration_initializer, $._declaration_list_body),
322
+
323
+ _record_declaration_initializer: ($) =>
324
+ seq(
325
+ repeat($._attribute_list),
326
+ repeat($.modifier),
327
+ 'record',
328
+ optional(choice('class', 'struct')),
329
+ field('name', $.identifier),
330
+ repeat(choice($.type_parameter_list, $.parameter_list)),
331
+ optional(alias($.record_base, $.base_list)),
332
+ repeat($.type_parameter_constraints_clause)
333
+ ),
334
+
335
+ record_base: ($) =>
336
+ choice(
337
+ seq(':', commaSep1($._name)),
338
+ seq(':', $.primary_constructor_base_type, optional(seq(',', commaSep1($._name))))
339
+ ),
340
+
341
+ _declaration_list_body: ($) => choice(seq(field('body', $.declaration_list), $._optional_semi), ';'),
342
+
343
+ primary_constructor_base_type: ($) => seq(field('type', $._name), $.argument_list),
344
+
345
+ modifier: () =>
346
+ prec.right(
347
+ choice(
348
+ 'abstract',
349
+ 'async',
350
+ 'const',
351
+ 'extern',
352
+ 'file',
353
+ 'fixed',
354
+ 'internal',
355
+ 'new',
356
+ 'override',
357
+ 'partial',
358
+ 'private',
359
+ 'protected',
360
+ 'public',
361
+ 'readonly',
362
+ 'required',
363
+ // 'ref', // `ref` as a modifier can only be used on struct declarations. Other than that it's a ref type or a ref parameter in a declaration.
364
+ // 'scoped', // `scoped` is either part of a scoped type or a scoped parameter. Both of which are handled outside of `modifier`.
365
+ 'sealed',
366
+ 'static',
367
+ 'unsafe',
368
+ 'virtual',
369
+ 'volatile'
370
+ )
371
+ ),
372
+
373
+ type_parameter_list: ($) => seq('<', commaSep1($.type_parameter), '>'),
374
+
375
+ type_parameter: ($) => seq(repeat($._attribute_list), optional(choice('in', 'out')), field('name', $.identifier)),
376
+
377
+ base_list: ($) => seq(':', commaSep1(seq($.type, optional($.argument_list)))),
378
+
379
+ type_parameter_constraints_clause: ($) => seq('where', $.identifier, ':', commaSep1($.type_parameter_constraint)),
380
+
381
+ type_parameter_constraint: ($) =>
382
+ choice(
383
+ seq('class', optional('?')),
384
+ 'struct',
385
+ 'notnull',
386
+ 'unmanaged',
387
+ $.constructor_constraint,
388
+ field('type', $.type)
389
+ ),
390
+
391
+ constructor_constraint: () => seq('new', '(', ')'),
392
+
393
+ operator_declaration: ($) =>
394
+ seq(
395
+ repeat($._attribute_list),
396
+ repeat($.modifier),
397
+ field('type', $.type),
398
+ optional($.explicit_interface_specifier),
399
+ 'operator',
400
+ optional('checked'),
401
+ field(
402
+ 'operator',
403
+ choice(
404
+ '!',
405
+ '~',
406
+ '++',
407
+ '--',
408
+ 'true',
409
+ 'false',
410
+ '+',
411
+ '-',
412
+ '*',
413
+ '/',
414
+ '%',
415
+ '^',
416
+ '|',
417
+ '&',
418
+ '<<',
419
+ '>>',
420
+ '>>>',
421
+ '==',
422
+ '!=',
423
+ '>',
424
+ '<',
425
+ '>=',
426
+ '<=',
427
+ // C# 14: user-defined compound assignment operators.
428
+ // https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#user-defined-compound-assignment-operators
429
+ '+=',
430
+ '-=',
431
+ '*=',
432
+ '/=',
433
+ '%=',
434
+ '^=',
435
+ '|=',
436
+ '&=',
437
+ '<<=',
438
+ '>>=',
439
+ '>>>='
440
+ )
441
+ ),
442
+ field('parameters', $.parameter_list),
443
+ $._function_body
444
+ ),
445
+
446
+ conversion_operator_declaration: ($) =>
447
+ seq(
448
+ repeat($._attribute_list),
449
+ repeat($.modifier),
450
+ choice('implicit', 'explicit'),
451
+ repeat1(
452
+ choice(
453
+ // Intentionally structured this way for grammar size
454
+ $.explicit_interface_specifier,
455
+ 'operator',
456
+ 'checked'
457
+ )
458
+ ),
459
+ field('type', $.type),
460
+ field('parameters', $.parameter_list),
461
+ $._function_body
462
+ ),
463
+
464
+ declaration_list: ($) => seq('{', repeat($.declaration), '}'),
465
+
466
+ declaration: ($) =>
467
+ choice(
468
+ $.class_declaration,
469
+ $.struct_declaration,
470
+ $.enum_declaration,
471
+ $.delegate_declaration,
472
+ $.field_declaration,
473
+ $.method_declaration,
474
+ $.event_declaration,
475
+ $.event_field_declaration,
476
+ $.record_declaration,
477
+ $.constructor_declaration,
478
+ $.destructor_declaration,
479
+ $.indexer_declaration,
480
+ $.interface_declaration,
481
+ $.namespace_declaration,
482
+ $.operator_declaration,
483
+ $.conversion_operator_declaration,
484
+ $.property_declaration,
485
+ $.using_directive,
486
+ $.preproc_if,
487
+ $.extension_declaration
488
+ ),
489
+
490
+ // C# 14: extension declarations introduce extension methods, properties,
491
+ // and operators with a shared receiver inside a non-generic static class.
492
+ // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-14.0/extensions
493
+ //
494
+ // extension_declaration:
495
+ // 'extension' type_parameter_list? '(' receiver_parameter ')'
496
+ // type_parameter_constraints_clause* extension_body
497
+ // extension_body: '{' extension_member_declaration* '}' ';'?
498
+ // extension_member_declaration:
499
+ // method_declaration | property_declaration | operator_declaration
500
+ // receiver_parameter: attributes? parameter_modifiers? type identifier?
501
+ //
502
+ // `extension` is contextual; it is recognized as the start of an
503
+ // extension declaration when followed by `<` or `(` in declaration
504
+ // position. Use prec.dynamic so an identifier named `extension` in
505
+ // other positions still parses.
506
+ extension_declaration: ($) =>
507
+ prec.dynamic(
508
+ 1,
509
+ seq(
510
+ repeat($._attribute_list),
511
+ 'extension',
512
+ optional($.type_parameter_list),
513
+ '(',
514
+ $.receiver_parameter,
515
+ ')',
516
+ repeat($.type_parameter_constraints_clause),
517
+ $.extension_body
518
+ )
519
+ ),
520
+
521
+ receiver_parameter: ($) =>
522
+ seq(repeat($._attribute_list), $._parameter_type_with_modifiers, optional(field('name', $.identifier))),
523
+
524
+ extension_body: ($) => seq('{', repeat($._extension_member_declaration), '}', optional(';')),
525
+
526
+ _extension_member_declaration: ($) => choice($.method_declaration, $.property_declaration, $.operator_declaration),
527
+
528
+ field_declaration: ($) => seq(repeat($._attribute_list), repeat($.modifier), $.variable_declaration, ';'),
529
+
530
+ constructor_declaration: ($) => seq($._constructor_declaration_initializer, $._function_body),
531
+
532
+ _constructor_declaration_initializer: ($) =>
533
+ seq(
534
+ repeat($._attribute_list),
535
+ repeat($.modifier),
536
+ field('name', $.identifier),
537
+ field('parameters', $.parameter_list),
538
+ optional($.constructor_initializer)
539
+ ),
540
+
541
+ destructor_declaration: ($) =>
542
+ seq(
543
+ repeat($._attribute_list),
544
+ optional('extern'),
545
+ '~',
546
+ field('name', $.identifier),
547
+ field('parameters', $.parameter_list),
548
+ $._function_body
549
+ ),
550
+
551
+ method_declaration: ($) =>
552
+ seq(
553
+ repeat($._attribute_list),
554
+ repeat($.modifier),
555
+ field('returns', $.type),
556
+ optional($.explicit_interface_specifier),
557
+ field('name', $.identifier),
558
+ field('type_parameters', optional($.type_parameter_list)),
559
+ field('parameters', $.parameter_list),
560
+ repeat($.type_parameter_constraints_clause),
561
+ $._function_body
562
+ ),
563
+
564
+ event_declaration: ($) =>
565
+ seq(
566
+ repeat($._attribute_list),
567
+ repeat($.modifier),
568
+ 'event',
569
+ field('type', $.type),
570
+ optional($.explicit_interface_specifier),
571
+ field('name', $.identifier),
572
+ choice(field('accessors', $.accessor_list), ';')
573
+ ),
574
+
575
+ event_field_declaration: ($) =>
576
+ prec.dynamic(1, seq(repeat($._attribute_list), repeat($.modifier), 'event', $.variable_declaration, ';')),
577
+
578
+ accessor_list: ($) => seq('{', repeat($.accessor_declaration), '}'),
579
+
580
+ accessor_declaration: ($) =>
581
+ seq(
582
+ repeat($._attribute_list),
583
+ repeat($.modifier),
584
+ field('name', choice('get', 'set', 'add', 'remove', 'init', $.identifier)),
585
+ $._function_body
586
+ ),
587
+
588
+ indexer_declaration: ($) =>
589
+ seq(
590
+ repeat($._attribute_list),
591
+ repeat($.modifier),
592
+ field('type', $.type),
593
+ optional($.explicit_interface_specifier),
594
+ 'this',
595
+ field('parameters', $.bracketed_parameter_list),
596
+ choice(field('accessors', $.accessor_list), seq(field('value', $.arrow_expression_clause), ';'))
597
+ ),
598
+
599
+ bracketed_parameter_list: ($) => seq('[', sep(choice($.parameter, $._parameter_array), ','), ']'),
600
+
601
+ property_declaration: ($) =>
602
+ seq(
603
+ repeat($._attribute_list),
604
+ repeat($.modifier),
605
+ field('type', $.type),
606
+ optional($.explicit_interface_specifier),
607
+ field('name', $.identifier),
608
+ choice(
609
+ seq(field('accessors', $.accessor_list), optional(seq('=', field('value', $.expression), ';'))),
610
+ seq(field('value', $.arrow_expression_clause), ';')
611
+ )
612
+ ),
613
+
614
+ explicit_interface_specifier: ($) => prec(PREC.DOT, seq($._name, '.')),
615
+
616
+ parameter_list: ($) => seq('(', sep(choice($.parameter, $._parameter_array), ','), ')'),
617
+
618
+ _parameter_type_with_modifiers: ($) =>
619
+ seq(
620
+ repeat(prec.left(alias(choice('this', 'scoped', 'ref', 'out', 'in', 'readonly'), $.modifier))),
621
+ field('type', $.type)
622
+ ),
623
+
624
+ parameter: ($) =>
625
+ seq(
626
+ repeat($._attribute_list),
627
+ optional($._parameter_type_with_modifiers),
628
+ field('name', $.identifier),
629
+ optional(seq('=', $.expression))
630
+ ),
631
+
632
+ _parameter_array: ($) =>
633
+ seq(repeat($._attribute_list), 'params', field('type', $.type), field('name', $.identifier)),
634
+
635
+ constructor_initializer: ($) => seq(':', choice('base', 'this'), $.argument_list),
636
+
637
+ argument_list: ($) => seq('(', commaSep($.argument), ')'),
638
+
639
+ tuple_pattern: ($) => seq('(', commaSep1(choice(field('name', $.identifier), $.discard, $.tuple_pattern)), ')'),
640
+
641
+ argument: ($) =>
642
+ prec(
643
+ 1,
644
+ seq(
645
+ optional(seq(field('name', $.identifier), ':')),
646
+ optional(choice('ref', 'out', 'in')),
647
+ choice($.expression, $.declaration_expression)
648
+ )
649
+ ),
650
+
651
+ block: ($) => seq('{', repeat($.statement), '}'),
652
+
653
+ arrow_expression_clause: ($) => seq('=>', $.expression),
654
+
655
+ _function_body: ($) => choice(field('body', $.block), seq(field('body', $.arrow_expression_clause), ';'), ';'),
656
+
657
+ variable_declaration: ($) => seq(field('type', $.type), commaSep1($.variable_declarator)),
658
+
659
+ using_variable_declaration: ($) =>
660
+ seq(field('type', $.type), commaSep1(alias($.using_variable_declarator, $.variable_declarator))),
661
+
662
+ variable_declarator: ($) =>
663
+ seq(
664
+ choice(field('name', $.identifier), $.tuple_pattern),
665
+ optional($.bracketed_argument_list),
666
+ optional(seq('=', $.expression))
667
+ ),
668
+
669
+ using_variable_declarator: ($) => seq(field('name', $.identifier), optional(seq('=', $.expression))),
670
+
671
+ bracketed_argument_list: ($) => seq('[', commaSep1($.argument), optional(','), ']'),
672
+
673
+ qualified_identifier: ($) => sep1($.identifier, '.'),
674
+
675
+ _name: ($) => choice($.alias_qualified_name, $.qualified_name, $._simple_name),
676
+
677
+ alias_qualified_name: ($) => seq(field('alias', $.identifier), '::', field('name', $._simple_name)),
678
+
679
+ _simple_name: ($) => choice($.identifier, $.generic_name),
680
+
681
+ qualified_name: ($) => prec(PREC.DOT, seq(field('qualifier', $._name), '.', field('name', $._simple_name))),
682
+
683
+ generic_name: ($) => seq($.identifier, $.type_argument_list),
684
+
685
+ type_argument_list: ($) => seq('<', choice(repeat(','), commaSep1($.type)), '>'),
686
+
687
+ type: ($) =>
688
+ choice(
689
+ $.implicit_type,
690
+ $.array_type,
691
+ $._name,
692
+ $.nullable_type,
693
+ $.pointer_type,
694
+ $.function_pointer_type,
695
+ $.predefined_type,
696
+ $.tuple_type,
697
+ $.ref_type,
698
+ $.scoped_type
699
+ ),
700
+
701
+ implicit_type: () => prec.dynamic(1, 'var'),
702
+
703
+ array_type: ($) => seq(field('type', $._array_base_type), field('rank', $.array_rank_specifier)),
704
+
705
+ _array_base_type: ($) =>
706
+ choice(
707
+ $.array_type,
708
+ $._name,
709
+ $.nullable_type,
710
+ $.pointer_type,
711
+ $.function_pointer_type,
712
+ $.predefined_type,
713
+ $.tuple_type
714
+ ),
715
+
716
+ array_rank_specifier: ($) => seq('[', commaSep(optional($.expression)), ']'),
717
+
718
+ nullable_type: ($) => seq(field('type', $._nullable_base_type), '?'),
719
+
720
+ _nullable_base_type: ($) => choice($.array_type, $._name, $.predefined_type, $.tuple_type),
721
+
722
+ pointer_type: ($) => seq(field('type', $._pointer_base_type), '*'),
723
+
724
+ _pointer_base_type: ($) =>
725
+ choice($._name, $.nullable_type, $.pointer_type, $.function_pointer_type, $.predefined_type, $.tuple_type),
726
+
727
+ function_pointer_type: ($) =>
728
+ seq(
729
+ 'delegate',
730
+ '*',
731
+ optional($.calling_convention),
732
+ '<',
733
+ repeat(seq($.function_pointer_parameter, ',')),
734
+ field('returns', $.type),
735
+ '>'
736
+ ),
737
+
738
+ calling_convention: ($) =>
739
+ choice(
740
+ 'managed',
741
+ seq(
742
+ 'unmanaged',
743
+ optional(seq('[', commaSep1(choice('Cdecl', 'Stdcall', 'Thiscall', 'Fastcall', $.identifier)), ']'))
744
+ )
745
+ ),
746
+
747
+ function_pointer_parameter: ($) => seq(optional(choice('ref', 'out', 'in')), field('type', $._ref_base_type)),
748
+
749
+ predefined_type: () =>
750
+ token(
751
+ choice(
752
+ 'bool',
753
+ 'byte',
754
+ 'char',
755
+ 'decimal',
756
+ 'double',
757
+ 'float',
758
+ 'int',
759
+ 'long',
760
+ 'object',
761
+ 'sbyte',
762
+ 'short',
763
+ 'string',
764
+ 'uint',
765
+ 'ulong',
766
+ 'ushort',
767
+ 'nint',
768
+ 'nuint',
769
+ 'void'
770
+ )
771
+ ),
772
+
773
+ ref_type: ($) => seq('ref', optional('readonly'), field('type', $.type)),
774
+
775
+ _ref_base_type: ($) =>
776
+ choice(
777
+ $.implicit_type,
778
+ $._name,
779
+ $.nullable_type,
780
+ $.array_type,
781
+ $.pointer_type,
782
+ $.function_pointer_type,
783
+ $.predefined_type,
784
+ $.tuple_type
785
+ ),
786
+
787
+ scoped_type: ($) => seq('scoped', field('type', $._scoped_base_type)),
788
+
789
+ _scoped_base_type: ($) => choice($._name, $.ref_type),
790
+
791
+ tuple_type: ($) => seq('(', commaSep2($.tuple_element), ')'),
792
+
793
+ tuple_element: ($) => seq(field('type', $.type), field('name', optional($.identifier))),
794
+
795
+ statement: ($) =>
796
+ prec(
797
+ 1,
798
+ choice(
799
+ $.block,
800
+ $.break_statement,
801
+ $.checked_statement,
802
+ $.continue_statement,
803
+ $.do_statement,
804
+ $.empty_statement,
805
+ $.expression_statement,
806
+ $.fixed_statement,
807
+ $.for_statement,
808
+ $.return_statement,
809
+ $.lock_statement,
810
+ $.yield_statement,
811
+ $.switch_statement,
812
+ $.throw_statement,
813
+ $.try_statement,
814
+ $.unsafe_statement,
815
+ $.using_statement,
816
+ $.foreach_statement,
817
+ $.goto_statement,
818
+ $.labeled_statement,
819
+ $.if_statement,
820
+ $.while_statement,
821
+ $.local_declaration_statement,
822
+ $.local_function_statement,
823
+ alias($.preproc_if_in_top_level, $.preproc_if)
824
+ )
825
+ ),
826
+
827
+ break_statement: () => seq('break', ';'),
828
+
829
+ checked_statement: ($) => seq(choice('checked', 'unchecked'), $.block),
830
+
831
+ continue_statement: () => seq('continue', ';'),
832
+
833
+ do_statement: ($) =>
834
+ seq('do', field('body', $.statement), 'while', '(', field('condition', $.expression), ')', ';'),
835
+
836
+ empty_statement: () => ';',
837
+
838
+ expression_statement: ($) => seq($._expression_statement_expression, ';'),
839
+
840
+ fixed_statement: ($) => seq('fixed', '(', $.variable_declaration, ')', $.statement),
841
+
842
+ for_statement: ($) => seq('for', $._for_statement_conditions, field('body', $.statement)),
843
+
844
+ _for_statement_conditions: ($) =>
845
+ seq(
846
+ '(',
847
+ field('initializer', optional(choice($.variable_declaration, commaSep1($.expression)))),
848
+ ';',
849
+ field('condition', optional($.expression)),
850
+ ';',
851
+ field('update', optional(commaSep1($.expression))),
852
+ ')'
853
+ ),
854
+
855
+ return_statement: ($) => seq('return', optional($.expression), ';'),
856
+
857
+ lock_statement: ($) => seq('lock', '(', $.expression, ')', $.statement),
858
+
859
+ yield_statement: ($) => seq('yield', choice(seq('return', $.expression), 'break'), ';'),
860
+
861
+ switch_statement: ($) =>
862
+ seq(
863
+ 'switch',
864
+ choice(seq('(', field('value', $.expression), ')'), field('value', $.tuple_expression)),
865
+ field('body', $.switch_body)
866
+ ),
867
+
868
+ switch_body: ($) => seq('{', repeat($.switch_section), '}'),
869
+
870
+ switch_section: ($) =>
871
+ prec.left(
872
+ seq(
873
+ choice(seq('case', choice($.expression, seq($.pattern, optional($.when_clause)))), 'default'),
874
+ ':',
875
+ repeat($.statement)
876
+ )
877
+ ),
878
+
879
+ throw_statement: ($) => seq('throw', optional($.expression), ';'),
880
+
881
+ try_statement: ($) => seq('try', field('body', $.block), repeat($.catch_clause), optional($.finally_clause)),
882
+
883
+ catch_clause: ($) =>
884
+ seq('catch', repeat(choice($.catch_declaration, $.catch_filter_clause)), field('body', $.block)),
885
+
886
+ catch_declaration: ($) => seq('(', field('type', $.type), optional(field('name', $.identifier)), ')'),
887
+
888
+ catch_filter_clause: ($) => seq('when', '(', $.expression, ')'),
889
+
890
+ finally_clause: ($) => seq('finally', $.block),
891
+
892
+ unsafe_statement: ($) => seq('unsafe', $.block),
893
+
894
+ using_statement: ($) =>
895
+ seq(
896
+ optional('await'),
897
+ 'using',
898
+ '(',
899
+ choice(alias($.using_variable_declaration, $.variable_declaration), $.expression),
900
+ ')',
901
+ field('body', $.statement)
902
+ ),
903
+
904
+ foreach_statement: ($) => seq($._foreach_statement_initializer, field('body', $.statement)),
905
+
906
+ _foreach_statement_initializer: ($) =>
907
+ seq(
908
+ optional('await'),
909
+ 'foreach',
910
+ '(',
911
+ choice(
912
+ seq(field('type', $.type), field('left', choice($.identifier, $.tuple_pattern))),
913
+ field('left', $.expression)
914
+ ),
915
+ 'in',
916
+ field('right', $.expression),
917
+ ')'
918
+ ),
919
+
920
+ goto_statement: ($) => seq('goto', optional(choice('case', 'default')), optional($.expression), ';'),
921
+
922
+ labeled_statement: ($) => seq($.identifier, ':', $.statement),
923
+
924
+ if_statement: ($) =>
925
+ prec.right(
926
+ seq(
927
+ 'if',
928
+ '(',
929
+ field('condition', $.expression),
930
+ ')',
931
+ field('consequence', $.statement),
932
+ optional(seq('else', field('alternative', $.statement)))
933
+ )
934
+ ),
935
+
936
+ while_statement: ($) => seq('while', '(', field('condition', $.expression), ')', field('body', $.statement)),
937
+
938
+ local_declaration_statement: ($) =>
939
+ seq(optional('await'), optional('using'), repeat($.modifier), $.variable_declaration, ';'),
940
+
941
+ local_function_statement: ($) =>
942
+ seq($._local_function_declaration, repeat($.type_parameter_constraints_clause), $._function_body),
943
+
944
+ _local_function_declaration: ($) =>
945
+ seq(
946
+ repeat($._attribute_list),
947
+ repeat($.modifier),
948
+ field('type', $.type),
949
+ field('name', $.identifier),
950
+ field('type_parameters', optional($.type_parameter_list)),
951
+ field('parameters', $.parameter_list)
952
+ ),
953
+
954
+ pattern: ($) =>
955
+ choice(
956
+ $.constant_pattern,
957
+ $.declaration_pattern,
958
+ $.discard,
959
+ $.recursive_pattern,
960
+ $.var_pattern,
961
+ $.negated_pattern,
962
+ // This must come before plain parenthesized_pattern to create GLR conflict
963
+ prec.dynamic(1, alias($._parenthesized_pattern_with_designation, $.recursive_pattern)),
964
+ $.parenthesized_pattern,
965
+ $.relational_pattern,
966
+ $.or_pattern,
967
+ $.and_pattern,
968
+ $.list_pattern,
969
+ $.type_pattern
970
+ ),
971
+
972
+ // Uses '(' pattern ')' to create direct conflict with parenthesized_pattern
973
+ _parenthesized_pattern_with_designation: ($) => seq('(', $.pattern, ')', $._variable_designation),
974
+
975
+ constant_pattern: ($) =>
976
+ choice(
977
+ $.binary_expression,
978
+ $.default_expression,
979
+ $.interpolated_string_expression,
980
+ $.parenthesized_expression,
981
+ $.postfix_unary_expression,
982
+ $.prefix_unary_expression,
983
+ $.sizeof_expression,
984
+ $.tuple_expression,
985
+ $.typeof_expression,
986
+ $.member_access_expression,
987
+ alias($._name_invocation_pattern, $.invocation_expression),
988
+ alias($._complex_invocation_expression, $.invocation_expression),
989
+ $.cast_expression,
990
+ $._simple_name,
991
+ $.literal
992
+ ),
993
+
994
+ // Invocation with name - creates conflict with recursive_pattern's Name(positional_pattern_clause)
995
+ _name_invocation_pattern: ($) => seq(field('function', $._name), field('arguments', $.argument_list)),
996
+
997
+ // Invocation where function is not a simple name
998
+ _complex_invocation_expression: ($) =>
999
+ prec(
1000
+ PREC.INVOCATION,
1001
+ seq(
1002
+ field(
1003
+ 'function',
1004
+ choice(
1005
+ $.member_access_expression,
1006
+ $.element_access_expression,
1007
+ $.invocation_expression,
1008
+ $.parenthesized_expression,
1009
+ $.conditional_access_expression,
1010
+ $.cast_expression
1011
+ )
1012
+ ),
1013
+ field('arguments', $.argument_list)
1014
+ )
1015
+ ),
1016
+
1017
+ discard: () => '_',
1018
+
1019
+ parenthesized_pattern: ($) => seq('(', $.pattern, ')'),
1020
+
1021
+ var_pattern: ($) => seq('var', $._variable_designation),
1022
+
1023
+ // No associativity: tree-sitter 0.27 resolves a precedence tie with a right-associative reduce as a shift, which
1024
+ // makes `case int when x:` and `x is A or nameof(y)` read `when` and `(y)` as a variable designation.
1025
+ // A name such as `A.B` in `R(A.B or C)` also parses as a constant pattern. Without the negative dynamic
1026
+ // precedence, the reading depends on the other GLR stack versions alive at that point, so an incremental
1027
+ // reparse can switch it without reporting a changed range.
1028
+ type_pattern: ($) => prec.dynamic(-1, field('type', $.type)),
1029
+
1030
+ list_pattern: ($) =>
1031
+ prec.right(
1032
+ seq(
1033
+ '[',
1034
+ optional(seq(commaSep1(choice($.pattern, $.slice_pattern)), optional(','))),
1035
+ ']',
1036
+ optional($._variable_designation)
1037
+ )
1038
+ ),
1039
+
1040
+ // C# 11 slice pattern: `..` optionally followed by a subpattern that
1041
+ // binds the captured slice. `[a, .. var rest, z]`, `[..]` (bare),
1042
+ // `[.. List<int> rest]` (declaration_pattern), etc.
1043
+ slice_pattern: ($) => prec.right(seq('..', optional($.pattern))),
1044
+
1045
+ recursive_pattern: ($) =>
1046
+ prec.left(
1047
+ choice(
1048
+ // name followed by positional pattern WITH variable designation
1049
+ prec.dynamic(
1050
+ 1,
1051
+ seq(
1052
+ field('type', $._name),
1053
+ $.positional_pattern_clause,
1054
+ optional($.property_pattern_clause),
1055
+ $._variable_designation
1056
+ )
1057
+ ),
1058
+ // name followed by positional pattern WITHOUT variable designation
1059
+ prec.dynamic(
1060
+ -1,
1061
+ seq(field('type', $._name), $.positional_pattern_clause, optional($.property_pattern_clause))
1062
+ ),
1063
+ // positional pattern with variable designation (no type prefix)
1064
+ prec.dynamic(1, seq($.positional_pattern_clause, $._variable_designation)),
1065
+ // positional pattern without variable designation (no type prefix)
1066
+ $.positional_pattern_clause,
1067
+ // other type followed by pattern clauses (type is required here to avoid ambiguity)
1068
+ seq(
1069
+ field('type', $.type),
1070
+ choice(seq($.positional_pattern_clause, optional($.property_pattern_clause)), $.property_pattern_clause),
1071
+ optional($._variable_designation)
1072
+ ),
1073
+ // no type, just pattern clauses (no variable designation to avoid conflict with above)
1074
+ seq(
1075
+ choice(seq($.positional_pattern_clause, $.property_pattern_clause), $.property_pattern_clause),
1076
+ optional($._variable_designation)
1077
+ )
1078
+ )
1079
+ ),
1080
+
1081
+ positional_pattern_clause: ($) => prec(1, seq('(', optional(commaSep($.subpattern)), ')')),
1082
+
1083
+ property_pattern_clause: ($) => prec(1, seq('{', commaSep($.subpattern), optional(','), '}')),
1084
+
1085
+ subpattern: ($) => prec.right(seq(optional(choice(seq($.expression, ':'), seq($.identifier, ':'))), $.pattern)),
1086
+
1087
+ relational_pattern: ($) =>
1088
+ choice(seq('<', $.expression), seq('<=', $.expression), seq('>', $.expression), seq('>=', $.expression)),
1089
+
1090
+ negated_pattern: ($) => seq('not', $.pattern),
1091
+
1092
+ and_pattern: ($) =>
1093
+ prec.left(PREC.AND, seq(field('left', $.pattern), field('operator', 'and'), field('right', $.pattern))),
1094
+
1095
+ or_pattern: ($) =>
1096
+ prec.left(PREC.OR, seq(field('left', $.pattern), field('operator', 'or'), field('right', $.pattern))),
1097
+
1098
+ declaration_pattern: ($) => seq(field('type', $.type), $._variable_designation),
1099
+
1100
+ _variable_designation: ($) =>
1101
+ prec(1, choice($.discard, $.parenthesized_variable_designation, field('name', $.identifier))),
1102
+
1103
+ parenthesized_variable_designation: ($) => seq('(', commaSep($._variable_designation), ')'),
1104
+
1105
+ expression: ($) => choice($.non_lvalue_expression, $.lvalue_expression),
1106
+
1107
+ non_lvalue_expression: ($) =>
1108
+ choice(
1109
+ 'base',
1110
+ $.binary_expression,
1111
+ $.interpolated_string_expression,
1112
+ $.conditional_expression,
1113
+ $.conditional_access_expression,
1114
+ $.literal,
1115
+ $._expression_statement_expression,
1116
+ $.is_expression,
1117
+ $.is_pattern_expression,
1118
+ $.as_expression,
1119
+ $.cast_expression,
1120
+ $.checked_expression,
1121
+ $.collection_expression,
1122
+ $.switch_expression,
1123
+ $.throw_expression,
1124
+ $.default_expression,
1125
+ $.lambda_expression,
1126
+ $.with_expression,
1127
+ $.sizeof_expression,
1128
+ $.typeof_expression,
1129
+ $.makeref_expression,
1130
+ $.ref_expression,
1131
+ // Address-of (see `_address_of_expression` below): aliased to
1132
+ // `prefix_unary_expression` to preserve the public AST shape.
1133
+ // Parallels `_pointer_indirection_expression` (the `*` operator),
1134
+ // which is similarly aliased back into `lvalue_expression`.
1135
+ alias($._address_of_expression, $.prefix_unary_expression),
1136
+ $.reftype_expression,
1137
+ $.refvalue_expression,
1138
+ $.stackalloc_expression,
1139
+ $.range_expression,
1140
+ $.array_creation_expression,
1141
+ $.anonymous_method_expression,
1142
+ $.anonymous_object_creation_expression,
1143
+ $.implicit_array_creation_expression,
1144
+ $.implicit_object_creation_expression,
1145
+ $.implicit_stackalloc_expression,
1146
+ $.initializer_expression,
1147
+ $.query_expression,
1148
+ alias($.preproc_if_in_expression, $.preproc_if)
1149
+ ),
1150
+
1151
+ lvalue_expression: ($) =>
1152
+ choice(
1153
+ 'this',
1154
+ $.member_access_expression,
1155
+ $.tuple_expression,
1156
+ $._simple_name,
1157
+ $.element_access_expression,
1158
+ alias($.bracketed_argument_list, $.element_binding_expression),
1159
+ alias($._pointer_indirection_expression, $.prefix_unary_expression),
1160
+ alias($._parenthesized_lvalue_expression, $.parenthesized_expression),
1161
+ // C# 14 null-conditional assignment: `obj?.x = v`, `obj?[i] = v`.
1162
+ // https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#null-conditional-assignment
1163
+ $.conditional_access_expression
1164
+ ),
1165
+
1166
+ // Covers error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
1167
+ _expression_statement_expression: ($) =>
1168
+ choice(
1169
+ $.assignment_expression,
1170
+ $.invocation_expression,
1171
+ $.postfix_unary_expression,
1172
+ $.prefix_unary_expression,
1173
+ $.await_expression,
1174
+ $.object_creation_expression,
1175
+ $.parenthesized_expression
1176
+ ),
1177
+
1178
+ assignment_expression: ($) =>
1179
+ seq(
1180
+ field('left', $.lvalue_expression),
1181
+ field('operator', choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '<<=', '>>=', '>>>=', '??=')),
1182
+ field('right', $.expression)
1183
+ ),
1184
+
1185
+ binary_expression: ($) =>
1186
+ choice(
1187
+ ...[
1188
+ ['&&', PREC.LOGICAL_AND],
1189
+ ['||', PREC.LOGICAL_OR],
1190
+ ['>>', PREC.SHIFT],
1191
+ ['>>>', PREC.SHIFT],
1192
+ ['<<', PREC.SHIFT],
1193
+ ['&', PREC.AND],
1194
+ ['^', PREC.XOR],
1195
+ ['|', PREC.OR],
1196
+ ['+', PREC.ADD],
1197
+ ['-', PREC.ADD],
1198
+ ['*', PREC.MULT],
1199
+ ['/', PREC.MULT],
1200
+ ['%', PREC.MULT],
1201
+ ['<', PREC.REL],
1202
+ ['<=', PREC.REL],
1203
+ ['==', PREC.EQUAL],
1204
+ ['!=', PREC.EQUAL],
1205
+ ['>=', PREC.REL],
1206
+ ['>', PREC.REL],
1207
+ ].map(([operator, precedence]) =>
1208
+ prec.left(
1209
+ precedence,
1210
+ seq(
1211
+ field('left', $.expression),
1212
+ // @ts-ignore
1213
+ field('operator', operator),
1214
+ field('right', $.expression)
1215
+ )
1216
+ )
1217
+ ),
1218
+ prec.right(
1219
+ PREC.COALESCING,
1220
+ seq(field('left', $.expression), field('operator', '??'), field('right', $.expression))
1221
+ )
1222
+ ),
1223
+
1224
+ postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq($.expression, choice('++', '--', '!'))),
1225
+
1226
+ prefix_unary_expression: ($) =>
1227
+ prec(
1228
+ PREC.UNARY,
1229
+ seq(
1230
+ // `&` and `*` are intentionally NOT in this choice list:
1231
+ // * `&` → `_address_of_expression` (operand restricted to lvalue
1232
+ // — see comment on that rule for the #413 rationale)
1233
+ // * `*` → `_pointer_indirection_expression` (same shape,
1234
+ // restricted to lvalue, surfaced in `lvalue_expression`)
1235
+ // Both are aliased back to `prefix_unary_expression` so the
1236
+ // public AST is unaffected.
1237
+ choice('++', '--', '+', '-', '!', '~', '^'),
1238
+ $.expression
1239
+ )
1240
+ ),
1241
+
1242
+ _pointer_indirection_expression: ($) => prec.right(PREC.UNARY, seq('*', $.lvalue_expression)),
1243
+
1244
+ // Address-of is split out from `prefix_unary_expression` so that
1245
+ // `&` can't act as a fallback when the lexer would otherwise
1246
+ // emit `&&`. Its operand is restricted to an lvalue (same shape
1247
+ // as the spec's `address-of-expression`). This is the fix for
1248
+ // tree-sitter#413: `(a) && (b > 0)` was misparsed as
1249
+ // `cast(a, &(&(b > 0)))` because the cast state accepted `&` as
1250
+ // a unary start and the lexer split `&&` into two `&` tokens.
1251
+ // With this split, `&` is only valid before an lvalue, which
1252
+ // `(b > 0)` is not — so the cast interpretation can no longer
1253
+ // consume the trailing parenthesized expression and `&&` must
1254
+ // be emitted as a single token for the binary path to succeed.
1255
+ _address_of_expression: ($) => prec.right(PREC.UNARY, seq('&', $.lvalue_expression)),
1256
+
1257
+ query_expression: ($) => seq($.from_clause, $._query_body),
1258
+
1259
+ from_clause: ($) => seq('from', optional(field('type', $.type)), field('name', $.identifier), 'in', $.expression),
1260
+
1261
+ _query_body: ($) =>
1262
+ prec.right(sep1(seq(repeat($._query_clause), $._select_or_group_clause), seq('into', $.identifier))),
1263
+
1264
+ _query_clause: ($) => choice($.from_clause, $.join_clause, $.let_clause, $.order_by_clause, $.where_clause),
1265
+
1266
+ join_clause: ($) => seq('join', $._join_header, $._join_body, optional($.join_into_clause)),
1267
+
1268
+ _join_header: ($) => seq(optional(field('type', $.type)), $.identifier, 'in', $.expression),
1269
+
1270
+ _join_body: ($) => seq('on', $.expression, 'equals', $.expression),
1271
+
1272
+ join_into_clause: ($) => seq('into', $.identifier),
1273
+
1274
+ let_clause: ($) => seq('let', $.identifier, '=', $.expression),
1275
+
1276
+ order_by_clause: ($) => seq('orderby', commaSep1($._ordering)),
1277
+
1278
+ _ordering: ($) => seq($.expression, optional(choice('ascending', 'descending'))),
1279
+
1280
+ where_clause: ($) => seq('where', $.expression),
1281
+
1282
+ _select_or_group_clause: ($) => choice($.group_clause, $.select_clause),
1283
+
1284
+ group_clause: ($) => seq('group', $.expression, 'by', $.expression),
1285
+
1286
+ select_clause: ($) => seq('select', $.expression),
1287
+
1288
+ conditional_expression: ($) =>
1289
+ prec.right(
1290
+ PREC.CONDITIONAL,
1291
+ seq(
1292
+ field('condition', $.expression),
1293
+ '?',
1294
+ field('consequence', $.expression),
1295
+ ':',
1296
+ field('alternative', $.expression)
1297
+ )
1298
+ ),
1299
+
1300
+ conditional_access_expression: ($) =>
1301
+ prec.right(
1302
+ PREC.CONDITIONAL,
1303
+ seq(
1304
+ field('condition', $.expression),
1305
+ '?',
1306
+ choice($.member_binding_expression, alias($.bracketed_argument_list, $.element_binding_expression))
1307
+ )
1308
+ ),
1309
+
1310
+ as_expression: ($) =>
1311
+ prec(PREC.REL, seq(field('left', $.expression), field('operator', 'as'), field('right', $.type))),
1312
+
1313
+ is_expression: ($) =>
1314
+ prec(PREC.REL, seq(field('left', $.expression), field('operator', 'is'), field('right', $.type))),
1315
+
1316
+ is_pattern_expression: ($) =>
1317
+ prec(PREC.REL, seq(field('expression', $.expression), 'is', field('pattern', $.pattern))),
1318
+
1319
+ cast_expression: ($) =>
1320
+ prec(
1321
+ PREC.CAST,
1322
+ prec.dynamic(
1323
+ 1,
1324
+ seq(
1325
+ // higher than invocation, lower than binary
1326
+ '(',
1327
+ field('type', $.type),
1328
+ ')',
1329
+ field('value', $.expression)
1330
+ )
1331
+ )
1332
+ ),
1333
+
1334
+ checked_expression: ($) => seq(choice('checked', 'unchecked'), '(', $.expression, ')'),
1335
+
1336
+ invocation_expression: ($) =>
1337
+ prec(PREC.INVOCATION, seq(field('function', $.expression), field('arguments', $.argument_list))),
1338
+
1339
+ switch_expression: ($) => prec(PREC.SWITCH, seq($.expression, 'switch', $._switch_expression_body)),
1340
+ _switch_expression_body: ($) => seq('{', commaSep($.switch_expression_arm), optional(','), '}'),
1341
+
1342
+ switch_expression_arm: ($) => seq($.pattern, optional($.when_clause), '=>', $.expression),
1343
+
1344
+ when_clause: ($) => seq('when', $.expression),
1345
+
1346
+ await_expression: ($) => prec.right(PREC.UNARY, seq('await', $.expression)),
1347
+
1348
+ throw_expression: ($) => seq('throw', $.expression),
1349
+
1350
+ element_access_expression: ($) =>
1351
+ prec(PREC.POSTFIX, seq(field('expression', $.expression), field('subscript', $.bracketed_argument_list))),
1352
+
1353
+ interpolated_string_expression: ($) =>
1354
+ choice(
1355
+ seq(
1356
+ alias($.interpolation_regular_start, $.interpolation_start),
1357
+ alias($.interpolation_start_quote, '"'),
1358
+ repeat($._interpolated_string_content),
1359
+ alias($.interpolation_end_quote, '"')
1360
+ ),
1361
+ seq(
1362
+ alias($.interpolation_verbatim_start, $.interpolation_start),
1363
+ alias($.interpolation_start_quote, '"'),
1364
+ repeat($._interpolated_verbatim_string_content),
1365
+ alias($.interpolation_end_quote, '"')
1366
+ ),
1367
+ seq(
1368
+ alias($.interpolation_raw_start, $.interpolation_start),
1369
+ alias($.interpolation_start_quote, $.interpolation_quote),
1370
+ repeat($._interpolated_raw_string_content),
1371
+ alias($.interpolation_end_quote, $.interpolation_quote)
1372
+ )
1373
+ ),
1374
+
1375
+ _interpolated_string_content: ($) =>
1376
+ choice(alias($.interpolation_string_content, $.string_content), $.escape_sequence, $.interpolation),
1377
+
1378
+ _interpolated_verbatim_string_content: ($) =>
1379
+ choice(alias($.interpolation_string_content, $.string_content), $.interpolation),
1380
+
1381
+ _interpolated_raw_string_content: ($) =>
1382
+ choice(alias($.interpolation_string_content, $.string_content), $.interpolation),
1383
+
1384
+ interpolation: ($) =>
1385
+ seq(
1386
+ alias($.interpolation_open_brace, $.interpolation_brace),
1387
+ $.expression,
1388
+ optional($.interpolation_alignment_clause),
1389
+ optional($.interpolation_format_clause),
1390
+ alias($.interpolation_close_brace, $.interpolation_brace)
1391
+ ),
1392
+
1393
+ interpolation_alignment_clause: ($) => seq(',', $.expression),
1394
+
1395
+ interpolation_format_clause: () => seq(':', /[^}"]+/),
1396
+
1397
+ member_access_expression: ($) =>
1398
+ prec(
1399
+ PREC.DOT,
1400
+ seq(
1401
+ field('expression', choice($.expression, $.predefined_type, $._name)),
1402
+ choice('.', '->'),
1403
+ field('name', $._simple_name)
1404
+ )
1405
+ ),
1406
+
1407
+ member_binding_expression: ($) => seq('.', field('name', $._simple_name)),
1408
+
1409
+ object_creation_expression: ($) =>
1410
+ prec.right(
1411
+ seq(
1412
+ 'new',
1413
+ field('type', $.type),
1414
+ field('arguments', optional($.argument_list)),
1415
+ field('initializer', optional($.initializer_expression))
1416
+ )
1417
+ ),
1418
+
1419
+ // inline
1420
+ _object_creation_type: ($) => choice($._name, $.nullable_type, $.predefined_type),
1421
+
1422
+ parenthesized_expression: ($) => seq('(', $.non_lvalue_expression, ')'),
1423
+
1424
+ _parenthesized_lvalue_expression: ($) => seq('(', $.lvalue_expression, ')'),
1425
+
1426
+ lambda_expression: ($) =>
1427
+ prec(-1, seq($._lambda_expression_init, '=>', field('body', choice($.block, $.expression)))),
1428
+
1429
+ _lambda_expression_init: ($) =>
1430
+ prec(
1431
+ -1,
1432
+ seq(
1433
+ repeat($._attribute_list),
1434
+ repeat(prec(-1, alias(choice('static', 'async'), $.modifier))),
1435
+ optional(field('type', $.type)),
1436
+ field('parameters', $._lambda_parameters)
1437
+ )
1438
+ ),
1439
+
1440
+ _lambda_parameters: ($) =>
1441
+ prec(
1442
+ -1,
1443
+ choice(
1444
+ $.parameter_list,
1445
+ alias($.identifier, $.implicit_parameter),
1446
+ // C# 14: `(ref x) => x`, `(out y) => ...`, `(text, out result) => ...`
1447
+ // The opening '(' is recognized via the external _lambda_paren_open
1448
+ // token, which the scanner only emits when it can confirm a closing
1449
+ // ')=>' follows a parameter list containing at least one modifier.
1450
+ $._implicit_parameter_list_with_modifiers
1451
+ )
1452
+ ),
1453
+
1454
+ // C# 14 simple-lambda parameter list with modifiers. Each element is
1455
+ // either a bare identifier or one or more modifiers (scoped/ref/out/in/
1456
+ // readonly) followed by an identifier. The opening token is the
1457
+ // external _lambda_paren_open; the closing ')' is the regular literal.
1458
+ _implicit_parameter_list_with_modifiers: ($) =>
1459
+ seq(
1460
+ $._lambda_paren_open,
1461
+ commaSep1(
1462
+ choice(
1463
+ seq(
1464
+ repeat1(alias(choice('scoped', 'ref', 'out', 'in', 'readonly'), $.modifier)),
1465
+ alias($.identifier, $.implicit_parameter)
1466
+ ),
1467
+ alias($.identifier, $.implicit_parameter)
1468
+ )
1469
+ ),
1470
+ ')'
1471
+ ),
1472
+
1473
+ array_creation_expression: ($) =>
1474
+ prec.dynamic(PREC.UNARY, seq('new', field('type', $.array_type), optional($.initializer_expression))),
1475
+
1476
+ anonymous_method_expression: ($) =>
1477
+ seq(
1478
+ repeat(prec(-1, alias(choice('static', 'async'), $.modifier))),
1479
+ 'delegate',
1480
+ optional(field('parameters', $.parameter_list)),
1481
+ $.block
1482
+ ),
1483
+
1484
+ anonymous_object_creation_expression: ($) =>
1485
+ seq('new', '{', commaSep($._anonymous_object_member_declarator), optional(','), '}'),
1486
+
1487
+ _anonymous_object_member_declarator: ($) => choice(seq($.identifier, '=', $.expression), $.expression),
1488
+
1489
+ implicit_array_creation_expression: ($) => seq('new', '[', repeat(','), ']', $.initializer_expression),
1490
+
1491
+ implicit_object_creation_expression: ($) =>
1492
+ prec.right(seq('new', $.argument_list, optional($.initializer_expression))),
1493
+
1494
+ implicit_stackalloc_expression: ($) => seq('stackalloc', '[', ']', $.initializer_expression),
1495
+
1496
+ collection_expression: ($) => seq('[', optional(seq(commaSep1($.collection_element), optional(','))), ']'),
1497
+
1498
+ collection_element: ($) => choice($.expression_element, $.spread_element),
1499
+
1500
+ expression_element: ($) => prec(1, $.expression),
1501
+
1502
+ spread_element: ($) => prec.dynamic(1, prec(PREC.RANGE, seq('..', $.expression))),
1503
+
1504
+ initializer_expression: ($) => seq('{', commaSep($.expression), optional(','), '}'),
1505
+
1506
+ declaration_expression: ($) => prec.dynamic(1, seq(field('type', $.type), field('name', $.identifier))),
1507
+
1508
+ default_expression: ($) => prec.right(seq('default', optional(seq('(', field('type', $.type), ')')))),
1509
+
1510
+ with_expression: ($) => prec.left(PREC.WITH, seq($.expression, 'with', $._with_body)),
1511
+ _with_body: ($) => seq('{', commaSep($.with_initializer), optional(','), '}'),
1512
+
1513
+ with_initializer: ($) => seq($.identifier, '=', $.expression),
1514
+
1515
+ sizeof_expression: ($) => seq('sizeof', '(', field('type', $.type), ')'),
1516
+
1517
+ typeof_expression: ($) => seq('typeof', '(', field('type', $.type), ')'),
1518
+
1519
+ makeref_expression: ($) => seq('__makeref', '(', $.expression, ')'),
1520
+
1521
+ ref_expression: ($) => seq('ref', $.expression),
1522
+
1523
+ reftype_expression: ($) => seq('__reftype', '(', $.expression, ')'),
1524
+
1525
+ refvalue_expression: ($) => seq('__refvalue', '(', field('value', $.expression), ',', field('type', $.type), ')'),
1526
+
1527
+ stackalloc_expression: ($) =>
1528
+ prec.left(seq('stackalloc', field('type', $.array_type), optional($.initializer_expression))),
1529
+
1530
+ range_expression: ($) => prec.right(PREC.RANGE, seq(optional($.expression), '..', optional($.expression))),
1531
+
1532
+ tuple_expression: ($) => seq('(', commaSep2($.argument), ')'),
1533
+
1534
+ literal: ($) =>
1535
+ choice(
1536
+ $.null_literal,
1537
+ $.character_literal,
1538
+ $.integer_literal,
1539
+ $.real_literal,
1540
+ $.boolean_literal,
1541
+ $.string_literal,
1542
+ $.verbatim_string_literal,
1543
+ $.raw_string_literal
1544
+ ),
1545
+
1546
+ null_literal: () => 'null',
1547
+
1548
+ character_literal: ($) => seq("'", choice($.character_literal_content, $.escape_sequence), "'"),
1549
+
1550
+ character_literal_content: () => token.immediate(/[^'\\]/),
1551
+
1552
+ integer_literal: () =>
1553
+ token(
1554
+ seq(
1555
+ choice(
1556
+ decimalDigitSequence, // Decimal
1557
+ /0[xX][0-9a-fA-F_]*[0-9a-fA-F]+/, // Hex
1558
+ /0[bB][01_]*[01]+/ // Binary
1559
+ ),
1560
+ optional(/([uU][lL]?|[lL][uU]?)/)
1561
+ )
1562
+ ),
1563
+
1564
+ real_literal: () => {
1565
+ const suffix = /[fFdDmM]/;
1566
+ const exponent = /[eE][+-]?[0-9][0-9_]*/;
1567
+ return token(
1568
+ choice(
1569
+ seq(decimalDigitSequence, '.', decimalDigitSequence, optional(exponent), optional(suffix)),
1570
+ seq('.', decimalDigitSequence, optional(exponent), optional(suffix)),
1571
+ seq(decimalDigitSequence, exponent, optional(suffix)),
1572
+ seq(decimalDigitSequence, suffix)
1573
+ )
1574
+ );
1575
+ },
1576
+
1577
+ string_literal: ($) =>
1578
+ seq('"', repeat(choice($.string_literal_content, $.escape_sequence)), '"', optional($.string_literal_encoding)),
1579
+
1580
+ string_literal_content: () => token.immediate(prec(1, /[^"\\\n]+/)),
1581
+
1582
+ escape_sequence: () =>
1583
+ token(choice(/\\x[0-9a-fA-F]{1,4}/, /\\u[0-9a-fA-F]{4}/, /\\U[0-9a-fA-F]{8}/, /\\[abefnrtv'"\\?0]/)),
1584
+
1585
+ string_literal_encoding: () => token.immediate(stringEncoding),
1586
+
1587
+ verbatim_string_literal: () => token(seq('@"', repeat(choice(/[^"]/, '""')), '"', optional(stringEncoding))),
1588
+
1589
+ raw_string_literal: ($) =>
1590
+ seq($.raw_string_start, $.raw_string_content, $.raw_string_end, optional(stringEncoding)),
1591
+
1592
+ boolean_literal: () => choice('true', 'false'),
1593
+
1594
+ _identifier_token: () =>
1595
+ token(
1596
+ seq(
1597
+ optional('@'),
1598
+ /(\p{XID_Start}|_|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})(\p{XID_Continue}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*/u
1599
+ )
1600
+ ),
1601
+ identifier: ($) => choice($._identifier_token, $._reserved_identifier),
1602
+
1603
+ _reserved_identifier: () =>
1604
+ choice(
1605
+ 'alias',
1606
+ 'ascending',
1607
+ 'by',
1608
+ 'descending',
1609
+ 'equals',
1610
+ // attribute_target_specifier keywords — contextual only when followed
1611
+ // by `:` in `[target: Attr]` position. Anywhere else they're
1612
+ // identifiers. Without listing them here the LR table preferred the
1613
+ // literal-keyword interpretation, breaking `[type]`, `[field]`, etc.
1614
+ // as collection_expression elements. Excludes `'event'` and `'return'`
1615
+ // from the attribute_target_specifier choice — those are real C#
1616
+ // keywords and must not be accepted as identifiers anywhere else.
1617
+ 'field',
1618
+ 'file',
1619
+ 'from',
1620
+ 'global',
1621
+ 'group',
1622
+ 'into',
1623
+ 'join',
1624
+ 'let',
1625
+ 'method',
1626
+ 'notnull',
1627
+ 'on',
1628
+ 'orderby',
1629
+ 'param',
1630
+ 'property',
1631
+ 'scoped',
1632
+ 'select',
1633
+ 'type',
1634
+ 'typevar',
1635
+ 'unmanaged',
1636
+ 'var',
1637
+ 'when',
1638
+ 'where',
1639
+ 'yield'
1640
+ ),
1641
+
1642
+ // Preprocessor
1643
+
1644
+ ...preprocIf('', ($) => $.declaration),
1645
+ ...preprocIf('_in_top_level', ($) => choice($._top_level_item_no_statement, $.statement)),
1646
+ ...preprocIf('_in_expression', ($) => $.expression, -2, false),
1647
+ ...preprocIf('_in_enum_member_declaration', ($) => $.enum_member_declaration, 0, false),
1648
+ ...preprocIf('_in_attribute_list', ($) => $.attribute_list, -1, false),
1649
+
1650
+ preproc_arg: () => token(prec(-1, /\S([^/\n]|\/[^*]|\\\r?\n)*/)),
1651
+ preproc_directive: () => /#[ \t]*[a-zA-Z0-9]\w*/,
1652
+
1653
+ _preproc_expression: ($) =>
1654
+ choice(
1655
+ $.identifier,
1656
+ $.boolean_literal,
1657
+ $.integer_literal,
1658
+ $.character_literal,
1659
+ alias($.preproc_unary_expression, $.unary_expression),
1660
+ alias($.preproc_binary_expression, $.binary_expression),
1661
+ alias($.preproc_parenthesized_expression, $.parenthesized_expression)
1662
+ ),
1663
+
1664
+ preproc_parenthesized_expression: ($) => seq('(', $._preproc_expression, ')'),
1665
+
1666
+ preproc_unary_expression: ($) =>
1667
+ prec.left(PREC.UNARY, seq(field('operator', '!'), field('argument', $._preproc_expression))),
1668
+
1669
+ preproc_binary_expression: ($) => {
1670
+ const table = [
1671
+ ['||', PREC.LOGICAL_OR],
1672
+ ['&&', PREC.LOGICAL_AND],
1673
+ ['==', PREC.EQUAL],
1674
+ ['!=', PREC.EQUAL],
1675
+ ];
1676
+
1677
+ return choice(
1678
+ ...table.map(([operator, precedence]) => {
1679
+ return prec.left(
1680
+ precedence,
1681
+ seq(
1682
+ field('left', $._preproc_expression),
1683
+ // @ts-ignore
1684
+ field('operator', operator),
1685
+ field('right', $._preproc_expression)
1686
+ )
1687
+ );
1688
+ })
1689
+ );
1690
+ },
1691
+
1692
+ preproc_region: ($) => seq(preprocessor('region'), optional(field('content', $.preproc_arg)), /\n/),
1693
+
1694
+ preproc_endregion: ($) => seq(preprocessor('endregion'), optional(field('content', $.preproc_arg)), /\n/),
1695
+
1696
+ preproc_line: ($) =>
1697
+ seq(
1698
+ preprocessor('line'),
1699
+ choice(
1700
+ 'default',
1701
+ 'hidden',
1702
+ seq($.integer_literal, optional($.string_literal)),
1703
+ seq(
1704
+ '(',
1705
+ $.integer_literal,
1706
+ ',',
1707
+ $.integer_literal,
1708
+ ')',
1709
+ '-',
1710
+ '(',
1711
+ $.integer_literal,
1712
+ ',',
1713
+ $.integer_literal,
1714
+ ')',
1715
+ optional($.integer_literal),
1716
+ $.string_literal
1717
+ )
1718
+ ),
1719
+ /\n/
1720
+ ),
1721
+
1722
+ preproc_pragma: ($) =>
1723
+ seq(
1724
+ preprocessor('pragma'),
1725
+ choice(
1726
+ seq('warning', choice('disable', 'restore'), commaSep(choice($.identifier, $.integer_literal))),
1727
+ seq('checksum', $.string_literal, $.string_literal, $.string_literal)
1728
+ ),
1729
+ /\n/
1730
+ ),
1731
+
1732
+ preproc_nullable: () =>
1733
+ seq(
1734
+ preprocessor('nullable'),
1735
+ choice('enable', 'disable', 'restore'),
1736
+ optional(choice('annotations', 'warnings')),
1737
+ /\n/
1738
+ ),
1739
+
1740
+ preproc_error: ($) => seq(preprocessor('error'), $.preproc_arg, /\n/),
1741
+
1742
+ preproc_warning: ($) => seq(preprocessor('warning'), $.preproc_arg, /\n/),
1743
+
1744
+ preproc_define: ($) => seq(preprocessor('define'), $.preproc_arg, /\n/),
1745
+
1746
+ preproc_undef: ($) => seq(preprocessor('undef'), $.preproc_arg, /\n/),
1747
+
1748
+ shebang_directive: () => token(seq('#!', /.*/)),
1749
+
1750
+ comment: () => token(choice(seq('//', /[^\n\r]*/), seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/'))),
1751
+ },
1752
+ });
1753
+
1754
+ /**
1755
+ * Creates a preprocessor regex rule
1756
+ *
1757
+ * @param {string} command
1758
+ *
1759
+ * @returns {AliasRule}
1760
+ */
1761
+ function preprocessor(command) {
1762
+ return alias(new RegExp('#[ \t]*' + command), '#' + command);
1763
+ }
1764
+
1765
+ /**
1766
+ *
1767
+ * @param {string} suffix
1768
+ *
1769
+ * @param {RuleBuilder<string>} content
1770
+ *
1771
+ * @param {number} precedence
1772
+ *
1773
+ * @param {boolean} rep
1774
+ *
1775
+ * @returns {RuleBuilders<string, string>}
1776
+ */
1777
+ function preprocIf(suffix, content, precedence = 0, rep = true) {
1778
+ /**
1779
+ *
1780
+ * @param {GrammarSymbols<string>} $
1781
+ *
1782
+ * @returns {ChoiceRule}
1783
+ */
1784
+ function alternativeBlock($) {
1785
+ return choice(
1786
+ suffix ? alias($['preproc_else' + suffix], $.preproc_else) : $.preproc_else,
1787
+ suffix ? alias($['preproc_elif' + suffix], $.preproc_elif) : $.preproc_elif
1788
+ );
1789
+ }
1790
+
1791
+ return {
1792
+ ['preproc_if' + suffix]: ($) =>
1793
+ prec(
1794
+ precedence,
1795
+ seq(
1796
+ preprocessor('if'),
1797
+ field('condition', $._preproc_expression),
1798
+ /\n/,
1799
+ rep ? repeat(content($)) : optional(content($)),
1800
+ field('alternative', optional(alternativeBlock($))),
1801
+ preprocessor('endif')
1802
+ )
1803
+ ),
1804
+
1805
+ ['preproc_else' + suffix]: ($) =>
1806
+ prec(precedence, seq(preprocessor('else'), rep ? repeat(content($)) : optional(content($)))),
1807
+
1808
+ ['preproc_elif' + suffix]: ($) =>
1809
+ prec(
1810
+ precedence,
1811
+ seq(
1812
+ preprocessor('elif'),
1813
+ field('condition', $._preproc_expression),
1814
+ /\n/,
1815
+ rep ? repeat(content($)) : optional(content($)),
1816
+ field('alternative', optional(alternativeBlock($)))
1817
+ )
1818
+ ),
1819
+ };
1820
+ }
1821
+
1822
+ /**
1823
+ * Creates a rule to match one or more of the rules separated by a comma
1824
+ *
1825
+ * @param {Rule} rule
1826
+ *
1827
+ * @returns {SeqRule}
1828
+ */
1829
+ function commaSep1(rule) {
1830
+ return seq(rule, repeat(seq(',', rule)));
1831
+ }
1832
+
1833
+ /**
1834
+ * Creates a rule to match two or more of the rules separated by a comma
1835
+ *
1836
+ * @param {Rule} rule
1837
+ *
1838
+ * @returns {SeqRule}
1839
+ */
1840
+ function commaSep2(rule) {
1841
+ return seq(rule, repeat1(seq(',', rule)));
1842
+ }
1843
+
1844
+ /**
1845
+ * Creates a rule to optionally match one or more of the rules separated by a comma
1846
+ *
1847
+ * @param {Rule} rule
1848
+ *
1849
+ * @returns {ChoiceRule}
1850
+ */
1851
+ function commaSep(rule) {
1852
+ return optional(commaSep1(rule));
1853
+ }
1854
+
1855
+ /**
1856
+ * Creates a rule to match one or more of the rules separated by `separator`
1857
+ *
1858
+ * @param {RuleOrLiteral} rule
1859
+ *
1860
+ * @param {RuleOrLiteral} separator
1861
+ *
1862
+ * @returns {SeqRule}
1863
+ */
1864
+ function sep1(rule, separator) {
1865
+ return seq(rule, repeat(seq(separator, rule)));
1866
+ }
1867
+
1868
+ /**
1869
+ * Creates a rule to optionally match one or more of the rules separated by `separator`
1870
+ *
1871
+ * @param {RuleOrLiteral} rule
1872
+ *
1873
+ * @param {RuleOrLiteral} separator
1874
+ *
1875
+ * @returns {ChoiceRule}
1876
+ */
1877
+ function sep(rule, separator) {
1878
+ return optional(sep1(rule, separator));
1879
+ }