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/grammar.js ADDED
@@ -0,0 +1,1831 @@
1
+ const PREC = {
2
+ UNARY: 8,
3
+ EXP: 7,
4
+ MULTI: 6,
5
+ ADD: 5,
6
+ COMPARE: 4,
7
+ LOGICAL: 3,
8
+ ASSIGN: 2,
9
+ EXTRA: -1
10
+ };
11
+
12
+ module.exports = grammar({
13
+ name: "abl",
14
+
15
+ externals: ($) => [
16
+ $._namedot,
17
+ $._namecolon,
18
+ $._namedoublecolon,
19
+ $._or_operator,
20
+ $._and_operator,
21
+ $._augmented_assignment,
22
+ $._escaped_string,
23
+ $._input_keyword,
24
+ $._output_keyword,
25
+ $._new_keyword,
26
+ $._old_keyword,
27
+ $._for_keyword,
28
+ $._def_keyword,
29
+ $._var_keyword,
30
+ $._special_character
31
+ ],
32
+ extras: ($) => [$.comment, /[\s\f\uFEFF\u2060\u200B]|\\\r?\n/],
33
+ word: ($) => $.identifier,
34
+ supertypes: ($) => [$._expression, $._statement],
35
+ conflicts: ($) => [
36
+ // [$.input_expression],
37
+ [$.record_phrase],
38
+ [$.sort_clause],
39
+ [$.string_literal],
40
+ ...combinations([$._statement, $.if_statement]),
41
+ ...combinations([$._statement, $.on_statement]),
42
+ // DEFINE * conflicts
43
+ ...combinations([
44
+ $.abl_statement,
45
+ $.variable_definition,
46
+ $.buffer_definition,
47
+ $.query_definition,
48
+ $.temp_table_definition,
49
+ $.workfile_definition,
50
+ $.property_definition,
51
+ $.data_source_definition,
52
+ $.event_definition,
53
+ $.dataset_definition,
54
+ $.stream_definition,
55
+ $.image_definition
56
+ ])
57
+ ],
58
+
59
+ rules: {
60
+ source_code: ($) => repeat($._statement),
61
+
62
+ body: ($) => seq(":", repeat($._statement)),
63
+ dot_body: ($) => seq(choice(":", "."), repeat($._statement)),
64
+
65
+ file_name: ($) => /[A-z-_|0-9|\/]+\.[i]/i,
66
+ comment: ($) =>
67
+ choice(seq("//", /.*/), seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/")),
68
+ constant: ($) =>
69
+ seq("{", optional("&"), choice($.identifier, $._integer_literal), "}"),
70
+
71
+ identifier: ($) => /[A-Z|a-z|\-|\\_]{1}[A-Z|a-z|\-|\\_|0-9]*/i,
72
+ qualified_name: ($) =>
73
+ seq(
74
+ $.identifier,
75
+ repeat1(seq(alias($._namedot, "."), choice($.identifier, "*")))
76
+ ),
77
+
78
+ _terminator: ($) => /\s*\./i,
79
+ _block_terminator: ($) => seq(kw("END"), "."),
80
+
81
+ null_statement: ($) => seq(choice($.object_access), $._terminator),
82
+
83
+ null_expression: ($) => /\?/,
84
+ boolean_literal: ($) =>
85
+ choice(kw("TRUE"), kw("FALSE"), kw("YES"), kw("NO")),
86
+ _integer_literal: ($) => /[0-9]+/,
87
+ _decimal_literal: ($) =>
88
+ seq($._integer_literal, alias($._namedot, "."), $._integer_literal),
89
+
90
+ number_literal: ($) => choice($._integer_literal, $._decimal_literal),
91
+ string_literal: ($) => seq($._escaped_string, optional(seq(":", $.string_literal_attribute))),
92
+
93
+ string_literal_attribute: ($) =>
94
+ choice(
95
+ seq(kw("R"), $._integer_literal),
96
+ seq(kw("L"), $._integer_literal),
97
+ seq(kw("C"), $._integer_literal),
98
+ seq(kw("T"), $._integer_literal),
99
+ kw("U")
100
+ ),
101
+
102
+ date_literal: ($) => /\d{1,2}\/\d{1,2}\/\d{4}|\d{2}/,
103
+ array_literal: ($) => seq("[", optional(choice($.range_notation, _list($._expression, ","))), "]"),
104
+
105
+ single_quoted_string: ($) =>
106
+ seq("'", repeat(choice(/[^'\\]+/, /\\./, $._special_character)), "'"),
107
+
108
+ parenthesized_expression: ($) => seq("(", $._expression, ")"),
109
+
110
+ _logical_operator: ($) =>
111
+ prec.left(
112
+ choice(alias($._and_operator, "AND"), alias($._or_operator, "OR"))
113
+ ),
114
+ logical_expression: ($) =>
115
+ prec.right(
116
+ PREC.LOGICAL,
117
+ seq($._expression, $._logical_operator, $._expression)
118
+ ),
119
+
120
+ type_tuning: ($) =>
121
+ choice(
122
+ seq(kw("AS"), field("type", $._type)),
123
+ seq(kw("LIKE"), field("type", $._type))
124
+ ),
125
+
126
+ assignment_operator: ($) => choice("=", $._augmented_assignment),
127
+
128
+ _unary_minus_expressions: ($) =>
129
+ choice(
130
+ $.identifier,
131
+ $.number_literal,
132
+ $.function_call,
133
+ $.qualified_name,
134
+ $.object_access,
135
+ $.member_access,
136
+ $.parenthesized_expression
137
+ ),
138
+
139
+ unary_expression: ($) =>
140
+ choice(
141
+ prec.left(
142
+ PREC.UNARY,
143
+ seq(kw("-"), prec.left($._unary_minus_expressions))
144
+ ),
145
+ prec.left(
146
+ PREC.LOGICAL,
147
+ seq(kw("NOT"), prec.left(PREC.LOGICAL, $._expression))
148
+ )
149
+ ),
150
+
151
+ ambiguous_expression: ($) => seq(kw("AMBIGUOUS"), $._expression),
152
+ temp_table_expression: ($) =>
153
+ seq(kw("TEMP-TABLE"), field("table", choice($._expression))),
154
+ current_changed_expression: ($) =>
155
+ seq(kw("CURRENT-CHANGED"), $._expression),
156
+ locked_expression: ($) => seq(kw("LOCKED"), $._expression),
157
+ dataset_expression: ($) => seq(prec.left(kw("DATASET")), $._expression),
158
+ input_expression: ($) =>
159
+ seq(
160
+ alias($._input_keyword, "INPUT"),
161
+ optional(seq(kw("FRAME"), field("frame", $.identifier))),
162
+ field("field", choice($.identifier, $.qualified_name))
163
+ ),
164
+
165
+ _additive_operator: ($) => choice("+", "-"),
166
+ additive_expression: ($) =>
167
+ prec.left(
168
+ PREC.ADD,
169
+ choice(seq($._expression, $._additive_operator, $._expression))
170
+ ),
171
+
172
+ _multiplicative_operator: ($) => choice("*", "/", kw("MODULO"), kw("MOD")),
173
+ multiplicative_expression: ($) =>
174
+ prec.left(
175
+ PREC.MULTI,
176
+ choice(seq($._expression, $._multiplicative_operator, $._expression))
177
+ ),
178
+
179
+ _comparison_operator: ($) =>
180
+ choice(
181
+ "<",
182
+ "<=",
183
+ "<>",
184
+ "=",
185
+ ">",
186
+ ">=",
187
+ kw("LT"),
188
+ kw("LE"),
189
+ kw("NE"),
190
+ kw("EQ"),
191
+ kw("GT"),
192
+ kw("GE"),
193
+ kw("BEGINS"),
194
+ kw("MATCHES"),
195
+ kw("CONTAINS")
196
+ ),
197
+ comparison_expression: ($) =>
198
+ prec.right(
199
+ PREC.COMPARE,
200
+ seq($._expression, $._comparison_operator, $._expression)
201
+ ),
202
+
203
+ _binary_expression: ($) =>
204
+ choice(
205
+ $.additive_expression,
206
+ $.multiplicative_expression,
207
+ $.comparison_expression,
208
+ $.logical_expression
209
+ ),
210
+
211
+ range_notation: ($) => seq($._expression, alias($._for_keyword, "FOR"), $._expression),
212
+ array_access: ($) =>
213
+ prec.right(
214
+ 1,
215
+ seq(
216
+ field("array", choice($.identifier, $.object_access)),
217
+ $.array_literal,
218
+ )
219
+ ),
220
+
221
+ /// Includes
222
+ include_argument: ($) =>
223
+ choice(
224
+ seq(
225
+ /\&/,
226
+ field("name", $.identifier),
227
+ "=",
228
+ field("value", $._expression)
229
+ ),
230
+ field("name", $.identifier),
231
+ field("value", $.string_literal),
232
+ $.constant
233
+ ),
234
+ include: ($) =>
235
+ seq(
236
+ "{",
237
+ repeat($.constant),
238
+ $.file_name,
239
+ optional(repeat($.include_argument)),
240
+ "}"
241
+ ),
242
+
243
+ primitive_type: ($) =>
244
+ choice(
245
+ kw("VOID"),
246
+ kw("LOGICAL"),
247
+ kw("INTEGER"),
248
+ kw("INT"),
249
+ kw("CHARACTER"),
250
+ kw("CHAR"),
251
+ kw("DECIMAL"),
252
+ kw("DATE"),
253
+ kw("DATETIME"),
254
+ kw("DATETIME-TZ"),
255
+ kw("INT64"),
256
+ kw("LONGCHAR"),
257
+ kw("MEMPTR"),
258
+ kw("RAW"),
259
+ kw("RECID"),
260
+ kw("ROWID"),
261
+ kw("HANDLE"),
262
+ kw("COM-HANDLE")
263
+ ),
264
+
265
+ class_type: ($) => seq(kw("CLASS"), choice($.identifier, $.qualified_name)),
266
+ generic_parameter: ($) => seq($.identifier, $.type_tuning),
267
+ generic_expression: ($) =>
268
+ seq(
269
+ "<",
270
+ _list(choice($.identifier, $.qualified_name, $.generic_parameter), ","),
271
+ ">"
272
+ ),
273
+ generic_type: ($) =>
274
+ seq(choice($.identifier, $.qualified_name), $.generic_expression),
275
+ _type: ($) =>
276
+ choice(
277
+ $.primitive_type,
278
+ $.identifier,
279
+ $.qualified_name,
280
+ $.class_type,
281
+ $.generic_type
282
+ ),
283
+
284
+ when_expression: ($) => seq(kw("WHEN"), $._expression),
285
+ assignment: ($) =>
286
+ prec.right(
287
+ PREC.ASSIGN,
288
+ seq(
289
+ prec.left(
290
+ field(
291
+ "name",
292
+ choice(
293
+ $.identifier,
294
+ $.qualified_name,
295
+ $.object_access,
296
+ $.member_access,
297
+ $.function_call,
298
+ $.array_access
299
+ )
300
+ )
301
+ ),
302
+ $.assignment_operator,
303
+ prec.right(choice($._expression, $.include)),
304
+ optional($.when_expression)
305
+ )
306
+ ),
307
+ variable_assignment: ($) => seq($.assignment, $._terminator),
308
+
309
+ _define: ($) =>
310
+ choice(
311
+ kw("DEFINE"),
312
+ alias($._def_keyword, "DEF"),
313
+ ),
314
+
315
+ variable_tuning: ($) =>
316
+ seq(
317
+ choice(
318
+ seq(choice(kw("INITIAL"), kw("INIT")), $._expression),
319
+ seq(kw("FORMAT"), $._expression),
320
+ seq(kw("LABEL"), $._expression),
321
+ seq(kw("COLUMN-LABEL"), $._expression),
322
+ seq(kw("DECIMALS"), $._expression),
323
+ seq(kw("EXTENT"), $.number_literal),
324
+ kw("NO-UNDO")
325
+ )
326
+ ),
327
+
328
+ scope_tuning: ($) =>
329
+ choice(alias($._new_keyword, "NEW"), kw("GLOBAL"), kw("SHARED"), kw("STATIC")),
330
+ access_tuning: ($) =>
331
+ choice(
332
+ kw("PRIVATE"),
333
+ kw("PROTECTED"),
334
+ kw("PUBLIC"),
335
+ kw("PACKAGE-PRIVATE"),
336
+ kw("PACKAGE-PROTECTED")
337
+ ),
338
+ serialization_tuning: ($) =>
339
+ choice(kw("SERIALIZABLE"), kw("NON-SERIALIZABLE")),
340
+
341
+ variable_definition: ($) =>
342
+ seq(
343
+ $._define,
344
+ repeat(choice($.scope_tuning, $.access_tuning, $.serialization_tuning)),
345
+ choice(kw("VARIABLE"), kw("VAR")),
346
+ field("name", $.identifier),
347
+ $.type_tuning,
348
+ repeat($.variable_tuning),
349
+ $._terminator
350
+ ),
351
+
352
+ buffer_definition: ($) =>
353
+ seq(
354
+ $._define,
355
+ repeat(choice($.scope_tuning, $.access_tuning)),
356
+ kw("BUFFER"),
357
+ field("name", $.identifier),
358
+ alias($._for_keyword, "FOR"),
359
+ optional(kw("TEMP-TABLE")),
360
+ field("table", choice($.identifier, $.qualified_name)),
361
+ $._terminator
362
+ ),
363
+
364
+ query_definition_tuning: ($) =>
365
+ choice(
366
+ seq(kw("CACHE"), $.number_literal),
367
+ "SCROLLING",
368
+ kw("RCODE-INFORMATION")
369
+ ),
370
+ query_fields: ($) => seq("(", repeat($.identifier), ")"),
371
+ query_definition: ($) =>
372
+ seq(
373
+ $._define,
374
+ repeat(choice($.scope_tuning, $.access_tuning)),
375
+ kw("QUERY"),
376
+ field("name", $.identifier),
377
+ alias($._for_keyword, "FOR"),
378
+ $.identifier,
379
+ optional(seq(kw("FIELDS"), $.query_fields)),
380
+ optional(seq(kw("EXCEPT"), $.query_fields)),
381
+ repeat($.query_definition_tuning),
382
+ $._terminator
383
+ ),
384
+
385
+ return_tuning: ($) => seq(kw("EXTENT"), $.number_literal),
386
+ return_type: ($) =>
387
+ seq(choice(kw("RETURNS"), kw("RETURN")), field("type", $._type)),
388
+
389
+ function_call_statement: ($) => seq($.function_call, $._terminator),
390
+
391
+ argument_mode: ($) =>
392
+ prec.right(
393
+ choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT"), kw("DATA-SOURCE"))
394
+ ),
395
+
396
+ argument_tuning: ($) =>
397
+ choice(kw("BY-VALUE"), kw("BY-REFERENCE"), kw("BIND"), kw("APPEND")),
398
+ function_call_argument: ($) =>
399
+ prec.right(
400
+ 1,
401
+ seq(
402
+ optional($.argument_mode),
403
+ choice(
404
+ seq(
405
+ choice($.identifier, $.object_access, $.qualified_name),
406
+ optional($.type_tuning)
407
+ ),
408
+ seq(
409
+ optional(
410
+ choice(
411
+ kw("TABLE"),
412
+ kw("TABLE-HANDLE"),
413
+ kw("DATASET"),
414
+ kw("DATASET-HANDLE")
415
+ )
416
+ ),
417
+ $._expression
418
+ )
419
+ ),
420
+ optional($.argument_tuning)
421
+ )
422
+ ),
423
+
424
+ function_arguments: ($) =>
425
+ seq(
426
+ "(",
427
+ optional(_list(alias($.function_call_argument, $.argument), ",")),
428
+ ")"
429
+ ),
430
+ function_call: ($) =>
431
+ prec.right(
432
+ 1,
433
+ seq(
434
+ field(
435
+ "function",
436
+ choice($.identifier, prec.right(2, $.object_access))
437
+ ),
438
+ alias($.function_arguments, $.arguments),
439
+ optional(kw("NO-ERROR"))
440
+ )
441
+ ),
442
+
443
+ if_statement: ($) =>
444
+ seq(
445
+ kw("IF"),
446
+ field("condition", $._expression),
447
+ kw("THEN"),
448
+ choice($.do_block, prec(2, $._statement)),
449
+ repeat(choice($.else_statement))
450
+ ),
451
+
452
+ else_statement: ($) =>
453
+ prec(
454
+ 1,
455
+ seq(
456
+ kw("ELSE"),
457
+ optional(
458
+ seq(kw("IF"), field("condition", $._expression), kw("THEN"))
459
+ ),
460
+ choice($.do_block, $._statement)
461
+ )
462
+ ),
463
+
464
+ ternary_expression: ($) =>
465
+ prec.right(
466
+ seq(
467
+ kw("IF"),
468
+ field("condition", $._expression),
469
+ kw("THEN"),
470
+ field("then", $._expression),
471
+ kw("ELSE"),
472
+ field("else", $._expression)
473
+ )
474
+ ),
475
+
476
+ label: ($) => seq($.identifier, ":"),
477
+
478
+ while_phrase: ($) => seq(kw("WHILE"), field("condition", $._expression)),
479
+
480
+ repeat_tuning: ($) => choice(seq(kw("WITH"), kw("FRAME"), $.identifier)),
481
+
482
+ repeat_statement: ($) =>
483
+ seq(
484
+ optional($.label),
485
+ kw("REPEAT"),
486
+ optional($.preselect_phrase),
487
+ optional($.to_phrase),
488
+ optional($.while_phrase),
489
+ repeat(
490
+ choice(
491
+ $.on_error_phrase,
492
+ $.on_quit_phrase,
493
+ $.on_stop_phrase,
494
+ $.on_endkey_phrase
495
+ )
496
+ ),
497
+ repeat($.repeat_tuning),
498
+ $.body,
499
+ $._block_terminator
500
+ ),
501
+
502
+ _procedure_terminator: ($) => seq(kw("END"), kw("PROCEDURE"), "."),
503
+ procedure_statement: ($) =>
504
+ seq(
505
+ kw("PROCEDURE"),
506
+ $.identifier,
507
+ optional(kw("PRIVATE")),
508
+ optional(alias($.dot_body, $.body)),
509
+ choice($._block_terminator, $._procedure_terminator)
510
+ ),
511
+
512
+ procedure_parameter_tuning: ($) =>
513
+ choice(kw("APPEND"), kw("BIND"), kw("BY-VALUE")),
514
+
515
+ procedure_parameter_definition: ($) =>
516
+ seq(
517
+ $._define,
518
+ optional(
519
+ choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT"), kw("RETURN"))
520
+ ),
521
+ choice(kw("PARAMETER"), kw("PARAM")),
522
+ optional(
523
+ choice(
524
+ seq(kw("BUFFER"), field("buffer", $.identifier)),
525
+ choice(
526
+ kw("TABLE"),
527
+ kw("TABLE-HANDLE"),
528
+ seq(kw("DATASET"), optional(token.immediate(kw("-HANDLE"))))
529
+ )
530
+ )
531
+ ),
532
+ optional(alias($._for_keyword, "FOR")),
533
+ field("name", $.identifier),
534
+ choice(
535
+ seq($.type_tuning, repeat($.variable_tuning)),
536
+ repeat($.procedure_parameter_tuning)
537
+ ),
538
+ $._terminator
539
+ ),
540
+
541
+ _function_terminator: ($) =>
542
+ choice(
543
+ $._block_terminator,
544
+ seq(kw("END"), kw("FUNCTION"), $._terminator)
545
+ ),
546
+ function_parameter_mode: ($) =>
547
+ choice(alias($._input_keyword, "INPUT"), alias($._output_keyword, "OUTPUT"), kw("INPUT-OUTPUT")),
548
+ function_parameter_tuning: ($) =>
549
+ choice(
550
+ kw("APPEND"),
551
+ kw("BIND"),
552
+ kw("BY-VALUE"),
553
+ seq(kw("EXTENT"), optional($.number_literal))
554
+ ),
555
+ function_parameter: ($) =>
556
+ choice(
557
+ seq(
558
+ optional(kw("TABLE-HANDLE")),
559
+ optional($.function_parameter_mode),
560
+ optional(
561
+ choice(
562
+ kw("TABLE "),
563
+ kw("TABLE-HANDLE"),
564
+ kw("DATASET-HANDLE"),
565
+ kw("DATASET ")
566
+ )
567
+ ),
568
+ field("name", $.identifier),
569
+ optional($.type_tuning),
570
+ repeat($.function_parameter_tuning)
571
+ ),
572
+ seq(
573
+ kw("BUFFER"),
574
+ field("buffer", $.identifier),
575
+ alias($._for_keyword, "FOR"),
576
+ field("table", choice($.identifier, $.qualified_name)),
577
+ optional(kw("PRESELECT"))
578
+ )
579
+ ),
580
+
581
+ function_parameters: ($) =>
582
+ seq("(", optional(_list($.function_parameter, ",")), ")"),
583
+
584
+ function_statement: ($) =>
585
+ seq(
586
+ kw("FUNCTION"),
587
+ field("name", $.identifier),
588
+ $.return_type,
589
+ optional($.return_tuning),
590
+ optional(alias($.function_parameters, $.parameters)),
591
+ optional(alias($.dot_body, $.body)),
592
+ $._function_terminator
593
+ ),
594
+
595
+ return_statement: ($) =>
596
+ seq(kw("RETURN"), optional($._expression), $._terminator),
597
+
598
+ interface_body: ($) =>
599
+ seq(
600
+ ":",
601
+ repeat(
602
+ choice(
603
+ $.property_definition,
604
+ $.temp_table_definition,
605
+ $.event_definition,
606
+ $.method_definition,
607
+ $.dataset_definition
608
+ )
609
+ )
610
+ ),
611
+
612
+ interface_tuning: ($) => choice($.inherits),
613
+ interface_statement: ($) =>
614
+ seq(
615
+ kw("INTERFACE"),
616
+ field("name", choice($.string_literal, $.identifier, $.qualified_name)),
617
+ repeat($.interface_tuning),
618
+ alias($.interface_body, $.body),
619
+ kw("END"),
620
+ optional(kw("INTERFACE")),
621
+ $._terminator
622
+ ),
623
+
624
+ property_type: ($) => choice(kw("ABSTRACT"), kw("OVERRIDE")),
625
+ property_tuning: ($) =>
626
+ choice(
627
+ seq(choice(kw("INITIAL"), kw("INIT")), $._expression),
628
+ seq(kw("DECIMALS"), $._expression),
629
+ seq(kw("EXTENT"), $.number_literal),
630
+ kw("NO-UNDO")
631
+ ),
632
+
633
+ getter: ($) =>
634
+ seq(
635
+ optional($.access_tuning),
636
+ kw("GET"),
637
+ optional(
638
+ seq(
639
+ optional(alias($.function_parameters, $.parameters)),
640
+ $.body,
641
+ kw("END"),
642
+ optional(kw("GET"))
643
+ )
644
+ ),
645
+ $._terminator
646
+ ),
647
+
648
+ setter: ($) =>
649
+ seq(
650
+ optional($.access_tuning),
651
+ kw("SET"),
652
+ optional(alias($.function_parameters, $.parameters)),
653
+ optional(seq($.body, kw("END"), optional(kw("SET")))),
654
+ $._terminator
655
+ ),
656
+
657
+ property_definition: ($) =>
658
+ seq(
659
+ $._define,
660
+ repeat(
661
+ choice(
662
+ $.access_tuning,
663
+ $.scope_tuning,
664
+ $.property_type,
665
+ $.serialization_tuning
666
+ )
667
+ ),
668
+ kw("PROPERTY"),
669
+ field("name", $.identifier),
670
+ $.type_tuning,
671
+ repeat($.property_tuning),
672
+ choice(repeat1(choice($.getter, $.setter)), $._terminator)
673
+ ),
674
+
675
+ event_definition: ($) =>
676
+ seq(
677
+ $._define,
678
+ repeat(choice($.access_tuning, $.scope_tuning, $.property_type)),
679
+ kw("EVENT"),
680
+ $.identifier,
681
+ optional(kw("SIGNATURE")),
682
+ kw("VOID"),
683
+ alias($.function_parameters, $.parameters),
684
+ $._terminator
685
+ ),
686
+
687
+ method_tuning: ($) => choice(kw("ABSTRACT"), kw("OVERRIDE"), kw("FINAL")),
688
+ method_definition: ($) =>
689
+ seq(
690
+ kw("METHOD"),
691
+ repeat(choice($.access_tuning, $.scope_tuning, $.method_tuning)),
692
+ alias($._type, $.return_type),
693
+ optional($.return_tuning),
694
+ field("name", $.identifier),
695
+ alias($.function_parameters, $.parameters),
696
+ optional(seq($.body, kw("END"), optional(kw("METHOD")))),
697
+ $._terminator
698
+ ),
699
+
700
+ data_relation: ($) =>
701
+ seq(
702
+ kw("DATA-RELATION"),
703
+ alias($._for_keyword, "FOR"),
704
+ _list(choice($.identifier, $.qualified_name), ","),
705
+ kw("RELATION-FIELDS"),
706
+ seq(
707
+ "(",
708
+ optional(_list(choice($.identifier, $.qualified_name), ",")),
709
+ ")"
710
+ )
711
+ ),
712
+ dataset_definition: ($) =>
713
+ seq(
714
+ $._define,
715
+ repeat(choice($.scope_tuning, $.access_tuning)),
716
+ kw("DATASET"),
717
+ field("name", $.identifier),
718
+ alias($._for_keyword, "FOR"),
719
+ _list(choice($.identifier, $.qualified_name), ","),
720
+ optional($.data_relation),
721
+ $._terminator
722
+ ),
723
+
724
+ using_statement: ($) =>
725
+ seq(
726
+ kw("USING"),
727
+ choice($.identifier, $.qualified_name),
728
+ optional(seq(kw("FROM"), choice(kw("ASSEMBLY"), kw("PROPATH")))),
729
+ $._terminator
730
+ ),
731
+
732
+ class_body: ($) =>
733
+ seq(
734
+ ":",
735
+ repeat(
736
+ choice(
737
+ $.property_definition,
738
+ $.temp_table_definition,
739
+ $.event_definition,
740
+ $.method_definition,
741
+ $.dataset_definition,
742
+ $.constructor_definition,
743
+ $.destructor_definition,
744
+ $.variable_definition,
745
+ $.query_definition,
746
+ $.buffer_definition,
747
+ $.data_source_definition,
748
+ $.stream_definition,
749
+ $.var_statement
750
+ )
751
+ )
752
+ ),
753
+
754
+ constructor_definition: ($) =>
755
+ seq(
756
+ kw("CONSTRUCTOR"),
757
+ repeat(choice($.scope_tuning, $.access_tuning)),
758
+ $.identifier,
759
+ alias($.function_parameters, $.parameters),
760
+ $.body,
761
+ kw("END"),
762
+ optional(choice(kw("CONSTRUCTOR"), kw("METHOD"))),
763
+ $._terminator
764
+ ),
765
+
766
+ destructor_definition: ($) =>
767
+ seq(
768
+ kw("DESTRUCTOR"),
769
+ repeat($.access_tuning),
770
+ $.identifier,
771
+ seq("(", ")"),
772
+ $.body,
773
+ kw("END"),
774
+ optional(kw("DESTRUCTOR")),
775
+ $._terminator
776
+ ),
777
+
778
+ class_tuning: ($) =>
779
+ choice(
780
+ $.inherits,
781
+ $.implements,
782
+ $.use_widget_pool,
783
+ $.abstract,
784
+ $.final,
785
+ $.serializable
786
+ ),
787
+
788
+ class_statement: ($) =>
789
+ seq(
790
+ kw("CLASS"),
791
+ field("name", choice($.string_literal, $.identifier, $.qualified_name)),
792
+ repeat($.class_tuning),
793
+ alias($.class_body, $.body),
794
+ kw("END"),
795
+ optional(kw("CLASS")),
796
+ $._terminator
797
+ ),
798
+
799
+ inherits: ($) =>
800
+ seq(
801
+ kw("INHERITS"),
802
+ _list(choice($.string_literal, $.identifier, $.qualified_name), ",")
803
+ ),
804
+
805
+ implements: ($) =>
806
+ seq(
807
+ kw("IMPLEMENTS"),
808
+ _list(choice($.string_literal, $.identifier, $.qualified_name), ",")
809
+ ),
810
+
811
+ use_widget_pool: ($) => kw("USE-WIDGET-POOL"),
812
+ abstract: ($) => kw("ABSTRACT"),
813
+ final: ($) => kw("FINAL"),
814
+ serializable: ($) => kw("SERIALIZABLE"),
815
+
816
+ new_expression: ($) =>
817
+ prec.right(
818
+ seq(
819
+ choice(alias($._new_keyword, "NEW"), kw("DYNAMIC-NEW")),
820
+ choice($.identifier, $.qualified_name),
821
+ alias($.function_arguments, $.arguments),
822
+ optional(kw("NO-ERROR"))
823
+ )
824
+ ),
825
+
826
+ object_access: ($) =>
827
+ seq(
828
+ field(
829
+ "object",
830
+ choice($.identifier, $.new_expression, $.function_call)
831
+ ),
832
+ repeat1(seq(alias($._namecolon, ":"), field("property", $.identifier)))
833
+ ),
834
+
835
+ member_access: ($) =>
836
+ seq(
837
+ field("object", $.identifier),
838
+ repeat1(
839
+ seq(alias($._namedoublecolon, "::"), field("property", $.identifier))
840
+ )
841
+ ),
842
+
843
+ stream_definition: ($) =>
844
+ seq(
845
+ $._define,
846
+ repeat(choice($.scope_tuning, $.access_tuning, $.serialization_tuning)),
847
+ kw("STREAM"),
848
+ field("name", $.identifier),
849
+ $._terminator
850
+ ),
851
+
852
+ input_close_statement: ($) =>
853
+ seq(
854
+ alias($._input_keyword, "INPUT"),
855
+ optional(
856
+ choice(
857
+ seq(kw("STREAM"), field("stream", $.identifier)),
858
+ seq(kw("STREAM-HANDLE"), field("stream_handle", $.identifier))
859
+ )
860
+ ),
861
+ kw("CLOSE"),
862
+ $._terminator
863
+ ),
864
+
865
+ output_close_statement: ($) =>
866
+ seq(
867
+ alias($._output_keyword, "OUTPUT"),
868
+ optional(
869
+ choice(
870
+ seq(kw("STREAM"), field("stream", $.identifier)),
871
+ seq(kw("STREAM-HANDLE"), field("stream_handle", $.identifier))
872
+ )
873
+ ),
874
+ kw("CLOSE"),
875
+ $._terminator
876
+ ),
877
+
878
+ _stream_statement: ($) =>
879
+ choice($.input_stream_statement, $.output_stream_statement),
880
+
881
+ input_stream_tuning: ($) =>
882
+ choice(
883
+ seq(kw("LOB-DIR"), $._expression),
884
+ kw("BINARY"),
885
+ kw("ECHO"),
886
+ kw("NO-ECHO"),
887
+ choice(seq(kw("MAP"), $._expression), kw("NO-MAP")),
888
+ kw("UNBUFFERED"),
889
+ kw("NO-CONVERT"),
890
+ seq(
891
+ kw("CONVERT"),
892
+ optional(seq(kw("TARGET"), $._expression)),
893
+ optional(seq(kw("SOURCE"), $._expression))
894
+ )
895
+ ),
896
+ input_stream_statement: ($) =>
897
+ seq(
898
+ alias($._input_keyword, "INPUT"),
899
+ optional(
900
+ seq(
901
+ choice(kw("STREAM"), kw("STREAM-HANDLE")),
902
+ field("source", $.identifier)
903
+ )
904
+ ),
905
+ kw("FROM"),
906
+ field("target", $._expression),
907
+ repeat($.input_stream_tuning),
908
+ $._terminator
909
+ ),
910
+
911
+ output_stream_tuning: ($) =>
912
+ choice(
913
+ choice(
914
+ seq(kw("LOB-DIR"), $._expression),
915
+ seq(kw("NUM-COPIES"), $._expression),
916
+ kw("COLLATE"),
917
+ kw("BINARY"),
918
+ choice(kw("LANDSCAPE"), kw("PORTRAIT")),
919
+ kw("APPEND"),
920
+ kw("ECHO"),
921
+ kw("NO-ECHO"),
922
+ kw("KEEP-MESSAGES"),
923
+ choice(seq(kw("MAP"), $._expression), kw("NO-MAP")),
924
+ kw("PAGED"),
925
+ seq(kw("PAGE-SIZE"), $._expression),
926
+ kw("UNBUFFERED"),
927
+ kw("NO-CONVERT"),
928
+ seq(
929
+ kw("CONVERT"),
930
+ optional(seq(kw("TARGET"), $._expression)),
931
+ optional(seq(kw("SOURCE"), $._expression))
932
+ )
933
+ )
934
+ ),
935
+ output_stream_statement: ($) =>
936
+ seq(
937
+ alias($._output_keyword, "OUTPUT"),
938
+ optional(
939
+ seq(
940
+ choice(kw("STREAM"), kw("STREAM-HANDLE")),
941
+ field("source", $.identifier)
942
+ )
943
+ ),
944
+ kw("TO"),
945
+ field("target", $._expression),
946
+ repeat($.output_stream_tuning),
947
+ $._terminator
948
+ ),
949
+
950
+ on_error_phrase: ($) =>
951
+ seq(
952
+ kw("ON"),
953
+ kw("ERROR"),
954
+ kw("UNDO"),
955
+ field("label", optional($.identifier)),
956
+ ",",
957
+ choice(
958
+ seq(kw("LEAVE"), field("label", optional($.identifier))),
959
+ seq(kw("NEXT"), field("label", optional($.identifier))),
960
+ seq(kw("RETRY"), field("label", optional($.identifier))),
961
+ seq(
962
+ kw("RETURN"),
963
+ choice(seq(kw("ERROR")), kw("NO-APPLY"), $.string_literal)
964
+ ),
965
+ kw("THROW")
966
+ )
967
+ ),
968
+
969
+ on_stop_phrase: ($) =>
970
+ seq(
971
+ kw("ON"),
972
+ kw("STOP"),
973
+ kw("UNDO"),
974
+ field("label", optional($.identifier)),
975
+ ",",
976
+ choice(
977
+ seq(kw("LEAVE"), field("label", optional($.identifier))),
978
+ seq(kw("NEXT"), field("label", optional($.identifier))),
979
+ seq(kw("RETRY"), field("label", optional($.identifier))),
980
+ seq(kw("RETURN"), choice(seq(kw("ERROR")), kw("NO-APPLY")))
981
+ )
982
+ ),
983
+
984
+ on_quit_phrase: ($) =>
985
+ seq(
986
+ kw("ON"),
987
+ kw("QUIT"),
988
+ optional(seq(kw("UNDO"), optional($.identifier))),
989
+ ",",
990
+ choice(
991
+ seq(kw("LEAVE"), field("label", optional($.identifier))),
992
+ seq(kw("NEXT"), field("label", optional($.identifier))),
993
+ seq(kw("RETRY"), field("label", optional($.identifier))),
994
+ seq(kw("RETURN"), choice(seq(kw("ERROR")), kw("NO-APPLY")))
995
+ )
996
+ ),
997
+
998
+ on_endkey_phrase: ($) =>
999
+ seq(
1000
+ kw("ON"),
1001
+ kw("ENDKEY"),
1002
+ optional(seq(kw("UNDO"), optional($.identifier))),
1003
+ ",",
1004
+ choice(
1005
+ seq(kw("LEAVE"), field("label", optional($.identifier))),
1006
+ seq(kw("NEXT"), field("label", optional($.identifier))),
1007
+ seq(kw("RETRY"), field("label", optional($.identifier))),
1008
+ seq(kw("RETURN"), choice(seq(kw("ERROR")), kw("NO-APPLY")))
1009
+ )
1010
+ ),
1011
+
1012
+ frame_phrase: ($) =>
1013
+ seq(
1014
+ kw("WITH"),
1015
+ repeat(
1016
+ choice(
1017
+ seq(kw("ACCUM"), optional($._expression)),
1018
+ // $.at_phrase, // TODO
1019
+ seq(kw("CANCEL-BUTTON"), $.identifier),
1020
+ kw("CENTERED"),
1021
+ // color specification
1022
+ seq(kw("COLUMN"), $._expression),
1023
+ seq($.number_literal, kw("COLUMNS")),
1024
+ kw("CONTEXT-HELP"),
1025
+ seq(kw("CONTEXT-HELP-FILE"), $.identifier),
1026
+ seq(kw("DEFAULT-BUTTON"), $.identifier),
1027
+ kw("DROP-TARGET"),
1028
+ seq(optional($._expression), kw("DOWN")),
1029
+ kw("EXPORT"),
1030
+ seq(kw("WIDGET-ID"), $.number_literal),
1031
+ seq(kw("FONT"), $._expression),
1032
+ seq(kw("FRAME"), $.identifier),
1033
+ kw("INHERIT-BGCOLOR"),
1034
+ kw("NO-INHERIT-BGCOLOR"),
1035
+ kw("INHERIT-FGCOLOR"),
1036
+ kw("NO-INHERIT-FGCOLOR"),
1037
+ kw("KEEP-TAB-ORDER"),
1038
+ kw("NO-BOX"),
1039
+ kw("NO-HIDE"),
1040
+ kw("NO-LABELS"),
1041
+ kw("USE-DICT-EXPS"),
1042
+ kw("NO-VALIDATE"),
1043
+ kw("NO-AUTO-VALIDATE"),
1044
+ kw("NO-HELP"),
1045
+ kw("NO-UNDERLINE"),
1046
+ kw("OVERLAY"),
1047
+ kw("PAGE-BOTTOM"),
1048
+ kw("PAGE-TOP"),
1049
+ seq(kw("RETAIN"), $.number_literal),
1050
+ seq(kw("ROW"), $._expression),
1051
+ kw("SCREEN-IO"),
1052
+ kw("STREAM-IO"),
1053
+ seq(kw("SCROLL"), $.number_literal),
1054
+ kw("SCROLLABLE"),
1055
+ kw("SIDE-LABELS"),
1056
+ $.size_phrase,
1057
+ seq(kw("STREAM"), field("stream", $.identifier)), // TODO: Refactor as reusable rule
1058
+ seq(kw("STREAM-HANDLE"), field("stream_handle", $.identifier)), // TODO: Refactor as reusable rule
1059
+ kw("THREE-D"),
1060
+ // title phrase
1061
+ kw("TOP-ONLY"),
1062
+ kw("USE-TEXT"),
1063
+ seq(kw("V6FRAME"), optional(choice(kw("USE-REVVIDEO"), kw("USE-UNDERLINE")))),
1064
+ seq(kw("VIEW-AS"), kw("DIALOG-BOX")),
1065
+ seq(kw("WIDTH"), $.number_literal),
1066
+ seq(kw("IN-WINDOW"), $.identifier)
1067
+ )
1068
+ )
1069
+ ),
1070
+
1071
+ stop_after_phrase: ($) => seq(kw("STOP-AFTER"), $._expression),
1072
+
1073
+ do_tuning: ($) => choice(kw("TRANSACTION")),
1074
+ to_phrase: ($) =>
1075
+ seq(
1076
+ $.assignment,
1077
+ kw("TO"),
1078
+ $._expression,
1079
+ optional(seq(kw("BY"), $.number_literal))
1080
+ ),
1081
+
1082
+ do_block: ($) =>
1083
+ seq(
1084
+ optional($.label),
1085
+ kw("DO"),
1086
+ optional($.preselect_phrase),
1087
+ optional($.to_phrase),
1088
+ optional($.do_tuning),
1089
+ optional($.while_phrase),
1090
+ optional($.stop_after_phrase),
1091
+ repeat(
1092
+ choice(
1093
+ $.on_error_phrase,
1094
+ $.on_quit_phrase,
1095
+ $.on_stop_phrase,
1096
+ $.on_endkey_phrase
1097
+ )
1098
+ ),
1099
+ $.body,
1100
+ $._block_terminator
1101
+ ),
1102
+
1103
+ _case_terminator: ($) =>
1104
+ choice($._block_terminator, seq(kw("END"), kw("CASE"), $._terminator)),
1105
+
1106
+ _case_branch_body: ($) =>
1107
+ prec(1, choice($.do_block, field("statement", $._statement))),
1108
+
1109
+ case_condition: ($) =>
1110
+ seq(optional(seq(kw("OR"), kw("WHEN"))), $._expression),
1111
+
1112
+ case_when_branch: ($) =>
1113
+ seq(kw("WHEN"), repeat($.case_condition), kw("THEN"), $._case_branch_body),
1114
+ case_otherwise_branch: ($) => seq(kw("OTHERWISE"), $._case_branch_body),
1115
+
1116
+ case_body: ($) =>
1117
+ seq(":", repeat1($.case_when_branch), optional($.case_otherwise_branch)),
1118
+
1119
+ case_statement: ($) =>
1120
+ seq(
1121
+ kw("CASE"),
1122
+ $._expression,
1123
+ alias($.case_body, $.body),
1124
+ $._case_terminator
1125
+ ),
1126
+
1127
+ where_clause: ($) => seq(kw("WHERE"), field("condition", $._expression)),
1128
+
1129
+ // HACK: progress spaghetti allows to define tuning order before where clause
1130
+ _pre_tuning: ($) => prec.right(1, $.query_tuning),
1131
+
1132
+ query_tuning: ($) =>
1133
+ choice(
1134
+ kw("NO-LOCK"),
1135
+ kw("SHARE-LOCK"),
1136
+ kw("EXCLUSIVE-LOCK"),
1137
+ kw("NO-WAIT"),
1138
+ kw("NO-ERROR"),
1139
+ kw("NO-PREFETCH"),
1140
+ seq(kw("USE-INDEX"), $.identifier),
1141
+ $.using
1142
+ ),
1143
+
1144
+ sort_order: ($) =>
1145
+ choice(kw("ASCENDING"), kw("DESCENDING"), kw("DESC"), kw("ASC")),
1146
+ sort_column: ($) =>
1147
+ seq(field("column", $._expression), optional($.sort_order)),
1148
+
1149
+ sort_clause: ($) =>
1150
+ seq(optional(kw("BREAK")), seq(kw("BY"), repeat1($.sort_column))),
1151
+
1152
+ for_phrase: ($) =>
1153
+ seq(
1154
+ optional(field("type", choice(kw("EACH"), kw("FIRST"), kw("LAST")))),
1155
+ field("table", choice($.identifier, $.qualified_name)),
1156
+ optional($.of),
1157
+ optional($._pre_tuning),
1158
+ optional($.where_clause),
1159
+ repeat($.query_tuning),
1160
+ optional(repeat($.sort_clause)),
1161
+ repeat(
1162
+ choice(
1163
+ $.on_error_phrase,
1164
+ $.on_quit_phrase,
1165
+ $.on_stop_phrase,
1166
+ $.on_endkey_phrase
1167
+ )
1168
+ )
1169
+ ),
1170
+
1171
+ for_statement: ($) =>
1172
+ seq(
1173
+ optional($.label),
1174
+ alias($._for_keyword, "FOR"),
1175
+ field("type", choice(kw("EACH"), kw("FIRST"), kw("LAST"))),
1176
+ field("table", choice($.identifier, $.qualified_name)),
1177
+ optional($.of),
1178
+ optional($._pre_tuning),
1179
+ optional($.where_clause),
1180
+ repeat($.query_tuning),
1181
+ repeat($.sort_clause),
1182
+ repeat(
1183
+ choice(
1184
+ $.on_error_phrase,
1185
+ $.on_quit_phrase,
1186
+ $.on_stop_phrase,
1187
+ $.on_endkey_phrase
1188
+ )
1189
+ ),
1190
+ repeat(seq(",", $.for_phrase)),
1191
+ optional($.frame_phrase),
1192
+ $.body,
1193
+ $._block_terminator
1194
+ ),
1195
+
1196
+ _find_type: ($) =>
1197
+ choice(kw("FIRST"), kw("LAST"), kw("NEXT"), kw("PREV"), kw("CURRENT")),
1198
+
1199
+ find_statement: ($) =>
1200
+ seq(
1201
+ kw("FIND"),
1202
+ field("type", optional($._find_type)),
1203
+ field("table", choice($.identifier, $.qualified_name)),
1204
+ optional($.of),
1205
+ optional($._pre_tuning),
1206
+ optional($.where_clause),
1207
+ repeat($.query_tuning),
1208
+ $._terminator
1209
+ ),
1210
+
1211
+ can_find_expression: ($) =>
1212
+ seq(
1213
+ kw("CAN-FIND"),
1214
+ "(",
1215
+ optional(choice(kw("FIRST"), kw("LAST"))),
1216
+ field("table", choice($.identifier, $.qualified_name)),
1217
+ optional(field("constant", $._expression)),
1218
+ repeat(choice($.query_tuning, $.of, $.where_clause)),
1219
+ ")"
1220
+ ),
1221
+
1222
+ of: ($) => seq(kw("OF"), choice($.identifier, $.qualified_name)),
1223
+ using: ($) =>
1224
+ seq(
1225
+ kw("USING"),
1226
+ seq($.using_field, repeat(seq(kw("AND"), $.using_field)))
1227
+ ),
1228
+ using_field: ($) =>
1229
+ seq(
1230
+ optional(seq(kw("FRAME"), field("frame", $.identifier))),
1231
+ field("field", choice($.identifier, $.qualified_name))
1232
+ ),
1233
+
1234
+ abl_statement: ($) =>
1235
+ seq(
1236
+ field("statement", $.identifier),
1237
+ repeat(prec(-1, $._expression)),
1238
+ $._terminator
1239
+ ),
1240
+
1241
+ assign_statement: ($) =>
1242
+ seq(
1243
+ kw("ASSIGN"),
1244
+ repeat($.assignment), // no need for choice
1245
+ optional(kw("NO-ERROR")),
1246
+ $._terminator
1247
+ ),
1248
+
1249
+ catch_statement: ($) =>
1250
+ seq(
1251
+ kw("CATCH"),
1252
+ field("variable", $.identifier),
1253
+ kw("AS"),
1254
+ field(
1255
+ "type",
1256
+ seq(optional(kw("CLASS")), choice($.identifier, $.qualified_name))
1257
+ ),
1258
+ $.body,
1259
+ kw("END"),
1260
+ optional(kw("CATCH")),
1261
+ $._terminator
1262
+ ),
1263
+
1264
+ finally_statement: ($) =>
1265
+ seq(
1266
+ kw("FINALLY"),
1267
+ $.body,
1268
+ kw("END"),
1269
+ optional(kw("FINALLY")),
1270
+ $._terminator
1271
+ ),
1272
+
1273
+ accumulate_aggregate: ($) =>
1274
+ choice(
1275
+ kw("AVERAGE"),
1276
+ kw("COUNT"),
1277
+ kw("MAXIMUM"),
1278
+ kw("MINIMUM"),
1279
+ kw("TOTAL"),
1280
+ kw("SUB-AVERAGE"),
1281
+ kw("SUB-COUNT"),
1282
+ kw("SUB-MAXIMUM"),
1283
+ kw("SUB-MINIMUM"),
1284
+ kw("SUB-TOTAL")
1285
+ ),
1286
+
1287
+ accumulate_statement: ($) =>
1288
+ seq(
1289
+ kw("ACCUMULATE"),
1290
+ choice($._expression, $.identifier),
1291
+ seq(
1292
+ "(",
1293
+ seq($.accumulate_aggregate, repeat(seq(" ", $.accumulate_aggregate))),
1294
+ ")"
1295
+ ),
1296
+ $._terminator
1297
+ ),
1298
+
1299
+ accumulate_expression: ($) =>
1300
+ seq(kw("ACCUM"), $.accumulate_aggregate, prec.left($._expression)),
1301
+
1302
+ available_expression: ($) =>
1303
+ seq(
1304
+ choice(kw("AVAIL"), kw("AVAILABLE")),
1305
+ choice($.parenthesized_expression, $.identifier)
1306
+ ),
1307
+
1308
+ undo_statement: ($) =>
1309
+ seq(
1310
+ kw("UNDO"),
1311
+ field("label", optional($.identifier)),
1312
+ ",",
1313
+ choice(
1314
+ seq(kw("LEAVE"), field("label", optional($.identifier))),
1315
+ seq(kw("NEXT"), field("label", optional($.identifier))),
1316
+ seq(kw("RETRY"), field("label", optional($.identifier))),
1317
+ seq(kw("RETURN"), choice(seq(kw("ERROR")), kw("NO-APPLY"))),
1318
+ seq(kw("THROW"), $._expression)
1319
+ ),
1320
+ $._terminator
1321
+ ),
1322
+
1323
+ error_scope_statement: ($) =>
1324
+ seq(
1325
+ choice(kw("ROUTINE-LEVEL"), kw("BLOCK-LEVEL")),
1326
+ $.on_error_phrase,
1327
+ $._terminator
1328
+ ),
1329
+
1330
+ like_phrase: ($) =>
1331
+ seq(
1332
+ choice(kw("LIKE"), kw("LIKE-SEQUENTIAL")),
1333
+ $.identifier,
1334
+ optional(kw("VALIDATE")),
1335
+ optional(seq(kw("USE-INDEX"), $.identifier, optional(seq(kw("AS"), kw("PRIMARY")))))
1336
+ ),
1337
+
1338
+ temp_table_tuning: ($) =>
1339
+ choice(
1340
+ kw("NO-UNDO"),
1341
+ seq(kw("NAMESPACE-URI"), $.string_literal),
1342
+ seq(kw("NAMESPACE-PREFIX"), $.string_literal),
1343
+ seq(kw("XML-NODE-NAME"), $.string_literal),
1344
+ seq(kw("SERIALIZE-NAME"), $.string_literal),
1345
+ kw("REFERENCE-ONLY"),
1346
+ $.like_phrase,
1347
+ kw("RCODE-INFORMATION"),
1348
+ seq(kw("BEFORE-TABLE"), $.identifier),
1349
+ $.constant
1350
+ ),
1351
+ field_option: ($) =>
1352
+ choice(
1353
+ seq(kw("BGCOLOR"), $._expression),
1354
+ seq(kw("COLUMN-LABEL"), $.string_literal),
1355
+ seq(kw("DCOLOR"), $._expression),
1356
+ seq(kw("LABEL"), $.string_literal, repeat(seq(",", $.string_literal))),
1357
+ seq(kw("FORMAT"), $.string_literal),
1358
+ seq(kw("DECIMALS"), $.number_literal),
1359
+ seq(kw("EXTENT"), $.number_literal),
1360
+ seq(kw("FONT"), $._expression),
1361
+ seq(kw("FGCOLOR"), $._expression),
1362
+ seq(kw("PFCOLOR"), $._expression),
1363
+ seq(kw("FORMAT"), $.string_literal),
1364
+ seq(choice(kw("INITIAL"), kw("INIT")), $._expression),
1365
+ kw("SERIALIZE-HIDDEN"),
1366
+ seq(kw("SERIALIZE-NAME"), $.string_literal),
1367
+ seq(kw("XML-DATA-TYPE"), $.string_literal),
1368
+ seq(kw("XML-NODE-TYPE"), $.string_literal),
1369
+ seq(kw("XML-NODE-NAME"), $.string_literal),
1370
+ seq(kw("HELP"), $.string_literal),
1371
+ seq(optional(kw("NOT")), kw("CASE-SENSITIVE")),
1372
+ seq(kw("MOUSE-POINTER"), $._expression),
1373
+ kw("TTCODEPAGE"),
1374
+ seq(kw("COLUMN-CODEPAGE"), $.string_literal),
1375
+ ),
1376
+ field_definition: ($) =>
1377
+ seq(kw("FIELD"), $.identifier, $.type_tuning, repeat($.field_option)),
1378
+ index_tuning: ($) =>
1379
+ seq(
1380
+ optional(choice(kw("IS"), kw("AS"))),
1381
+ choice(
1382
+ kw("PRIMARY"),
1383
+ kw("UNIQUE"),
1384
+ kw("WORD-INDEX")
1385
+ )
1386
+ ),
1387
+ index_definition: ($) =>
1388
+ prec.left(
1389
+ seq(
1390
+ kw("INDEX"),
1391
+ $.identifier,
1392
+ repeat($.index_tuning),
1393
+ repeat($.sort_column)
1394
+ )
1395
+ ),
1396
+
1397
+ workfile_tuning: ($) => kw("NO-UNDO"),
1398
+ workfile_definition: ($) =>
1399
+ seq(
1400
+ $._define,
1401
+ repeat(choice($.access_tuning, $.scope_tuning)),
1402
+ choice(kw("WORKFILE"), kw("WORK-TABLE")),
1403
+ field("name", $.identifier),
1404
+ repeat($.workfile_tuning),
1405
+ optional($.type_tuning),
1406
+ repeat($.field_definition),
1407
+ $._terminator
1408
+ ),
1409
+
1410
+ temp_table_definition: ($) =>
1411
+ seq(
1412
+ $._define,
1413
+ repeat(choice($.scope_tuning, $.access_tuning, $.serialization_tuning, $.constant)),
1414
+ kw("TEMP-TABLE"),
1415
+ choice($.identifier, $.constant),
1416
+ repeat($.temp_table_tuning),
1417
+ repeat(choice($.field_definition, $.index_definition, $.include)),
1418
+ $._terminator
1419
+ ),
1420
+
1421
+ widget_phrase: ($) =>
1422
+ choice(
1423
+ seq(kw("FRAME"), $.identifier),
1424
+ seq(optional(kw("FIELD")), $.identifier, optional(seq(kw("IN"), kw("FRAME"), $.identifier))),
1425
+ seq($.identifier, optional(seq(kw("IN"), kw("BROWSE"), $.identifier))),
1426
+ seq(choice(kw("MENU"), kw("SUB-MENU")), $.identifier),
1427
+ seq(kw("MENU-ITEM"), $.identifier, optional(seq(kw("IN"), kw("MENU"), $.identifier))),
1428
+ seq($.identifier, repeat(seq(",", $.identifier)))
1429
+ ),
1430
+
1431
+ referencing_phrase: ($) =>
1432
+ seq(
1433
+ alias($._new_keyword, "NEW"), optional(kw("BUFFER")),
1434
+ $.identifier,
1435
+ alias($._old_keyword, "OLD"), optional(kw("BUFFER")),
1436
+ $.identifier,
1437
+ ),
1438
+
1439
+ of_phrase: ($) =>
1440
+ seq(
1441
+ kw("OF"),
1442
+ $.widget_phrase,
1443
+ optional(kw("ANYWHERE"))
1444
+ ),
1445
+
1446
+ _on_statement_database_phrase: ($) =>
1447
+ prec(2, seq(
1448
+ choice(
1449
+ kw("CREATE"),
1450
+ kw("DELETE"),
1451
+ kw("FIND"),
1452
+ kw("WRITE"),
1453
+ kw("ASSIGN"),
1454
+ ),
1455
+ kw("OF"),
1456
+ choice($.qualified_name, $.identifier), repeat(seq(",", choice($.qualified_name, $.identifier))),
1457
+ optional($.referencing_phrase),
1458
+ optional(kw("OVERRIDE")),
1459
+ choice($.do_block, prec(2, $._statement), kw("REVERT"))
1460
+ )),
1461
+
1462
+ _on_statement_widget_phrase: ($) =>
1463
+ prec(2, seq(
1464
+ _list(choice($.identifier, $.constant), ","),
1465
+ choice(kw("ANYWHERE"), $.of_phrase),
1466
+ choice($.do_block, prec(2, $._statement), kw("REVERT"), seq(kw("PERSISTENT"), $.run_statement))
1467
+ )),
1468
+
1469
+ on_statement: ($) =>
1470
+ seq(
1471
+ kw("ON"),
1472
+ choice(
1473
+ $._on_statement_widget_phrase,
1474
+ $._on_statement_database_phrase,
1475
+ seq(field("label", $.identifier), field("function", $.identifier), $._terminator),
1476
+ seq(alias("\"WEB-NOTIFY\"", $.string_literal), kw("ANYWHERE"), choice($.do_block, prec(2, $._statement)))
1477
+ )
1478
+ ),
1479
+
1480
+ data_source_definition: ($) =>
1481
+ seq(
1482
+ $._define,
1483
+ optional($.access_tuning),
1484
+ optional($.scope_tuning),
1485
+ kw("DATA-SOURCE"),
1486
+ $.identifier,
1487
+ alias($._for_keyword, "FOR"),
1488
+ optional(seq(kw("QUERY"), $.identifier)),
1489
+ choice(
1490
+ seq(
1491
+ _list(choice($.identifier, $.qualified_name), ","),
1492
+ $._terminator
1493
+ ),
1494
+ $._terminator
1495
+ )
1496
+ ),
1497
+
1498
+ prompt_for_statement: ($) =>
1499
+ seq(
1500
+ kw("PROMPT-FOR"),
1501
+ choice($.identifier, $.qualified_name),
1502
+ optional(seq(kw("FRAME"), field("frame", $.identifier))),
1503
+ choice(seq(kw("EDITING"), $.body, $._block_terminator), $._terminator)
1504
+ ),
1505
+
1506
+ variable: ($) => choice(field("name", $.identifier), $.assignment),
1507
+ var_statement: ($) =>
1508
+ seq(
1509
+ alias($._var_keyword, "VAR"),
1510
+ optional(
1511
+ choice($.scope_tuning, $.access_tuning, $.serialization_tuning)
1512
+ ),
1513
+ alias(choice($._type, $.string_literal), $.type_tuning),
1514
+ optional(field("size", $.array_literal)),
1515
+ repeat(seq($.variable, optional(","))),
1516
+ $._terminator
1517
+ ),
1518
+
1519
+ image_phrase: ($) =>
1520
+ seq(
1521
+ choice(kw("IMAGE"), kw("IMAGE-UP")),
1522
+ seq(kw("FILE"), $.string_literal),
1523
+ optional(
1524
+ seq(
1525
+ choice(
1526
+ kw("IMAGE-SIZE"),
1527
+ kw("IMAGE-SIZE-CHARS"),
1528
+ kw("IMAGE-SIZE-PIXELS")
1529
+ ),
1530
+ field("width", $.number_literal),
1531
+ kw("BY"),
1532
+ field("height", $.number_literal)
1533
+ )
1534
+ ),
1535
+ optional(
1536
+ seq(
1537
+ kw("FROM"),
1538
+ choice(
1539
+ seq(kw("X"), $.number_literal, kw("Y"), $.number_literal),
1540
+ seq(kw("ROW"), $.number_literal, kw("COLUMN"), $.number_literal)
1541
+ )
1542
+ )
1543
+ )
1544
+ ),
1545
+
1546
+ size_phrase: ($) =>
1547
+ seq(
1548
+ choice(kw("SIZE"), kw("SIZE-CHARS"), kw("SIZE-PIXELS")),
1549
+ field("width", $.number_literal),
1550
+ kw("BY"),
1551
+ field("height", $.number_literal)
1552
+ ),
1553
+
1554
+ button_tuning: ($) =>
1555
+ choice(
1556
+ seq(kw("AUTO-GO"), optional(kw("AUTO-ENDKEY"))),
1557
+ kw("DEFAULT"),
1558
+ seq(kw("BGCOLOR"), $._expression),
1559
+ seq(kw("CONTEXT-HELP-ID"), $._expression),
1560
+ seq(kw("DCOLOR"), $._expression),
1561
+ kw("DROP-TARGET"),
1562
+ seq(kw("FGCOLOR"), $._expression),
1563
+ seq(kw("FONT"), $.number_literal),
1564
+ seq(kw("IMAGE-DOWN"), $.image_phrase),
1565
+ seq(kw("IMAGE"), $.image_phrase),
1566
+ seq(kw("IMAGE-UP"), $.image_phrase),
1567
+ seq(kw("IMAGE-INSENSITIVE"), $.image_phrase),
1568
+ seq(kw("MOUSE-POINTER"), $.identifier),
1569
+ seq(kw("LABEL"), $.string_literal),
1570
+ seq(kw("LIKE"), $.identifier),
1571
+ seq(kw("PFCOLOR"), $._expression),
1572
+ seq(kw("NO-FOCUS"), optional(kw("FLAT-BUTTON"))),
1573
+ kw("NO-CONVERT-3D-COLORS"),
1574
+ seq(kw("TOOLTIP"), $.string_literal),
1575
+ $.size_phrase
1576
+ ),
1577
+
1578
+ button_definition: ($) =>
1579
+ seq(
1580
+ $._define,
1581
+ optional($.access_tuning),
1582
+ kw("BUTTON"),
1583
+ field("name", $.identifier),
1584
+ repeat($.button_tuning),
1585
+ $._terminator
1586
+ ),
1587
+
1588
+ image_tuning: ($) =>
1589
+ choice(
1590
+ seq(kw("BGCOLOR"), $._expression),
1591
+ seq(kw("FGCOLOR"), $._expression),
1592
+ kw("CONVERT-3D-COLORS"),
1593
+ seq(kw("TOOLTIP"), $.identifier),
1594
+ seq(kw("STRETCH-TO-FIT"), optional(kw("RETAIN-SHAPE"))),
1595
+ kw("TRANSPARENT")
1596
+ ),
1597
+
1598
+ image_definition: ($) =>
1599
+ seq(
1600
+ $._define,
1601
+ optional($.access_tuning),
1602
+ kw("IMAGE"),
1603
+ field("name", $.identifier),
1604
+ choice($.size_phrase, $.image_phrase, seq(kw("LIKE"), $.identifier)),
1605
+ repeat($.image_tuning),
1606
+ $._terminator
1607
+ ),
1608
+
1609
+ run_tuning: ($) =>
1610
+ choice(
1611
+ kw("PERSISTENT"),
1612
+ kw("SINGLE-RUN"),
1613
+ kw("SINGLETON"),
1614
+ kw("ASYNCHRONOUS"),
1615
+ seq(kw("SET"), $.identifier),
1616
+ seq(kw("ON"), kw("SERVER"), $.identifier),
1617
+ seq(kw("IN"), choice(kw("THIS-PROCEDURE"), $.identifier)),
1618
+ seq(kw("EVENT-PROCEDURE"), $.string_literal)
1619
+ ),
1620
+ run_statement: ($) =>
1621
+ seq(
1622
+ kw("RUN"),
1623
+ field(
1624
+ "procedure",
1625
+ choice($.identifier, $.qualified_name, $.function_call)
1626
+ ),
1627
+ repeat($.run_tuning),
1628
+ optional(alias($.function_arguments, $.arguments)),
1629
+ optional(kw("NO-ERROR")),
1630
+ $._terminator
1631
+ ),
1632
+
1633
+ enum_body: ($) => seq(":", repeat($.enum_definition)),
1634
+ enum_member: ($) =>
1635
+ seq(
1636
+ field("name", $.identifier),
1637
+ field(
1638
+ "value",
1639
+ optional(
1640
+ seq(
1641
+ kw("="),
1642
+ _list(
1643
+ choice($.identifier, $.number_literal, $.string_literal),
1644
+ ","
1645
+ )
1646
+ )
1647
+ )
1648
+ )
1649
+ ),
1650
+ enum_definition: ($) =>
1651
+ seq(
1652
+ $._define,
1653
+ kw("ENUM"),
1654
+ repeat($.enum_member),
1655
+ $._terminator
1656
+ ),
1657
+
1658
+ enum_tuning: ($) => choice(kw("FLAGS")),
1659
+ enum_statement: ($) =>
1660
+ seq(
1661
+ kw("ENUM"),
1662
+ field("name", $.identifier),
1663
+ repeat($.enum_tuning),
1664
+ alias($.enum_body, $.body),
1665
+ kw("END"),
1666
+ optional(kw("ENUM")),
1667
+ $._terminator
1668
+ ),
1669
+
1670
+ record_phrase: ($) =>
1671
+ seq(
1672
+ optional(field("type", choice(kw("EACH"), kw("FIRST"), kw("LAST")))),
1673
+ _list(choice($.identifier, $.qualified_name), ","),
1674
+ optional($.of)
1675
+ ),
1676
+ preselect_phrase: ($) =>
1677
+ seq(
1678
+ kw("PRESELECT"),
1679
+ _list($.record_phrase, ","),
1680
+ optional($._pre_tuning),
1681
+ optional($.where_clause),
1682
+ repeat($.query_tuning),
1683
+ optional(repeat($.sort_clause))
1684
+ ),
1685
+
1686
+ preprocessor_directive: $ =>
1687
+ seq(
1688
+ "&",
1689
+ token(
1690
+ choice(
1691
+ seq(
1692
+ /[^\n~]+/,
1693
+ repeat(seq("~", /\s*\n/, /[^\n~]*/))
1694
+ ),
1695
+ seq(
1696
+ kw("IF"),
1697
+ /[^\n]*/,
1698
+ repeat(seq(/\n/, /[^\n]*/)),
1699
+ /\n\s*/,
1700
+ "&", kw("ENDIF")
1701
+ )
1702
+ ),
1703
+ )
1704
+ ),
1705
+
1706
+ // Supertypes
1707
+ _expression: ($) =>
1708
+ choice(
1709
+ $.parenthesized_expression,
1710
+ $.unary_expression,
1711
+ $.null_expression,
1712
+ $._binary_expression,
1713
+ $.ternary_expression,
1714
+ $.available_expression,
1715
+ $.accumulate_expression,
1716
+ $.ambiguous_expression,
1717
+ $.temp_table_expression,
1718
+ $.current_changed_expression,
1719
+ $.locked_expression,
1720
+ $.dataset_expression,
1721
+ $.input_expression,
1722
+ $.can_find_expression,
1723
+ $.new_expression,
1724
+
1725
+ $.boolean_literal,
1726
+ $.string_literal,
1727
+ $.date_literal,
1728
+ $.number_literal,
1729
+ $.array_literal,
1730
+
1731
+ $.object_access,
1732
+ $.member_access,
1733
+ $.array_access,
1734
+ $.function_call,
1735
+
1736
+ $.qualified_name,
1737
+ $.identifier,
1738
+ $.constant
1739
+ ),
1740
+
1741
+ _statement: ($) =>
1742
+ choice(
1743
+ $.var_statement,
1744
+ $.null_statement,
1745
+ $.procedure_statement,
1746
+ $.function_statement,
1747
+ $.function_call_statement,
1748
+ $.return_statement,
1749
+ $.if_statement,
1750
+ $.for_statement,
1751
+ $.repeat_statement,
1752
+ $.find_statement,
1753
+ $._stream_statement,
1754
+ $.case_statement,
1755
+ $.input_close_statement,
1756
+ $.output_close_statement,
1757
+ $.assign_statement,
1758
+ $.catch_statement,
1759
+ $.finally_statement,
1760
+ $.accumulate_statement,
1761
+ $.undo_statement,
1762
+ $.error_scope_statement,
1763
+ $.using_statement,
1764
+ $.class_statement,
1765
+ $.interface_statement,
1766
+ $.on_statement,
1767
+ $.prompt_for_statement,
1768
+ $.run_statement,
1769
+ $.enum_statement,
1770
+ $.abl_statement,
1771
+
1772
+ $.variable_definition,
1773
+ $.buffer_definition,
1774
+ $.query_definition,
1775
+ $.stream_definition,
1776
+ $.procedure_parameter_definition,
1777
+ $.temp_table_definition,
1778
+ $.workfile_definition,
1779
+ $.dataset_definition,
1780
+ $.button_definition,
1781
+ $.image_definition,
1782
+
1783
+ $.variable_assignment,
1784
+ $.do_block,
1785
+ $.preprocessor_directive,
1786
+ $.include
1787
+ )
1788
+ }
1789
+ });
1790
+
1791
+ function _list(rule, separator) {
1792
+ return seq(rule, repeat(seq(separator, rule)));
1793
+ }
1794
+
1795
+ function kw(keyword) {
1796
+ if (keyword.toUpperCase() != keyword) {
1797
+ throw new Error(`Expected upper case keyword got ${keyword}`);
1798
+ }
1799
+
1800
+ return alias(reserved(createCaseInsensitiveRegex(keyword)), keyword);
1801
+ }
1802
+
1803
+ function reserved(regex) {
1804
+ return token(prec(1, new RegExp(regex)));
1805
+ }
1806
+
1807
+ function createCaseInsensitiveRegex(word) {
1808
+ return new RegExp(
1809
+ word
1810
+ .split("")
1811
+ .map((letter) => `[${letter.toLowerCase()}${letter.toUpperCase()}]`)
1812
+ .join("")
1813
+ );
1814
+ }
1815
+
1816
+ function combinations(arr) {
1817
+ let result = [];
1818
+
1819
+ // Helper function to generate combinations
1820
+ function generateCombination(start, combination) {
1821
+ for (let i = start; i < arr.length; i++) {
1822
+ combination.push(arr[i]);
1823
+ result.push([...combination]);
1824
+ generateCombination(i + 1, combination);
1825
+ combination.pop();
1826
+ }
1827
+ }
1828
+
1829
+ generateCombination(0, []);
1830
+ return result;
1831
+ }