tree-sitter-sed 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +43 -0
- package/README.md +6 -4
- package/bindings/rust/build.rs +40 -0
- package/bindings/rust/lib.rs +70 -0
- package/common/grammar.js +216 -260
- package/common/regex.js +38 -92
- package/common/scanner.h +766 -1112
- package/package.json +7 -8
- package/queries/highlights.scm +2 -5
- package/sed_ere/queries/highlights.scm +2 -5
- package/sed_ere/src/grammar.json +725 -1283
- package/sed_ere/src/node-types.json +73 -75
- package/sed_ere/src/parser.c +28116 -37719
- package/src/grammar.json +658 -1104
- package/src/node-types.json +82 -74
- package/src/parser.c +31873 -41451
- package/tree-sitter.json +2 -2
- package/CMakeLists.txt +0 -121
- package/Makefile +0 -145
- package/bindings/c/tree-sitter-sed.pc.in +0 -10
- package/bindings/c/tree_sitter/tree-sitter-sed.h +0 -17
- package/test/binding.test.c +0 -9
package/common/grammar.js
CHANGED
|
@@ -13,6 +13,21 @@ function missingAtEndOrBoundary($, reason) {
|
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function blankSeparatedFileOperand($, name, operand) {
|
|
17
|
+
return seq(
|
|
18
|
+
$._blanks,
|
|
19
|
+
choice(operand, missingAtEndOrBoundary($, `missing_${name}`)),
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fileOperandForms($, name, operand) {
|
|
24
|
+
return [
|
|
25
|
+
blankSeparatedFileOperand($, name, operand),
|
|
26
|
+
seq(issueField($, "omitted_file_separator"), operand),
|
|
27
|
+
missingAtEndOrBoundary($, `missing_${name}`),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
function missingCommandSeparator($) {
|
|
17
32
|
return choice(
|
|
18
33
|
issueNode($, "missing_command_separator"),
|
|
@@ -24,14 +39,6 @@ function functionVerb($, spelling) {
|
|
|
24
39
|
return field("verb", alias(spelling, $.function_verb));
|
|
25
40
|
}
|
|
26
41
|
|
|
27
|
-
function leadingEmptyCommands($) {
|
|
28
|
-
return alias($._leading_empty_commands, $.empty_command);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function withLeadingEmptyCommands($, commands) {
|
|
32
|
-
return choice(commands, seq(leadingEmptyCommands($), optional(commands)));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
42
|
const delimiterNames = [
|
|
36
43
|
"regex_address_start",
|
|
37
44
|
"escaped_regex_address_start",
|
|
@@ -139,16 +146,35 @@ const functionDefinitions = [
|
|
|
139
146
|
},
|
|
140
147
|
];
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
// A known verb never becomes an unknown function: address maxima are owned by
|
|
150
|
+
// the excess address clauses, and a token that could also match a verb would
|
|
151
|
+
// let a GLR branch that expects other verbs compete with the valid parse.
|
|
152
|
+
const unknownFunctionCharacter = new RegExp(
|
|
153
|
+
`[^[:blank:][:digit:]$\\/\\\\!;}\\n${functionDefinitions
|
|
154
|
+
.map(({ spelling }) => spelling)
|
|
155
|
+
.join("")}]`,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Letter flags are aliased at their use sites: a rule that is only a string
|
|
159
|
+
// shares its token with the function verbs and would wrap an anonymous leaf.
|
|
160
|
+
const letterSubstitutionFlags = {
|
|
161
|
+
global_flag: "g",
|
|
162
|
+
case_insensitive_flag: "i",
|
|
163
|
+
print_flag: "p",
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
function nonWriteSubstitutionFlags($) {
|
|
167
|
+
return [
|
|
168
|
+
$.occurrence_flag,
|
|
169
|
+
...Object.entries(letterSubstitutionFlags).map(([rule, spelling]) =>
|
|
170
|
+
alias(spelling, $[rule]),
|
|
171
|
+
),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
148
174
|
|
|
149
175
|
function postWriteSubstitutionFlagChoice($) {
|
|
150
176
|
return choice(
|
|
151
|
-
...
|
|
177
|
+
...nonWriteSubstitutionFlags($),
|
|
152
178
|
alias("w", $.substitution_flag),
|
|
153
179
|
);
|
|
154
180
|
}
|
|
@@ -236,22 +262,9 @@ function commandListRules() {
|
|
|
236
262
|
_command_list: ($) =>
|
|
237
263
|
choice($._final_line, seq($._terminated_line, optional($._command_list))),
|
|
238
264
|
|
|
239
|
-
_final_line: ($) =>
|
|
240
|
-
choice($._line_content, alias($._blanks, $.empty_command)),
|
|
241
|
-
|
|
242
|
-
_terminated_line: ($) =>
|
|
243
|
-
choice(
|
|
244
|
-
seq($._line_content, $._newline_separator),
|
|
245
|
-
alias($._empty_terminated_line, $.empty_command),
|
|
246
|
-
),
|
|
247
|
-
|
|
248
|
-
_empty_terminated_line: ($) =>
|
|
249
|
-
seq(optional($._blanks), $._newline_separator),
|
|
265
|
+
_final_line: ($) => choice($._command_sequence, $._blanks),
|
|
250
266
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
_leading_empty_commands: ($) =>
|
|
254
|
-
seq(optional($._blanks), $._semicolon_separators),
|
|
267
|
+
_terminated_line: ($) => seq($._command_sequence, $._newline_separator),
|
|
255
268
|
|
|
256
269
|
_command_sequence: ($) =>
|
|
257
270
|
choice(
|
|
@@ -261,9 +274,9 @@ function commandListRules() {
|
|
|
261
274
|
),
|
|
262
275
|
seq(
|
|
263
276
|
$._recovered_line_terminated_command_item,
|
|
264
|
-
optional($.
|
|
277
|
+
optional(choice($._command_sequence, $._blanks)),
|
|
265
278
|
),
|
|
266
|
-
seq($.
|
|
279
|
+
seq($._separable_command_item, optional($._command_sequence_tail)),
|
|
267
280
|
seq(
|
|
268
281
|
$._unmatched_closing_brace_item,
|
|
269
282
|
optional($._unmatched_closing_brace_tail_content),
|
|
@@ -272,7 +285,10 @@ function commandListRules() {
|
|
|
272
285
|
|
|
273
286
|
_command_sequence_tail: ($) =>
|
|
274
287
|
choice(
|
|
275
|
-
seq(
|
|
288
|
+
seq(
|
|
289
|
+
$._semicolon_separator,
|
|
290
|
+
optional(choice($._command_sequence, $._blanks)),
|
|
291
|
+
),
|
|
276
292
|
$._unmatched_closing_brace_tail,
|
|
277
293
|
),
|
|
278
294
|
|
|
@@ -295,6 +311,9 @@ function commandListRules() {
|
|
|
295
311
|
),
|
|
296
312
|
),
|
|
297
313
|
|
|
314
|
+
_separable_command_item: ($) =>
|
|
315
|
+
choice($.empty_command, $._chainable_command_item),
|
|
316
|
+
|
|
298
317
|
_chainable_command_item: ($) =>
|
|
299
318
|
choice(
|
|
300
319
|
alias($._chainable_editing_command, $.editing_command),
|
|
@@ -312,39 +331,32 @@ function commandListRules() {
|
|
|
312
331
|
$._line_terminated_command_item,
|
|
313
332
|
seq(
|
|
314
333
|
$._recovered_line_terminated_command_item,
|
|
315
|
-
optional($.
|
|
334
|
+
optional($._block_command_sequence),
|
|
316
335
|
),
|
|
317
336
|
seq(
|
|
318
|
-
$.
|
|
319
|
-
optional(
|
|
337
|
+
$._separable_command_item,
|
|
338
|
+
optional(
|
|
339
|
+
seq($._semicolon_separator, optional($._block_command_sequence)),
|
|
340
|
+
),
|
|
320
341
|
),
|
|
321
342
|
),
|
|
322
343
|
|
|
323
|
-
_block_command_sequence_tail: ($) =>
|
|
324
|
-
seq($._semicolon_separators, optional($._block_command_sequence)),
|
|
325
|
-
|
|
326
|
-
_block_line_content: ($) =>
|
|
327
|
-
withLeadingEmptyCommands($, $._block_command_sequence),
|
|
328
|
-
|
|
329
|
-
_block_line_content_before_close: ($) =>
|
|
330
|
-
withLeadingEmptyCommands($, $._block_command_sequence_before_close),
|
|
331
|
-
|
|
332
344
|
_block_command_sequence_before_close: ($) =>
|
|
333
345
|
choice(
|
|
334
346
|
seq(
|
|
335
|
-
$.
|
|
336
|
-
$.
|
|
347
|
+
$._separable_command_item,
|
|
348
|
+
$._semicolon_separator,
|
|
337
349
|
optional($._block_command_sequence_before_close),
|
|
338
350
|
),
|
|
339
351
|
seq(
|
|
340
352
|
$._recovered_line_terminated_command_item,
|
|
341
|
-
optional($.
|
|
353
|
+
optional($._block_command_sequence_before_close),
|
|
342
354
|
),
|
|
343
355
|
),
|
|
344
356
|
|
|
345
357
|
_block_command_list: ($) =>
|
|
346
358
|
choice(
|
|
347
|
-
$.
|
|
359
|
+
$._block_command_sequence_before_close,
|
|
348
360
|
seq($._terminated_block_line, optional($._block_command_list)),
|
|
349
361
|
),
|
|
350
362
|
|
|
@@ -354,26 +366,18 @@ function commandListRules() {
|
|
|
354
366
|
_block_command_list_missing_separator: ($) =>
|
|
355
367
|
choice(
|
|
356
368
|
missingCommandSeparator($),
|
|
357
|
-
seq(
|
|
358
|
-
optional(leadingEmptyCommands($)),
|
|
359
|
-
$._block_command_sequence,
|
|
360
|
-
missingCommandSeparator($),
|
|
361
|
-
),
|
|
369
|
+
seq($._block_command_sequence, missingCommandSeparator($)),
|
|
362
370
|
seq($._terminated_block_line, $._block_command_list_missing_separator),
|
|
363
371
|
),
|
|
364
372
|
|
|
365
373
|
_terminated_block_line: ($) =>
|
|
366
|
-
|
|
367
|
-
seq($._block_line_content, $._newline_separator),
|
|
368
|
-
alias($._empty_terminated_line, $.empty_command),
|
|
369
|
-
),
|
|
374
|
+
seq($._block_command_sequence, $._newline_separator),
|
|
370
375
|
|
|
371
376
|
_newline_separator: ($) => alias("\n", $.command_separator),
|
|
372
377
|
|
|
373
|
-
|
|
378
|
+
_semicolon_separator: ($) => alias(";", $.command_separator),
|
|
374
379
|
|
|
375
|
-
|
|
376
|
-
prec.right(seq(alias(";", $.command_separator), optional($._blanks))),
|
|
380
|
+
empty_command: ($) => seq(optional($._blanks), $._empty_command_marker),
|
|
377
381
|
|
|
378
382
|
_blanks: () => token(/[[:blank:]]+/),
|
|
379
383
|
};
|
|
@@ -434,12 +438,10 @@ function addressRules(mode) {
|
|
|
434
438
|
field("second", $.address),
|
|
435
439
|
),
|
|
436
440
|
seq(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
seq(
|
|
442
|
-
issueField($, "omitted_first_address"),
|
|
441
|
+
choice(
|
|
442
|
+
field("first", $.address),
|
|
443
|
+
issueField($, "omitted_first_address"),
|
|
444
|
+
),
|
|
443
445
|
commaSeparator($),
|
|
444
446
|
$._omitted_second_address_issue,
|
|
445
447
|
),
|
|
@@ -541,55 +543,56 @@ function addressRules(mode) {
|
|
|
541
543
|
};
|
|
542
544
|
}
|
|
543
545
|
|
|
546
|
+
function delimitedFunction($, spelling, name, first, middleReason, rest) {
|
|
547
|
+
return seq(
|
|
548
|
+
functionVerb($, spelling),
|
|
549
|
+
choice(
|
|
550
|
+
seq(
|
|
551
|
+
field("opening", delimiter($, `${name}_start`)),
|
|
552
|
+
optional(first),
|
|
553
|
+
choice(
|
|
554
|
+
seq(field("middle", delimiter($, `${name}_middle`)), ...rest),
|
|
555
|
+
field("middle", unterminatedDelimiter($, middleReason)),
|
|
556
|
+
),
|
|
557
|
+
),
|
|
558
|
+
missingOpeningDelimiter($),
|
|
559
|
+
),
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
544
563
|
function operandRules(mode) {
|
|
545
564
|
const expression = mode === "bre" ? "basic_reg_exp" : "extended_reg_exp";
|
|
546
565
|
|
|
547
566
|
function substitutionFlagChoice($) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
567
|
+
return choice(
|
|
568
|
+
...nonWriteSubstitutionFlags($),
|
|
569
|
+
issueField($, "invalid_substitution_flag"),
|
|
570
|
+
);
|
|
551
571
|
}
|
|
552
572
|
|
|
553
573
|
return {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
optional(field("replacement", $.replacement)),
|
|
572
|
-
field("closing", delimiter($, "substitute_end")),
|
|
573
|
-
),
|
|
574
|
-
|
|
575
|
-
_incomplete_substitute_function: ($) =>
|
|
576
|
-
seq(
|
|
577
|
-
functionVerb($, "s"),
|
|
578
|
-
choice(
|
|
579
|
-
missingOpeningDelimiter($),
|
|
580
|
-
seq(
|
|
581
|
-
field("opening", delimiter($, "substitute_start")),
|
|
582
|
-
optional(field("expression", $[expression])),
|
|
583
|
-
choice(
|
|
584
|
-
seq(
|
|
585
|
-
field("middle", delimiter($, "substitute_middle")),
|
|
586
|
-
optional(field("replacement", $.replacement)),
|
|
587
|
-
field("closing", unterminatedDelimiter($, "replacement")),
|
|
574
|
+
substitute_function: ($) =>
|
|
575
|
+
delimitedFunction(
|
|
576
|
+
$,
|
|
577
|
+
"s",
|
|
578
|
+
"substitute",
|
|
579
|
+
field("expression", $[expression]),
|
|
580
|
+
"regular_expression",
|
|
581
|
+
[
|
|
582
|
+
optional(field("replacement", $.replacement)),
|
|
583
|
+
choice(
|
|
584
|
+
seq(
|
|
585
|
+
field("closing", delimiter($, "substitute_end")),
|
|
586
|
+
optional(
|
|
587
|
+
field(
|
|
588
|
+
"flags",
|
|
589
|
+
alias($._substitution_flags, $.substitution_flags),
|
|
590
|
+
),
|
|
588
591
|
),
|
|
589
|
-
field("middle", unterminatedDelimiter($, "regular_expression")),
|
|
590
592
|
),
|
|
593
|
+
field("closing", unterminatedDelimiter($, "replacement")),
|
|
591
594
|
),
|
|
592
|
-
|
|
595
|
+
],
|
|
593
596
|
),
|
|
594
597
|
|
|
595
598
|
replacement: ($) =>
|
|
@@ -663,59 +666,38 @@ function operandRules(mode) {
|
|
|
663
666
|
|
|
664
667
|
occurrence_flag: () => /[[:digit:]]+/,
|
|
665
668
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
print_flag: () => "p",
|
|
671
|
-
|
|
672
|
-
write_flag: ($) =>
|
|
673
|
-
seq(
|
|
669
|
+
write_flag: ($) => {
|
|
670
|
+
const wfile = field("wfile", alias($._substitution_wfile, $.wfile));
|
|
671
|
+
return seq(
|
|
674
672
|
field("verb", alias("w", $.substitution_flag)),
|
|
675
673
|
choice(
|
|
676
674
|
seq(
|
|
677
675
|
$._flag_after_write_marker,
|
|
678
676
|
repeat1(postWriteSubstitutionFlagChoice($)),
|
|
679
|
-
|
|
680
|
-
choice(
|
|
681
|
-
field("wfile", alias($._substitution_wfile, $.wfile)),
|
|
682
|
-
missingAtEndOrBoundary($, "missing_wfile"),
|
|
683
|
-
),
|
|
677
|
+
blankSeparatedFileOperand($, "wfile", wfile),
|
|
684
678
|
),
|
|
685
|
-
|
|
686
|
-
seq($._blanks, missingAtEndOrBoundary($, "missing_wfile")),
|
|
687
|
-
seq(
|
|
688
|
-
issueField($, "omitted_file_separator"),
|
|
689
|
-
field("wfile", alias($._substitution_wfile, $.wfile)),
|
|
690
|
-
),
|
|
691
|
-
missingAtEndOrBoundary($, "missing_wfile"),
|
|
679
|
+
...fileOperandForms($, "wfile", wfile),
|
|
692
680
|
),
|
|
693
|
-
)
|
|
681
|
+
);
|
|
682
|
+
},
|
|
694
683
|
|
|
695
684
|
translate_function: ($) =>
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
685
|
+
delimitedFunction(
|
|
686
|
+
$,
|
|
687
|
+
"y",
|
|
688
|
+
"translate",
|
|
689
|
+
field("string1", $.translation_string),
|
|
690
|
+
"translation",
|
|
691
|
+
[
|
|
692
|
+
optional(field("string2", $.translation_string)),
|
|
693
|
+
field(
|
|
694
|
+
"closing",
|
|
702
695
|
choice(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
optional(field("string2", $.translation_string)),
|
|
706
|
-
field(
|
|
707
|
-
"closing",
|
|
708
|
-
choice(
|
|
709
|
-
delimiter($, "translate_end"),
|
|
710
|
-
unterminatedDelimiter($, "translation"),
|
|
711
|
-
),
|
|
712
|
-
),
|
|
713
|
-
),
|
|
714
|
-
field("middle", unterminatedDelimiter($, "translation")),
|
|
696
|
+
delimiter($, "translate_end"),
|
|
697
|
+
unterminatedDelimiter($, "translation"),
|
|
715
698
|
),
|
|
716
699
|
),
|
|
717
|
-
|
|
718
|
-
),
|
|
700
|
+
],
|
|
719
701
|
),
|
|
720
702
|
|
|
721
703
|
translation_string: ($) =>
|
|
@@ -760,10 +742,12 @@ function functionRules() {
|
|
|
760
742
|
issueField($, "unspecified_text_escape"),
|
|
761
743
|
),
|
|
762
744
|
),
|
|
763
|
-
|
|
764
|
-
$._text_end,
|
|
745
|
+
$._text_tail,
|
|
765
746
|
),
|
|
766
747
|
|
|
748
|
+
_text_tail: ($) =>
|
|
749
|
+
seq(optional(issueField($, "missing_text")), $._text_end),
|
|
750
|
+
|
|
767
751
|
_text_end: ($) => choice($._text_line_end, $._text_eof),
|
|
768
752
|
|
|
769
753
|
text_literal: ($) =>
|
|
@@ -778,6 +762,9 @@ function functionRules() {
|
|
|
778
762
|
text_introducer: ($) =>
|
|
779
763
|
namedExternal($, $._text_command_start, "text_introducer_token"),
|
|
780
764
|
|
|
765
|
+
_incomplete_text_introducer: ($) =>
|
|
766
|
+
issueField($, "incomplete_text_introducer"),
|
|
767
|
+
|
|
781
768
|
rfile: ($) => namedExternal($, $._file_argument, "rfile_token"),
|
|
782
769
|
|
|
783
770
|
wfile: ($) => namedExternal($, $._file_argument, "wfile_token"),
|
|
@@ -797,15 +784,7 @@ function functionRules() {
|
|
|
797
784
|
};
|
|
798
785
|
|
|
799
786
|
function fileForm(form) {
|
|
800
|
-
|
|
801
|
-
return ($) => [
|
|
802
|
-
choice(
|
|
803
|
-
seq($._blanks, field(form, $[form])),
|
|
804
|
-
seq($._blanks, missingAtEndOrBoundary($, missingFileReason)),
|
|
805
|
-
seq(issueField($, "omitted_file_separator"), field(form, $[form])),
|
|
806
|
-
missingAtEndOrBoundary($, missingFileReason),
|
|
807
|
-
),
|
|
808
|
-
];
|
|
787
|
+
return ($) => [choice(...fileOperandForms($, form, field(form, $[form])))];
|
|
809
788
|
}
|
|
810
789
|
|
|
811
790
|
const formArguments = {
|
|
@@ -818,10 +797,11 @@ function functionRules() {
|
|
|
818
797
|
choice(
|
|
819
798
|
seq(
|
|
820
799
|
field("introducer", $.text_introducer),
|
|
821
|
-
choice(
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
800
|
+
choice(field("text", $.text), $._text_tail),
|
|
801
|
+
),
|
|
802
|
+
field(
|
|
803
|
+
"introducer",
|
|
804
|
+
alias($._incomplete_text_introducer, $.text_introducer),
|
|
825
805
|
),
|
|
826
806
|
missingAtEndOrBoundary($, "missing_text_introducer"),
|
|
827
807
|
),
|
|
@@ -830,7 +810,10 @@ function functionRules() {
|
|
|
830
810
|
optional(
|
|
831
811
|
prec.right(
|
|
832
812
|
seq(
|
|
833
|
-
field(
|
|
813
|
+
field(
|
|
814
|
+
"separator",
|
|
815
|
+
namedExternal($, $._argument_separator, "argument_separator"),
|
|
816
|
+
),
|
|
834
817
|
optional(field("label", $.label)),
|
|
835
818
|
),
|
|
836
819
|
),
|
|
@@ -863,124 +846,101 @@ function functionRules() {
|
|
|
863
846
|
}
|
|
864
847
|
|
|
865
848
|
function editingCommandRules() {
|
|
866
|
-
const
|
|
867
|
-
(
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
);
|
|
872
|
-
const lineTerminated = regularDefinitions.filter(
|
|
873
|
-
({ lineTerminated: isLineTerminated }) => isLineTerminated,
|
|
874
|
-
);
|
|
875
|
-
|
|
876
|
-
function functionsByMaximum(definitions, maximum) {
|
|
877
|
-
return definitions
|
|
878
|
-
.filter(({ maxAddresses = 2 }) => maxAddresses === maximum)
|
|
879
|
-
.map(({ rule }) => rule);
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
function wrapperName(kind, maximum) {
|
|
883
|
-
return `_${kind}_${maximum}_address_function`;
|
|
884
|
-
}
|
|
849
|
+
const addressClauses = {
|
|
850
|
+
0: ($) => alias($._max0_address_clause, $.address_clause),
|
|
851
|
+
1: ($) => alias($._max1_address_clause, $.address_clause),
|
|
852
|
+
2: ($) => $.address_clause,
|
|
853
|
+
};
|
|
885
854
|
|
|
886
|
-
|
|
887
|
-
|
|
855
|
+
// One wrapper rule per (chainable or line-terminated) kind and address
|
|
856
|
+
// maximum keeps the maximum-specific GLR paths distinct until the verb.
|
|
857
|
+
const wrappers = [];
|
|
858
|
+
for (const [kind, isLineTerminated] of [
|
|
859
|
+
["chainable", false],
|
|
860
|
+
["line_terminated", true],
|
|
861
|
+
]) {
|
|
862
|
+
for (const maximum of [0, 1, 2]) {
|
|
863
|
+
const names = functionDefinitions
|
|
864
|
+
.filter(
|
|
865
|
+
({ lineTerminated = false, maxAddresses = 2 }) =>
|
|
866
|
+
lineTerminated === isLineTerminated && maxAddresses === maximum,
|
|
867
|
+
)
|
|
868
|
+
.map(({ rule }) => rule);
|
|
869
|
+
if (names.length > 0) {
|
|
870
|
+
wrappers.push({
|
|
871
|
+
kind,
|
|
872
|
+
maximum,
|
|
873
|
+
name: `_${kind}_${maximum}_address_function`,
|
|
874
|
+
names,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
}
|
|
888
878
|
}
|
|
889
879
|
|
|
890
|
-
function
|
|
891
|
-
|
|
892
|
-
return alias($._max0_address_clause, $.address_clause);
|
|
893
|
-
}
|
|
894
|
-
if (maximum === 1) {
|
|
895
|
-
return alias($._max1_address_clause, $.address_clause);
|
|
896
|
-
}
|
|
897
|
-
return $.address_clause;
|
|
880
|
+
function addressesPrefix($, addresses) {
|
|
881
|
+
return seq(field("addresses", addresses), optional($._blanks));
|
|
898
882
|
}
|
|
899
883
|
|
|
900
884
|
function addressedCommand($, addresses, selectedFunction) {
|
|
901
885
|
return seq(
|
|
902
886
|
optional($._blanks),
|
|
903
|
-
optional(
|
|
887
|
+
optional(addressesPrefix($, addresses)),
|
|
904
888
|
optional(field("negation", $.negation)),
|
|
905
889
|
field("function", selectedFunction),
|
|
906
890
|
);
|
|
907
891
|
}
|
|
908
892
|
|
|
909
|
-
function
|
|
910
|
-
return
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
for (const maximum of [0, 1, 2]) {
|
|
920
|
-
const names = functionsByMaximum(definitions, maximum);
|
|
921
|
-
if (names.length === 0) {
|
|
922
|
-
continue;
|
|
923
|
-
}
|
|
924
|
-
forms.push(
|
|
925
|
-
addressedCommand(
|
|
926
|
-
$,
|
|
927
|
-
addressClauseForMaximum($, maximum),
|
|
928
|
-
functionWrapper($, wrapperName(kind, maximum)),
|
|
893
|
+
function addressedForms($, kind) {
|
|
894
|
+
return choice(
|
|
895
|
+
...wrappers
|
|
896
|
+
.filter((wrapper) => wrapper.kind === kind)
|
|
897
|
+
.map(({ maximum, name }) =>
|
|
898
|
+
addressedCommand(
|
|
899
|
+
$,
|
|
900
|
+
addressClauses[maximum]($),
|
|
901
|
+
alias($[name], $.function),
|
|
902
|
+
),
|
|
929
903
|
),
|
|
930
|
-
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
return choice(...forms);
|
|
904
|
+
);
|
|
934
905
|
}
|
|
935
906
|
|
|
936
907
|
const rules = {
|
|
937
908
|
_chainable_editing_command: ($) =>
|
|
938
909
|
seq(
|
|
939
|
-
|
|
940
|
-
addressedForms($, chainable, "chainable"),
|
|
941
|
-
addressedFunction($, $._chainable_substitute_function),
|
|
942
|
-
),
|
|
910
|
+
addressedForms($, "chainable"),
|
|
943
911
|
optional(issueField($, "unexpected_command_text")),
|
|
944
912
|
),
|
|
945
913
|
|
|
946
914
|
_line_terminated_editing_command: ($) =>
|
|
947
915
|
seq(
|
|
948
|
-
addressedForms($,
|
|
916
|
+
addressedForms($, "line_terminated"),
|
|
949
917
|
optional(issueField($, "unexpected_command_text")),
|
|
950
918
|
),
|
|
951
919
|
|
|
952
920
|
_recovered_line_terminated_editing_command: ($) =>
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
issueField($, "forbidden_command_separator"),
|
|
957
|
-
optional($._blanks),
|
|
958
|
-
),
|
|
921
|
+
seq(
|
|
922
|
+
$._line_terminated_editing_command,
|
|
923
|
+
issueField($, "forbidden_command_separator"),
|
|
959
924
|
),
|
|
960
925
|
|
|
961
926
|
_recovered_editing_command: ($) =>
|
|
962
927
|
choice(
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
seq(field("addresses", $.address_clause), optional($._blanks)),
|
|
968
|
-
),
|
|
969
|
-
field("negation", $.negation),
|
|
970
|
-
field("function", alias($._reserved_unknown_function, $.function)),
|
|
928
|
+
addressedCommand(
|
|
929
|
+
$,
|
|
930
|
+
$.address_clause,
|
|
931
|
+
alias($._unknown_function, $.function),
|
|
971
932
|
),
|
|
972
933
|
seq(
|
|
973
934
|
optional($._blanks),
|
|
974
|
-
|
|
975
|
-
|
|
935
|
+
optional(addressesPrefix($, $.address_clause)),
|
|
936
|
+
field("negation", $.negation),
|
|
976
937
|
field("function", alias($._reserved_unknown_function, $.function)),
|
|
977
938
|
),
|
|
978
939
|
seq(
|
|
979
940
|
optional($._blanks),
|
|
980
941
|
choice(
|
|
981
942
|
seq(
|
|
982
|
-
|
|
983
|
-
optional($._blanks),
|
|
943
|
+
addressesPrefix($, $.address_clause),
|
|
984
944
|
optional(field("negation", $.negation)),
|
|
985
945
|
),
|
|
986
946
|
field("negation", $.negation),
|
|
@@ -1003,9 +963,6 @@ function editingCommandRules() {
|
|
|
1003
963
|
|
|
1004
964
|
_missing_function: ($) => missingAtEndOrBoundary($, "missing_function"),
|
|
1005
965
|
|
|
1006
|
-
_chainable_substitute_function: ($) =>
|
|
1007
|
-
alias($._substitute_function, $.substitute_function),
|
|
1008
|
-
|
|
1009
966
|
negation: ($) =>
|
|
1010
967
|
seq(
|
|
1011
968
|
field("operator", alias("!", $.negation_operator)),
|
|
@@ -1019,16 +976,8 @@ function editingCommandRules() {
|
|
|
1019
976
|
),
|
|
1020
977
|
};
|
|
1021
978
|
|
|
1022
|
-
for (const
|
|
1023
|
-
[
|
|
1024
|
-
["line_terminated", lineTerminated],
|
|
1025
|
-
]) {
|
|
1026
|
-
for (const maximum of [0, 1, 2]) {
|
|
1027
|
-
const names = functionsByMaximum(definitions, maximum);
|
|
1028
|
-
if (names.length > 0) {
|
|
1029
|
-
rules[wrapperName(kind, maximum)] = ($) => choiceForRules($, names);
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
979
|
+
for (const { name, names } of wrappers) {
|
|
980
|
+
rules[name] = ($) => choiceForRules($, names);
|
|
1032
981
|
}
|
|
1033
982
|
|
|
1034
983
|
return rules;
|
|
@@ -1276,19 +1225,19 @@ function issueDefinitions(mode) {
|
|
|
1276
1225
|
},
|
|
1277
1226
|
{
|
|
1278
1227
|
reason: "bre_subexpression_left_anchor",
|
|
1279
|
-
outcome: "
|
|
1228
|
+
outcome: "invalid_syntax",
|
|
1280
1229
|
rule: ($) => $._regex_bre_subexpression_caret,
|
|
1281
1230
|
},
|
|
1282
1231
|
{
|
|
1283
1232
|
reason: "bre_subexpression_right_anchor",
|
|
1284
|
-
outcome: "
|
|
1233
|
+
outcome: "invalid_syntax",
|
|
1285
1234
|
rule: ($) => $._regex_bre_subexpression_dollar,
|
|
1286
1235
|
},
|
|
1287
1236
|
]
|
|
1288
1237
|
: []),
|
|
1289
1238
|
{
|
|
1290
1239
|
reason: "omitted_file_separator",
|
|
1291
|
-
outcome: "
|
|
1240
|
+
outcome: "invalid_syntax",
|
|
1292
1241
|
rule: missing("omitted_file_separator"),
|
|
1293
1242
|
},
|
|
1294
1243
|
{
|
|
@@ -1321,7 +1270,7 @@ function issueDefinitions(mode) {
|
|
|
1321
1270
|
{
|
|
1322
1271
|
reason: "unknown_function",
|
|
1323
1272
|
outcome: "nonconforming_syntax",
|
|
1324
|
-
rule: () => token(prec(-2,
|
|
1273
|
+
rule: () => token(prec(-2, unknownFunctionCharacter)),
|
|
1325
1274
|
},
|
|
1326
1275
|
{
|
|
1327
1276
|
id: "reserved_unknown_function",
|
|
@@ -1341,7 +1290,7 @@ function issueDefinitions(mode) {
|
|
|
1341
1290
|
{
|
|
1342
1291
|
reason: "forbidden_command_separator",
|
|
1343
1292
|
outcome: "nonconforming_syntax",
|
|
1344
|
-
rule: () => token.immediate(";"),
|
|
1293
|
+
rule: ($) => alias(token.immediate(";"), $.command_separator),
|
|
1345
1294
|
},
|
|
1346
1295
|
{
|
|
1347
1296
|
reason: "blanks_around_address_separator",
|
|
@@ -1388,7 +1337,7 @@ function issueDefinitions(mode) {
|
|
|
1388
1337
|
{
|
|
1389
1338
|
reason: "invalid_delimiter",
|
|
1390
1339
|
outcome: "nonconforming_syntax",
|
|
1391
|
-
rule: () => "\\",
|
|
1340
|
+
rule: ($) => field("token", alias("\\", $.delimiter_token)),
|
|
1392
1341
|
},
|
|
1393
1342
|
{
|
|
1394
1343
|
reason: "unterminated_regular_expression",
|
|
@@ -1449,6 +1398,11 @@ function issueDefinitions(mode) {
|
|
|
1449
1398
|
outcome: "incomplete_syntax",
|
|
1450
1399
|
rule: missing("missing_text_introducer"),
|
|
1451
1400
|
},
|
|
1401
|
+
{
|
|
1402
|
+
reason: "incomplete_text_introducer",
|
|
1403
|
+
outcome: "incomplete_syntax",
|
|
1404
|
+
rule: ($) => $._text_incomplete_introducer,
|
|
1405
|
+
},
|
|
1452
1406
|
{
|
|
1453
1407
|
reason: "missing_text",
|
|
1454
1408
|
outcome: "incomplete_syntax",
|
|
@@ -1651,6 +1605,7 @@ function externalTokens($, mode) {
|
|
|
1651
1605
|
$._invalid_substitution_flag,
|
|
1652
1606
|
$._flag_after_write_marker,
|
|
1653
1607
|
$._text_command_start,
|
|
1608
|
+
$._text_incomplete_introducer,
|
|
1654
1609
|
$._text_literal,
|
|
1655
1610
|
$._text_backslash_escape,
|
|
1656
1611
|
$._text_escaped_newline,
|
|
@@ -1662,7 +1617,9 @@ function externalTokens($, mode) {
|
|
|
1662
1617
|
$._file_argument,
|
|
1663
1618
|
$._substitution_wfile_argument,
|
|
1664
1619
|
$._line_word,
|
|
1620
|
+
$._argument_separator,
|
|
1665
1621
|
$._right_brace,
|
|
1622
|
+
$._empty_command_marker,
|
|
1666
1623
|
$._reserved_unknown_function_token,
|
|
1667
1624
|
$._regex_incomplete_group,
|
|
1668
1625
|
$._regex_incomplete_bracket_term,
|
|
@@ -1692,7 +1649,6 @@ function defineGrammar(name, mode) {
|
|
|
1692
1649
|
extras: () => [],
|
|
1693
1650
|
|
|
1694
1651
|
conflicts: ($) => [
|
|
1695
|
-
[$.address_clause, $._recovered_editing_command],
|
|
1696
1652
|
[$.address_clause, $._max1_address_clause],
|
|
1697
1653
|
[$._double_address_clause, $._excess_address_unit1_reason],
|
|
1698
1654
|
[$.address, $._max0_address],
|