@willbooster/tree-sitter-python 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,881 @@
1
+ /**
2
+ * @file Python grammar for tree-sitter
3
+ * @author Max Brunsfeld
4
+ * @license MIT
5
+ * @see {@link https://docs.python.org/2/reference/grammar.html|Python 2 grammar}
6
+ * @see {@link https://docs.python.org/3/reference/grammar.html|Python 3 grammar}
7
+ */
8
+
9
+ /// <reference types="tree-sitter-cli/dsl" />
10
+ // @ts-check
11
+
12
+ const PREC = {
13
+ // this resolves a conflict between the usage of ':' in a lambda vs in a
14
+ // typed parameter. In the case of a lambda, we don't allow typed parameters.
15
+ lambda: -2,
16
+ typed_parameter: -1,
17
+ conditional: -1,
18
+
19
+ parenthesized_expression: 1,
20
+ parenthesized_list_splat: 1,
21
+ or: 10,
22
+ and: 11,
23
+ not: 12,
24
+ compare: 13,
25
+ bitwise_or: 14,
26
+ bitwise_and: 15,
27
+ xor: 16,
28
+ shift: 17,
29
+ plus: 18,
30
+ times: 19,
31
+ unary: 20,
32
+ power: 21,
33
+ call: 22,
34
+ };
35
+
36
+ const SEMICOLON = ';';
37
+
38
+ // oxlint-disable-next-line unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads grammar.js as CommonJS.
39
+ module.exports = grammar({
40
+ name: 'python',
41
+
42
+ extras: ($) => [$.comment, /[\s\f\uFEFF\u2060\u200B]|\r?\n/, $.line_continuation],
43
+
44
+ conflicts: ($) => [
45
+ [$.primary_expression, $.pattern],
46
+ [$.primary_expression, $.list_splat_pattern],
47
+ [$.tuple, $.tuple_pattern],
48
+ [$.list, $.list_pattern],
49
+ [$.with_item, $._collection_elements],
50
+ [$.named_expression, $.as_pattern],
51
+ [$.print_statement, $.primary_expression],
52
+ [$.type_alias_statement, $.primary_expression],
53
+ [$.match_statement, $.primary_expression],
54
+ ],
55
+
56
+ supertypes: ($) => [
57
+ $._simple_statement,
58
+ $._compound_statement,
59
+ $.expression,
60
+ $.primary_expression,
61
+ $.pattern,
62
+ $.parameter,
63
+ ],
64
+
65
+ externals: ($) => [
66
+ $._newline,
67
+ $._indent,
68
+ $._dedent,
69
+ $.string_start,
70
+ $._string_content,
71
+ $.escape_interpolation,
72
+ $.string_end,
73
+
74
+ // Mark comments as external tokens so that the external scanner is always
75
+ // invoked, even if no external token is expected. This allows for better
76
+ // error recovery, because the external scanner can maintain the overall
77
+ // structure by returning dedent tokens whenever a dedent occurs, even
78
+ // if no dedent is expected.
79
+ $.comment,
80
+
81
+ // Allow the external scanner to check for the validity of closing brackets
82
+ // so that it can avoid returning dedent tokens between brackets.
83
+ ']',
84
+ ')',
85
+ '}',
86
+ 'except',
87
+ ],
88
+
89
+ inline: ($) => [
90
+ $._simple_statement,
91
+ $._compound_statement,
92
+ $._suite,
93
+ $._expressions,
94
+ $._left_hand_side,
95
+ $.keyword_identifier,
96
+ ],
97
+
98
+ reserved: {
99
+ global: () => [
100
+ // https://docs.python.org/3/reference/lexical_analysis.html#keywords
101
+ 'False',
102
+ 'await',
103
+ 'else',
104
+ 'import',
105
+ 'pass',
106
+ 'None',
107
+ 'break',
108
+ 'except',
109
+ 'in',
110
+ 'raise',
111
+ 'True',
112
+ 'class',
113
+ 'finally',
114
+ 'is',
115
+ 'return',
116
+ 'and',
117
+ 'continue',
118
+ 'for',
119
+ 'lambda',
120
+ 'try',
121
+ 'as',
122
+ 'def',
123
+ 'from',
124
+ 'nonlocal',
125
+ 'while',
126
+ 'assert',
127
+ 'del',
128
+ 'global',
129
+ 'not',
130
+ 'with',
131
+ 'async',
132
+ 'elif',
133
+ 'if',
134
+ 'or',
135
+ 'yield',
136
+ ],
137
+ },
138
+
139
+ word: ($) => $.identifier,
140
+
141
+ rules: {
142
+ module: ($) => repeat($._statement),
143
+
144
+ _statement: ($) => choice($._simple_statements, $._compound_statement),
145
+
146
+ // Simple statements
147
+
148
+ _simple_statements: ($) => seq(sep1($._simple_statement, SEMICOLON), optional(SEMICOLON), $._newline),
149
+
150
+ _simple_statement: ($) =>
151
+ choice(
152
+ $.future_import_statement,
153
+ $.import_statement,
154
+ $.import_from_statement,
155
+ $.print_statement,
156
+ $.assert_statement,
157
+ $.expression_statement,
158
+ $.return_statement,
159
+ $.delete_statement,
160
+ $.raise_statement,
161
+ $.pass_statement,
162
+ $.break_statement,
163
+ $.continue_statement,
164
+ $.global_statement,
165
+ $.nonlocal_statement,
166
+ $.exec_statement,
167
+ $.type_alias_statement
168
+ ),
169
+
170
+ import_statement: ($) => seq('import', $._import_list),
171
+
172
+ import_prefix: () => repeat1('.'),
173
+
174
+ relative_import: ($) => seq($.import_prefix, optional($.dotted_name)),
175
+
176
+ future_import_statement: ($) =>
177
+ seq('from', '__future__', 'import', choice($._import_list, seq('(', $._import_list, ')'))),
178
+
179
+ import_from_statement: ($) =>
180
+ seq(
181
+ 'from',
182
+ field('module_name', choice($.relative_import, $.dotted_name)),
183
+ 'import',
184
+ choice($.wildcard_import, $._import_list, seq('(', $._import_list, ')'))
185
+ ),
186
+
187
+ _import_list: ($) => seq(commaSep1(field('name', choice($.dotted_name, $.aliased_import))), optional(',')),
188
+
189
+ aliased_import: ($) => seq(field('name', $.dotted_name), 'as', field('alias', $.identifier)),
190
+
191
+ wildcard_import: () => '*',
192
+
193
+ print_statement: ($) =>
194
+ choice(
195
+ prec(1, seq('print', $.chevron, repeat(seq(',', field('argument', $.expression))), optional(','))),
196
+ prec(-3, prec.dynamic(-1, seq('print', commaSep1(field('argument', $.expression)), optional(','))))
197
+ ),
198
+
199
+ chevron: ($) => seq('>>', $.expression),
200
+
201
+ assert_statement: ($) => seq('assert', commaSep1($.expression)),
202
+
203
+ expression_statement: ($) =>
204
+ choice($.expression, seq(commaSep1($.expression), optional(',')), $.assignment, $.augmented_assignment, $.yield),
205
+
206
+ named_expression: ($) => seq(field('name', $._named_expression_lhs), ':=', field('value', $.expression)),
207
+
208
+ _named_expression_lhs: ($) => choice($.identifier, $.keyword_identifier),
209
+
210
+ return_statement: ($) => seq('return', optional($._expressions)),
211
+
212
+ delete_statement: ($) => seq('del', $._expressions),
213
+
214
+ _expressions: ($) => choice($.expression, $.expression_list),
215
+
216
+ raise_statement: ($) => seq('raise', optional($._expressions), optional(seq('from', field('cause', $.expression)))),
217
+
218
+ pass_statement: () => prec.left('pass'),
219
+ break_statement: () => prec.left('break'),
220
+ continue_statement: () => prec.left('continue'),
221
+
222
+ // Compound statements
223
+
224
+ _compound_statement: ($) =>
225
+ choice(
226
+ $.if_statement,
227
+ $.for_statement,
228
+ $.while_statement,
229
+ $.try_statement,
230
+ $.with_statement,
231
+ $.function_definition,
232
+ $.class_definition,
233
+ $.decorated_definition,
234
+ $.match_statement
235
+ ),
236
+
237
+ if_statement: ($) =>
238
+ seq(
239
+ 'if',
240
+ field('condition', $.expression),
241
+ ':',
242
+ field('consequence', $._suite),
243
+ repeat(field('alternative', $.elif_clause)),
244
+ optional(field('alternative', $.else_clause))
245
+ ),
246
+
247
+ elif_clause: ($) => seq('elif', field('condition', $.expression), ':', field('consequence', $._suite)),
248
+
249
+ else_clause: ($) => seq('else', ':', field('body', $._suite)),
250
+
251
+ match_statement: ($) =>
252
+ seq(
253
+ 'match',
254
+ commaSep1(field('subject', $.expression)),
255
+ optional(','),
256
+ ':',
257
+ field('body', alias($._match_block, $.block))
258
+ ),
259
+
260
+ _match_block: ($) => choice(seq($._indent, repeat(field('alternative', $.case_clause)), $._dedent), $._newline),
261
+
262
+ case_clause: ($) =>
263
+ seq(
264
+ 'case',
265
+ commaSep1($.case_pattern),
266
+ optional(','),
267
+ optional(field('guard', $.if_clause)),
268
+ ':',
269
+ field('consequence', $._suite)
270
+ ),
271
+
272
+ for_statement: ($) =>
273
+ seq(
274
+ optional('async'),
275
+ 'for',
276
+ field('left', $._left_hand_side),
277
+ 'in',
278
+ field('right', $._expressions),
279
+ ':',
280
+ field('body', $._suite),
281
+ field('alternative', optional($.else_clause))
282
+ ),
283
+
284
+ while_statement: ($) =>
285
+ seq(
286
+ 'while',
287
+ field('condition', $.expression),
288
+ ':',
289
+ field('body', $._suite),
290
+ optional(field('alternative', $.else_clause))
291
+ ),
292
+
293
+ try_statement: ($) =>
294
+ seq(
295
+ 'try',
296
+ ':',
297
+ field('body', $._suite),
298
+ repeat($.except_clause),
299
+ optional($.else_clause),
300
+ optional($.finally_clause)
301
+ ),
302
+
303
+ except_clause: ($) =>
304
+ seq(
305
+ 'except',
306
+ optional(token(prec(1, '*'))),
307
+ optional(
308
+ choice(
309
+ seq(field('value', $.expression), optional(seq('as', field('alias', $.expression)))),
310
+ commaSep1(field('value', $.expression))
311
+ )
312
+ ),
313
+ ':',
314
+ $._suite
315
+ ),
316
+
317
+ finally_clause: ($) => seq('finally', ':', $._suite),
318
+
319
+ with_statement: ($) => seq(optional('async'), 'with', $.with_clause, ':', field('body', $._suite)),
320
+
321
+ with_clause: ($) =>
322
+ choice(seq(commaSep1($.with_item), optional(',')), seq('(', commaSep1($.with_item), optional(','), ')')),
323
+
324
+ with_item: ($) => prec.dynamic(1, seq(field('value', $.expression))),
325
+
326
+ function_definition: ($) =>
327
+ seq(
328
+ optional('async'),
329
+ 'def',
330
+ field('name', $.identifier),
331
+ field('type_parameters', optional($.type_parameter)),
332
+ field('parameters', $.parameters),
333
+ optional(seq('->', field('return_type', $.type))),
334
+ ':',
335
+ field('body', $._suite)
336
+ ),
337
+
338
+ parameters: ($) => seq('(', optional($._parameters), ')'),
339
+
340
+ lambda_parameters: ($) => $._parameters,
341
+
342
+ list_splat: ($) => seq('*', $.expression),
343
+
344
+ dictionary_splat: ($) => seq('**', $.expression),
345
+
346
+ global_statement: ($) => seq('global', commaSep1($.identifier)),
347
+
348
+ nonlocal_statement: ($) => seq('nonlocal', commaSep1($.identifier)),
349
+
350
+ exec_statement: ($) =>
351
+ seq('exec', field('code', choice($.string, $.identifier)), optional(seq('in', commaSep1($.expression)))),
352
+
353
+ type_alias_statement: ($) => prec.dynamic(1, seq('type', field('left', $.type), '=', field('right', $.type))),
354
+
355
+ class_definition: ($) =>
356
+ seq(
357
+ 'class',
358
+ field('name', $.identifier),
359
+ field('type_parameters', optional($.type_parameter)),
360
+ field('superclasses', optional($.argument_list)),
361
+ ':',
362
+ field('body', $._suite)
363
+ ),
364
+ type_parameter: ($) => seq('[', commaSep1($.type), optional(','), ']'),
365
+
366
+ parenthesized_list_splat: ($) =>
367
+ prec(
368
+ PREC.parenthesized_list_splat,
369
+ seq('(', choice(alias($.parenthesized_list_splat, $.parenthesized_expression), $.list_splat), ')')
370
+ ),
371
+
372
+ argument_list: ($) =>
373
+ seq(
374
+ '(',
375
+ optional(
376
+ commaSep1(
377
+ choice(
378
+ $.expression,
379
+ $.list_splat,
380
+ $.dictionary_splat,
381
+ alias($.parenthesized_list_splat, $.parenthesized_expression),
382
+ $.keyword_argument
383
+ )
384
+ )
385
+ ),
386
+ optional(','),
387
+ ')'
388
+ ),
389
+
390
+ decorated_definition: ($) =>
391
+ seq(repeat1($.decorator), field('definition', choice($.class_definition, $.function_definition))),
392
+
393
+ decorator: ($) => seq('@', $.expression, $._newline),
394
+
395
+ _suite: ($) => choice(alias($._simple_statements, $.block), seq($._indent, $.block), alias($._newline, $.block)),
396
+
397
+ block: ($) => seq(repeat($._statement), $._dedent),
398
+
399
+ expression_list: ($) =>
400
+ prec.right(seq($.expression, choice(',', seq(repeat1(seq(',', $.expression)), optional(','))))),
401
+
402
+ dotted_name: ($) => prec(1, sep1($.identifier, '.')),
403
+
404
+ // Match cases
405
+
406
+ case_pattern: ($) => prec(1, choice(alias($._as_pattern, $.as_pattern), $.keyword_pattern, $._simple_pattern)),
407
+
408
+ _simple_pattern: ($) =>
409
+ prec(
410
+ 1,
411
+ choice(
412
+ $.class_pattern,
413
+ $.splat_pattern,
414
+ $.union_pattern,
415
+ alias($._list_pattern, $.list_pattern),
416
+ alias($._tuple_pattern, $.tuple_pattern),
417
+ $.dict_pattern,
418
+ $.string,
419
+ $.concatenated_string,
420
+ $.true,
421
+ $.false,
422
+ $.none,
423
+ seq(optional('-'), choice($.integer, $.float)),
424
+ $.complex_pattern,
425
+ $.dotted_name,
426
+ '_'
427
+ )
428
+ ),
429
+
430
+ _as_pattern: ($) => seq($.case_pattern, 'as', $.identifier),
431
+
432
+ union_pattern: ($) => prec.right(seq($._simple_pattern, repeat1(prec.left(seq('|', $._simple_pattern))))),
433
+
434
+ _list_pattern: ($) => seq('[', optional(seq(commaSep1($.case_pattern), optional(','))), ']'),
435
+
436
+ _tuple_pattern: ($) => seq('(', optional(seq(commaSep1($.case_pattern), optional(','))), ')'),
437
+
438
+ dict_pattern: ($) =>
439
+ seq('{', optional(seq(commaSep1(choice($._key_value_pattern, $.splat_pattern)), optional(','))), '}'),
440
+
441
+ _key_value_pattern: ($) => seq(field('key', $._simple_pattern), ':', field('value', $.case_pattern)),
442
+
443
+ keyword_pattern: ($) => seq($.identifier, '=', $._simple_pattern),
444
+
445
+ splat_pattern: ($) => prec(1, seq(choice('*', '**'), choice($.identifier, '_'))),
446
+
447
+ class_pattern: ($) => seq($.dotted_name, '(', optional(seq(commaSep1($.case_pattern), optional(','))), ')'),
448
+
449
+ complex_pattern: ($) =>
450
+ prec(1, seq(optional('-'), choice($.integer, $.float), choice('+', '-'), choice($.integer, $.float))),
451
+
452
+ // Patterns
453
+
454
+ _parameters: ($) => seq(commaSep1($.parameter), optional(',')),
455
+
456
+ _patterns: ($) => seq(commaSep1($.pattern), optional(',')),
457
+
458
+ parameter: ($) =>
459
+ choice(
460
+ $.identifier,
461
+ $.typed_parameter,
462
+ $.default_parameter,
463
+ $.typed_default_parameter,
464
+ $.list_splat_pattern,
465
+ $.tuple_pattern,
466
+ $.keyword_separator,
467
+ $.positional_separator,
468
+ $.dictionary_splat_pattern
469
+ ),
470
+
471
+ pattern: ($) =>
472
+ choice(
473
+ $.identifier,
474
+ $.keyword_identifier,
475
+ $.subscript,
476
+ $.attribute,
477
+ $.list_splat_pattern,
478
+ $.tuple_pattern,
479
+ $.list_pattern
480
+ ),
481
+
482
+ tuple_pattern: ($) => seq('(', optional($._patterns), ')'),
483
+
484
+ list_pattern: ($) => seq('[', optional($._patterns), ']'),
485
+
486
+ default_parameter: ($) =>
487
+ seq(field('name', choice($.identifier, $.tuple_pattern)), '=', field('value', $.expression)),
488
+
489
+ typed_default_parameter: ($) =>
490
+ prec(
491
+ PREC.typed_parameter,
492
+ seq(field('name', $.identifier), ':', field('type', $.type), '=', field('value', $.expression))
493
+ ),
494
+
495
+ list_splat_pattern: ($) => seq('*', choice($.identifier, $.keyword_identifier, $.subscript, $.attribute)),
496
+
497
+ dictionary_splat_pattern: ($) => seq('**', choice($.identifier, $.keyword_identifier, $.subscript, $.attribute)),
498
+
499
+ // Extended patterns (patterns allowed in match statement are far more flexible than simple patterns though still a subset of "expression")
500
+
501
+ as_pattern: ($) => prec.left(seq($.expression, 'as', field('alias', alias($.expression, $.as_pattern_target)))),
502
+
503
+ // Expressions
504
+
505
+ _expression_within_for_in_clause: ($) => choice($.expression, alias($.lambda_within_for_in_clause, $.lambda)),
506
+
507
+ expression: ($) =>
508
+ choice(
509
+ $.comparison_operator,
510
+ $.not_operator,
511
+ $.boolean_operator,
512
+ $.lambda,
513
+ $.primary_expression,
514
+ $.conditional_expression,
515
+ $.named_expression,
516
+ $.as_pattern
517
+ ),
518
+
519
+ primary_expression: ($) =>
520
+ choice(
521
+ $.await,
522
+ $.binary_operator,
523
+ $.identifier,
524
+ $.keyword_identifier,
525
+ $.string,
526
+ $.concatenated_string,
527
+ $.integer,
528
+ $.float,
529
+ $.true,
530
+ $.false,
531
+ $.none,
532
+ $.unary_operator,
533
+ $.attribute,
534
+ $.subscript,
535
+ $.call,
536
+ $.list,
537
+ $.list_comprehension,
538
+ $.dictionary,
539
+ $.dictionary_comprehension,
540
+ $.set,
541
+ $.set_comprehension,
542
+ $.tuple,
543
+ $.parenthesized_expression,
544
+ $.generator_expression,
545
+ $.ellipsis,
546
+ alias($.list_splat_pattern, $.list_splat)
547
+ ),
548
+
549
+ not_operator: ($) => prec(PREC.not, seq('not', field('argument', $.expression))),
550
+
551
+ boolean_operator: ($) =>
552
+ choice(
553
+ prec.left(PREC.and, seq(field('left', $.expression), field('operator', 'and'), field('right', $.expression))),
554
+ prec.left(PREC.or, seq(field('left', $.expression), field('operator', 'or'), field('right', $.expression)))
555
+ ),
556
+
557
+ binary_operator: ($) => {
558
+ /* oxlint-disable typescript/unbound-method -- prec.left and prec.right do not use `this`. */
559
+ /** @type {[typeof prec.left | typeof prec.right, string, number][]} */
560
+ const table = [
561
+ [prec.left, '+', PREC.plus],
562
+ [prec.left, '-', PREC.plus],
563
+ [prec.left, '*', PREC.times],
564
+ [prec.left, '@', PREC.times],
565
+ [prec.left, '/', PREC.times],
566
+ [prec.left, '%', PREC.times],
567
+ [prec.left, '//', PREC.times],
568
+ [prec.right, '**', PREC.power],
569
+ [prec.left, '|', PREC.bitwise_or],
570
+ [prec.left, '&', PREC.bitwise_and],
571
+ [prec.left, '^', PREC.xor],
572
+ [prec.left, '<<', PREC.shift],
573
+ [prec.left, '>>', PREC.shift],
574
+ ];
575
+ /* oxlint-enable typescript/unbound-method */
576
+
577
+ return choice(
578
+ ...table.map(([fn, operator, precedence]) =>
579
+ fn(
580
+ precedence,
581
+ seq(field('left', $.primary_expression), field('operator', operator), field('right', $.primary_expression))
582
+ )
583
+ )
584
+ );
585
+ },
586
+
587
+ unary_operator: ($) =>
588
+ prec(PREC.unary, seq(field('operator', choice('+', '-', '~')), field('argument', $.primary_expression))),
589
+
590
+ _not_in: () => seq('not', 'in'),
591
+
592
+ _is_not: () => seq('is', 'not'),
593
+
594
+ comparison_operator: ($) =>
595
+ prec.left(
596
+ PREC.compare,
597
+ seq(
598
+ $.primary_expression,
599
+ repeat1(
600
+ seq(
601
+ field(
602
+ 'operators',
603
+ choice(
604
+ '<',
605
+ '<=',
606
+ '==',
607
+ '!=',
608
+ '>=',
609
+ '>',
610
+ '<>',
611
+ 'in',
612
+ alias($._not_in, 'not in'),
613
+ 'is',
614
+ alias($._is_not, 'is not')
615
+ )
616
+ ),
617
+ $.primary_expression
618
+ )
619
+ )
620
+ )
621
+ ),
622
+
623
+ lambda: ($) =>
624
+ prec(
625
+ PREC.lambda,
626
+ seq('lambda', field('parameters', optional($.lambda_parameters)), ':', field('body', $.expression))
627
+ ),
628
+
629
+ lambda_within_for_in_clause: ($) =>
630
+ seq(
631
+ 'lambda',
632
+ field('parameters', optional($.lambda_parameters)),
633
+ ':',
634
+ field('body', $._expression_within_for_in_clause)
635
+ ),
636
+
637
+ assignment: ($) =>
638
+ seq(
639
+ field('left', $._left_hand_side),
640
+ choice(
641
+ seq('=', field('right', $._right_hand_side)),
642
+ seq(':', field('type', $.type)),
643
+ seq(':', field('type', $.type), '=', field('right', $._right_hand_side))
644
+ )
645
+ ),
646
+
647
+ augmented_assignment: ($) =>
648
+ seq(
649
+ field('left', $._left_hand_side),
650
+ field('operator', choice('+=', '-=', '*=', '/=', '@=', '//=', '%=', '**=', '>>=', '<<=', '&=', '^=', '|=')),
651
+ field('right', $._right_hand_side)
652
+ ),
653
+
654
+ _left_hand_side: ($) => choice($.pattern, $.pattern_list),
655
+
656
+ pattern_list: ($) => seq($.pattern, choice(',', seq(repeat1(seq(',', $.pattern)), optional(',')))),
657
+
658
+ _right_hand_side: ($) =>
659
+ choice($.expression, $.expression_list, $.assignment, $.augmented_assignment, $.pattern_list, $.yield),
660
+
661
+ yield: ($) => prec.right(seq('yield', choice(seq('from', $.expression), optional($._expressions)))),
662
+
663
+ attribute: ($) =>
664
+ prec(PREC.call, seq(field('object', $.primary_expression), '.', field('attribute', $.identifier))),
665
+
666
+ subscript: ($) =>
667
+ prec(
668
+ PREC.call,
669
+ seq(
670
+ field('value', $.primary_expression),
671
+ '[',
672
+ commaSep1(field('subscript', choice($.expression, $.slice))),
673
+ optional(','),
674
+ ']'
675
+ )
676
+ ),
677
+
678
+ slice: ($) => seq(optional($.expression), ':', optional($.expression), optional(seq(':', optional($.expression)))),
679
+
680
+ ellipsis: () => '...',
681
+
682
+ call: ($) =>
683
+ prec(
684
+ PREC.call,
685
+ seq(
686
+ field('function', $.primary_expression),
687
+ field('arguments', choice($.generator_expression, $.argument_list))
688
+ )
689
+ ),
690
+
691
+ typed_parameter: ($) =>
692
+ prec(
693
+ PREC.typed_parameter,
694
+ seq(choice($.identifier, $.list_splat_pattern, $.dictionary_splat_pattern), ':', field('type', $.type))
695
+ ),
696
+
697
+ type: ($) =>
698
+ choice(prec(1, $.expression), $.splat_type, $.generic_type, $.union_type, $.constrained_type, $.member_type),
699
+ splat_type: ($) => prec(1, seq(choice('*', '**'), $.identifier)),
700
+ generic_type: ($) => prec(1, seq(choice($.identifier, alias('type', $.identifier)), $.type_parameter)),
701
+ union_type: ($) => prec.left(seq($.type, '|', $.type)),
702
+ constrained_type: ($) => prec.right(seq($.type, ':', $.type)),
703
+ member_type: ($) => seq($.type, '.', $.identifier),
704
+
705
+ keyword_argument: ($) =>
706
+ seq(field('name', choice($.identifier, $.keyword_identifier)), '=', field('value', $.expression)),
707
+
708
+ // Literals
709
+
710
+ list: ($) => seq('[', optional($._collection_elements), ']'),
711
+
712
+ set: ($) => seq('{', $._collection_elements, '}'),
713
+
714
+ tuple: ($) => seq('(', optional($._collection_elements), ')'),
715
+
716
+ dictionary: ($) => seq('{', optional(commaSep1(choice($.pair, $.dictionary_splat))), optional(','), '}'),
717
+
718
+ pair: ($) => seq(field('key', $.expression), ':', field('value', $.expression)),
719
+
720
+ list_comprehension: ($) => seq('[', field('body', $.expression), $._comprehension_clauses, ']'),
721
+
722
+ dictionary_comprehension: ($) => seq('{', field('body', $.pair), $._comprehension_clauses, '}'),
723
+
724
+ set_comprehension: ($) => seq('{', field('body', $.expression), $._comprehension_clauses, '}'),
725
+
726
+ generator_expression: ($) => seq('(', field('body', $.expression), $._comprehension_clauses, ')'),
727
+
728
+ _comprehension_clauses: ($) => seq($.for_in_clause, repeat(choice($.for_in_clause, $.if_clause))),
729
+
730
+ parenthesized_expression: ($) => prec(PREC.parenthesized_expression, seq('(', choice($.expression, $.yield), ')')),
731
+
732
+ _collection_elements: ($) =>
733
+ seq(commaSep1(choice($.expression, $.yield, $.list_splat, $.parenthesized_list_splat)), optional(',')),
734
+
735
+ for_in_clause: ($) =>
736
+ prec.left(
737
+ seq(
738
+ optional('async'),
739
+ 'for',
740
+ field('left', $._left_hand_side),
741
+ 'in',
742
+ field('right', commaSep1($._expression_within_for_in_clause)),
743
+ optional(',')
744
+ )
745
+ ),
746
+
747
+ if_clause: ($) => seq('if', $.expression),
748
+
749
+ conditional_expression: ($) =>
750
+ prec.right(PREC.conditional, seq($.expression, 'if', $.expression, 'else', $.expression)),
751
+
752
+ concatenated_string: ($) => seq($.string, repeat1($.string)),
753
+
754
+ string: ($) => seq($.string_start, repeat(choice($.interpolation, $.string_content)), $.string_end),
755
+
756
+ string_content: ($) =>
757
+ prec.right(repeat1(choice($.escape_interpolation, $.escape_sequence, $._not_escape_sequence, $._string_content))),
758
+
759
+ interpolation: ($) =>
760
+ seq(
761
+ '{',
762
+ field('expression', $._f_expression),
763
+ optional('='),
764
+ optional(field('type_conversion', $.type_conversion)),
765
+ optional(field('format_specifier', $.format_specifier)),
766
+ '}'
767
+ ),
768
+
769
+ _f_expression: ($) => choice($.expression, $.expression_list, $.pattern_list, $.yield),
770
+
771
+ escape_sequence: () =>
772
+ token.immediate(
773
+ prec(
774
+ 1,
775
+ seq(
776
+ '\\',
777
+ choice(
778
+ /u[a-fA-F\d]{4}/,
779
+ /U[a-fA-F\d]{8}/,
780
+ /x[a-fA-F\d]{2}/,
781
+ /\d{1,3}/,
782
+ /\r?\n/,
783
+ /['"abfrntv\\]/,
784
+ /N\{[^}]+\}/
785
+ )
786
+ )
787
+ )
788
+ ),
789
+
790
+ _not_escape_sequence: () => token.immediate('\\'),
791
+
792
+ format_specifier: ($) =>
793
+ seq(':', repeat(choice(token(prec(1, /[^{}\n]+/)), alias($.interpolation, $.format_expression)))),
794
+
795
+ type_conversion: () => /![a-z]/,
796
+
797
+ integer: () =>
798
+ token(
799
+ choice(
800
+ seq(choice('0x', '0X'), repeat1(/_?[A-Fa-f0-9]+/), optional(/[Ll]/)),
801
+ seq(choice('0o', '0O'), repeat1(/_?[0-7]+/), optional(/[Ll]/)),
802
+ seq(choice('0b', '0B'), repeat1(/_?[0-1]+/), optional(/[Ll]/)),
803
+ seq(
804
+ repeat1(/[0-9]+_?/),
805
+ choice(
806
+ optional(/[Ll]/), // long numbers
807
+ optional(/[jJ]/) // complex numbers
808
+ )
809
+ )
810
+ )
811
+ ),
812
+
813
+ float: () => {
814
+ const digits = repeat1(/[0-9]+_?/);
815
+ // oxlint-disable-next-line no-useless-escape -- The pattern stays as upstream wrote it, so that src/grammar.json stays identical to upstream's.
816
+ const exponent = seq(/[eE][\+-]?/, digits);
817
+
818
+ return token(
819
+ seq(
820
+ choice(
821
+ seq(digits, '.', optional(digits), optional(exponent)),
822
+ seq(optional(digits), '.', digits, optional(exponent)),
823
+ seq(digits, exponent)
824
+ ),
825
+ optional(/[jJ]/)
826
+ )
827
+ );
828
+ },
829
+
830
+ // @ts-expect-error -- tree-sitter's regex engine takes Unicode property escapes without the `u` flag, which would be recorded in src/grammar.json.
831
+ identifier: () => /[_\p{XID_Start}][_\p{XID_Continue}]*/,
832
+
833
+ keyword_identifier: ($) =>
834
+ choice(
835
+ prec(-3, alias(choice('print', 'exec', 'async', 'await'), $.identifier)),
836
+ alias(choice('type', 'match'), $.identifier)
837
+ ),
838
+
839
+ true: () => 'True',
840
+ false: () => 'False',
841
+ none: () => 'None',
842
+
843
+ await: ($) => prec(PREC.unary, seq('await', $.primary_expression)),
844
+
845
+ comment: () => token(seq('#', /.*/)),
846
+
847
+ line_continuation: () => token(seq('\\', choice(seq(optional('\r'), '\n'), '\0'))),
848
+
849
+ positional_separator: () => '/',
850
+ keyword_separator: () => '*',
851
+ },
852
+ });
853
+
854
+ // Keeps upstream's `PREC` export for grammars that extend this one. `Object.assign` adds the property without declaring
855
+ // a second export, which the type checker rejects next to the export assignment above.
856
+ // oxlint-disable-next-line unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads grammar.js as CommonJS.
857
+ Object.assign(module.exports, { PREC });
858
+
859
+ /**
860
+ * Creates a rule to match one or more of the rules separated by a comma
861
+ *
862
+ * @param {RuleOrLiteral} rule
863
+ *
864
+ * @returns {SeqRule}
865
+ */
866
+ function commaSep1(rule) {
867
+ return sep1(rule, ',');
868
+ }
869
+
870
+ /**
871
+ * Creates a rule to match one or more occurrences of `rule` separated by `sep`
872
+ *
873
+ * @param {RuleOrLiteral} rule
874
+ *
875
+ * @param {RuleOrLiteral} separator
876
+ *
877
+ * @returns {SeqRule}
878
+ */
879
+ function sep1(rule, separator) {
880
+ return seq(rule, repeat(seq(separator, rule)));
881
+ }