@acristoffers/tree-sitter-matlab 1.2.4

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,1000 @@
1
+ /**
2
+ * @file Matlab grammar for tree-sitter
3
+ * @author Álan Crístoffer <acristoffers@startmail.com>
4
+ * @author Amaan Qureshi <amaanq12@gmail.com>
5
+ * @license MIT
6
+ */
7
+
8
+ /* eslint-disable arrow-parens */
9
+ /* eslint-disable camelcase */
10
+ /* eslint-disable-next-line spaced-comment */
11
+ /// <reference types="tree-sitter-cli/dsl" />
12
+ // @ts-check
13
+
14
+ const PREC = {
15
+ parenthesis: -1,
16
+ or: 10,
17
+ and: 11,
18
+ not: 12,
19
+ compare: 13,
20
+ bitwise_or: 14,
21
+ bitwise_and: 15,
22
+ xor: 16,
23
+ shift: 17,
24
+ plus: 18,
25
+ times: 19,
26
+ unary: 20,
27
+ postfix: 21,
28
+ power: 22,
29
+ call: 23,
30
+ member: 23,
31
+ };
32
+
33
+ module.exports = grammar({
34
+ name: 'matlab',
35
+
36
+ conflicts: ($) => [
37
+ [$._expression, $._range_element],
38
+ [$._expression, $._index_expression],
39
+ [$.range],
40
+ [$.block],
41
+ [$._index_range],
42
+ [$._index_arguments],
43
+ [$._index_matrix, $.matrix],
44
+ [$._index_row, $.row],
45
+ [$.function_call, $._function_call_with_keywords],
46
+ [$.block, $._functionless_block],
47
+ ],
48
+
49
+ externals: ($) => [
50
+ $.comment,
51
+ $.line_continuation,
52
+ $.command_name,
53
+ $.command_argument,
54
+ $._single_quote_string_start,
55
+ $._single_quote_string_end,
56
+ $._double_quote_string_start,
57
+ $._double_quote_string_end,
58
+ $.formatting_sequence,
59
+ $.escape_sequence,
60
+ $.string_content,
61
+ $._entry_delimiter,
62
+ $._multioutput_variable_start,
63
+ $._external_identifier,
64
+ $._catch_identifier,
65
+ $._transpose,
66
+ $._ctranspose,
67
+ $.error_sentinel,
68
+ ],
69
+
70
+ extras: ($) => [/\s/, $.comment, $.line_continuation],
71
+
72
+ rules: {
73
+ source_file: ($) =>
74
+ choice(
75
+ optional(seq($._block, repeat($.function_definition))),
76
+ repeat1($.function_definition),
77
+ ),
78
+
79
+ _block: ($) =>
80
+ repeat1(
81
+ seq(
82
+ choice(
83
+ $._statement,
84
+ $._expression,
85
+ alias($._function_definition_with_end, $.function_definition),
86
+ ),
87
+ repeat1($._end_of_line),
88
+ ),
89
+ ),
90
+ _functionless_block: ($) =>
91
+ prec(1, repeat1(
92
+ seq(
93
+ choice($._statement, $._expression),
94
+ repeat1($._end_of_line),
95
+ ),
96
+ )),
97
+ block: ($) => $._block,
98
+
99
+ identifier: ($) => choice($._external_identifier, $._keywords),
100
+
101
+ _statement: ($) =>
102
+ choice(
103
+ $.assignment,
104
+ $.break_statement,
105
+ $.class_definition,
106
+ $.command,
107
+ $.continue_statement,
108
+ $.for_statement,
109
+ $.global_operator,
110
+ $.if_statement,
111
+ $.persistent_operator,
112
+ $.return_statement,
113
+ $.spmd_statement,
114
+ $.switch_statement,
115
+ $.try_statement,
116
+ $.while_statement,
117
+ ),
118
+
119
+ _expression: ($) =>
120
+ choice(
121
+ $.binary_operator,
122
+ $.boolean_operator,
123
+ $.cell,
124
+ $.comparison_operator,
125
+ $.function_call,
126
+ $.handle_operator,
127
+ $.identifier,
128
+ $.lambda,
129
+ $.matrix,
130
+ $.metaclass_operator,
131
+ $.not_operator,
132
+ $.number,
133
+ $.parenthesis,
134
+ $.postfix_operator,
135
+ $.range,
136
+ $.string,
137
+ $.unary_operator,
138
+ $.field_expression,
139
+ ),
140
+
141
+ parenthesis: ($) => prec(PREC.parenthesis, seq('(', $._expression, ')')),
142
+
143
+ _binary_expression: ($) =>
144
+ prec(
145
+ 1,
146
+ choice(
147
+ $.binary_operator,
148
+ $.boolean_operator,
149
+ $.cell,
150
+ $.comparison_operator,
151
+ $.function_call,
152
+ $.identifier,
153
+ $.matrix,
154
+ $.not_operator,
155
+ $.number,
156
+ $.parenthesis,
157
+ $.postfix_operator,
158
+ $.string,
159
+ $.field_expression,
160
+ $.unary_operator,
161
+ ),
162
+ ),
163
+
164
+ binary_operator: ($) => {
165
+ const table = [
166
+ [prec.left, '+', PREC.plus],
167
+ [prec.left, '.+', PREC.plus],
168
+ [prec.left, '-', PREC.plus],
169
+ [prec.left, '.-', PREC.plus],
170
+ [prec.left, '*', PREC.times],
171
+ [prec.left, '.*', PREC.times],
172
+ [prec.left, '/', PREC.times],
173
+ [prec.left, './', PREC.times],
174
+ [prec.left, '\\', PREC.times],
175
+ [prec.left, '.\\', PREC.times],
176
+ [prec.right, '^', PREC.power],
177
+ [prec.right, '.^', PREC.power],
178
+ [prec.left, '|', PREC.bitwise_or],
179
+ [prec.left, '&', PREC.bitwise_and],
180
+ ];
181
+
182
+ return choice(
183
+ // @ts-ignore
184
+ ...table.map(([fn, operator, precedence]) =>
185
+ fn(
186
+ precedence,
187
+ seq(
188
+ field('left', $._binary_expression),
189
+ // @ts-ignore
190
+ operator,
191
+ field('right', $._binary_expression),
192
+ ),
193
+ ),
194
+ ),
195
+ );
196
+ },
197
+
198
+ unary_operator: ($) =>
199
+ prec(
200
+ PREC.unary,
201
+ seq(
202
+ choice('+', '-'),
203
+ field(
204
+ 'operand',
205
+ choice(
206
+ $.cell,
207
+ $.field_expression,
208
+ $.function_call,
209
+ $.identifier,
210
+ $.matrix,
211
+ $.not_operator,
212
+ $.number,
213
+ $.parenthesis,
214
+ $.postfix_operator,
215
+ $.string,
216
+ $.unary_operator,
217
+ ),
218
+ ),
219
+ ),
220
+ ),
221
+
222
+ indirect_access: ($) =>
223
+ prec(
224
+ -2,
225
+ seq(
226
+ '(',
227
+ choice(
228
+ $.number,
229
+ $.binary_operator,
230
+ $.field_expression,
231
+ $.function_call,
232
+ $.identifier,
233
+ $.matrix,
234
+ $.parenthesis,
235
+ $.postfix_operator,
236
+ $.string,
237
+ $.unary_operator,
238
+ ),
239
+ ')',
240
+ ),
241
+ ),
242
+ field_expression: ($) =>
243
+ prec.left(
244
+ PREC.member,
245
+ seq(
246
+ field('object', choice($.identifier, $.function_call)),
247
+ repeat1(
248
+ seq(
249
+ '.',
250
+ field(
251
+ 'field',
252
+ choice(
253
+ $.identifier,
254
+ alias($._extended_keywords, $.identifier),
255
+ alias($._function_call_with_keywords, $.function_call),
256
+ $.indirect_access
257
+ ),
258
+ ),
259
+ ),
260
+ ),
261
+ ),
262
+ ),
263
+
264
+ not_operator: ($) => prec(PREC.not, seq('~', $._expression)),
265
+
266
+ metaclass_operator: ($) => prec.left(seq('?', seq($.identifier, repeat(seq('.', $.identifier))))),
267
+
268
+ handle_operator: ($) =>
269
+ seq('@', seq($.identifier, repeat(seq('.', $.identifier)))),
270
+
271
+ comparison_operator: ($) =>
272
+ prec.left(
273
+ PREC.compare,
274
+ seq(
275
+ $._expression,
276
+ choice('<', '<=', '==', '~=', '>=', '>'),
277
+ $._expression,
278
+ ),
279
+ ),
280
+
281
+ boolean_operator: ($) =>
282
+ choice(
283
+ prec.left(
284
+ PREC.and,
285
+ seq(field('left', $._expression), '&&', field('right', $._expression)),
286
+ ),
287
+ prec.left(
288
+ PREC.or,
289
+ seq(field('left', $._expression), '||', field('right', $._expression)),
290
+ ),
291
+ ),
292
+
293
+ postfix_operator: ($) =>
294
+ prec(
295
+ PREC.postfix,
296
+ seq(
297
+ field(
298
+ 'operand',
299
+ choice(
300
+ $.binary_operator,
301
+ $.cell,
302
+ $.function_call,
303
+ $.identifier,
304
+ $.matrix,
305
+ $.number,
306
+ $.parenthesis,
307
+ $.postfix_operator,
308
+ $.string,
309
+ $.field_expression,
310
+ $.unary_operator,
311
+ ),
312
+ ),
313
+ choice(alias($._transpose, "'"), alias($._ctranspose, ".'")),
314
+ ),
315
+ ),
316
+
317
+ string: ($) =>
318
+ choice(
319
+ seq(
320
+ alias($._double_quote_string_start, '"'),
321
+ repeat(
322
+ choice($.string_content, $.escape_sequence, $.formatting_sequence),
323
+ ),
324
+ alias($._double_quote_string_end, '"'),
325
+ ),
326
+ seq(
327
+ alias($._single_quote_string_start, '\''),
328
+ repeat(
329
+ choice($.string_content, $.escape_sequence, $.formatting_sequence),
330
+ ),
331
+ alias($._single_quote_string_end, '\''),
332
+ ),
333
+ ),
334
+
335
+ row: ($) =>
336
+ seq(
337
+ optional(','),
338
+ choice($._expression, $.ignored_argument),
339
+ repeat(
340
+ seq(alias($._entry_delimiter, ','), choice($._expression, $.ignored_argument)),
341
+ ),
342
+ optional(alias($._entry_delimiter, ',')),
343
+ ),
344
+ matrix: ($) =>
345
+ seq(
346
+ '[',
347
+ repeat("\n"),
348
+ optional(seq($.row, repeat(seq(choice(';', /[\r\n]/), optional($.row))))),
349
+ ']',
350
+ ),
351
+ cell: ($) =>
352
+ seq(
353
+ '{',
354
+ repeat("\n"),
355
+ optional(seq($.row, repeat(seq(choice(';', /[\r\n]/), optional($.row))))),
356
+ '}',
357
+ ),
358
+
359
+ ignored_argument: (_) => prec(PREC.not + 1, '~'),
360
+
361
+ // A = B
362
+ // A(1) = B
363
+ // A{1} = B
364
+ // A.b = B
365
+ // [A, B, C] = D
366
+ assignment: ($) =>
367
+ seq(
368
+ field(
369
+ 'left',
370
+ choice(
371
+ $.identifier,
372
+ $.field_expression,
373
+ $.ignored_argument,
374
+ $.function_call,
375
+ $.multioutput_variable,
376
+ ),
377
+ ),
378
+ '=',
379
+ field('right', $._expression),
380
+ ),
381
+
382
+ multioutput_variable: ($) =>
383
+ seq(
384
+ alias($._multioutput_variable_start, '['),
385
+ repeat("\n"),
386
+ optionalCommaSep(
387
+ choice(
388
+ $.identifier,
389
+ $.field_expression,
390
+ $.ignored_argument,
391
+ $.function_call,
392
+ $.ignored_argument,
393
+ ),
394
+ ),
395
+ ']',
396
+ ),
397
+
398
+ spread_operator: (_) => ':',
399
+
400
+ _index_boolean_operator: ($) =>
401
+ choice(
402
+ prec.left(
403
+ PREC.and + 1,
404
+ seq(field('left', alias($._index_expression, $._expression)), '&&', field('right', alias($._index_expression, $._expression))),
405
+ ),
406
+ prec.left(
407
+ PREC.or + 1,
408
+ seq(field('left', alias($._index_expression, $._expression)), '||', field('right', alias($._index_expression, $._expression))),
409
+ ),
410
+ ),
411
+ _index_comparison_operator: ($) =>
412
+ prec.left(
413
+ PREC.compare + 1,
414
+ seq(
415
+ $._index_expression,
416
+ choice('<', '<=', '==', '~=', '>=', '>'),
417
+ $._index_expression,
418
+ ),
419
+ ),
420
+ _index_not_operator: ($) => prec(PREC.not + 1, seq('~', alias($._index_expression, $._expression))),
421
+ _index_unary_operator: ($) =>
422
+ prec(
423
+ PREC.unary + 1,
424
+ seq(
425
+ choice('+', '-'),
426
+ field(
427
+ 'operand',
428
+ choice(
429
+ $.cell,
430
+ $.field_expression,
431
+ $.function_call,
432
+ $.identifier,
433
+ alias($._index_matrix, $.matrix),
434
+ alias($._index_not_operator, $.not_operator),
435
+ $.number,
436
+ alias($._index_parenthesis, $.parenthesis),
437
+ alias($._index_postfix_operator, $.postfix_operator),
438
+ $.string,
439
+ alias($._index_unary_operator, $.unary_operator),
440
+ ),
441
+ ),
442
+ ),
443
+ ),
444
+ _index_postfix_operator: ($) =>
445
+ prec(
446
+ PREC.postfix + 1,
447
+ seq(
448
+ field(
449
+ 'operand',
450
+ choice(
451
+ alias($._index_binary_operator, $.binary_operator),
452
+ $.cell,
453
+ $.function_call,
454
+ $.identifier,
455
+ alias($._index_matrix, $.matrix),
456
+ $.number,
457
+ alias($._index_parenthesis, $.parenthesis),
458
+ alias($._index_postfix_operator, $.postfix_operator),
459
+ $.string,
460
+ $.field_expression,
461
+ alias($._index_unary_operator, $.unary_operator),
462
+ ),
463
+ ),
464
+ choice(".'", "'"),
465
+ ),
466
+ ),
467
+ _index_row: ($) =>
468
+ seq(
469
+ optional(','),
470
+ choice($._index_expression, $.ignored_argument),
471
+ repeat(
472
+ seq(alias($._entry_delimiter, ','), choice($._index_expression, $.ignored_argument)),
473
+ ),
474
+ optional(alias($._entry_delimiter, ',')),
475
+ ),
476
+ _index_matrix: ($) =>
477
+ seq(
478
+ '[',
479
+ repeat("\n"),
480
+ optional(seq(alias($._index_row, $.row), repeat(seq(choice(';', /[\r\n]/), optional(alias($._index_row, $.row)))))),
481
+ ']',
482
+ ),
483
+ _index_range_element: ($) =>
484
+ prec(1, choice(
485
+ $.field_expression,
486
+ $.function_call,
487
+ $.identifier,
488
+ alias($._index_matrix, $.matrix),
489
+ alias($._index_not_operator, $.not_operator),
490
+ $.number,
491
+ alias($._index_parenthesis, $.parenthesis),
492
+ alias($._index_postfix_operator, $.postfix_operator),
493
+ $.string,
494
+ prec.dynamic(-1, alias($._index_unary_operator, $.unary_operator)),
495
+ prec.dynamic(1, alias($._index_binary_operator, $.binary_operator)),
496
+ $.end_keyword,
497
+ )),
498
+ _index_range: ($) =>
499
+ prec.right(
500
+ PREC.postfix + 1,
501
+ seq(
502
+ $._index_range_element,
503
+ ':',
504
+ $._index_range_element,
505
+ optional(seq(':', $._index_range_element)),
506
+ ),
507
+ ),
508
+ _index_parenthesis: ($) => seq('(', $._index_expression, ')'),
509
+ _index_expression: ($) =>
510
+ choice(
511
+ alias($._index_boolean_operator, $.boolean_operator),
512
+ $.field_expression,
513
+ $.function_call,
514
+ $.identifier,
515
+ $.cell,
516
+ alias($._index_matrix, $.matrix),
517
+ alias($._index_not_operator, $.not_operator),
518
+ $.number,
519
+ alias($._index_comparison_operator, $.comparison_operator),
520
+ alias($._index_parenthesis, $.parenthesis),
521
+ alias($._index_range, $.range),
522
+ alias($._index_binary_operator, $.binary_operator),
523
+ alias($._index_postfix_operator, $.postfix_operator),
524
+ $.string,
525
+ alias($._index_unary_operator, $.unary_operator),
526
+ $.end_keyword,
527
+ ),
528
+ _index_binary_expression: ($) =>
529
+ prec(
530
+ 2,
531
+ choice(
532
+ alias($._index_binary_operator, $.binary_operator),
533
+ alias($._index_boolean_operator, $.boolean_operator),
534
+ $.cell,
535
+ alias($._index_comparison_operator, $.comparison_operator),
536
+ $.function_call,
537
+ $.identifier,
538
+ alias($._index_matrix, $.matrix),
539
+ alias($._index_not_operator, $.not_operator),
540
+ $.number,
541
+ alias($._index_parenthesis, $.parenthesis),
542
+ alias($._index_postfix_operator, $.postfix_operator),
543
+ $.string,
544
+ $.field_expression,
545
+ alias($._index_unary_operator, $.unary_operator),
546
+ $.end_keyword,
547
+ ),
548
+ ),
549
+ _index_binary_operator: ($) => {
550
+ const table = [
551
+ [prec.left, '+', PREC.plus],
552
+ [prec.left, '.+', PREC.plus],
553
+ [prec.left, '-', PREC.plus],
554
+ [prec.left, '.-', PREC.plus],
555
+ [prec.left, '*', PREC.times],
556
+ [prec.left, '.*', PREC.times],
557
+ [prec.left, '/', PREC.times],
558
+ [prec.left, './', PREC.times],
559
+ [prec.left, '\\', PREC.times],
560
+ [prec.left, '.\\', PREC.times],
561
+ [prec.right, '^', PREC.power],
562
+ [prec.right, '.^', PREC.power],
563
+ [prec.left, '|', PREC.bitwise_or],
564
+ [prec.left, '&', PREC.bitwise_and],
565
+ ];
566
+ return choice(
567
+ ...table.map(([fn, op, p]) =>
568
+ fn(p, seq(field('left', $._index_binary_expression), op, field('right', $._index_binary_expression))),
569
+ ),
570
+ );
571
+ },
572
+ _index_argument: ($) => choice($.spread_operator, choice(prec.dynamic(1, $._index_expression), prec.dynamic(-1, $._expression))),
573
+ _index_arguments: ($) => commaSep1(field('argument', $._index_argument)),
574
+
575
+ arguments: ($) =>
576
+ choice(
577
+ seq(
578
+ $._index_arguments,
579
+ optional(seq(',', commaSep1(seq($.identifier, '=', $._expression)))),
580
+ ),
581
+ commaSep1(seq($.identifier, '=', $._expression)),
582
+ ),
583
+ _args: ($) =>
584
+ choice(
585
+ seq('(', optional($.arguments), ')'),
586
+ seq('{', optional($.arguments), '}'),
587
+ ),
588
+ function_call: ($) =>
589
+ choice(
590
+ prec.right(
591
+ PREC.call,
592
+ seq(
593
+ field(
594
+ 'name',
595
+ choice(
596
+ alias($.end_keyword, $.identifier),
597
+ $.identifier,
598
+ $.function_call,
599
+ $.indirect_access,
600
+ ),
601
+ ),
602
+ optional(seq('@', alias($.property_name, $.superclass))),
603
+ $._args,
604
+ ),
605
+ ),
606
+ prec.right(
607
+ PREC.call,
608
+ seq(
609
+ field(
610
+ 'name',
611
+ choice(
612
+ $.identifier,
613
+ $.function_call,
614
+ $.indirect_access,
615
+ ),
616
+ ),
617
+ seq('@', alias($.property_name, $.superclass)),
618
+ optional($._args),
619
+ ),
620
+ ),),
621
+ _function_call_with_keywords: ($) =>
622
+ choice(
623
+ prec.right(
624
+ PREC.call,
625
+ seq(
626
+ field(
627
+ 'name',
628
+ choice(
629
+ alias($.end_keyword, $.identifier),
630
+ alias($._extended_keywords, $.identifier),
631
+ $.identifier,
632
+ $.function_call,
633
+ $.indirect_access,
634
+ ),
635
+ ),
636
+ optional(seq('@', alias($.property_name, $.superclass))),
637
+ $._args,
638
+ ),
639
+ ),
640
+ prec.right(
641
+ PREC.call,
642
+ seq(
643
+ field(
644
+ 'name',
645
+ choice(
646
+ $.identifier,
647
+ $.function_call,
648
+ $.indirect_access,
649
+ ),
650
+ ),
651
+ seq('@', alias($.property_name, $.superclass)),
652
+ optional($._args),
653
+ ),
654
+ ),),
655
+
656
+ command: ($) => prec.right(seq($.command_name, repeat($.command_argument))),
657
+
658
+ // Unary operators cannot bind stronger in this case_clause, lest the world falls apart.
659
+ _range_element: ($) =>
660
+ choice(
661
+ $.field_expression,
662
+ $.function_call,
663
+ $.identifier,
664
+ $.matrix,
665
+ $.not_operator,
666
+ $.number,
667
+ $.parenthesis,
668
+ $.postfix_operator,
669
+ $.string,
670
+ prec.dynamic(-1, $.unary_operator),
671
+ prec.dynamic(1, $.binary_operator),
672
+ ),
673
+ range: ($) =>
674
+ prec.right(
675
+ PREC.postfix,
676
+ seq(
677
+ $._range_element,
678
+ ':',
679
+ $._range_element,
680
+ optional(seq(':', $._range_element)),
681
+ ),
682
+ ),
683
+
684
+ return_statement: (_) => 'return',
685
+ continue_statement: (_) => 'continue',
686
+ break_statement: (_) => 'break',
687
+
688
+ elseif_clause: ($) => prec.left(
689
+ seq(
690
+ 'elseif',
691
+ field('condition', $._expression),
692
+ repeat($._end_of_line),
693
+ optional($.block),
694
+ )),
695
+ else_clause: ($) => prec.left(seq('else', repeat($._end_of_line), optional($.block))),
696
+ if_statement: ($) =>
697
+ seq(
698
+ 'if',
699
+ field('condition', $._expression),
700
+ repeat($._end_of_line),
701
+ optional($.block),
702
+ repeat($.elseif_clause),
703
+ optional($.else_clause),
704
+ 'end',
705
+ ),
706
+
707
+ iterator: ($) => seq($.identifier, '=', $._expression),
708
+ parfor_options: ($) => choice($.number, $.identifier, $.function_call, $.string),
709
+ for_statement: ($) =>
710
+ choice(
711
+ seq(
712
+ choice('for', 'parfor'),
713
+ choice($.iterator, seq("(", $.iterator, ")")),
714
+ repeat($._end_of_line),
715
+ optional($.block),
716
+ 'end',
717
+ ),
718
+ seq(
719
+ 'parfor',
720
+ '(',
721
+ $.iterator,
722
+ ',',
723
+ $.parfor_options,
724
+ ')',
725
+ repeat($._end_of_line),
726
+ optional($.block),
727
+ 'end',
728
+ ),
729
+ ),
730
+
731
+ while_statement: ($) =>
732
+ seq(
733
+ 'while',
734
+ field('condition', $._expression),
735
+ repeat($._end_of_line),
736
+ optional($.block),
737
+ 'end',
738
+ ),
739
+
740
+ case_clause: ($) => prec.left(
741
+ seq(
742
+ 'case',
743
+ // MATLAB says it should be a `switch_expr`, but then accepts any expression
744
+ field('condition', $._expression),
745
+ repeat1($._end_of_line),
746
+ optional($.block),
747
+ )),
748
+ otherwise_clause: ($) => prec.left(seq('otherwise', repeat($._end_of_line), optional($.block))),
749
+ switch_statement: ($) =>
750
+ seq(
751
+ 'switch',
752
+ field('condition', $._expression),
753
+ repeat($._end_of_line),
754
+ repeat($.case_clause),
755
+ optional($.otherwise_clause),
756
+ 'end',
757
+ ),
758
+
759
+ _lambda_arguments: ($) =>
760
+ commaSep1(choice($.ignored_argument, $.identifier)),
761
+ lambda: ($) =>
762
+ prec.right(
763
+ seq(
764
+ '@',
765
+ '(',
766
+ alias(optional($._lambda_arguments), $.arguments),
767
+ ')',
768
+ field('expression', $._expression),
769
+ ),
770
+ ),
771
+
772
+ global_operator: ($) => seq('global', repeat($.identifier)),
773
+
774
+ persistent_operator: ($) => seq('persistent', repeat($.identifier)),
775
+
776
+ _argument_attributes: ($) =>
777
+ seq(
778
+ '(',
779
+ field('argument', $.identifier),
780
+ repeat(seq(',', field('argument', $.identifier))),
781
+ ')',
782
+ ),
783
+ class_property: ($) => seq($.identifier, '.?', $.identifier, repeat(seq('.', $.identifier))),
784
+ arguments_statement: ($) =>
785
+ prec.right(1, seq(
786
+ 'arguments',
787
+ optional(alias($._argument_attributes, $.attributes)),
788
+ repeat1($._end_of_line),
789
+ repeat(choice($.property, seq($.class_property, repeat1($._end_of_line)))),
790
+ 'end',
791
+ optional($._end_of_line),
792
+ )),
793
+
794
+ function_output: ($) =>
795
+ seq(choice($.identifier, $.multioutput_variable), '='),
796
+ function_arguments: ($) =>
797
+ seq('(', field('arguments', optional($._lambda_arguments)), ')'),
798
+ function_definition: ($) =>
799
+ prec.right(seq(
800
+ 'function',
801
+ optional($.function_output),
802
+ optional(choice('get.', 'set.')),
803
+ field('name', choice($.identifier, $.property_name, alias($.end_keyword, $.identifier))),
804
+ optional($.function_arguments),
805
+ $._end_of_line,
806
+ repeat($.arguments_statement),
807
+ repeat($.comment),
808
+ repeat($._end_of_line),
809
+ optional(alias($._functionless_block, $.block)),
810
+ optional(seq(choice('end', 'endfunction'), optional(';'))),
811
+ )),
812
+ _function_definition_with_end: ($) =>
813
+ prec.right(seq(
814
+ 'function',
815
+ optional($.function_output),
816
+ optional(choice('get.', 'set.')),
817
+ field('name', choice($.identifier, $.property_name, alias($.end_keyword, $.identifier))),
818
+ optional($.function_arguments),
819
+ $._end_of_line,
820
+ repeat($.arguments_statement),
821
+ repeat($.comment),
822
+ repeat($._end_of_line),
823
+ optional($.block),
824
+ choice('end', 'endfunction'),
825
+ optional(';'),
826
+ )),
827
+
828
+ attribute: ($) => seq($.identifier, optional(seq('=', $._expression))),
829
+ attributes: ($) =>
830
+ seq('(', $.attribute, repeat(seq(',', $.attribute)), ')'),
831
+ superclasses: ($) =>
832
+ seq('<', $.property_name, repeat(seq('&', $.property_name))),
833
+ dimensions: ($) =>
834
+ seq('(', commaSep1(choice($.number, $.spread_operator)), ')'),
835
+ validation_functions: ($) =>
836
+ seq('{', choice($.function_call, $.identifier, $.field_expression), repeat(seq(optional(","), choice($.function_call, $.identifier, $.field_expression))), '}'),
837
+ default_value: ($) => seq('=', $._expression),
838
+ property_name: ($) =>
839
+ prec.right(
840
+ prec.dynamic(
841
+ -1,
842
+ seq(
843
+ $.identifier,
844
+ repeat(seq('.', $.identifier)),
845
+ optional(seq('.', '*')),
846
+ ),
847
+ ),
848
+ ),
849
+ property: ($) =>
850
+ choice(
851
+ seq(
852
+ field(
853
+ 'name',
854
+ choice($.identifier, $.property_name, $.ignored_argument),
855
+ ),
856
+ optional($.dimensions),
857
+ optional(choice($.identifier, $.property_name)),
858
+ optional($.validation_functions),
859
+ optional($.default_value),
860
+ repeat1($._end_of_line),
861
+ ),
862
+ seq(
863
+ field(
864
+ 'name',
865
+ choice($.identifier, $.property_name, $.ignored_argument),
866
+ ),
867
+ '@',
868
+ $.identifier,
869
+ alias(optional(choice('vector', 'matrix', 'scalar')), $.identifier),
870
+ optional($.default_value),
871
+ repeat1($._end_of_line),
872
+ )
873
+ ),
874
+ properties: ($) =>
875
+ seq(
876
+ 'properties',
877
+ optional($.attributes),
878
+ repeat1($._end_of_line),
879
+ repeat($.property),
880
+ 'end',
881
+ ),
882
+ function_signature: ($) =>
883
+ seq(
884
+ optional($.function_output),
885
+ optional(choice('get.', 'set.')),
886
+ field('name', alias(choice($._external_identifier, 'get', 'set', 'arguments'), $.identifier)),
887
+ optional($.function_arguments),
888
+ ),
889
+ methods: ($) =>
890
+ seq(
891
+ 'methods',
892
+ optional($.attributes),
893
+ repeat1($._end_of_line),
894
+ repeat(
895
+ seq(
896
+ choice(
897
+ alias(seq($.function_output, field('name', alias('end', $.identifier)), $.function_arguments), $.function_signature),
898
+ $.function_signature,
899
+ alias($._function_definition_with_end, $.function_definition)),
900
+ repeat($._end_of_line)),
901
+ ),
902
+ 'end',
903
+ ),
904
+ events: ($) =>
905
+ seq(
906
+ 'events',
907
+ optional($.attributes),
908
+ $._end_of_line,
909
+ repeat(choice(seq($.identifier, $._end_of_line), $._end_of_line)),
910
+ 'end',
911
+ ),
912
+ enum: ($) =>
913
+ seq($.identifier, optional(seq('(', commaSep1($._expression), ')'))),
914
+ enumeration: ($) =>
915
+ seq(
916
+ 'enumeration',
917
+ optional($.attributes),
918
+ $._end_of_line,
919
+ repeat(choice(seq($.enum, $._end_of_line), $._end_of_line)),
920
+ 'end',
921
+ ),
922
+ class_definition: ($) =>
923
+ seq(
924
+ 'classdef',
925
+ optional($.attributes),
926
+ field('name', $.identifier),
927
+ optional($.superclasses),
928
+ $._end_of_line,
929
+ repeat(choice($.properties, $.methods, $.events, $.enumeration, ';')),
930
+ 'end',
931
+ ),
932
+
933
+ catch_clause: ($) => prec.left(
934
+ seq(
935
+ 'catch',
936
+ optional(seq(alias($._catch_identifier, $.identifier), $._end_of_line)),
937
+ repeat($._end_of_line),
938
+ optional($.block),
939
+ )),
940
+ try_statement: ($) =>
941
+ seq(
942
+ 'try',
943
+ repeat($._end_of_line),
944
+ optional($.block),
945
+ optional($.catch_clause),
946
+ 'end',
947
+ ),
948
+
949
+ spmd_statement: ($) =>
950
+ seq(
951
+ 'spmd',
952
+ optional(seq('(', optional(choice($._expression, seq($._expression, ',', $._expression))), ')')),
953
+ repeat($._end_of_line),
954
+ optional($.block),
955
+ 'end',
956
+ ),
957
+
958
+ number: ($) => choice(
959
+ /(\d+|\d+\.\d*|\.\d+)([eEdD][+-]?\d+)?[ij]?/,
960
+ /0[xX][\dA-Fa-f]+([su](8|16|32|64))?/,
961
+ /0[bB][01]+([su](8|16|32|64))?/
962
+ ),
963
+
964
+ end_keyword: ($) => 'end',
965
+
966
+ _keywords: ($) => choice("get", "set", "properties", "arguments", "enumeration", "events", "methods"),
967
+
968
+ _extended_keywords: ($) => prec(100, choice(
969
+ "break", "case", "catch", "classdef", "continue", "else", "elseif", "end", "for", "function",
970
+ "global", "if", "otherwise", "parfor", "persistent", "return", "spmd", "switch", "try",
971
+ "while",
972
+ )),
973
+
974
+ _end_of_line: ($) => choice(';', '\n', '\r', ','),
975
+ },
976
+ });
977
+
978
+ /**
979
+ * Creates a rule to match one or more of the rules separated by a comma
980
+ *
981
+ * @param {Rule} rule
982
+ *
983
+ * @return {SeqRule}
984
+ *
985
+ */
986
+ function commaSep1(rule) {
987
+ return seq(rule, repeat(seq(',', rule)));
988
+ }
989
+
990
+ /**
991
+ * Creates a rule to match zero or more of the rules optionally separated by a comma
992
+ *
993
+ * @param {Rule} rule
994
+ *
995
+ * @return {SeqRule}
996
+ *
997
+ */
998
+ function optionalCommaSep(rule) {
999
+ return optional(seq(rule, repeat(seq(optional(','), rule)), optional(',')));
1000
+ }