tree-sitter-sed 0.14.0 → 0.15.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 CHANGED
@@ -10,7 +10,7 @@ name = "tree-sitter-sed"
10
10
  publish = false
11
11
  readme = "README.md"
12
12
  repository = "https://github.com/konomanoasa/tree-sitter-sed"
13
- version = "0.14.0"
13
+ version = "0.15.0"
14
14
 
15
15
  build = "bindings/rust/build.rs"
16
16
  include = [
@@ -199,7 +199,7 @@ mod tests {
199
199
  9,
200
200
  1,
201
201
  6,
202
- ["unexpected_command_text", "invalid_substitution_flag"],
202
+ ["invalid_substitution_flag"; 2],
203
203
  ),
204
204
  ] {
205
205
  for (invalid_byte, reason) in [0, 0xff].into_iter().zip(reasons) {
package/common/grammar.js CHANGED
@@ -47,6 +47,18 @@ function lineOperand($, first, rest) {
47
47
  );
48
48
  }
49
49
 
50
+ function operandAtoms($, literal, ...atoms) {
51
+ return repeat1(
52
+ choice(
53
+ literal,
54
+ seq($._escape_prefix, issueField($, "invalid_encoding")),
55
+ issueField($, "nul_character"),
56
+ issueField($, "invalid_encoding"),
57
+ ...atoms,
58
+ ),
59
+ );
60
+ }
61
+
50
62
  function commentText($) {
51
63
  return choice(
52
64
  namedExternal($, $._comment_text, "comment_text"),
@@ -205,6 +217,14 @@ function editingCommand($, kind) {
205
217
  return alias($[`_${kind}_editing_command`], $.editing_command);
206
218
  }
207
219
 
220
+ function newlineSeparator($) {
221
+ return alias("\n", $.command_separator);
222
+ }
223
+
224
+ function semicolonSeparator($) {
225
+ return alias(";", $.command_separator);
226
+ }
227
+
208
228
  function commandListRules() {
209
229
  return {
210
230
  script: ($) => optional(alias($._script_command_list, $.command_list)),
@@ -215,9 +235,7 @@ function commandListRules() {
215
235
  _initial_suppressing_comment_command_list: ($) =>
216
236
  seq(
217
237
  alias($._initial_suppressing_comment_command, $.editing_command),
218
- optional(
219
- seq(alias("\n", $.command_separator), optional($._command_list)),
220
- ),
238
+ optional(seq(newlineSeparator($), optional($._command_list))),
221
239
  ),
222
240
 
223
241
  _initial_suppressing_comment_command: ($) =>
@@ -248,116 +266,91 @@ function commandListRules() {
248
266
  repeat(commentText($)),
249
267
  ),
250
268
 
269
+ // Lists are built with repeat so that Tree-sitter balances them; explicit
270
+ // recursion nests hidden nodes as deep as the command count, which makes
271
+ // cursor traversal quadratic.
251
272
  _command_list: ($) =>
252
273
  choice(
253
- $._command_sequence,
274
+ seq(
275
+ repeat1($._command_unit),
276
+ optional(choice($._command_item, $._blanks)),
277
+ ),
278
+ $._command_item,
254
279
  $._blanks,
255
- seq($._terminated_line, optional($._command_list)),
256
280
  ),
257
281
 
258
- _terminated_line: ($) =>
259
- seq($._command_sequence, alias("\n", $.command_separator)),
260
-
261
- _command_sequence: ($) =>
282
+ _command_unit: ($) =>
262
283
  choice(
263
284
  seq(
264
- editingCommand($, "line_terminated"),
265
- optional($._unmatched_closing_brace_tail),
266
- ),
267
- seq(
268
- editingCommand($, "recovered_line_terminated"),
269
- optional(choice($._command_sequence, $._blanks)),
285
+ $._separable_command_item,
286
+ choice(
287
+ semicolonSeparator($),
288
+ newlineSeparator($),
289
+ issueNode($, "missing_separator_before_unmatched_brace"),
290
+ ),
270
291
  ),
271
- seq($._separable_command_item, optional($._command_sequence_tail)),
272
292
  seq(
273
293
  $._unmatched_closing_brace_item,
274
- optional($._unmatched_closing_brace_tail_content),
294
+ choice(
295
+ semicolonSeparator($),
296
+ newlineSeparator($),
297
+ issueNode($, "missing_separator_before_unmatched_brace"),
298
+ issueNode($, "missing_separator_after_unmatched_brace"),
299
+ ),
275
300
  ),
276
- ),
277
-
278
- _command_sequence_tail: ($) =>
279
- choice(
280
301
  seq(
281
- alias(";", $.command_separator),
282
- optional(choice($._command_sequence, $._blanks)),
302
+ editingCommand($, "line_terminated"),
303
+ choice(
304
+ newlineSeparator($),
305
+ issueNode($, "missing_separator_before_unmatched_brace"),
306
+ ),
283
307
  ),
284
- $._unmatched_closing_brace_tail,
308
+ editingCommand($, "recovered_line_terminated"),
285
309
  ),
286
310
 
287
- _unmatched_closing_brace_tail: ($) =>
288
- seq(
289
- issueNode($, "missing_separator_before_unmatched_brace"),
311
+ _command_item: ($) =>
312
+ choice(
313
+ $._separable_command_item,
290
314
  $._unmatched_closing_brace_item,
291
- optional($._unmatched_closing_brace_tail_content),
315
+ editingCommand($, "line_terminated"),
292
316
  ),
293
317
 
294
318
  _unmatched_closing_brace_item: ($) =>
295
- seq(issueNode($, "unmatched_closing_brace"), optional($._blanks)),
296
-
297
- _unmatched_closing_brace_tail_content: ($) =>
298
- choice(
299
- $._command_sequence_tail,
300
- seq(
301
- issueNode($, "missing_separator_after_unmatched_brace"),
302
- $._command_sequence,
303
- ),
319
+ seq(
320
+ optional($._brace_leading_blanks),
321
+ issueNode($, "unmatched_closing_brace"),
322
+ optional($._blanks),
304
323
  ),
305
324
 
306
325
  _separable_command_item: ($) =>
307
- choice($.empty_command, $._chainable_command_item),
308
-
309
- _chainable_command_item: ($) =>
310
- choice(editingCommand($, "chainable"), editingCommand($, "recovered")),
326
+ choice(
327
+ $.empty_command,
328
+ editingCommand($, "chainable"),
329
+ editingCommand($, "recovered"),
330
+ ),
311
331
 
312
- _block_command_sequence: ($) =>
332
+ _block_commands: ($) =>
313
333
  choice(
314
- editingCommand($, "line_terminated"),
334
+ repeat1($._block_unit),
315
335
  seq(
316
- editingCommand($, "recovered_line_terminated"),
317
- optional($._block_command_sequence),
318
- ),
319
- seq(
320
- $._separable_command_item,
321
- optional(
322
- seq(
323
- alias(";", $.command_separator),
324
- optional($._block_command_sequence),
325
- ),
326
- ),
336
+ repeat($._block_unit),
337
+ optional($._block_item),
338
+ missingCommandSeparator($),
327
339
  ),
328
340
  ),
329
341
 
330
- _block_command_sequence_before_close: ($) =>
342
+ _block_unit: ($) =>
331
343
  choice(
332
344
  seq(
333
345
  $._separable_command_item,
334
- alias(";", $.command_separator),
335
- optional($._block_command_sequence_before_close),
336
- ),
337
- seq(
338
- editingCommand($, "recovered_line_terminated"),
339
- optional($._block_command_sequence_before_close),
346
+ choice(semicolonSeparator($), newlineSeparator($)),
340
347
  ),
348
+ seq(editingCommand($, "line_terminated"), newlineSeparator($)),
349
+ editingCommand($, "recovered_line_terminated"),
341
350
  ),
342
351
 
343
- _block_command_list: ($) =>
344
- choice(
345
- $._block_command_sequence_before_close,
346
- seq($._terminated_block_line, optional($._block_command_list)),
347
- ),
348
-
349
- _block_commands: ($) =>
350
- choice($._block_command_list, $._block_command_list_missing_separator),
351
-
352
- _block_command_list_missing_separator: ($) =>
353
- choice(
354
- missingCommandSeparator($),
355
- seq($._block_command_sequence, missingCommandSeparator($)),
356
- seq($._terminated_block_line, $._block_command_list_missing_separator),
357
- ),
358
-
359
- _terminated_block_line: ($) =>
360
- seq($._block_command_sequence, alias("\n", $.command_separator)),
352
+ _block_item: ($) =>
353
+ choice($._separable_command_item, editingCommand($, "line_terminated")),
361
354
 
362
355
  empty_command: ($) => seq(optional($._blanks), $._empty_command_marker),
363
356
 
@@ -429,12 +422,9 @@ function addressRules(mode) {
429
422
  _max2_excess_address_clause: ($) =>
430
423
  prec.dynamic(
431
424
  1,
432
- choice(
433
- seq($._double_address_clause, issueField($, "excess_address_unit2")),
434
- seq(
435
- $._max2_excess_address_clause,
436
- issueField($, "excess_address_unit2"),
437
- ),
425
+ seq(
426
+ $._double_address_clause,
427
+ repeat1(issueField($, "excess_address_unit2")),
438
428
  ),
439
429
  ),
440
430
 
@@ -444,29 +434,27 @@ function addressRules(mode) {
444
434
  _max1_excess_address_clause: ($) =>
445
435
  prec.dynamic(
446
436
  1,
447
- choice(
448
- seq(field("first", $.address), issueField($, "excess_address_unit1")),
449
- seq(
437
+ seq(
438
+ choice(
439
+ field("first", $.address),
450
440
  issueField($, "omitted_first_address_unit1"),
451
- issueField($, "excess_address_unit1"),
452
- ),
453
- seq(
454
- $._max1_excess_address_clause,
455
- issueField($, "excess_address_unit1"),
456
441
  ),
442
+ repeat1(issueField($, "excess_address_unit1")),
457
443
  ),
458
444
  ),
459
445
 
460
446
  _max0_address_clause: ($) =>
461
447
  prec.dynamic(
462
448
  1,
463
- choice(
464
- issueField($, "excess_address"),
465
- seq(
466
- issueField($, "omitted_first_address_unit0"),
467
- issueField($, "excess_address_unit0"),
449
+ seq(
450
+ choice(
451
+ issueField($, "excess_address"),
452
+ seq(
453
+ issueField($, "omitted_first_address_unit0"),
454
+ issueField($, "excess_address_unit0"),
455
+ ),
468
456
  ),
469
- seq($._max0_address_clause, issueField($, "excess_address_unit0")),
457
+ repeat(issueField($, "excess_address_unit0")),
470
458
  ),
471
459
  ),
472
460
 
@@ -567,21 +555,17 @@ function operandRules(mode) {
567
555
  ),
568
556
 
569
557
  replacement: ($) =>
570
- repeat1(
571
- choice(
572
- $.replacement_literal,
573
- seq($._escape_prefix, issueField($, "invalid_encoding")),
574
- issueField($, "nul_character"),
575
- issueField($, "invalid_encoding"),
576
- $.matched_text_reference,
577
- $.replacement_backreference,
578
- $.replacement_escaped_delimiter,
579
- issueField($, "replacement_ampersand_delimiter_escape"),
580
- $.replacement_escape,
581
- $.escaped_newline,
582
- issueField($, "unspecified_replacement_escape"),
583
- issueField($, "incomplete_replacement_escape"),
584
- ),
558
+ operandAtoms(
559
+ $,
560
+ $.replacement_literal,
561
+ $.matched_text_reference,
562
+ $.replacement_backreference,
563
+ $.replacement_escaped_delimiter,
564
+ issueField($, "replacement_ampersand_delimiter_escape"),
565
+ $.replacement_escape,
566
+ $.escaped_newline,
567
+ issueField($, "unspecified_replacement_escape"),
568
+ issueField($, "incomplete_replacement_escape"),
585
569
  ),
586
570
 
587
571
  replacement_literal: ($) => $._replacement_literal,
@@ -599,16 +583,8 @@ function operandRules(mode) {
599
583
  _substitution_flags: ($) =>
600
584
  prec.right(
601
585
  choice(
602
- $._substitution_flags_without_write,
603
- seq(optional($._substitution_flags_without_write), $.write_flag),
604
- ),
605
- ),
606
-
607
- _substitution_flags_without_write: ($) =>
608
- choice(
609
- substitutionFlagChoice($),
610
- prec.left(
611
- seq($._substitution_flags_without_write, substitutionFlagChoice($)),
586
+ repeat1(substitutionFlagChoice($)),
587
+ seq(repeat(substitutionFlagChoice($)), $.write_flag),
612
588
  ),
613
589
  ),
614
590
 
@@ -646,17 +622,13 @@ function operandRules(mode) {
646
622
  ),
647
623
 
648
624
  translation_string: ($) =>
649
- repeat1(
650
- choice(
651
- $.translation_literal,
652
- seq($._escape_prefix, issueField($, "invalid_encoding")),
653
- issueField($, "nul_character"),
654
- issueField($, "invalid_encoding"),
655
- $.translation_escape,
656
- $.translation_escaped_delimiter,
657
- issueField($, "undefined_translation_escape"),
658
- issueField($, "incomplete_translation_escape"),
659
- ),
625
+ operandAtoms(
626
+ $,
627
+ $.translation_literal,
628
+ $.translation_escape,
629
+ $.translation_escaped_delimiter,
630
+ issueField($, "undefined_translation_escape"),
631
+ issueField($, "incomplete_translation_escape"),
660
632
  ),
661
633
 
662
634
  translation_literal: ($) => $._translate_literal,
@@ -675,16 +647,12 @@ function functionRules() {
675
647
  const rules = {
676
648
  text: ($) =>
677
649
  seq(
678
- repeat1(
679
- choice(
680
- $.text_literal,
681
- seq($._escape_prefix, issueField($, "invalid_encoding")),
682
- issueField($, "nul_character"),
683
- issueField($, "invalid_encoding"),
684
- $.text_backslash_escape,
685
- $.text_escaped_newline,
686
- issueField($, "unspecified_text_escape"),
687
- ),
650
+ operandAtoms(
651
+ $,
652
+ $.text_literal,
653
+ $.text_backslash_escape,
654
+ $.text_escaped_newline,
655
+ issueField($, "unspecified_text_escape"),
688
656
  ),
689
657
  $._text_tail,
690
658
  ),
@@ -742,6 +710,7 @@ function functionRules() {
742
710
  const formArguments = {
743
711
  block: ($) => [
744
712
  field("commands", alias($._block_commands, $.command_list)),
713
+ optional($._brace_leading_blanks),
745
714
  choice(
746
715
  field("closing", $.closing_brace),
747
716
  issueField($, "missing_closing_brace"),
@@ -1362,7 +1331,11 @@ function issueDefinitions(mode) {
1362
1331
  reason: "invalid_substitution_flag",
1363
1332
  outcome: "nonconforming_syntax",
1364
1333
  rule: ($) =>
1365
- choice($._invalid_substitution_flag, issueField($, "invalid_encoding")),
1334
+ choice(
1335
+ $._invalid_substitution_flag,
1336
+ $._nul_character,
1337
+ issueField($, "invalid_encoding"),
1338
+ ),
1366
1339
  },
1367
1340
  {
1368
1341
  reason: "invalid_delimiter",
@@ -1616,6 +1589,7 @@ function externalTokens($, mode) {
1616
1589
  $._line_word,
1617
1590
  $._argument_separator,
1618
1591
  $._right_brace,
1592
+ $._brace_leading_blanks,
1619
1593
  $._block_trailing_blanks,
1620
1594
  $._empty_command_marker,
1621
1595
  $._reserved_unknown_function_token,
package/common/regex.js CHANGED
@@ -123,6 +123,33 @@ function bracketExpression($, ambiguous) {
123
123
  );
124
124
  }
125
125
 
126
+ // Character and equivalence classes are not portable range endpoints; their
127
+ // ranges keep the range_expression shape with the endpoint inside an issue.
128
+ const nonportableRangeClasses = ["character_class", "equivalence_class"];
129
+
130
+ function rangeOperator($) {
131
+ return field(
132
+ "operator",
133
+ namedExternal($, $._regex_bracket_hyphen, "range_operator"),
134
+ );
135
+ }
136
+
137
+ function nonportableRangeRules() {
138
+ const rules = {};
139
+ for (const kind of nonportableRangeClasses) {
140
+ rules[`_${kind}_start_range`] = ($) =>
141
+ seq(
142
+ field("start", issueNode($, `${kind}_range_start`)),
143
+ rangeOperator($),
144
+ );
145
+ }
146
+ for (const kind of nonportableRangeClasses) {
147
+ rules[`_${kind}_end_range`] = ($) =>
148
+ field("term", issueNode($, `${kind}_range_end`));
149
+ }
150
+ return rules;
151
+ }
152
+
126
153
  function bracketRules() {
127
154
  return {
128
155
  bracket_expression: ($) => bracketExpression($, false),
@@ -193,8 +220,9 @@ function bracketRules() {
193
220
  "start",
194
221
  choice(
195
222
  $.start_range,
196
- alias($._character_class_start_range, $.start_range),
197
- alias($._equivalence_class_start_range, $.start_range),
223
+ ...nonportableRangeClasses.map((kind) =>
224
+ alias($[`_${kind}_start_range`], $.start_range),
225
+ ),
198
226
  ),
199
227
  ),
200
228
  choice(
@@ -202,8 +230,9 @@ function bracketRules() {
202
230
  "end",
203
231
  choice(
204
232
  $.end_range,
205
- alias($._character_class_end_range, $.end_range),
206
- alias($._equivalence_class_end_range, $.end_range),
233
+ ...nonportableRangeClasses.map((kind) =>
234
+ alias($[`_${kind}_end_range`], $.end_range),
235
+ ),
207
236
  ),
208
237
  ),
209
238
  field(
@@ -217,38 +246,9 @@ function bracketRules() {
217
246
  ),
218
247
  ),
219
248
 
220
- _character_class_start_range: ($) =>
221
- seq(
222
- field("start", issueNode($, "character_class_range_start")),
223
- field(
224
- "operator",
225
- namedExternal($, $._regex_bracket_hyphen, "range_operator"),
226
- ),
227
- ),
228
-
229
- _equivalence_class_start_range: ($) =>
230
- seq(
231
- field("start", issueNode($, "equivalence_class_range_start")),
232
- field(
233
- "operator",
234
- namedExternal($, $._regex_bracket_hyphen, "range_operator"),
235
- ),
236
- ),
237
-
238
- _character_class_end_range: ($) =>
239
- field("term", issueNode($, "character_class_range_end")),
249
+ ...nonportableRangeRules(),
240
250
 
241
- _equivalence_class_end_range: ($) =>
242
- field("term", issueNode($, "equivalence_class_range_end")),
243
-
244
- start_range: ($) =>
245
- seq(
246
- field("start", $.end_range),
247
- field(
248
- "operator",
249
- namedExternal($, $._regex_bracket_hyphen, "range_operator"),
250
- ),
251
- ),
251
+ start_range: ($) => seq(field("start", $.end_range), rangeOperator($)),
252
252
 
253
253
  end_range: ($) =>
254
254
  choice(