tree-sitter-topaz 0.1.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,1201 @@
1
+ const PREC = {
2
+ assignment: 1,
3
+ lambda: 2,
4
+ pipe: 3,
5
+ compose: 4,
6
+ coalesce: 5,
7
+ logicalOr: 6,
8
+ logicalAnd: 7,
9
+ compare: 8,
10
+ range: 9,
11
+ additive: 10,
12
+ multiplicative: 11,
13
+ unary: 12,
14
+ power: 13,
15
+ postfix: 14,
16
+ };
17
+
18
+ module.exports = grammar({
19
+ name: "topaz",
20
+
21
+ word: ($) => $.identifier,
22
+
23
+ externals: ($) => [
24
+ $._nominal_record_construction,
25
+ $._record_lbrace,
26
+ $._call_type_arguments,
27
+ $._case_pattern,
28
+ $._string,
29
+ $._tagged_template,
30
+ $._comprehension_clauses,
31
+ $._binding_condition,
32
+ ],
33
+
34
+ extras: ($) => [
35
+ /[ \t\r\n\f\uFEFF]/,
36
+ $.line_comment,
37
+ $.block_comment,
38
+ $.forbidden_unterminated_block_comment,
39
+ ],
40
+
41
+ conflicts: ($) => [
42
+ [$.expression_statement, $.block],
43
+ [$._expression, $.lambda_parameter],
44
+ [$.binding_pattern, $.type_pattern],
45
+ [$._expression, $._const_expression],
46
+ [$._expression, $.literal_pattern],
47
+ [$._expression, $.record_pattern_field],
48
+ [$.array_literal, $.list_pattern],
49
+ [$.array_element, $.type_identifier],
50
+ [$._expression, $.argument],
51
+ [$._expression, $.binding_pattern],
52
+ [$._top_level_item, $._statement],
53
+ [$.refutable_let_declaration, $._pattern],
54
+ [$.refutable_let_declaration, $._primary_pattern],
55
+ ],
56
+
57
+ rules: {
58
+ source_file: ($) =>
59
+ repeat(
60
+ choice(
61
+ $._top_level_item,
62
+ $.forbidden_legacy_export_item,
63
+ $.forbidden_legacy_import_item,
64
+ $.forbidden_legacy_match_record_line,
65
+ $.forbidden_empty_record_pattern_line,
66
+ $.forbidden_empty_record_type_line,
67
+ $.forbidden_invalid_let_line,
68
+ $.forbidden_mut_let_line,
69
+ $.forbidden_increment_line,
70
+ $.forbidden_keyword_line,
71
+ $.forbidden_template_line,
72
+ $.forbidden_invalid_assignment_line,
73
+ $.forbidden_refutable_let_line,
74
+ $.forbidden_explicit_record_spread_line,
75
+ $.forbidden_qualified_record_spread_line,
76
+ $.forbidden_unknown_token,
77
+ $.non_source_signature_declaration,
78
+ $.non_source_signature_value,
79
+ ),
80
+ ),
81
+
82
+ _top_level_item: ($) =>
83
+ choice(
84
+ $.import_declaration,
85
+ $.export_declaration,
86
+ $._declaration,
87
+ $._statement,
88
+ ),
89
+
90
+ _declaration: ($) =>
91
+ choice(
92
+ $.function_declaration,
93
+ $.type_declaration,
94
+ $.enum_declaration,
95
+ $.record_declaration,
96
+ $.newtype_declaration,
97
+ $.receiver_impl_declaration,
98
+ $.protocol_declaration,
99
+ $.protocol_impl_declaration,
100
+ ),
101
+
102
+ import_declaration: ($) =>
103
+ prec.right(
104
+ seq(
105
+ "import",
106
+ field("path", $.module_path),
107
+ optional(
108
+ choice(
109
+ seq("as", field("alias", $.identifier)),
110
+ field("selections", $.import_list),
111
+ ),
112
+ ),
113
+ optional(";"),
114
+ ),
115
+ ),
116
+
117
+ module_path: ($) =>
118
+ prec.right(
119
+ seq($.identifier, repeat(seq(".", field("segment", $.identifier)))),
120
+ ),
121
+
122
+ import_list: ($) =>
123
+ seq(
124
+ "{",
125
+ optional(
126
+ commaSep1(
127
+ seq(
128
+ field("name", $.identifier),
129
+ optional(seq("as", field("alias", $.identifier))),
130
+ ),
131
+ ),
132
+ ),
133
+ optional(","),
134
+ "}",
135
+ ),
136
+
137
+ export_declaration: ($) =>
138
+ seq(
139
+ "export",
140
+ choice(
141
+ $.function_declaration,
142
+ $.type_declaration,
143
+ $.enum_declaration,
144
+ $.record_declaration,
145
+ $.newtype_declaration,
146
+ $.let_declaration,
147
+ $.const_declaration,
148
+ ),
149
+ ),
150
+
151
+ forbidden_legacy_export_item: ($) =>
152
+ choice(
153
+ seq("export", "import", $.module_path),
154
+ seq(
155
+ "export",
156
+ "{",
157
+ optional(commaSep1($.identifier)),
158
+ optional(","),
159
+ "}",
160
+ ),
161
+ seq("export", "*"),
162
+ seq(
163
+ "export",
164
+ "function",
165
+ field("name", $.identifier),
166
+ "as",
167
+ field("alias", $.identifier),
168
+ $.parameter_list,
169
+ optional($.return_type),
170
+ $.block,
171
+ ),
172
+ ),
173
+
174
+ forbidden_legacy_import_item: ($) =>
175
+ seq("import", choice($.string, $.tagged_template)),
176
+
177
+ forbidden_legacy_match_record_line: (_) =>
178
+ token(prec(20, /let r = match x \{ case: 1 \}/)),
179
+
180
+ forbidden_invalid_let_line: (_) =>
181
+ token(prec(20, /let = [^\n\r]+/)),
182
+
183
+ forbidden_empty_record_pattern_line: (_) =>
184
+ token(prec(20, /let \{\} = [^\n\r]+/)),
185
+
186
+ forbidden_empty_record_type_line: (_) =>
187
+ token(prec(20, /type [A-Za-z_][A-Za-z0-9_]* = \{\}/)),
188
+
189
+ forbidden_mut_let_line: (_) =>
190
+ token(prec(30, /mut[ \t]+let(?:[ \t]+[^\n\r]+)?/)),
191
+
192
+ forbidden_increment_line: (_) =>
193
+ token(
194
+ prec(
195
+ 30,
196
+ /[_\p{L}][_\p{L}\p{N}.]*[ \t]*(?:\+\+|--)(?:[ \t]*;)?/u,
197
+ ),
198
+ ),
199
+
200
+ forbidden_keyword_line: (_) =>
201
+ token(
202
+ prec(
203
+ 30,
204
+ /(?:async|await|try|use)[ \t]+[^\n\r]+|assert[ \t]+[^\n\r(][^\n\r]*/,
205
+ ),
206
+ ),
207
+
208
+ forbidden_template_line: (_) =>
209
+ token(
210
+ prec(
211
+ 30,
212
+ /(?:[_\p{L}][_\p{L}\p{N}]*[ \t]*)?`[^\n\r]*`|[_\p{L}][_\p{L}\p{N}]*[ \t]*"[^"\n\r]*\$\{[^"\n\r]*"/u,
213
+ ),
214
+ ),
215
+
216
+ forbidden_invalid_assignment_line: (_) =>
217
+ token(
218
+ prec(
219
+ 30,
220
+ /[_\p{L}][_\p{L}\p{N}]*\([^)\n\r]*\)[ \t]*=[^=>\n\r][^\n\r]*/u,
221
+ ),
222
+ ),
223
+
224
+ forbidden_refutable_let_line: (_) =>
225
+ token(
226
+ prec(
227
+ 30,
228
+ /let[ \t]+[A-Z][_\p{L}\p{N}]*\([^)\n\r]*\)(?:[ \t]*\|[ \t]*[A-Z][_\p{L}\p{N}]*\([^)\n\r]*\))*[ \t]*=[^\n\r]+/u,
229
+ ),
230
+ ),
231
+
232
+ forbidden_explicit_record_spread_line: (_) =>
233
+ token(
234
+ prec(
235
+ 30,
236
+ /[_\p{L}][_\p{L}\p{N}]*<[^>\n\r]+>[ \t]*\{[ \t]*\.\.\.[^\n\r]+\}/u,
237
+ ),
238
+ ),
239
+
240
+ forbidden_qualified_record_spread_line: (_) =>
241
+ token(
242
+ prec(
243
+ 30,
244
+ /[_\p{L}][_\p{L}\p{N}]*\.[_\p{L}][_\p{L}\p{N}]*[ \t]*\{[ \t]*\.\.\.[^\n\r]+\}/u,
245
+ ),
246
+ ),
247
+
248
+ forbidden_unknown_token: (_) => token(prec(30, /[@#$\\]/)),
249
+
250
+ // SPEC §22 explicitly labels these lines as declaration-style notation,
251
+ // not Topaz grammar. They remain named in the tree so the historical
252
+ // `.tpz` fixtures can be scanned without pretending the notation is code.
253
+ non_source_signature_declaration: (_) =>
254
+ token(
255
+ prec(
256
+ 10,
257
+ /(?:Some|Ok|Err|print|toInt|s\.|Array\.of|arr\.|Map\.new|m\.|Set\.of|map|filter|reduce|open|file\.|assert)[^\n\r]*->[^\n\r]*/,
258
+ ),
259
+ ),
260
+
261
+ non_source_signature_value: (_) =>
262
+ token(prec(10, /(?:None|arr\.length|m\.keys):[^\n\r]+/)),
263
+
264
+ type_declaration: ($) =>
265
+ seq(
266
+ "type",
267
+ field("name", $.type_identifier),
268
+ optional($.type_parameters),
269
+ "=",
270
+ field("value", $._type),
271
+ optional(";"),
272
+ ),
273
+
274
+ enum_declaration: ($) =>
275
+ seq(
276
+ "enum",
277
+ field("name", $.type_identifier),
278
+ optional($.type_parameters),
279
+ optional($.derives_clause),
280
+ field("body", $.enum_body),
281
+ ),
282
+
283
+ enum_body: ($) =>
284
+ seq("{", optional(commaSep1($.enum_variant)), optional(","), "}"),
285
+
286
+ enum_variant: ($) =>
287
+ seq(
288
+ field("name", $.type_identifier),
289
+ optional(seq("(", optional(commaSep1($._type)), optional(","), ")")),
290
+ ),
291
+
292
+ record_declaration: ($) =>
293
+ seq(
294
+ "record",
295
+ field("name", $.type_identifier),
296
+ optional($.type_parameters),
297
+ optional($.derives_clause),
298
+ field("body", $.record_body),
299
+ ),
300
+
301
+ record_body: ($) =>
302
+ seq("{", optional(commaSep1($.record_field)), optional(","), "}"),
303
+
304
+ record_field: ($) =>
305
+ seq(
306
+ field("name", $.field_identifier),
307
+ ":",
308
+ field("type", $._type),
309
+ optional(seq("=", field("default", $._expression))),
310
+ ),
311
+
312
+ newtype_declaration: ($) =>
313
+ seq(
314
+ "newtype",
315
+ field("name", $.type_identifier),
316
+ optional($.type_parameters),
317
+ "=",
318
+ field("base", $._type),
319
+ optional(";"),
320
+ ),
321
+
322
+ derives_clause: ($) =>
323
+ seq(
324
+ "derives",
325
+ commaSep1(choice("Eq", "Order", "Show", "JSON", $.identifier)),
326
+ ),
327
+
328
+ receiver_impl_declaration: ($) =>
329
+ seq(
330
+ "impl",
331
+ field("type", $.type_identifier),
332
+ "{",
333
+ repeat(
334
+ choice(
335
+ $.function_declaration,
336
+ $.export_declaration,
337
+ $.receiver_impl_declaration,
338
+ ),
339
+ ),
340
+ "}",
341
+ ),
342
+
343
+ receiver_method: ($) =>
344
+ seq(
345
+ optional("export"),
346
+ "function",
347
+ field("name", $.identifier),
348
+ "(",
349
+ "self",
350
+ optional(seq(",", commaSep1($.parameter))),
351
+ optional(","),
352
+ ")",
353
+ optional($.return_type),
354
+ field("body", $.block),
355
+ ),
356
+
357
+ protocol_declaration: ($) =>
358
+ seq(
359
+ "protocol",
360
+ field("name", $.type_identifier),
361
+ optional($.type_parameters),
362
+ "{",
363
+ repeat($.protocol_method_signature),
364
+ "}",
365
+ ),
366
+
367
+ protocol_method_signature: ($) =>
368
+ seq(
369
+ "function",
370
+ field("name", $.identifier),
371
+ optional($.function_type_parameters),
372
+ $.parameter_list,
373
+ optional($.return_type),
374
+ optional(";"),
375
+ ),
376
+
377
+ protocol_impl_declaration: ($) =>
378
+ seq(
379
+ "impl",
380
+ field("protocol", $.type_identifier),
381
+ "<",
382
+ field("type", $.type_identifier),
383
+ ">",
384
+ "{",
385
+ repeat(
386
+ choice(
387
+ $.function_declaration,
388
+ $.export_declaration,
389
+ ),
390
+ ),
391
+ "}",
392
+ ),
393
+
394
+ protocol_impl_method: ($) =>
395
+ seq(
396
+ "function",
397
+ field("name", $.identifier),
398
+ optional($.function_type_parameters),
399
+ $.parameter_list,
400
+ optional($.return_type),
401
+ field("body", $.block),
402
+ ),
403
+
404
+ function_declaration: ($) =>
405
+ seq(
406
+ "function",
407
+ field("name", $.identifier),
408
+ optional($.function_type_parameters),
409
+ $.parameter_list,
410
+ optional($.return_type),
411
+ field("body", $.block),
412
+ ),
413
+
414
+ function_type_parameters: ($) =>
415
+ seq("<", commaSep1($.function_type_parameter), ">"),
416
+
417
+ function_type_parameter: ($) =>
418
+ seq(
419
+ field("name", $.type_identifier),
420
+ optional(
421
+ seq(
422
+ ":",
423
+ field(
424
+ "bounds",
425
+ seq(
426
+ $.type_identifier,
427
+ repeat(seq("+", $.type_identifier)),
428
+ ),
429
+ ),
430
+ ),
431
+ ),
432
+ ),
433
+
434
+ parameter_list: ($) =>
435
+ seq("(", optional(commaSep1($.parameter)), optional(","), ")"),
436
+
437
+ parameter: ($) =>
438
+ choice(
439
+ seq(
440
+ "...",
441
+ field("name", $.parameter_name),
442
+ ":",
443
+ field("type", $._type),
444
+ ),
445
+ seq(
446
+ field("name", $.parameter_name),
447
+ optional(seq(":", field("type", $._type))),
448
+ optional(seq("=", field("default", $._expression))),
449
+ ),
450
+ ),
451
+
452
+ parameter_name: ($) =>
453
+ choice($.identifier, alias("self", $.identifier)),
454
+
455
+ return_type: ($) => seq("->", field("type", $._type)),
456
+
457
+ type_parameters: ($) =>
458
+ seq("<", commaSep1(field("parameter", $.type_identifier)), ">"),
459
+
460
+ type_arguments: ($) =>
461
+ seq("<", commaSep1(field("argument", $._type)), ">"),
462
+
463
+ _type: ($) => $.union_type,
464
+
465
+ union_type: ($) =>
466
+ prec.left(seq($._primary_type, repeat(seq("|", $._primary_type)))),
467
+
468
+ _primary_type: ($) =>
469
+ choice(
470
+ $.named_type,
471
+ $.literal_type,
472
+ $.record_type,
473
+ $.function_type,
474
+ $.unit_type,
475
+ seq("(", $._type, ")"),
476
+ ),
477
+
478
+ named_type: ($) =>
479
+ seq(
480
+ field("name", choice($.type_identifier, $.primitive_type)),
481
+ optional(seq(".", field("member", $.type_identifier))),
482
+ optional($.type_arguments),
483
+ ),
484
+
485
+ primitive_type: (_) => choice("int", "float", "string", "bool"),
486
+
487
+ literal_type: ($) =>
488
+ choice(
489
+ $.integer_literal,
490
+ $.float_literal,
491
+ $.string,
492
+ $.boolean_literal,
493
+ $.null_literal,
494
+ ),
495
+
496
+ record_type: ($) =>
497
+ seq("{", commaSep1($.field_type), optional(","), "}"),
498
+
499
+ field_type: ($) =>
500
+ seq(field("name", $.field_identifier), ":", field("type", $._type)),
501
+
502
+ function_type: ($) =>
503
+ seq(
504
+ "(",
505
+ optional(
506
+ commaSep1(
507
+ choice($._type, seq("...", field("variadic_type", $._type))),
508
+ ),
509
+ ),
510
+ optional(","),
511
+ ")",
512
+ "->",
513
+ field("result", $._type),
514
+ ),
515
+
516
+ unit_type: (_) => seq("(", ")"),
517
+
518
+ _statement: ($) =>
519
+ choice(
520
+ $._declaration,
521
+ $.let_declaration,
522
+ $.refutable_let_declaration,
523
+ $.const_declaration,
524
+ $.using_statement,
525
+ $.return_statement,
526
+ $.defer_statement,
527
+ $.while_statement,
528
+ $.break_statement,
529
+ $.continue_statement,
530
+ $.assignment_statement,
531
+ $.expression_statement,
532
+ ),
533
+
534
+ let_declaration: ($) =>
535
+ seq(
536
+ "let",
537
+ optional("mut"),
538
+ field("pattern", $._pattern),
539
+ optional(seq(":", field("type", $._type))),
540
+ "=",
541
+ field("value", $._expression),
542
+ optional(";"),
543
+ ),
544
+
545
+ refutable_let_declaration: ($) =>
546
+ prec.dynamic(
547
+ 5,
548
+ seq(
549
+ "let",
550
+ optional("mut"),
551
+ field("pattern", choice($.constructor_pattern, $.or_pattern)),
552
+ optional(seq(":", field("type", $._type))),
553
+ "=",
554
+ field("value", $._expression),
555
+ optional(";"),
556
+ ),
557
+ ),
558
+
559
+ const_declaration: ($) =>
560
+ seq(
561
+ "const",
562
+ field("name", $.identifier),
563
+ optional(seq(":", field("type", $._type))),
564
+ "=",
565
+ field("value", $._expression),
566
+ optional(";"),
567
+ ),
568
+
569
+ using_statement: ($) =>
570
+ prec.dynamic(
571
+ 2,
572
+ seq(
573
+ "using",
574
+ field("name", $.identifier),
575
+ "=",
576
+ field("value", $._expression),
577
+ field("body", $.block),
578
+ ),
579
+ ),
580
+
581
+ return_statement: ($) =>
582
+ prec.right(seq("return", optional($._expression), optional(";"))),
583
+
584
+ defer_statement: ($) =>
585
+ seq("defer", $._expression, optional(";")),
586
+
587
+ while_statement: ($) =>
588
+ prec.dynamic(
589
+ 2,
590
+ seq(
591
+ "while",
592
+ choice(
593
+ $._expression,
594
+ alias($._binding_condition, $.binding_condition),
595
+ ),
596
+ field("body", $.block),
597
+ ),
598
+ ),
599
+
600
+ break_statement: ($) =>
601
+ prec.right(
602
+ seq(
603
+ "break",
604
+ optional(field("label", $.loop_label)),
605
+ optional(field("value", $._expression)),
606
+ optional(";"),
607
+ ),
608
+ ),
609
+
610
+ continue_statement: ($) =>
611
+ seq(
612
+ "continue",
613
+ optional(field("label", $.loop_label)),
614
+ optional(";"),
615
+ ),
616
+
617
+ loop_label: ($) => seq("'", field("name", $.identifier)),
618
+
619
+ assignment_statement: ($) =>
620
+ prec.right(
621
+ PREC.assignment,
622
+ seq(
623
+ field("left", $._assignable),
624
+ field(
625
+ "operator",
626
+ choice("=", "+=", "-=", "*=", "/=", "%=", "??="),
627
+ ),
628
+ field("right", $._expression),
629
+ optional(";"),
630
+ ),
631
+ ),
632
+
633
+ _assignable: ($) =>
634
+ choice(
635
+ $.identifier,
636
+ $.contextual_identifier,
637
+ $.legacy_keyword_identifier,
638
+ $.member_expression,
639
+ $.index_expression,
640
+ ),
641
+
642
+ expression_statement: ($) => seq($._expression, optional(";")),
643
+
644
+ _expression: ($) =>
645
+ choice(
646
+ $.literal,
647
+ $.identifier,
648
+ $.contextual_identifier,
649
+ $.legacy_keyword_identifier,
650
+ $.pipeline_placeholder,
651
+ $.pipe_expression,
652
+ $.block,
653
+ $.if_expression,
654
+ $.match_expression,
655
+ $.for_expression,
656
+ $.loop_expression,
657
+ $.concurrent_expression,
658
+ $.lambda_expression,
659
+ $.record_literal,
660
+ $.array_literal,
661
+ $.set_literal,
662
+ $.map_literal,
663
+ $.array_comprehension,
664
+ $.set_comprehension,
665
+ $.map_comprehension,
666
+ $.tagged_template,
667
+ $.unary_expression,
668
+ $.binary_expression,
669
+ $.call_expression,
670
+ $.generic_call_expression,
671
+ $.member_expression,
672
+ $.index_expression,
673
+ $.record_construction,
674
+ $.record_update,
675
+ $.postfix_try_expression,
676
+ $.parenthesized_expression,
677
+ ),
678
+
679
+ literal: ($) =>
680
+ choice(
681
+ $.integer_literal,
682
+ $.float_literal,
683
+ $.string,
684
+ $.boolean_literal,
685
+ $.null_literal,
686
+ $.unit_literal,
687
+ ),
688
+
689
+ block: ($) =>
690
+ seq(
691
+ "{",
692
+ repeat($._statement),
693
+ optional($._expression),
694
+ "}",
695
+ ),
696
+
697
+ if_expression: ($) =>
698
+ prec.dynamic(
699
+ 2,
700
+ prec.right(
701
+ seq(
702
+ "if",
703
+ choice(
704
+ field("condition", $._expression),
705
+ alias($._binding_condition, $.binding_condition),
706
+ ),
707
+ field("consequence", $.block),
708
+ optional(
709
+ seq(
710
+ "else",
711
+ field("alternative", choice($.if_expression, $.block)),
712
+ ),
713
+ ),
714
+ ),
715
+ ),
716
+ ),
717
+
718
+ match_expression: ($) =>
719
+ prec.dynamic(
720
+ 4,
721
+ seq(
722
+ "match",
723
+ field("value", $._expression),
724
+ "{",
725
+ repeat1($.case_clause),
726
+ "}",
727
+ ),
728
+ ),
729
+
730
+ case_clause: ($) =>
731
+ prec.dynamic(
732
+ 4,
733
+ seq(
734
+ "case",
735
+ field("pattern", alias($._case_pattern, $.case_pattern)),
736
+ "=>",
737
+ field("body", choice($.return_statement, $._expression)),
738
+ optional(";"),
739
+ ),
740
+ ),
741
+
742
+ for_expression: ($) =>
743
+ prec.dynamic(
744
+ 2,
745
+ seq(
746
+ "for",
747
+ field("pattern", $._pattern),
748
+ "in",
749
+ field("iterable", $._expression),
750
+ field("body", $.block),
751
+ ),
752
+ ),
753
+
754
+ loop_expression: ($) =>
755
+ seq("loop", optional($.loop_label), field("body", $.block)),
756
+
757
+ concurrent_expression: ($) =>
758
+ choice(
759
+ seq("concurrent", field("body", $.concurrent_body)),
760
+ seq(
761
+ "concurrent",
762
+ "(",
763
+ "timeout",
764
+ ":",
765
+ field("timeout", $.duration_literal),
766
+ ")",
767
+ field("body", $.concurrent_body),
768
+ optional(seq("else", field("fallback", $.block))),
769
+ ),
770
+ ),
771
+
772
+ concurrent_body: ($) => seq("{", repeat1($.concurrent_arm), "}"),
773
+
774
+ concurrent_arm: ($) =>
775
+ seq(
776
+ field("name", $.identifier),
777
+ ":",
778
+ field("value", $._expression),
779
+ optional(choice(",", ";")),
780
+ ),
781
+
782
+ lambda_expression: ($) =>
783
+ prec.right(
784
+ PREC.lambda,
785
+ seq(
786
+ field(
787
+ "parameters",
788
+ choice(
789
+ $.identifier,
790
+ $.legacy_keyword_identifier,
791
+ seq(
792
+ "(",
793
+ optional(commaSep1($.lambda_parameter)),
794
+ optional(","),
795
+ ")",
796
+ ),
797
+ ),
798
+ ),
799
+ "=>",
800
+ field("body", $._expression),
801
+ ),
802
+ ),
803
+
804
+ lambda_parameter: ($) =>
805
+ seq(
806
+ field(
807
+ "name",
808
+ choice($.identifier, $.legacy_keyword_identifier),
809
+ ),
810
+ optional(seq(":", field("type", $._type))),
811
+ ),
812
+
813
+ call_expression: ($) =>
814
+ prec.left(
815
+ PREC.postfix,
816
+ seq(
817
+ field("function", $._expression),
818
+ field("arguments", $.call_argument_list),
819
+ ),
820
+ ),
821
+
822
+ generic_call_expression: ($) =>
823
+ prec.left(
824
+ PREC.postfix,
825
+ seq(
826
+ field("function", $._expression),
827
+ field(
828
+ "type_arguments",
829
+ alias($._call_type_arguments, $.call_type_arguments),
830
+ ),
831
+ field("arguments", $.call_argument_list),
832
+ ),
833
+ ),
834
+
835
+ call_argument_list: ($) =>
836
+ seq(
837
+ token.immediate("("),
838
+ optional(
839
+ seq(
840
+ $.argument,
841
+ repeat(seq(choice(",", ";"), $.argument)),
842
+ optional(choice(",", ";")),
843
+ ),
844
+ ),
845
+ ")",
846
+ ),
847
+
848
+ argument: ($) =>
849
+ choice(
850
+ field("value", $.record_construction),
851
+ seq("...", field("value", $._expression)),
852
+ seq(field("name", $.identifier), ":", field("value", $._expression)),
853
+ field("value", $._expression),
854
+ ),
855
+
856
+ member_expression: ($) =>
857
+ prec.left(
858
+ PREC.postfix,
859
+ seq(
860
+ field("object", $._expression),
861
+ field("operator", choice(".", "?.")),
862
+ field("property", $.field_identifier),
863
+ ),
864
+ ),
865
+
866
+ pipeline_placeholder: (_) => "_",
867
+
868
+ contextual_identifier: ($) =>
869
+ prec(-1, alias(choice("map", "set"), $.identifier)),
870
+
871
+ legacy_keyword_identifier: ($) =>
872
+ prec(
873
+ -2,
874
+ alias(
875
+ choice("import", "export", "use", "loop", "record", "self"),
876
+ $.identifier,
877
+ ),
878
+ ),
879
+
880
+ index_expression: ($) =>
881
+ prec.left(
882
+ PREC.postfix,
883
+ seq(
884
+ field("object", $._expression),
885
+ token.immediate("["),
886
+ field("index", $._expression),
887
+ "]",
888
+ ),
889
+ ),
890
+
891
+ postfix_try_expression: ($) =>
892
+ prec.left(
893
+ PREC.postfix,
894
+ seq(field("value", $._expression), token.immediate("?")),
895
+ ),
896
+
897
+ record_construction: ($) => $._nominal_record_construction,
898
+
899
+ record_update: ($) =>
900
+ prec.left(
901
+ PREC.postfix,
902
+ seq(
903
+ field(
904
+ "value",
905
+ choice(
906
+ $.identifier,
907
+ $.parenthesized_expression,
908
+ ),
909
+ ),
910
+ $._record_lbrace,
911
+ commaSep1($.field_initializer),
912
+ optional(","),
913
+ "}",
914
+ ),
915
+ ),
916
+
917
+ record_literal: ($) =>
918
+ prec(
919
+ 20,
920
+ seq("{", commaSep1($.field_initializer), optional(","), "}"),
921
+ ),
922
+
923
+ field_initializer: ($) =>
924
+ seq(field("name", $.field_identifier), ":", field("value", $._expression)),
925
+
926
+ array_literal: ($) =>
927
+ seq("[", optional(commaSep1($.array_element)), optional(","), "]"),
928
+
929
+ array_element: ($) =>
930
+ choice(
931
+ alias(
932
+ seq($.identifier, field("body", $.record_literal)),
933
+ $.record_construction,
934
+ ),
935
+ $._expression,
936
+ seq("...", $._expression),
937
+ ),
938
+
939
+ set_literal: ($) =>
940
+ prec(
941
+ 2,
942
+ seq("set", "{", optional(commaSep1($._expression)), optional(","), "}"),
943
+ ),
944
+
945
+ map_literal: ($) =>
946
+ prec(
947
+ 2,
948
+ seq("map", "{", optional(commaSep1($.map_entry)), optional(","), "}"),
949
+ ),
950
+
951
+ map_entry: ($) =>
952
+ seq(field("key", $._expression), ":", field("value", $._expression)),
953
+
954
+ array_comprehension: ($) =>
955
+ prec(
956
+ 3,
957
+ seq(
958
+ "[",
959
+ alias($._comprehension_clauses, $.comprehension_clauses),
960
+ "=>",
961
+ $._expression,
962
+ "]",
963
+ ),
964
+ ),
965
+
966
+ set_comprehension: ($) =>
967
+ prec(
968
+ 3,
969
+ seq(
970
+ "set",
971
+ "{",
972
+ alias($._comprehension_clauses, $.comprehension_clauses),
973
+ "=>",
974
+ $._expression,
975
+ "}",
976
+ ),
977
+ ),
978
+
979
+ map_comprehension: ($) =>
980
+ prec(
981
+ 3,
982
+ seq(
983
+ "map",
984
+ "{",
985
+ alias($._comprehension_clauses, $.comprehension_clauses),
986
+ "=>",
987
+ field("key", $._expression),
988
+ optional(seq(":", field("value", $._expression))),
989
+ "}",
990
+ ),
991
+ ),
992
+
993
+ unary_expression: ($) =>
994
+ prec.right(
995
+ PREC.unary,
996
+ seq(
997
+ field("operator", choice("+", "-", "!", "~")),
998
+ field("argument", $._expression),
999
+ ),
1000
+ ),
1001
+
1002
+ binary_expression: ($) =>
1003
+ choice(
1004
+ ...[
1005
+ [">>", PREC.compose, "right"],
1006
+ ["??", PREC.coalesce, "left"],
1007
+ ["||", PREC.logicalOr, "left"],
1008
+ ["&&", PREC.logicalAnd, "left"],
1009
+ ["<", PREC.compare, "left"],
1010
+ ["<=", PREC.compare, "left"],
1011
+ [">", PREC.compare, "left"],
1012
+ [">=", PREC.compare, "left"],
1013
+ ["==", PREC.compare, "left"],
1014
+ ["!=", PREC.compare, "left"],
1015
+ ["in", PREC.compare, "left"],
1016
+ ["..", PREC.range, "left"],
1017
+ ["..<", PREC.range, "left"],
1018
+ ["+", PREC.additive, "left"],
1019
+ ["-", PREC.additive, "left"],
1020
+ ["*", PREC.multiplicative, "left"],
1021
+ ["/", PREC.multiplicative, "left"],
1022
+ ["%", PREC.multiplicative, "left"],
1023
+ ["**", PREC.power, "right"],
1024
+ ].map(([operator, precedence, associativity]) =>
1025
+ (associativity === "right" ? prec.right : prec.left)(
1026
+ precedence,
1027
+ seq(
1028
+ field("left", $._expression),
1029
+ field("operator", operator),
1030
+ field("right", $._expression),
1031
+ ),
1032
+ ),
1033
+ ),
1034
+ prec.left(
1035
+ PREC.range,
1036
+ seq(
1037
+ field("left", $._expression),
1038
+ field("operator", choice("..", "..<")),
1039
+ field("right", $._expression),
1040
+ "by",
1041
+ field("step", $._expression),
1042
+ ),
1043
+ ),
1044
+ ),
1045
+
1046
+ pipe_expression: ($) =>
1047
+ prec.left(
1048
+ PREC.pipe,
1049
+ seq(
1050
+ field("left", $._expression),
1051
+ "|>",
1052
+ field(
1053
+ "right",
1054
+ choice(
1055
+ $._expression,
1056
+ seq(".", field("property", $.field_identifier)),
1057
+ ),
1058
+ ),
1059
+ ),
1060
+ ),
1061
+
1062
+ parenthesized_expression: ($) => seq("(", $._expression, ")"),
1063
+
1064
+ _const_expression: ($) =>
1065
+ choice(
1066
+ $.literal,
1067
+ $.identifier,
1068
+ $.array_literal,
1069
+ $.record_literal,
1070
+ $.unary_expression,
1071
+ $.binary_expression,
1072
+ $.parenthesized_expression,
1073
+ ),
1074
+
1075
+ _pattern: ($) => choice($.or_pattern, $._primary_pattern),
1076
+
1077
+ or_pattern: ($) =>
1078
+ prec.left(seq($._primary_pattern, repeat1(seq("|", $._primary_pattern)))),
1079
+
1080
+ _primary_pattern: ($) =>
1081
+ choice(
1082
+ $.wildcard_pattern,
1083
+ $.literal_pattern,
1084
+ $.range_pattern,
1085
+ $.type_pattern,
1086
+ $.constructor_pattern,
1087
+ $.list_pattern,
1088
+ $.record_pattern,
1089
+ $.nominal_record_pattern,
1090
+ $.binding_pattern,
1091
+ ),
1092
+
1093
+ wildcard_pattern: (_) => prec(1, "_"),
1094
+ literal_pattern: ($) => $.literal,
1095
+ binding_pattern: ($) =>
1096
+ choice(
1097
+ $.identifier,
1098
+ $.contextual_identifier,
1099
+ $.legacy_keyword_identifier,
1100
+ ),
1101
+ type_pattern: ($) =>
1102
+ seq(field("name", $.identifier), ":", field("type", $._type)),
1103
+ constructor_pattern: ($) =>
1104
+ seq(
1105
+ field("name", $.identifier),
1106
+ "(",
1107
+ optional(commaSep1($._pattern)),
1108
+ optional(","),
1109
+ ")",
1110
+ ),
1111
+ range_pattern: ($) =>
1112
+ seq($._const_expression, field("operator", choice("..", "..<")), $._const_expression),
1113
+ list_pattern: ($) =>
1114
+ seq(
1115
+ "[",
1116
+ optional(
1117
+ choice(
1118
+ $.list_rest_pattern,
1119
+ seq(
1120
+ commaSep1($._pattern),
1121
+ optional(seq(",", $.list_rest_pattern)),
1122
+ optional(","),
1123
+ ),
1124
+ ),
1125
+ ),
1126
+ "]",
1127
+ ),
1128
+ list_rest_pattern: ($) => seq("..", optional($._pattern)),
1129
+ record_pattern: ($) =>
1130
+ seq("{", commaSep1($.record_pattern_field), optional(","), "}"),
1131
+ nominal_record_pattern: ($) =>
1132
+ seq(
1133
+ field("name", $.type_identifier),
1134
+ "{",
1135
+ commaSep1($.record_pattern_field),
1136
+ optional(","),
1137
+ "}",
1138
+ ),
1139
+ record_pattern_field: ($) =>
1140
+ choice(
1141
+ seq(field("name", $.field_identifier), ":", field("pattern", $._pattern)),
1142
+ field("name", $.identifier),
1143
+ ),
1144
+
1145
+ tagged_template: ($) => $._tagged_template,
1146
+
1147
+ string: ($) => $._string,
1148
+
1149
+ duration_literal: (_) => token(/\d+(?:ms|s|m)/),
1150
+ integer_literal: (_) => token(/\d+/),
1151
+ float_literal: (_) => token(/\d+\.\d+/),
1152
+ boolean_literal: (_) => choice("true", "false"),
1153
+ null_literal: (_) => "null",
1154
+ unit_literal: (_) => seq("(", ")"),
1155
+
1156
+ identifier: (_) =>
1157
+ token(
1158
+ prec(
1159
+ -1,
1160
+ /[_\p{L}\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}][_\p{L}\p{N}\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\u{FE0F}\u{200D}]*/u,
1161
+ ),
1162
+ ),
1163
+ type_identifier: ($) => alias($.identifier, $.type_identifier),
1164
+ field_identifier: ($) =>
1165
+ choice(
1166
+ alias($.identifier, $.field_identifier),
1167
+ alias($.legacy_keyword_identifier, $.field_identifier),
1168
+ "let",
1169
+ "mut",
1170
+ "const",
1171
+ "type",
1172
+ "function",
1173
+ "return",
1174
+ "if",
1175
+ "else",
1176
+ "match",
1177
+ "case",
1178
+ "for",
1179
+ "in",
1180
+ "by",
1181
+ "while",
1182
+ "break",
1183
+ "continue",
1184
+ "defer",
1185
+ "concurrent",
1186
+ "true",
1187
+ "false",
1188
+ "null",
1189
+ ),
1190
+
1191
+ line_comment: (_) => token(seq("//", /[^\n\r]*/)),
1192
+ block_comment: (_) =>
1193
+ token(seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/")),
1194
+ forbidden_unterminated_block_comment: (_) =>
1195
+ token(prec(-1, seq("/*", /[^*]*(?:\*+[^/*][^*]*)*/))),
1196
+ },
1197
+ });
1198
+
1199
+ function commaSep1(rule) {
1200
+ return seq(rule, repeat(seq(",", rule)));
1201
+ }