tree-sitter-abl 0.0.47

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/random2.js ADDED
@@ -0,0 +1,2349 @@
1
+ // Precedence pulled from: https://www.tutorialspoint.com/fortran/fortran_operators.htm
2
+ // I need to test this because there are some conflicts between info here and
3
+ // that provided in: https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-summary-of-operator-precedence
4
+ // and in http://earth.uni-muenster.de/~joergs/doc/f90/lrm/lrm0067.htm
5
+ // my final settings will be based on gfortran test cases
6
+ // Additional ref info:
7
+ // https://userpage.physik.fu-berlin.de/~tburnus/gcc-trunk/FortranRef/fQuickRef1.pdf
8
+ // http://earth.uni-muenster.de/~joergs/doc/f90/lrm/dflrm.htm#book-toc
9
+ // http://www.lahey.com/docs/lfprohelp/F95AREXTERNALStmt.htm
10
+ // http://www.personal.psu.edu/jhm/f90/statements/intrinsic.html
11
+ // http://earth.uni-muenster.de/~joergs/doc/f90/lrm/lrm0083.htm#data_type_declar
12
+ //
13
+ // I'll need to figure out how best to add support for statement labels
14
+ // since the parser doesn't support the ^ regex token, a using a seq
15
+ // might work as long as the label is optional.
16
+ //
17
+ const PREC = {
18
+ ASSIGNMENT: -10,
19
+ DEFAULT: 0,
20
+ DEFINED_OPERATOR: 2,
21
+ LOGICAL_EQUIV: 5,
22
+ LOGICAL_OR: 10,
23
+ LOGICAL_AND: 20,
24
+ LOGICAL_NOT: 30,
25
+ RELATIONAL: 40,
26
+ ADDITIVE: 50,
27
+ MULTIPLICATIVE: 60,
28
+ EXPONENT: 70,
29
+ CALL: 80,
30
+ UNARY: 90,
31
+ TYPE_MEMBER: 100
32
+ }
33
+
34
+ const PREPROC_PREC = {
35
+ DEFAULT: 0,
36
+ LOGICAL_OR: 1,
37
+ LOGICAL_AND: 2,
38
+ INCLUSIVE_OR: 3,
39
+ EXCLUSIVE_OR: 4,
40
+ BITWISE_AND: 5,
41
+ EQUAL: 6,
42
+ RELATIONAL: 7,
43
+ OFFSETOF: 8,
44
+ SHIFT: 9,
45
+ ADD: 10,
46
+ MULTIPLY: 11,
47
+ UNARY: 14,
48
+ CALL: 15,
49
+ };
50
+
51
+ module.exports = grammar({
52
+ name: 'fortran',
53
+
54
+ externals: $ => [
55
+ '&',
56
+ $._integer_literal,
57
+ $._float_literal,
58
+ $._boz_literal,
59
+ $._string_literal,
60
+ $._string_literal_kind,
61
+ $._external_end_of_statement,
62
+ $._preproc_unary_operator,
63
+ ],
64
+
65
+ extras: $ => [
66
+ // This allows escaping newlines everywhere, although this is only valid in
67
+ // preprocessor statements
68
+ /\s|\\\r?\n/,
69
+ $.comment,
70
+ '&',
71
+ ],
72
+
73
+ inline: $ => [
74
+ $._top_level_item,
75
+ $._statement
76
+ ],
77
+
78
+ conflicts: $ => [
79
+ [$._expression, $.complex_literal],
80
+ [$._argument_list, $.parenthesized_expression],
81
+ [$.case_statement],
82
+ [$.data_set, $._expression],
83
+ [$.data_statement, $.identifier],
84
+ [$.data_value, $._expression],
85
+ [$.else_clause],
86
+ [$.elseif_clause, $.identifier],
87
+ [$.elseif_clause],
88
+ [$.elsewhere_clause],
89
+ [$.intrinsic_type],
90
+ [$._intrinsic_type, $.identifier],
91
+ [$.module_statement, $.procedure_qualifier],
92
+ [$.procedure_declaration],
93
+ [$.rank_statement],
94
+ [$.stop_statement, $.identifier],
95
+ [$.type_statement],
96
+ [$.preproc_ifdef_in_specification_part, $.program],
97
+ [$.preproc_else_in_specification_part, $.program],
98
+ [$.statement_function, $._expression],
99
+ [$.coarray_critical_statement, $.identifier],
100
+ ],
101
+
102
+ rules: {
103
+ translation_unit: $ => seq(
104
+ repeat($._top_level_item),
105
+ optional($.program),
106
+ ),
107
+
108
+ _top_level_item: $ => prec(2, choice(
109
+ seq($.include_statement, $._end_of_statement),
110
+ $.program,
111
+ $.module,
112
+ $.submodule,
113
+ $.interface,
114
+ $.subroutine,
115
+ $.function,
116
+ $.preproc_if,
117
+ $.preproc_ifdef,
118
+ $.preproc_include,
119
+ $.preproc_def,
120
+ $.preproc_function_def,
121
+ $.preproc_call,
122
+ )),
123
+
124
+ // Preprocessor
125
+
126
+ preproc_include: $ => seq(
127
+ preprocessor('include'),
128
+ field('path', choice(
129
+ $.string_literal,
130
+ $.identifier,
131
+ $.system_lib_string,
132
+ alias($.preproc_call_expression, $.call_expression),
133
+ )),
134
+ /\r?\n/,
135
+ ),
136
+
137
+ preproc_def: $ => seq(
138
+ preprocessor('define'),
139
+ field('name', $.identifier),
140
+ field('value', optional($.preproc_arg)),
141
+ token.immediate(/\r?\n/),
142
+ ),
143
+
144
+ preproc_function_def: $ => seq(
145
+ preprocessor('define'),
146
+ field('name', $.identifier),
147
+ field('parameters', $.preproc_params),
148
+ field('value', optional($.preproc_arg)),
149
+ token.immediate(/\r?\n/),
150
+ ),
151
+
152
+ preproc_params: $ => seq(
153
+ token.immediate('('), commaSep(choice($.identifier, '...')), ')',
154
+ ),
155
+
156
+ preproc_call: $ => seq(
157
+ field('directive', $.preproc_directive),
158
+ field('argument', optional($.preproc_arg)),
159
+ token.immediate(/\r?\n/),
160
+ ),
161
+
162
+ ...preprocIf('', $ => repeat($._top_level_item)),
163
+ ...preprocIf('_in_module', $ => seq(
164
+ repeat($._specification_part),
165
+ optional($.internal_procedures)
166
+ )),
167
+ ...preprocIf('_in_specification_part', $ => seq(
168
+ repeat($._specification_part),
169
+ repeat($._statement),
170
+ optional($.internal_procedures)
171
+ ), 3),
172
+ ...preprocIf('_in_statements', $ => seq(
173
+ repeat($._statement),
174
+ optional($.internal_procedures)
175
+ ), 1),
176
+ ...preprocIf('_in_procedure_statements', $ => seq(
177
+ repeat($._statement),
178
+ optional($.internal_procedures)
179
+ ), 2),
180
+ ...preprocIf('_in_internal_procedures', $ => repeat($._internal_procedures)),
181
+ ...preprocIf('_in_interface', $ => repeat($._interface_items)),
182
+ ...preprocIf('_in_derived_type', $ => repeat($.variable_declaration)),
183
+ ...preprocIf('_in_bound_procedures', $ => repeat($.procedure_statement)),
184
+ ...preprocIf('_in_select_case', $ => $.case_statement),
185
+ ...preprocIf('_in_select_type', $ => $.type_statement),
186
+ ...preprocIf('_in_select_rank', $ => $.rank_statement),
187
+
188
+ preproc_arg: _ => token(prec(-1, /\S([^/\n]|\/[^*]|\\\r?\n)*/)),
189
+ preproc_directive: _ => /#[ \t]*[a-zA-Z0-9]\w*/,
190
+
191
+ _preproc_expression: $ => choice(
192
+ $.identifier,
193
+ alias($.preproc_call_expression, $.call_expression),
194
+ $.number_literal,
195
+ $.string_literal,
196
+ $.preproc_defined,
197
+ alias($.preproc_unary_expression, $.unary_expression),
198
+ alias($.preproc_binary_expression, $.binary_expression),
199
+ alias($.preproc_parenthesized_expression, $.parenthesized_expression),
200
+ ),
201
+
202
+ preproc_parenthesized_expression: $ => seq(
203
+ '(',
204
+ $._preproc_expression,
205
+ ')',
206
+ ),
207
+
208
+ preproc_defined: $ => choice(
209
+ prec(PREPROC_PREC.CALL, seq('defined', '(', $.identifier, ')')),
210
+ seq('defined', $.identifier),
211
+ ),
212
+
213
+ // Preprocessor unary operator uses an external scanner to catch
214
+ // '!' before its parsed as a comment
215
+ preproc_unary_expression: $ => prec.left(PREPROC_PREC.UNARY, seq(
216
+ field('operator', $._preproc_unary_operator),
217
+ field('argument', $._preproc_expression),
218
+ )),
219
+
220
+ preproc_call_expression: $ => prec(PREPROC_PREC.CALL, seq(
221
+ field('function', $.identifier),
222
+ field('arguments', alias($.preproc_argument_list, $.argument_list)),
223
+ )),
224
+
225
+ preproc_argument_list: $ => seq(
226
+ '(',
227
+ commaSep($._preproc_expression),
228
+ ')',
229
+ ),
230
+
231
+ preproc_comment: $ => /\/\*.*\*\//,
232
+
233
+ preproc_binary_expression: $ => {
234
+ const table = [
235
+ ['+', PREPROC_PREC.ADD],
236
+ ['-', PREPROC_PREC.ADD],
237
+ ['*', PREPROC_PREC.MULTIPLY],
238
+ ['/', PREPROC_PREC.MULTIPLY],
239
+ ['%', PREPROC_PREC.MULTIPLY],
240
+ ['||', PREPROC_PREC.LOGICAL_OR],
241
+ ['&&', PREPROC_PREC.LOGICAL_AND],
242
+ ['|', PREPROC_PREC.INCLUSIVE_OR],
243
+ ['^', PREPROC_PREC.EXCLUSIVE_OR],
244
+ ['&', PREPROC_PREC.BITWISE_AND],
245
+ ['==', PREPROC_PREC.EQUAL],
246
+ ['!=', PREPROC_PREC.EQUAL],
247
+ ['>', PREPROC_PREC.RELATIONAL],
248
+ ['>=', PREPROC_PREC.RELATIONAL],
249
+ ['<=', PREPROC_PREC.RELATIONAL],
250
+ ['<', PREPROC_PREC.RELATIONAL],
251
+ ['<<', PREPROC_PREC.SHIFT],
252
+ ['>>', PREPROC_PREC.SHIFT],
253
+ ];
254
+
255
+ return choice(...table.map(([operator, precedence]) => {
256
+ return prec.left(precedence, seq(
257
+ field('left', $._preproc_expression),
258
+ // @ts-ignore
259
+ field('operator', operator),
260
+ field('right', $._preproc_expression),
261
+ ));
262
+ }));
263
+ },
264
+
265
+ system_lib_string: _ => token(seq(
266
+ '<',
267
+ repeat(choice(/[^>\n]/, '\\>')),
268
+ '>',
269
+ )),
270
+
271
+ // Block level structures
272
+
273
+ program: $ => seq(
274
+ optional($.program_statement),
275
+ repeat(
276
+ choice(
277
+ $._specification_part,
278
+ alias($.preproc_if_in_specification_part, $.preproc_if),
279
+ alias($.preproc_ifdef_in_specification_part, $.preproc_ifdef)
280
+ ),
281
+ ),
282
+ repeat($._statement),
283
+ optional($.internal_procedures),
284
+ $.end_program_statement
285
+ ),
286
+
287
+ program_statement: $ => seq(caseInsensitive('program'), $._name),
288
+ end_program_statement: $ => blockStructureEnding($, 'program'),
289
+
290
+ module: $ => seq(
291
+ $.module_statement,
292
+ repeat(
293
+ choice(
294
+ $._specification_part,
295
+ alias($.preproc_if_in_module, $.preproc_if),
296
+ alias($.preproc_ifdef_in_module, $.preproc_ifdef)
297
+ ),
298
+ ),
299
+ optional($.internal_procedures),
300
+ $.end_module_statement
301
+ ),
302
+
303
+ module_statement: $ => seq(caseInsensitive('module'), $._name),
304
+ end_module_statement: $ => blockStructureEnding($, 'module'),
305
+
306
+ submodule: $ => seq(
307
+ $.submodule_statement,
308
+ repeat(
309
+ choice(
310
+ $._specification_part,
311
+ alias($.preproc_if_in_module, $.preproc_if),
312
+ alias($.preproc_ifdef_in_module, $.preproc_ifdef)
313
+ ),
314
+ ),
315
+ optional($.internal_procedures),
316
+ $.end_submodule_statement
317
+ ),
318
+
319
+ submodule_statement: $ => seq(
320
+ caseInsensitive('submodule'),
321
+ '(',
322
+ field('ancestor', $.module_name),
323
+ optional(seq(
324
+ ':', field('parent', $.module_name)
325
+ )),
326
+ ')',
327
+ $._name
328
+ ),
329
+ end_submodule_statement: $ => blockStructureEnding($, 'submodule'),
330
+ module_name: $ => $._name,
331
+
332
+ interface: $ => seq(
333
+ $.interface_statement,
334
+ repeat(choice(
335
+ $._interface_items,
336
+ $.preproc_include,
337
+ $.preproc_def,
338
+ $.preproc_function_def,
339
+ $.preproc_call,
340
+ alias($.preproc_if_in_interface, $.preproc_if),
341
+ alias($.preproc_ifdef_in_interface, $.preproc_ifdef),
342
+ )),
343
+ $.end_interface_statement
344
+ ),
345
+
346
+ _interface_items: $ => choice(
347
+ $.import_statement,
348
+ $.procedure_statement,
349
+ $.function,
350
+ $.subroutine
351
+ ),
352
+
353
+ interface_statement: $ => seq(
354
+ optional($.abstract_specifier),
355
+ caseInsensitive('interface'),
356
+ optional(choice($._name, $._generic_procedure)),
357
+ $._end_of_statement,
358
+ ),
359
+
360
+ end_interface_statement: $ => prec.right(seq(
361
+ whiteSpacedKeyword('end', 'interface'),
362
+ optional(choice($._name, $._generic_procedure)),
363
+ $._end_of_statement
364
+ )),
365
+
366
+ assignment: $ => seq(caseInsensitive('assignment'), '(', '=', ')'),
367
+ operator: $ => seq(caseInsensitive('operator'), '(', /[^()]+/, ')'),
368
+ defined_io_procedure: $ => seq(
369
+ choice(caseInsensitive('read'), caseInsensitive('write')),
370
+ '(',
371
+ choice(caseInsensitive('formatted'), caseInsensitive('unformatted')),
372
+ ')'
373
+ ),
374
+ _generic_procedure: $ => choice(
375
+ $.assignment,
376
+ $.operator,
377
+ $.defined_io_procedure,
378
+ ),
379
+
380
+ subroutine: $ => procedure($, $.subroutine_statement, $.end_subroutine_statement),
381
+
382
+ subroutine_statement: $ => seq(
383
+ optional($._callable_interface_qualifers),
384
+ caseInsensitive('subroutine'),
385
+ field('name', $._name),
386
+ optional(field('parameters',$._parameters)),
387
+ optional($.language_binding)
388
+ ),
389
+
390
+ end_subroutine_statement: $ => blockStructureEnding($, 'subroutine'),
391
+
392
+ module_procedure: $ => procedure($, $.module_procedure_statement, $.end_module_procedure_statement),
393
+
394
+ module_procedure_statement: $ => seq(
395
+ optional($._callable_interface_qualifers),
396
+ seq(caseInsensitive('module'), caseInsensitive('procedure')),
397
+ field('name', $._name)
398
+ ),
399
+
400
+ end_module_procedure_statement: $ => blockStructureEnding($, 'procedure'),
401
+
402
+ function: $ => procedure($, $.function_statement, $.end_function_statement),
403
+
404
+ function_statement: $ => seq(
405
+ optional($._callable_interface_qualifers),
406
+ caseInsensitive('function'),
407
+ field('name', $._name),
408
+ optional(field('parameters',$._parameters)),
409
+ optional(repeat(choice(
410
+ $.language_binding,
411
+ $.function_result
412
+ )))
413
+ ),
414
+
415
+ language_binding: $ => seq(
416
+ caseInsensitive('bind'),
417
+ '(',
418
+ $.identifier,
419
+ optional(seq(',', $.keyword_argument)),
420
+ ')'
421
+ ),
422
+
423
+ _callable_interface_qualifers: $ => repeat1(
424
+ prec.right(1, choice(
425
+ $.procedure_attributes,
426
+ $.procedure_qualifier,
427
+ field('type', $.intrinsic_type),
428
+ field('type', $.derived_type)
429
+ ))),
430
+
431
+ procedure_attributes: $ => prec(1, seq(
432
+ caseInsensitive('attributes'),
433
+ '(',
434
+ commaSep1(choice(
435
+ caseInsensitive('global'),
436
+ caseInsensitive('device'),
437
+ caseInsensitive('host'),
438
+ caseInsensitive('grid_global'))),
439
+ ')'
440
+ )),
441
+
442
+ end_function_statement: $ => blockStructureEnding($, 'function'),
443
+
444
+ function_result: $ => seq(
445
+ caseInsensitive('result'),
446
+ '(',
447
+ $.identifier,
448
+ ')'
449
+ ),
450
+
451
+ _name: $ => alias($.identifier, $.name),
452
+
453
+ _parameters: $ => choice(
454
+ seq('(', ')'),
455
+ $.parameters
456
+ ),
457
+
458
+ parameters: $ => seq(
459
+ '(',
460
+ commaSep1($.identifier),
461
+ ')'
462
+ ),
463
+
464
+ internal_procedures: $ => seq(
465
+ $.contains_statement,
466
+ $._end_of_statement,
467
+ repeat($._internal_procedures)
468
+ ),
469
+
470
+ contains_statement: $ => caseInsensitive('contains'),
471
+
472
+ _internal_procedures: $ => choice(
473
+ $.function,
474
+ $.module_procedure,
475
+ $.subroutine,
476
+ $.include_statement,
477
+ alias($.preproc_if_in_internal_procedures, $.preproc_if),
478
+ alias($.preproc_ifdef_in_internal_procedures, $.preproc_ifdef),
479
+ $.preproc_include,
480
+ $.preproc_def,
481
+ $.preproc_function_def,
482
+ $.preproc_call,
483
+ ),
484
+
485
+ // Variable Declarations
486
+
487
+ _specification_part: $ => prec(1, choice(
488
+ prec(1, seq($.include_statement, $._end_of_statement)),
489
+ seq($.use_statement, $._end_of_statement),
490
+ seq($.implicit_statement, $._end_of_statement),
491
+ seq($.save_statement, $._end_of_statement),
492
+ seq($.import_statement, $._end_of_statement),
493
+ $.public_statement,
494
+ $.private_statement,
495
+ $.enum,
496
+ $.enumeration_type,
497
+ $.interface,
498
+ $.derived_type_definition,
499
+ seq($.namelist_statement, $._end_of_statement),
500
+ seq($.common_statement, $._end_of_statement),
501
+ seq($.variable_declaration, $._end_of_statement),
502
+ seq($.variable_modification, $._end_of_statement),
503
+ seq($.parameter_statement, $._end_of_statement),
504
+ seq($.equivalence_statement, $._end_of_statement),
505
+ seq($.data_statement, $._end_of_statement),
506
+ seq($.statement_function, $._end_of_statement),
507
+ prec(1, seq($.statement_label, $.format_statement, $._end_of_statement)),
508
+ $.preproc_include,
509
+ $.preproc_def,
510
+ $.preproc_function_def,
511
+ $.preproc_call,
512
+ )),
513
+
514
+ use_statement: $ => seq(
515
+ caseInsensitive('use'),
516
+ choice(
517
+ optional(
518
+ seq(',', choice(caseInsensitive('intrinsic'), caseInsensitive('non_intrinsic')), '::')
519
+ ),
520
+ optional('::')
521
+ ),
522
+ alias($.identifier, $.module_name),
523
+ optional(
524
+ choice(
525
+ seq(',', commaSep1($.use_alias)),
526
+ $.included_items
527
+ )
528
+ )
529
+ ),
530
+
531
+ included_items: $ => seq(
532
+ ',',
533
+ caseInsensitive('only'),
534
+ ':',
535
+ optional(commaSep1(
536
+ choice(
537
+ $.use_alias,
538
+ $.identifier,
539
+ $._generic_procedure)
540
+ ))
541
+ ),
542
+
543
+ use_alias: $ => seq(
544
+ alias($.identifier, $.local_name),
545
+ '=>',
546
+ $.identifier
547
+ ),
548
+
549
+ implicit_statement: $ => seq(
550
+ caseInsensitive('implicit'),
551
+ choice(
552
+ commaSep1(seq(
553
+ $.intrinsic_type,
554
+ '(',
555
+ commaSep1($.implicit_range),
556
+ ')'
557
+ )),
558
+ seq(
559
+ alias(caseInsensitive('none', false), $.none),
560
+ optional(seq(
561
+ '(',
562
+ commaSep1(choice(
563
+ caseInsensitive('type'),
564
+ caseInsensitive('external')
565
+ )),
566
+ ')'
567
+ ))
568
+ )
569
+ )
570
+ ),
571
+
572
+ save_statement: $ => prec(1, seq(
573
+ caseInsensitive('save'),
574
+ optional(seq(
575
+ optional('::'),
576
+ commaSep1(choice(
577
+ $.identifier,
578
+ seq('/', $.identifier, '/'),
579
+ )),
580
+ ))
581
+ )),
582
+
583
+ private_statement: $ => prec.right(1, seq(
584
+ caseInsensitive('private'),
585
+ optional(seq(
586
+ optional('::'),
587
+ commaSep1(choice($.identifier, $._generic_procedure))
588
+ )),
589
+ $._end_of_statement,
590
+ )),
591
+
592
+ public_statement: $ => prec.right(1, seq(
593
+ caseInsensitive('public'),
594
+ optional(seq(
595
+ optional('::'),
596
+ commaSep1(choice($.identifier, $._generic_procedure))
597
+ )),
598
+ $._end_of_statement,
599
+ )),
600
+
601
+ namelist_statement: $ => seq(
602
+ caseInsensitive('namelist'),
603
+ repeat1($.variable_group)
604
+ ),
605
+
606
+ common_statement: $ => seq(
607
+ caseInsensitive('common'),
608
+ repeat1(choice(
609
+ $.variable_group,
610
+ commaSep1($._variable_declarator)
611
+ ))
612
+ ),
613
+
614
+ variable_group: $ => seq(
615
+ '/',
616
+ $._name,
617
+ '/',
618
+ commaSep1($._variable_declarator)
619
+ ),
620
+
621
+ implicit_range: $ => seq(
622
+ /[a-zA-Z]/,
623
+ optional(seq('-', /[a-zA-Z]/))
624
+ ),
625
+
626
+ import_statement: $ => prec.left(seq(
627
+ caseInsensitive('import'),
628
+ optional($._import_names)
629
+ )),
630
+ _import_names: $ => choice(
631
+ seq(optional('::'), commaSep1($.identifier)),
632
+ seq(',',
633
+ choice(
634
+ seq(caseInsensitive('only'), ':', commaSep1($.identifier)),
635
+ caseInsensitive('none'),
636
+ caseInsensitive('all')
637
+ )
638
+ )
639
+ ),
640
+
641
+ derived_type_definition: $ => seq(
642
+ $.derived_type_statement,
643
+ repeat(choice(
644
+ $.public_statement,
645
+ $.private_statement,
646
+ seq(
647
+ alias(caseInsensitive('sequence'), $.sequence_statement),
648
+ $._end_of_statement
649
+ ),
650
+ seq($.include_statement, $._end_of_statement),
651
+ seq($.variable_declaration, $._end_of_statement),
652
+ $.preproc_include,
653
+ $.preproc_def,
654
+ $.preproc_function_def,
655
+ $.preproc_call,
656
+ alias($.preproc_if_in_derived_type, $.preproc_if),
657
+ alias($.preproc_ifdef_in_derived_type, $.preproc_ifdef),
658
+ )),
659
+ optional($.derived_type_procedures),
660
+ $.end_type_statement
661
+ ),
662
+
663
+ abstract_specifier: $ => caseInsensitive('abstract'),
664
+
665
+ access_specifier: $ => choice(
666
+ caseInsensitive('public'),
667
+ caseInsensitive('private')
668
+ ),
669
+
670
+ base_type_specifier: $ => seq(
671
+ caseInsensitive('extends'),
672
+ '(', $.identifier, ')'
673
+ ),
674
+
675
+ // These are only valid to specify once each, but tree-sitter
676
+ // doesn't support permutations
677
+ _derived_type_qualifier: $ => choice(
678
+ $.abstract_specifier,
679
+ field('access', $.access_specifier),
680
+ field('base', $.base_type_specifier),
681
+ $.language_binding
682
+ ),
683
+
684
+ derived_type_statement: $ => seq(
685
+ optional($.statement_label),
686
+ caseInsensitive('type'),
687
+ choice(
688
+ seq(optional('::'), $._type_name),
689
+ seq(',', commaSep1($._derived_type_qualifier), '::', $._type_name)
690
+ ),
691
+ optional(alias($.argument_list, $.derived_type_parameter_list)),
692
+ $._end_of_statement
693
+ ),
694
+
695
+ end_type_statement: $ => blockStructureEnding($, 'type'),
696
+
697
+ _type_name: $ => alias($.identifier, $.type_name),
698
+
699
+ derived_type_procedures: $ => seq(
700
+ $.contains_statement,
701
+ repeat(choice(
702
+ $.public_statement,
703
+ $.private_statement,
704
+ $.procedure_statement,
705
+ alias($.preproc_if_in_bound_procedures, $.preproc_if),
706
+ alias($.preproc_ifdef_in_bound_procedures, $.preproc_ifdef),
707
+ )),
708
+ ),
709
+
710
+ procedure_statement: $ => seq(
711
+ $.procedure_kind,
712
+ optional(seq(
713
+ '(', alias($.identifier, $.procedure_interface), ')'
714
+ )),
715
+ optional(seq(
716
+ ',',
717
+ commaSep1($.procedure_attribute)
718
+ )),
719
+ optional('::'),
720
+ commaSep1(field('declarator', choice(
721
+ $.method_name,
722
+ $.binding,
723
+ ))),
724
+ $._end_of_statement,
725
+ ),
726
+ binding: $ => seq($.binding_name, '=>', $.method_name),
727
+ binding_name: $ => choice(
728
+ $.identifier,
729
+ $._generic_procedure
730
+ ),
731
+ method_name: $ => alias($.identifier, 'method_name'),
732
+
733
+ procedure_kind: $ => choice(
734
+ caseInsensitive('generic'),
735
+ caseInsensitive('initial'),
736
+ caseInsensitive('procedure'),
737
+ seq(caseInsensitive('module'), caseInsensitive('procedure')),
738
+ caseInsensitive('property'),
739
+ caseInsensitive('final')
740
+ ),
741
+
742
+ procedure_attribute: $ => prec.left(choice(
743
+ caseInsensitive('deferred'),
744
+ seq(
745
+ caseInsensitive('pass'),
746
+ optional(seq('(', $.identifier, ')'))
747
+ ),
748
+ caseInsensitive('nopass'),
749
+ caseInsensitive('non_overridable'),
750
+ caseInsensitive('public'),
751
+ caseInsensitive('private'),
752
+ caseInsensitive('family'),
753
+ caseInsensitive('pointer')
754
+ )),
755
+
756
+ variable_declaration: $ => seq(
757
+ field('type', choice(
758
+ $.intrinsic_type,
759
+ $.derived_type,
760
+ alias($.procedure_declaration, $.procedure),
761
+ $.declared_type,
762
+ )),
763
+ optional(seq(',',
764
+ commaSep1(
765
+ field(
766
+ 'attribute',
767
+ choice(
768
+ $.type_qualifier,
769
+ $.language_binding
770
+ ))
771
+ )
772
+ )),
773
+ optional('::'),
774
+ $._declaration_targets
775
+ ),
776
+
777
+ procedure_declaration: $ => seq(
778
+ caseInsensitive('procedure'),
779
+ optional(seq(
780
+ '(', optional(alias($.identifier, $.procedure_interface)), ')'
781
+ )),
782
+ optional(seq(',', commaSep1($.procedure_attribute))),
783
+ ),
784
+
785
+ variable_modification: $ => seq(
786
+ repeat1(choice(
787
+ alias($._standalone_type_qualifier, $.type_qualifier),
788
+ $.variable_attributes,
789
+ $.language_binding,
790
+ )),
791
+ optional('::'),
792
+ commaSep1(field('declarator', $._variable_declarator)),
793
+ ),
794
+
795
+ variable_attributes: $ => seq(
796
+ caseInsensitive('attributes'),
797
+ '(',
798
+ choice(
799
+ caseInsensitive('device'),
800
+ caseInsensitive('managed'),
801
+ caseInsensitive('constant'),
802
+ caseInsensitive('shared'),
803
+ caseInsensitive('pinned'),
804
+ caseInsensitive('texture')),
805
+ ')'
806
+ ),
807
+
808
+ _variable_declarator: $ => choice(
809
+ $.identifier,
810
+ $.sized_declarator,
811
+ $.coarray_declarator,
812
+ ),
813
+
814
+ sized_declarator: $ => prec.right(1, seq(
815
+ $.identifier,
816
+ choice(
817
+ alias($.argument_list, $.size),
818
+ $.character_length
819
+ )
820
+ )),
821
+
822
+ _declaration_assignment: $ => seq(
823
+ field('left', $._variable_declarator),
824
+ '=',
825
+ field('right', $._expression)
826
+ ),
827
+ _declaration_pointer_association: $ => seq(
828
+ field('left', $._variable_declarator),
829
+ '=>',
830
+ field('right', $._expression)
831
+ ),
832
+
833
+ _declaration_targets: $ => commaSep1(field('declarator', choice(
834
+ $._variable_declarator,
835
+ alias($._declaration_assignment, $.init_declarator),
836
+ alias($._declaration_pointer_association, $.pointer_init_declarator),
837
+ ))),
838
+
839
+ _intrinsic_type: $ => choice(
840
+ caseInsensitive('byte'),
841
+ caseInsensitive('integer'),
842
+ caseInsensitive('real'),
843
+ whiteSpacedKeyword('double', 'precision'),
844
+ caseInsensitive('complex'),
845
+ whiteSpacedKeyword('double', 'complex'),
846
+ caseInsensitive('logical'),
847
+ caseInsensitive('character'),
848
+ ),
849
+
850
+ intrinsic_type: $ => seq(
851
+ $._intrinsic_type,
852
+ optional(field('kind', $.kind)),
853
+ ),
854
+
855
+ derived_type: $ => seq(
856
+ choice(caseInsensitive('type'), caseInsensitive('class')),
857
+ '(',
858
+ // Strictly, only `class` can be unlimited polymorphic
859
+ choice(
860
+ seq(
861
+ field('name', choice(
862
+ prec.dynamic(1, alias($._intrinsic_type, $.intrinsic_type)),
863
+ $._type_name,
864
+ )),
865
+ optional(field('kind', $.kind)),
866
+ ),
867
+ $.unlimited_polymorphic
868
+ ),
869
+ ')'
870
+ ),
871
+
872
+ declared_type: $ => seq(
873
+ choice(
874
+ caseInsensitive('typeof'),
875
+ caseInsensitive('classof'),
876
+ ),
877
+ '(',
878
+ field('name', choice(
879
+ $.identifier,
880
+ $.derived_type_member_expression,
881
+ )),
882
+ ')'
883
+ ),
884
+
885
+ unlimited_polymorphic: $ => '*',
886
+
887
+ kind: $ => choice(
888
+ seq(optional(alias('*', $.assumed_size)), $._argument_list),
889
+ seq('*', choice(alias(/\d+/, $.number_literal), $.parenthesized_expression))
890
+ ),
891
+
892
+ character_length: $ => seq(
893
+ '*',
894
+ optional(/\d+/),
895
+ optional(seq('(', '*', ')'))
896
+ ),
897
+
898
+ _standalone_type_qualifier: $ => choice(
899
+ caseInsensitive('abstract'),
900
+ caseInsensitive('allocatable'),
901
+ caseInsensitive('automatic'),
902
+ prec.right(seq(
903
+ caseInsensitive('codimension'),
904
+ alias($.coarray_index, $.coarray_size),
905
+ )),
906
+ prec.right(seq(
907
+ caseInsensitive('dimension'),
908
+ optional($.argument_list)
909
+ )),
910
+ caseInsensitive('constant'),
911
+ caseInsensitive('contiguous'),
912
+ caseInsensitive('device'),
913
+ caseInsensitive('external'),
914
+ seq(
915
+ caseInsensitive('intent'),
916
+ '(',
917
+ choice(
918
+ caseInsensitive('in'),
919
+ caseInsensitive('out'),
920
+ whiteSpacedKeyword('in', 'out')
921
+ ),
922
+ ')'
923
+ ),
924
+ caseInsensitive('intrinsic'),
925
+ caseInsensitive('managed'),
926
+ caseInsensitive('optional'),
927
+ caseInsensitive('parameter'),
928
+ caseInsensitive('pinned'),
929
+ caseInsensitive('pointer'),
930
+ caseInsensitive('private'),
931
+ caseInsensitive('protected'),
932
+ caseInsensitive('public'),
933
+ seq(
934
+ caseInsensitive('rank'),
935
+ $.argument_list
936
+ ),
937
+ caseInsensitive('save'),
938
+ caseInsensitive('sequence'),
939
+ caseInsensitive('shared'),
940
+ caseInsensitive('static'),
941
+ caseInsensitive('target'),
942
+ caseInsensitive('texture'),
943
+ caseInsensitive('value'),
944
+ caseInsensitive('volatile')
945
+ ),
946
+
947
+ // These are split out to avoid clash with assignment statements
948
+ // as it turns out `len` is more likely to be used as a variable
949
+ // name than any of the other qualifiers
950
+ type_qualifier: $ => choice(
951
+ $._standalone_type_qualifier,
952
+ // Next two technically only valid on derived type components
953
+ field('type_param', caseInsensitive('kind')),
954
+ field('type_param', caseInsensitive('len')),
955
+ ),
956
+
957
+ procedure_qualifier: $ => choice(
958
+ caseInsensitive('elemental'),
959
+ caseInsensitive('impure'),
960
+ caseInsensitive('module'),
961
+ caseInsensitive('pure'),
962
+ caseInsensitive('recursive'),
963
+ caseInsensitive('simple'),
964
+ ),
965
+
966
+ parameter_statement: $ => prec(1, seq(
967
+ caseInsensitive('parameter'),
968
+ '(',
969
+ commaSep1($.parameter_assignment),
970
+ ')'
971
+ )),
972
+
973
+ parameter_assignment: $ => seq($.identifier, '=', $._expression),
974
+
975
+ equivalence_statement: $ => seq(
976
+ caseInsensitive('equivalence'),
977
+ commaSep1($.equivalence_set)
978
+ ),
979
+
980
+ equivalence_set: $ => seq(
981
+ '(',
982
+ choice($.identifier, $.call_expression),
983
+ ',',
984
+ commaSep1(choice($.identifier, $.call_expression)),
985
+ ')'
986
+ ),
987
+
988
+ // Statements
989
+
990
+ _statement: $ => choice(
991
+ alias($.preproc_if_in_statements, $.preproc_if),
992
+ alias($.preproc_ifdef_in_statements, $.preproc_ifdef),
993
+ $.preproc_include,
994
+ $.preproc_def,
995
+ $.preproc_function_def,
996
+ $.preproc_call,
997
+ seq(
998
+ optional($.statement_label),
999
+ $._statements,
1000
+ $._end_of_statement
1001
+ ),
1002
+ ';'
1003
+ ),
1004
+
1005
+ _statements: $ => choice(
1006
+ $.assignment_statement,
1007
+ $.pointer_association_statement,
1008
+ $.call_expression,
1009
+ $.subroutine_call,
1010
+ $.keyword_statement,
1011
+ $.include_statement,
1012
+ $.if_statement,
1013
+ $.arithmetic_if_statement,
1014
+ $.where_statement,
1015
+ $.forall_statement,
1016
+ $.select_case_statement,
1017
+ $.select_type_statement,
1018
+ $.select_rank_statement,
1019
+ $.do_loop_statement,
1020
+ $.do_label_statement,
1021
+ $.end_do_label_statement,
1022
+ $.format_statement,
1023
+ $.open_statement,
1024
+ $.close_statement,
1025
+ $.print_statement,
1026
+ $.write_statement,
1027
+ $.read_statement,
1028
+ $.inquire_statement,
1029
+ $.stop_statement,
1030
+ $.block_construct,
1031
+ $.associate_statement,
1032
+ $.file_position_statement,
1033
+ $.allocate_statement,
1034
+ $.entry_statement,
1035
+ $.coarray_statement,
1036
+ $.coarray_team_statement,
1037
+ $.coarray_critical_statement,
1038
+ ),
1039
+
1040
+ statement_label: $ => prec(1, alias($._integer_literal, 'statement_label')),
1041
+
1042
+ statement_label_reference: $ => alias($.statement_label, 'statement_label_reference'),
1043
+
1044
+ stop_statement: $ => seq(
1045
+ optional(caseInsensitive("error")),
1046
+ caseInsensitive('stop'),
1047
+ optional($._expression),
1048
+ optional(seq(
1049
+ ',',
1050
+ prec(1, seq(caseInsensitive('quiet'), '=', $._expression))
1051
+ ))
1052
+ ),
1053
+
1054
+ assignment_statement: $ => prec.right(PREC.ASSIGNMENT, seq(
1055
+ field('left',$._expression),
1056
+ '=',
1057
+ field('right',$._expression),
1058
+ )),
1059
+
1060
+ pointer_association_statement: $ => prec.right(seq(
1061
+ $._expression, // this needs to support structs i.e. mytype%attr
1062
+ '=>',
1063
+ $._expression
1064
+ )),
1065
+
1066
+ // `call` should bind more tightly than ordinary expressions
1067
+ subroutine_call: $ => prec(1, seq(
1068
+ caseInsensitive('call'),
1069
+ // Allow expressions to allow calling type-bound procedures
1070
+ field('subroutine', $._expression),
1071
+ optional($.cuda_kernel_argument_list),
1072
+ optional($.argument_list)
1073
+ )),
1074
+
1075
+ cuda_kernel_argument_list: $ => seq(
1076
+ '<<<',
1077
+ commaSep1($._expression),
1078
+ '>>>'
1079
+ ),
1080
+
1081
+ keyword_statement: $ => choice(
1082
+ caseInsensitive('continue'),
1083
+ seq(caseInsensitive('cycle'), optional($.identifier)),
1084
+ seq(caseInsensitive('exit'), optional($.identifier)),
1085
+ seq(
1086
+ whiteSpacedKeyword('go', 'to'),
1087
+ choice(
1088
+ $.statement_label_reference,
1089
+ // Computed goto (obsolete)
1090
+ seq(
1091
+ '(', commaSep1($.statement_label_reference), ')',
1092
+ optional(','),
1093
+ $._expression,
1094
+ )
1095
+ )
1096
+ ),
1097
+ caseInsensitive('return'),
1098
+ ),
1099
+
1100
+ include_statement: $ => seq(
1101
+ caseInsensitive('include'),
1102
+ field("path", alias($.string_literal, $.filename))
1103
+ ),
1104
+
1105
+ data_statement: $ => seq(
1106
+ caseInsensitive('data'),
1107
+ commaSep1($.data_set)
1108
+ ),
1109
+ data_set: $ => prec(1, seq(
1110
+ commaSep1(
1111
+ choice(
1112
+ $.identifier,
1113
+ $.implied_do_loop_expression,
1114
+ $.call_expression, // For array indexing
1115
+ $.derived_type_member_expression
1116
+ )
1117
+ ),
1118
+ $.data_value,
1119
+ )),
1120
+ data_value: $ => seq(
1121
+ '/',
1122
+ commaSep1(seq(
1123
+ optional(prec(1, seq(field('repeat', $.number_literal), '*'))),
1124
+ choice(
1125
+ $.number_literal,
1126
+ $.complex_literal,
1127
+ $.string_literal,
1128
+ $.boolean_literal,
1129
+ $.unary_expression,
1130
+ $.null_literal,
1131
+ $.identifier,
1132
+ $.call_expression
1133
+ )
1134
+ )),
1135
+ '/'
1136
+ ),
1137
+
1138
+ do_loop_statement: $ => seq(
1139
+ optional($.block_label_start_expression),
1140
+ caseInsensitive('do'),
1141
+ optional(','),
1142
+ optional(choice(
1143
+ $.while_statement,
1144
+ $.loop_control_expression,
1145
+ $.concurrent_statement
1146
+ )),
1147
+ $._end_of_statement,
1148
+ repeat($._statement),
1149
+ optional($.statement_label),
1150
+ $.end_do_loop_statement
1151
+ ),
1152
+
1153
+ end_do_loop_statement: $ => seq(
1154
+ whiteSpacedKeyword('end', 'do'),
1155
+ optional($._block_label)
1156
+ ),
1157
+
1158
+ // Deleted feature: non-block `do`. Actually, labelled-do is still
1159
+ // valid (but obsolescent), but we need to capture them separately
1160
+ // because otherwise it's too had to capture them at all
1161
+ do_label_statement: $ => seq(
1162
+ caseInsensitive('do'),
1163
+ $.statement_label_reference,
1164
+ optional(','),
1165
+ $.loop_control_expression
1166
+ ),
1167
+
1168
+ // Because we've lumped together labelled-do and non-block-do in
1169
+ // `do_label_statement`, we also need to be able to capture `end
1170
+ // do` for a labelled-do
1171
+ end_do_label_statement: $ => prec(-1, seq(
1172
+ $.statement_label,
1173
+ whiteSpacedKeyword('end', 'do'),
1174
+ )),
1175
+
1176
+ while_statement: $ => seq(caseInsensitive('while'),
1177
+ $.parenthesized_expression),
1178
+
1179
+ concurrent_statement: $ => seq(
1180
+ $.concurrent_header,
1181
+ repeat($.concurrent_locality)
1182
+ ),
1183
+
1184
+ concurrent_header: $ => seq(
1185
+ caseInsensitive('concurrent'),
1186
+ '(',
1187
+ optional(seq(
1188
+ // This is actually limited to integer types only
1189
+ field('type', $.intrinsic_type),
1190
+ '::'
1191
+ )),
1192
+ commaSep1($.concurrent_control),
1193
+ optional(seq(',', alias($._expression, $.concurrent_mask))),
1194
+ ')'
1195
+ ),
1196
+
1197
+ concurrent_control: $ => seq(
1198
+ $.identifier,
1199
+ '=',
1200
+ field('initial', $._expression),
1201
+ ':',
1202
+ field('final', $._expression),
1203
+ optional(seq(
1204
+ ':',
1205
+ field('step', $._expression)
1206
+ ))
1207
+ ),
1208
+
1209
+ concurrent_locality: $ => choice(
1210
+ seq(
1211
+ choice(
1212
+ caseInsensitive('local'),
1213
+ caseInsensitive('local_init'),
1214
+ caseInsensitive('shared'),
1215
+ ),
1216
+ '(', commaSep1($.identifier), ')'
1217
+ ),
1218
+ seq(
1219
+ caseInsensitive('default'),
1220
+ '(', caseInsensitive('none'), ')'
1221
+ ),
1222
+ seq(
1223
+ caseInsensitive('reduce'),
1224
+ '(', $.binary_op, ':', commaSep1($.identifier), ')',
1225
+ ),
1226
+ ),
1227
+ binary_op: $ => choice('+', '*', /(\.\w+\.|\w+)/),
1228
+
1229
+ if_statement: $ => choice(
1230
+ $._inline_if_statement,
1231
+ $._block_if_statement
1232
+ ),
1233
+
1234
+ _inline_if_statement: $ => prec.right(2, seq(
1235
+ caseInsensitive('if'),
1236
+ $.parenthesized_expression,
1237
+ $._statements
1238
+ )),
1239
+
1240
+ arithmetic_if_statement: $ => prec.right(seq(
1241
+ caseInsensitive('if'),
1242
+ $.parenthesized_expression,
1243
+ $.statement_label_reference,
1244
+ ',',
1245
+ $.statement_label_reference,
1246
+ ',',
1247
+ $.statement_label_reference,
1248
+ )),
1249
+
1250
+ _block_if_statement: $ => seq(
1251
+ optional($.block_label_start_expression),
1252
+ caseInsensitive('if'),
1253
+ $.parenthesized_expression,
1254
+ caseInsensitive('then'),
1255
+ optional($._block_label),
1256
+ $._end_of_statement,
1257
+ repeat($._statement),
1258
+ repeat($.elseif_clause),
1259
+ optional($.else_clause),
1260
+ optional($.statement_label),
1261
+ $.end_if_statement
1262
+ ),
1263
+
1264
+ end_if_statement: $ => seq(
1265
+ whiteSpacedKeyword('end', 'if'),
1266
+ optional($._block_label)
1267
+ ),
1268
+
1269
+ elseif_clause: $ => seq(
1270
+ whiteSpacedKeyword('else', 'if'),
1271
+ $.parenthesized_expression,
1272
+ caseInsensitive('then'),
1273
+ optional($._block_label),
1274
+ $._end_of_statement,
1275
+ repeat($._statement)
1276
+ ),
1277
+
1278
+ else_clause: $ => seq(
1279
+ caseInsensitive('else'),
1280
+ optional($._block_label),
1281
+ $._end_of_statement,
1282
+ repeat($._statement)
1283
+ ),
1284
+
1285
+ where_statement: $ => choice(
1286
+ $._inline_where_statement,
1287
+ $._block_where_statement
1288
+ ),
1289
+
1290
+ _inline_where_statement: $ => prec.right(seq(
1291
+ caseInsensitive('where'),
1292
+ $.parenthesized_expression,
1293
+ $._statements
1294
+ )),
1295
+
1296
+ _block_where_statement: $ => seq(
1297
+ optional($.block_label_start_expression),
1298
+ caseInsensitive('where'),
1299
+ $.parenthesized_expression,
1300
+ $._end_of_statement,
1301
+ repeat($._statement),
1302
+ repeat($.elsewhere_clause),
1303
+ $.end_where_statement
1304
+ ),
1305
+
1306
+ end_where_statement: $ => seq(
1307
+ whiteSpacedKeyword('end', 'where'),
1308
+ optional($._block_label)
1309
+ ),
1310
+
1311
+ elsewhere_clause: $ => seq(
1312
+ whiteSpacedKeyword('else', 'where'),
1313
+ optional($.parenthesized_expression),
1314
+ optional($._block_label),
1315
+ $._end_of_statement,
1316
+ repeat($._statement)
1317
+ ),
1318
+
1319
+ forall_statement: $ => choice(
1320
+ $._inline_forall_statement,
1321
+ $._block_forall_statement
1322
+ ),
1323
+
1324
+ triplet_spec: $ => seq(
1325
+ $.identifier,
1326
+ '=',
1327
+ $._expression,
1328
+ ':',
1329
+ $._expression,
1330
+ optional(seq(
1331
+ ':',
1332
+ $._expression
1333
+ ))
1334
+ ),
1335
+
1336
+ _forall_control_expression: $ => seq(
1337
+ caseInsensitive('forall'),
1338
+ '(',
1339
+ commaSep1($.triplet_spec),
1340
+ optional(seq(',', choice($.logical_expression, $.relational_expression))),
1341
+ ')'
1342
+ ),
1343
+
1344
+ _inline_forall_statement: $ => seq(
1345
+ $._forall_control_expression,
1346
+ $._statements
1347
+ ),
1348
+
1349
+ _block_forall_statement: $ => seq(
1350
+ optional($.block_label_start_expression),
1351
+ $._forall_control_expression,
1352
+ $._end_of_statement,
1353
+ repeat($._statement),
1354
+ optional($.statement_label),
1355
+ $.end_forall_statement
1356
+ ),
1357
+
1358
+ end_forall_statement: $ => seq(
1359
+ whiteSpacedKeyword('end', 'forall'),
1360
+ optional($._block_label)
1361
+ ),
1362
+
1363
+ select_case_statement: $ => seq(
1364
+ optional($.block_label_start_expression),
1365
+ whiteSpacedKeyword('select', 'case'),
1366
+ $.selector,
1367
+ $._end_of_statement,
1368
+ repeat1(choice(
1369
+ $.case_statement,
1370
+ $.preproc_include,
1371
+ $.preproc_def,
1372
+ $.preproc_function_def,
1373
+ $.preproc_call,
1374
+ alias($.preproc_if_in_select_case, $.preproc_if),
1375
+ alias($.preproc_ifdef_in_select_case, $.preproc_ifdef),
1376
+ )),
1377
+ optional($.statement_label),
1378
+ $.end_select_statement
1379
+ ),
1380
+
1381
+ select_type_statement: $ => seq(
1382
+ optional($.block_label_start_expression),
1383
+ whiteSpacedKeyword('select', 'type'),
1384
+ $.selector,
1385
+ $._end_of_statement,
1386
+ repeat1(choice(
1387
+ $.type_statement,
1388
+ $.preproc_include,
1389
+ $.preproc_def,
1390
+ $.preproc_function_def,
1391
+ $.preproc_call,
1392
+ alias($.preproc_if_in_select_type, $.preproc_if),
1393
+ alias($.preproc_ifdef_in_select_type, $.preproc_ifdef),
1394
+ )),
1395
+ optional($.statement_label),
1396
+ $.end_select_statement
1397
+ ),
1398
+
1399
+ select_rank_statement: $ => seq(
1400
+ optional($.block_label_start_expression),
1401
+ whiteSpacedKeyword('select', 'rank'),
1402
+ $.selector,
1403
+ $._end_of_statement,
1404
+ repeat1(choice(
1405
+ $.rank_statement,
1406
+ $.preproc_include,
1407
+ $.preproc_def,
1408
+ $.preproc_function_def,
1409
+ $.preproc_call,
1410
+ alias($.preproc_if_in_select_rank, $.preproc_if),
1411
+ alias($.preproc_ifdef_in_select_rank, $.preproc_ifdef),
1412
+ )),
1413
+ optional($.statement_label),
1414
+ $.end_select_statement
1415
+ ),
1416
+
1417
+ end_select_statement: $ => seq(
1418
+ whiteSpacedKeyword('end', 'select'),
1419
+ optional($._block_label)
1420
+ ),
1421
+
1422
+ selector: $ => seq('(',
1423
+ choice($._expression, $.pointer_association_statement),
1424
+ ')'),
1425
+
1426
+ case_statement: $ => seq(
1427
+ caseInsensitive('case'),
1428
+ choice(
1429
+ seq('(', $.case_value_range_list, ')'),
1430
+ alias(caseInsensitive('default'), $.default)
1431
+ ),
1432
+ optional($._block_label),
1433
+ $._end_of_statement,
1434
+ repeat($._statement)
1435
+ ),
1436
+
1437
+ type_statement: $ => seq(
1438
+ choice(
1439
+ seq(
1440
+ choice(
1441
+ whiteSpacedKeyword('type', 'is'),
1442
+ whiteSpacedKeyword('class', 'is')
1443
+ ),
1444
+ choice(
1445
+ seq('(', field('type', choice($.intrinsic_type, $.identifier)), ')'),
1446
+ ),
1447
+ ),
1448
+ alias($._class_default, $.default)
1449
+ ),
1450
+ optional($._block_label),
1451
+ $._end_of_statement,
1452
+ repeat($._statement)
1453
+ ),
1454
+
1455
+ // Standalone rule otherwise it gets aliased as '(default) (default)'
1456
+ _class_default: $ => whiteSpacedKeyword('class', 'default', false),
1457
+
1458
+ case_value_range_list: $ => commaSep1(choice(
1459
+ $._expression,
1460
+ $.extent_specifier
1461
+ )),
1462
+
1463
+ rank_statement: $ => prec(2, seq(
1464
+ caseInsensitive('rank'),
1465
+ choice(
1466
+ seq('(', $.case_value_range_list, ')'),
1467
+ alias(caseInsensitive('default'), $.default)
1468
+ ),
1469
+ optional($._block_label),
1470
+ $._end_of_statement,
1471
+ repeat($._statement)
1472
+ )),
1473
+
1474
+ block_construct: $ => seq(
1475
+ optional($.block_label_start_expression),
1476
+ caseInsensitive('block'),
1477
+ $._end_of_statement,
1478
+ repeat($._specification_part),
1479
+ repeat($._statement),
1480
+ $.end_block_construct_statement
1481
+ ),
1482
+
1483
+ end_block_construct_statement: $ => seq(
1484
+ whiteSpacedKeyword('end', 'block'),
1485
+ optional($._block_label)
1486
+ ),
1487
+
1488
+ associate_statement: $ => seq(
1489
+ optional($.block_label_start_expression),
1490
+ caseInsensitive('associate'),
1491
+ '(',
1492
+ commaSep1($.association),
1493
+ ')',
1494
+ $._end_of_statement,
1495
+ repeat($._statement),
1496
+ $.end_associate_statement
1497
+ ),
1498
+
1499
+ association: $ => seq(
1500
+ field('name', $.identifier),
1501
+ '=>',
1502
+ field('selector', $._expression)
1503
+ ),
1504
+
1505
+ end_associate_statement: $ => seq(
1506
+ whiteSpacedKeyword('end', 'associate'),
1507
+ optional($._block_label)
1508
+ ),
1509
+
1510
+ format_statement: $ => prec(1, seq(
1511
+ caseInsensitive('format'),
1512
+ '(',
1513
+ alias($._transfer_items, $.transfer_items),
1514
+ ')'
1515
+ )),
1516
+
1517
+ _transfer_item: $ => choice(
1518
+ $.string_literal,
1519
+ $.edit_descriptor,
1520
+ $.hollerith_constant,
1521
+ seq('(', $._transfer_items, ')')
1522
+ ),
1523
+
1524
+ // Comma is technically only optional in certain circumstances,
1525
+ // but capturing all of those is complicated!
1526
+ _transfer_items: $ => seq(
1527
+ $._transfer_item,
1528
+ repeat(seq(optional(','), $._transfer_item))
1529
+ ),
1530
+
1531
+ // H is not a valid edit descriptor because it clashes with Hollerith constants
1532
+ edit_descriptor: $ => /[a-gi-zA-GI-Z0-9/:.*$]+/,
1533
+ hollerith_constant: $ => prec.right(10, /[0-9]+H[^/,)]+/),
1534
+
1535
+ _io_arguments: $ => seq(
1536
+ '(',
1537
+ choice(
1538
+ $.unit_identifier,
1539
+ seq($.unit_identifier, ',', $.format_identifier),
1540
+ seq($.unit_identifier, ',', $.format_identifier, ',', commaSep1($.keyword_argument)),
1541
+ seq($.unit_identifier, ',', commaSep1($.keyword_argument)),
1542
+ commaSep1($.keyword_argument)
1543
+ ),
1544
+ ')'
1545
+ ),
1546
+
1547
+ read_statement: $ => prec(1, choice(
1548
+ $._simple_read_statement,
1549
+ $._parameterized_read_statement
1550
+ )),
1551
+
1552
+ _simple_read_statement: $ => prec(1, seq(
1553
+ caseInsensitive('read'),
1554
+ $.format_identifier,
1555
+ optional(seq(',', $.input_item_list))
1556
+ )),
1557
+
1558
+ _parameterized_read_statement: $ => prec(1, seq(
1559
+ caseInsensitive('read'),
1560
+ $._io_arguments,
1561
+ optional($.input_item_list)
1562
+ )),
1563
+
1564
+ print_statement: $ => seq(
1565
+ caseInsensitive('print'),
1566
+ $.format_identifier,
1567
+ optional(seq(',', $.output_item_list))
1568
+ ),
1569
+
1570
+ open_statement: $ => seq(
1571
+ caseInsensitive('open'),
1572
+ $._io_arguments,
1573
+ optional($.output_item_list)
1574
+ ),
1575
+
1576
+ close_statement: $ => prec(1,
1577
+ seq(
1578
+ caseInsensitive('close'),
1579
+ '(',
1580
+ choice(
1581
+ $.unit_identifier,
1582
+ seq($.unit_identifier, ',', commaSep1($.keyword_argument)),
1583
+ commaSep1($.keyword_argument)
1584
+ ),
1585
+ ')',
1586
+ )),
1587
+
1588
+ write_statement: $ => prec(1, seq(
1589
+ caseInsensitive('write'),
1590
+ $._io_arguments,
1591
+ // Trailing comma here is a legacy extension to gfortran
1592
+ optional(','),
1593
+ optional($.output_item_list)
1594
+ )),
1595
+
1596
+ inquire_statement: $ => prec(1, seq(
1597
+ caseInsensitive('inquire'),
1598
+ $._io_arguments,
1599
+ optional($.output_item_list),
1600
+ )),
1601
+
1602
+ enum: $ => seq(
1603
+ $.enum_statement,
1604
+ repeat($.enumerator_statement),
1605
+ $.end_enum_statement,
1606
+ $._end_of_statement
1607
+ ),
1608
+
1609
+ enum_statement: $ => seq(
1610
+ caseInsensitive('enum'),
1611
+ ',',
1612
+ $.language_binding
1613
+ ),
1614
+
1615
+ enumeration_type: $ => seq(
1616
+ $.enumeration_type_statement,
1617
+ repeat($.enumerator_statement),
1618
+ $.end_enumeration_type_statement,
1619
+ $._end_of_statement
1620
+ ),
1621
+
1622
+ enumeration_type_statement: $ => seq(
1623
+ caseInsensitive('enumeration'),
1624
+ caseInsensitive('type'),
1625
+ optional(seq(',', $.access_specifier)),
1626
+ optional('::'),
1627
+ $._type_name,
1628
+ ),
1629
+
1630
+ enumerator_statement: $ => seq(
1631
+ caseInsensitive('enumerator'),
1632
+ optional('::'),
1633
+ commaSep1(field('declarator', choice(
1634
+ $.identifier,
1635
+ alias($._declaration_assignment, $.init_declarator),
1636
+ )))
1637
+ ),
1638
+
1639
+ end_enum_statement: $ => whiteSpacedKeyword('end', 'enum'),
1640
+ end_enumeration_type_statement: $ => seq(
1641
+ caseInsensitive('end'),
1642
+ caseInsensitive('enumeration'),
1643
+ caseInsensitive('type'),
1644
+ optional($._name)
1645
+ ),
1646
+
1647
+ // precedence is used to override a conflict with the complex literal
1648
+ unit_identifier: $ => prec(1, choice(
1649
+ $.number_literal,
1650
+ $._io_expressions
1651
+ )),
1652
+
1653
+ format_identifier: $ => choice(
1654
+ $.statement_label_reference,
1655
+ $._io_expressions
1656
+ ),
1657
+
1658
+ _file_position_spec: $ => choice(
1659
+ $.unit_identifier,
1660
+ seq('(', $.unit_identifier, ',', commaSep1($.keyword_argument), ')'),
1661
+ seq('(', commaSep1($.keyword_argument), ')'),
1662
+ ),
1663
+
1664
+ file_position_statement: $ => choice(
1665
+ seq(caseInsensitive('backspace'), $._file_position_spec),
1666
+ seq(caseInsensitive('endfile'), $._file_position_spec),
1667
+ seq(caseInsensitive('rewind'), $._file_position_spec),
1668
+ // Deleted feature -- not quite file position statement
1669
+ seq(caseInsensitive('pause'), optional($.string_literal)),
1670
+ ),
1671
+
1672
+ // This is a limited set of expressions that can be used in IO statements
1673
+ // precedence is used to override a conflict with the complex literal
1674
+ _io_expressions: $ => prec(1, choice(
1675
+ '*',
1676
+ $.string_literal,
1677
+ $.identifier,
1678
+ $.derived_type_member_expression,
1679
+ $.concatenation_expression,
1680
+ $.math_expression,
1681
+ $.parenthesized_expression,
1682
+ $.call_expression
1683
+ )),
1684
+
1685
+ input_item_list: $ => prec.right(commaSep1($._expression)),
1686
+
1687
+ output_item_list: $ => prec.right(commaSep1($._expression)),
1688
+
1689
+ allocate_statement: $ => seq(
1690
+ caseInsensitive('allocate'),
1691
+ '(',
1692
+ optional(field('type', seq(
1693
+ choice(
1694
+ $.intrinsic_type,
1695
+ $.identifier,
1696
+ ),
1697
+ '::'
1698
+ ))),
1699
+ commaSep1(field('allocation', choice(
1700
+ $.identifier,
1701
+ $.derived_type_member_expression,
1702
+ $.sized_allocation,
1703
+ $.coarray_allocation,
1704
+
1705
+ ))),
1706
+ optional(seq(',', commaSep1($.keyword_argument))),
1707
+ ')',
1708
+ ),
1709
+
1710
+ sized_allocation: $ => prec.right(1, seq(
1711
+ $._expression,
1712
+ alias($.argument_list, $.size),
1713
+ )),
1714
+
1715
+ coarray_allocation: $ => seq(
1716
+ choice(
1717
+ $._expression,
1718
+ $.sized_allocation,
1719
+ ),
1720
+ alias($.coarray_index, $.coarray_size),
1721
+ ),
1722
+
1723
+ // Obsolescent feature
1724
+ statement_function: $ => prec.right(seq(
1725
+ $.identifier,
1726
+ alias($._statement_function_arg_list, $.argument_list),
1727
+ '=',
1728
+ $._expression,
1729
+ )),
1730
+
1731
+ _statement_function_arg_list: $ => seq('(', commaSep1($.identifier), ')'),
1732
+
1733
+ // Obsolescent feature
1734
+ entry_statement: $ => seq(
1735
+ caseInsensitive('entry'),
1736
+ field('name', $._name),
1737
+ optional(field('parameters',$._parameters)),
1738
+ optional(repeat(choice(
1739
+ $.language_binding,
1740
+ $.function_result
1741
+ ))),
1742
+ ),
1743
+
1744
+ // Expressions
1745
+
1746
+ _expression: $ => choice(
1747
+ $.number_literal,
1748
+ $.complex_literal,
1749
+ $.string_literal,
1750
+ $.boolean_literal,
1751
+ $.array_literal,
1752
+ $.null_literal,
1753
+ $.identifier,
1754
+ $.derived_type_member_expression,
1755
+ $.logical_expression,
1756
+ $.relational_expression,
1757
+ $.concatenation_expression,
1758
+ $.math_expression,
1759
+ $.unary_expression,
1760
+ $.parenthesized_expression,
1761
+ $.call_expression,
1762
+ $.implied_do_loop_expression,
1763
+ $.coarray_expression,
1764
+ $.conditional_expression,
1765
+ ),
1766
+
1767
+ parenthesized_expression: $ => seq(
1768
+ '(',
1769
+ $._expression,
1770
+ ')'
1771
+ ),
1772
+
1773
+ derived_type_member_expression: $ => prec.right(PREC.TYPE_MEMBER, seq(
1774
+ $._expression,
1775
+ '%',
1776
+ alias($.identifier, $.type_member)
1777
+ )),
1778
+
1779
+ logical_expression: $ => {
1780
+ const table = [
1781
+ [caseInsensitive('\\.or\\.'), PREC.LOGICAL_OR],
1782
+ [caseInsensitive('\\.and\\.'), PREC.LOGICAL_AND],
1783
+ [caseInsensitive('\\.eqv\\.'), PREC.LOGICAL_EQUIV],
1784
+ [caseInsensitive('\\.neqv\\.'), PREC.LOGICAL_EQUIV]
1785
+ ]
1786
+
1787
+ return choice(...table.map(([operator, precedence]) => {
1788
+ return prec.left(precedence, seq(
1789
+ field('left', $._expression),
1790
+ field('operator', operator),
1791
+ field('right', $._expression)
1792
+ ))
1793
+ }).concat(
1794
+ [prec.left(PREC.LOGICAL_NOT, seq(caseInsensitive('\\.not\\.'), $._expression))])
1795
+ )
1796
+ },
1797
+
1798
+ relational_expression: $ => {
1799
+ const operators = [
1800
+ '<',
1801
+ caseInsensitive('\\.lt\\.'),
1802
+ '>',
1803
+ caseInsensitive('\\.gt\\.'),
1804
+ '<=',
1805
+ caseInsensitive('\\.le\\.'),
1806
+ '>=',
1807
+ caseInsensitive('\\.ge\\.'),
1808
+ '==',
1809
+ caseInsensitive('\\.eq\\.'),
1810
+ '/=',
1811
+ caseInsensitive('\\.ne\\.')
1812
+ ]
1813
+
1814
+ return choice(...operators.map((operator) => {
1815
+ return prec.left(PREC.RELATIONAL, seq(
1816
+ field('left', $._expression),
1817
+ field('operator', operator),
1818
+ field('right', $._expression)
1819
+ ))
1820
+ }))
1821
+ },
1822
+
1823
+ concatenation_expression: $ => prec.right(PREC.ADDITIVE, seq(
1824
+ field('left', $._expression),
1825
+ field('operator', '//'),
1826
+ field('right', $._expression)
1827
+ )),
1828
+
1829
+ math_expression: $ => {
1830
+ const table = [
1831
+ ['+', PREC.ADDITIVE],
1832
+ ['-', PREC.ADDITIVE],
1833
+ ['*', PREC.MULTIPLICATIVE],
1834
+ ['/', PREC.MULTIPLICATIVE],
1835
+ ['**', PREC.EXPONENT],
1836
+ [$.user_defined_operator, PREC.DEFINED_OPERATOR]
1837
+ ]
1838
+
1839
+ return choice(...table.map(([operator, precedence]) => {
1840
+ return prec.left(precedence, seq(
1841
+ field('left', $._expression),
1842
+ field('operator', operator),
1843
+ field('right', $._expression)
1844
+ ))
1845
+ }))
1846
+ },
1847
+
1848
+ unary_expression: $ => prec.left(PREC.UNARY, seq(
1849
+ field('operator', choice('-', '+', $.user_defined_operator)),
1850
+ field('argument', $._expression)
1851
+ )),
1852
+
1853
+ user_defined_operator: $ => prec.right(seq(
1854
+ '.', /[a-zA-Z]+/, '.'
1855
+ )),
1856
+
1857
+ // Due to the fact Fortran uses parentheses for both function calls and
1858
+ // array access there is no way to differentiate the two except for the
1859
+ // isolated case of assignment, since you can't assign to a function call.
1860
+ // Because the difference is context specific it is better to consistently
1861
+ // use the call expression for all cases instead of adding a few odd
1862
+ // corner cases when the two can be differentiated.
1863
+ // Similarly call_expressions can also get chained e.g. accessing
1864
+ // elements of an array of strings so we need to repeat the arg list.
1865
+ // Ideally we'd nest call_expressions innermost to outer but that
1866
+ // isn't easy to do.
1867
+ call_expression: $ => prec(
1868
+ PREC.CALL,
1869
+ seq($._expression, repeat1($.argument_list))
1870
+ ),
1871
+
1872
+ implied_do_loop_expression: $ => seq(
1873
+ '(',
1874
+ commaSep1($._expression),
1875
+ ',',
1876
+ $.loop_control_expression,
1877
+ ')'
1878
+ ),
1879
+
1880
+ // Unnamed node so we can reuse it for e.g. kind
1881
+ _argument_list: $ => prec.dynamic(
1882
+ 1,
1883
+ seq(
1884
+ '(',
1885
+ commaSep(choice(
1886
+ $.keyword_argument,
1887
+ $.extent_specifier,
1888
+ $.assumed_size,
1889
+ $.assumed_rank,
1890
+ $._expression,
1891
+ $.multiple_subscript,
1892
+ $.multiple_subscript_triplet,
1893
+ )),
1894
+ ')'
1895
+ )
1896
+ ),
1897
+
1898
+ argument_list: $ => $._argument_list,
1899
+
1900
+ // precedence is used to prevent conflict with assignment expression
1901
+ keyword_argument: $ => prec(1, seq(
1902
+ field("name",$.identifier),
1903
+ '=',
1904
+ field("value",choice($._expression, $.assumed_size, $.assumed_shape))
1905
+ )),
1906
+
1907
+ _extent_specifier: $ => seq(
1908
+ optional($._expression), // start
1909
+ ':',
1910
+ optional(choice($._expression, $.assumed_size)), // stop
1911
+ optional(seq(':', $._expression)) // stride
1912
+ ),
1913
+ extent_specifier: $=> $._extent_specifier,
1914
+
1915
+ multiple_subscript: $ => seq('@', $._expression),
1916
+ multiple_subscript_triplet: $ => seq('@', $._extent_specifier),
1917
+
1918
+ assumed_size: $ => '*',
1919
+
1920
+ assumed_shape: $ => ':',
1921
+
1922
+ assumed_rank: $ => '..',
1923
+
1924
+ block_label_start_expression: $ => seq(alias($.identifier, 'label'), ':'),
1925
+ _block_label: $ => alias($.identifier, $.block_label),
1926
+
1927
+ loop_control_expression: $ => seq(
1928
+ $.identifier,
1929
+ '=',
1930
+ $._expression,
1931
+ ',',
1932
+ $._expression,
1933
+ optional(seq(',', $._expression))
1934
+ ),
1935
+
1936
+ array_literal: $ => choice(
1937
+ $._array_constructor_legacy,
1938
+ $._array_constructor_f2003
1939
+ ),
1940
+
1941
+ _array_constructor_legacy: $ => seq('(/', $._ac_value_list, '/)'),
1942
+
1943
+ _array_constructor_f2003: $ => seq('[', $._ac_value_list, ']'),
1944
+
1945
+ _type_spec: $ => seq(choice($.intrinsic_type, $.derived_type), '::'),
1946
+
1947
+ _ac_value_list: $ => choice(
1948
+ field('type', $._type_spec),
1949
+ seq(
1950
+ optional(field('type', $._type_spec)),
1951
+ commaSep1($._expression)
1952
+ )
1953
+ ),
1954
+
1955
+ complex_literal: $ => seq(
1956
+ '(',
1957
+ choice($.number_literal, $.identifier, $.unary_expression),
1958
+ ',',
1959
+ choice($.number_literal, $.identifier, $.unary_expression),
1960
+ ')'
1961
+ ),
1962
+
1963
+ number_literal: $ => seq(
1964
+ choice(
1965
+ $._integer_literal,
1966
+ $._float_literal,
1967
+ $._boz_literal
1968
+ ),
1969
+ optional($._kind)
1970
+ ),
1971
+
1972
+ boolean_literal: $ => seq(
1973
+ choice(
1974
+ caseInsensitive('\\.true\\.'),
1975
+ caseInsensitive('\\.false\\.')
1976
+ ),
1977
+ optional($._kind)
1978
+ ),
1979
+
1980
+ _kind: $ => seq(
1981
+ token.immediate('_'),
1982
+ field(
1983
+ 'kind',
1984
+ choice(
1985
+ alias(token.immediate(/[a-zA-Z]\w*/), $.identifier),
1986
+ alias(token.immediate(/\d+/), $.number_literal)
1987
+ )
1988
+ )
1989
+ ),
1990
+
1991
+ null_literal: $ => prec(1, seq(
1992
+ caseInsensitive('null'), '(', ')'
1993
+ )),
1994
+
1995
+ string_literal: $ => seq(
1996
+ // Having a kind _prefix_, with an underscore and no whitespace,
1997
+ // is _really_ hard to parse without breaking other things, so
1998
+ // we have to rely on an external scanner
1999
+ optional(seq(
2000
+ field('kind', alias($._string_literal_kind, $.identifier)),
2001
+ // Although external scanner enforces trailing underscore, we
2002
+ // also need to *capture* it here
2003
+ token.immediate('_'),
2004
+ )),
2005
+ $._string_literal,
2006
+ ),
2007
+
2008
+ // Coarrays
2009
+
2010
+ coarray_index: $ => seq(
2011
+ '[',
2012
+ commaSep1(choice(
2013
+ $._expression,
2014
+ alias($._coarray_extent_specifier, $.extent_specifier),
2015
+ '*',
2016
+ )),
2017
+ commaSep(seq(',', $.keyword_argument)),
2018
+ ']'
2019
+ ),
2020
+
2021
+ // Copy of `extent_specifier` but we don't want `*` to be named `assumed_size`
2022
+ _coarray_extent_specifier: $ => seq(
2023
+ optional($._expression), // start
2024
+ ':',
2025
+ optional(choice($._expression, '*')), // stop
2026
+ optional(seq(':', $._expression)) // stride
2027
+ ),
2028
+
2029
+ coarray_declarator: $ => prec.right(seq(
2030
+ choice(
2031
+ $.identifier,
2032
+ $.sized_declarator,
2033
+ ),
2034
+ alias($.coarray_index, $.coarray_size),
2035
+ )),
2036
+
2037
+ coarray_expression: $ => prec.right(seq(
2038
+ $._expression,
2039
+ $.coarray_index,
2040
+ )),
2041
+
2042
+ coarray_statement: $ => choice(
2043
+ seq(
2044
+ choice(
2045
+ caseInsensitive('sync'),
2046
+ caseInsensitive('form'),
2047
+ ),
2048
+ choice(
2049
+ caseInsensitive('all'),
2050
+ caseInsensitive('images'),
2051
+ caseInsensitive('memory'),
2052
+ caseInsensitive('team'),
2053
+ ),
2054
+ optional($.argument_list),
2055
+ ),
2056
+ seq(caseInsensitive('fail'), caseInsensitive('image')),
2057
+ seq(
2058
+ caseInsensitive('event'),
2059
+ choice(
2060
+ caseInsensitive('post'),
2061
+ caseInsensitive('wait'),
2062
+ ),
2063
+ $.argument_list,
2064
+ ),
2065
+ prec.right(1, seq(
2066
+ choice(
2067
+ caseInsensitive('lock'),
2068
+ caseInsensitive('unlock'),
2069
+ ),
2070
+ $.argument_list,
2071
+ )),
2072
+ seq(
2073
+ caseInsensitive('notify'),
2074
+ caseInsensitive('wait'),
2075
+ $.argument_list,
2076
+ ),
2077
+ ),
2078
+
2079
+ coarray_team_statement: $ => seq(
2080
+ optional($.block_label_start_expression),
2081
+ caseInsensitive('change'),
2082
+ caseInsensitive('team'),
2083
+ $.argument_list,
2084
+ $._end_of_statement,
2085
+ repeat($._statement),
2086
+ $.end_coarray_team_statement,
2087
+ ),
2088
+
2089
+ end_coarray_team_statement: $ => seq(
2090
+ whiteSpacedKeyword('end', 'team'),
2091
+ optional($.argument_list),
2092
+ optional($._block_label),
2093
+ ),
2094
+
2095
+ coarray_critical_statement: $ => seq(
2096
+ optional($.block_label_start_expression),
2097
+ caseInsensitive('critical'),
2098
+ optional($.argument_list),
2099
+ $._end_of_statement,
2100
+ repeat($._statement),
2101
+ $.end_coarray_critical_statement,
2102
+ ),
2103
+
2104
+ end_coarray_critical_statement: $ => seq(
2105
+ whiteSpacedKeyword('end', 'critical'),
2106
+ optional($._block_label),
2107
+ ),
2108
+
2109
+ conditional_expression: $ => seq(
2110
+ field('condition', $._expression),
2111
+ '?',
2112
+ field('consequence', choice(prec.left($._expression), $.nil_literal)),
2113
+ ':',
2114
+ field('alternative', choice(prec.left($._expression), $.nil_literal)),
2115
+ ),
2116
+
2117
+ // Strictly only valid when used in a conditional_expression as an
2118
+ // actual argument
2119
+ nil_literal: $ => caseInsensitive('\\.nil\\.'),
2120
+
2121
+ // Fortran doesn't have reserved keywords, and to allow _just
2122
+ // enough_ ambiguity so that tree-sitter can parse tokens
2123
+ // correctly as either a keyword or a plain identifier, we must
2124
+ // add the keywords here -- and possibly in `conflicts` too.
2125
+ identifier: $ => choice(
2126
+ /[a-zA-Z_$][\w$]*/,
2127
+ caseInsensitive('allocatable'),
2128
+ caseInsensitive('automatic'),
2129
+ caseInsensitive('block'),
2130
+ caseInsensitive('byte'),
2131
+ caseInsensitive('change'),
2132
+ caseInsensitive('constant'),
2133
+ caseInsensitive('contiguous'),
2134
+ caseInsensitive('critical'),
2135
+ caseInsensitive('cycle'),
2136
+ caseInsensitive('data'),
2137
+ caseInsensitive('device'),
2138
+ prec(-1, caseInsensitive('dimension')),
2139
+ caseInsensitive('double'),
2140
+ caseInsensitive('elseif'),
2141
+ caseInsensitive('end'),
2142
+ caseInsensitive('endif'),
2143
+ caseInsensitive('entry'),
2144
+ caseInsensitive('error'),
2145
+ caseInsensitive('event'),
2146
+ caseInsensitive('exit'),
2147
+ caseInsensitive('external'),
2148
+ caseInsensitive('fail'),
2149
+ caseInsensitive('form'),
2150
+ caseInsensitive('format'),
2151
+ caseInsensitive('if'),
2152
+ caseInsensitive('inquire'),
2153
+ caseInsensitive('intrinsic'),
2154
+ caseInsensitive('kind'),
2155
+ caseInsensitive('len'),
2156
+ caseInsensitive('lock'),
2157
+ caseInsensitive('null'),
2158
+ caseInsensitive('optional'),
2159
+ caseInsensitive('parameter'),
2160
+ caseInsensitive('pointer'),
2161
+ caseInsensitive('private'),
2162
+ caseInsensitive('public'),
2163
+ prec(-1, caseInsensitive('rank')),
2164
+ caseInsensitive('read'),
2165
+ caseInsensitive('real'),
2166
+ caseInsensitive('save'),
2167
+ caseInsensitive('select'),
2168
+ caseInsensitive('sequence'),
2169
+ caseInsensitive('shared'),
2170
+ caseInsensitive('static'),
2171
+ caseInsensitive('stop'),
2172
+ caseInsensitive('sync'),
2173
+ caseInsensitive('target'),
2174
+ caseInsensitive('texture'),
2175
+ caseInsensitive('unlock'),
2176
+ caseInsensitive('value'),
2177
+ caseInsensitive('write'),
2178
+ ),
2179
+
2180
+ comment: $ => token(seq('!', /.*/)),
2181
+
2182
+ _end_of_statement: $ => choice(';', $._external_end_of_statement),
2183
+
2184
+ _newline: $ => '\n',
2185
+ }
2186
+ })
2187
+
2188
+ module.exports.PREC = PREC
2189
+
2190
+ function caseInsensitive (keyword, aliasAsWord = true) {
2191
+ let result = new RegExp(keyword
2192
+ .split('')
2193
+ .map(l => l !== l.toUpperCase() ? `[${l}${l.toUpperCase()}]` : l)
2194
+ .join('')
2195
+ )
2196
+ if (aliasAsWord) result = alias(result, keyword)
2197
+ return result
2198
+ }
2199
+
2200
+ function whiteSpacedKeyword (prefix, suffix, aliasAsWord = true) {
2201
+ let result = choice(
2202
+ seq(caseInsensitive(prefix, false), caseInsensitive(suffix, false)),
2203
+ caseInsensitive(prefix + suffix, false))
2204
+ if (aliasAsWord) result = alias(result, prefix + suffix)
2205
+ return result
2206
+ }
2207
+
2208
+ function commaSep (rule) {
2209
+ return optional(commaSep1(rule))
2210
+ }
2211
+
2212
+ function commaSep1 (rule) {
2213
+ return sep1(rule, ',')
2214
+ }
2215
+
2216
+ function sep1 (rule, separator) {
2217
+ return seq(rule, repeat(seq(separator, rule)))
2218
+ }
2219
+
2220
+ // This can be merged with whiteSpacedKeyword, keeping for now.
2221
+ function blockStructureEnding ($, structType) {
2222
+ const obj = prec.right(seq(
2223
+ alias(choice(
2224
+ seq(
2225
+ caseInsensitive('end', false),
2226
+ optional(caseInsensitive(structType, false))),
2227
+ caseInsensitive('end' + structType, false)),
2228
+ 'end' + structType),
2229
+ optional($._name),
2230
+ $._end_of_statement
2231
+ ))
2232
+ return obj
2233
+ }
2234
+
2235
+ /**
2236
+ *
2237
+ * @param {string} suffix
2238
+ *
2239
+ * @param {RuleBuilder<string>} content
2240
+ *
2241
+ * @param {number} precedence
2242
+ *
2243
+ * @return {RuleBuilders<string, string>}
2244
+ */
2245
+ function preprocIf(suffix, content, precedence = 0) {
2246
+ /**
2247
+ *
2248
+ * @param {GrammarSymbols<string>} $
2249
+ *
2250
+ * @return {ChoiceRule}
2251
+ *
2252
+ */
2253
+ function alternativeBlock($) {
2254
+ return choice(
2255
+ suffix ? alias($['preproc_else' + suffix], $.preproc_else) : $.preproc_else,
2256
+ suffix ? alias($['preproc_elif' + suffix], $.preproc_elif) : $.preproc_elif,
2257
+ suffix ? alias($['preproc_elifdef' + suffix], $.preproc_elifdef) : $.preproc_elifdef,
2258
+ );
2259
+ }
2260
+
2261
+ return {
2262
+ ['preproc_if' + suffix]: $ => prec(precedence, seq(
2263
+ preprocessor('if'),
2264
+ field('condition', $._preproc_expression),
2265
+ optional($.preproc_comment),
2266
+ '\n',
2267
+ content($),
2268
+ field('alternative', optional(alternativeBlock($))),
2269
+ preprocessor('endif'),
2270
+ optional($.preproc_comment),
2271
+ )),
2272
+
2273
+ ['preproc_ifdef' + suffix]: $ => prec(precedence, seq(
2274
+ choice(preprocessor('ifdef'), preprocessor('ifndef')),
2275
+ field('name', $.identifier),
2276
+ optional($.preproc_comment),
2277
+ content($),
2278
+ field('alternative', optional(alternativeBlock($))),
2279
+ preprocessor('endif'),
2280
+ optional($.preproc_comment),
2281
+ )),
2282
+
2283
+ ['preproc_else' + suffix]: $ => prec(precedence, seq(
2284
+ preprocessor('else'),
2285
+ optional($.preproc_comment),
2286
+ content($),
2287
+ )),
2288
+
2289
+ ['preproc_elif' + suffix]: $ => prec(precedence, seq(
2290
+ preprocessor('elif'),
2291
+ optional($.preproc_comment),
2292
+ field('condition', $._preproc_expression),
2293
+ '\n',
2294
+ content($),
2295
+ field('alternative', optional(alternativeBlock($))),
2296
+ )),
2297
+
2298
+ ['preproc_elifdef' + suffix]: $ => prec(precedence, seq(
2299
+ choice(preprocessor('elifdef'), preprocessor('elifndef')),
2300
+ field('name', $.identifier),
2301
+ optional($.preproc_comment),
2302
+ content($),
2303
+ field('alternative', optional(alternativeBlock($))),
2304
+ )),
2305
+ };
2306
+ }
2307
+
2308
+ /**
2309
+ * Creates a preprocessor regex rule
2310
+ *
2311
+ * @param {RegExp|Rule|String} command
2312
+ *
2313
+ * @return {AliasRule}
2314
+ */
2315
+ function preprocessor(command) {
2316
+ return alias(new RegExp('#[ \t]*' + command), '#' + command);
2317
+ }
2318
+
2319
+ /**
2320
+ * Common rule for procedures (function, subroutine, module procedure)
2321
+ *
2322
+ * @param {GrammarSymbols<string>} $
2323
+ * @param {Rule} start_statement
2324
+ * @param {Rule} end_statement
2325
+ *
2326
+ * @return {Rule}
2327
+ */
2328
+ function procedure($, start_statement, end_statement) {
2329
+ return seq(
2330
+ start_statement,
2331
+ $._end_of_statement,
2332
+ repeat(
2333
+ choice(
2334
+ $._specification_part,
2335
+ alias($.preproc_if_in_specification_part, $.preproc_if),
2336
+ alias($.preproc_ifdef_in_specification_part, $.preproc_ifdef)
2337
+ ),
2338
+ ),
2339
+ repeat(
2340
+ choice(
2341
+ $._statement,
2342
+ alias($.preproc_if_in_procedure_statements, $.preproc_if),
2343
+ alias($.preproc_ifdef_in_procedure_statements, $.preproc_ifdef)
2344
+ ),
2345
+ ),
2346
+ optional($.internal_procedures),
2347
+ end_statement
2348
+ );
2349
+ }