tree-sitter-sed 0.11.0 → 0.13.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.11.0"
13
+ version = "0.13.0"
14
14
 
15
15
  build = "bindings/rust/build.rs"
16
16
  include = [
@@ -10,8 +10,9 @@ fn compile_parser(
10
10
  let mut c_config = cc::Build::new();
11
11
  c_config.std("c17").include(source_dir);
12
12
 
13
- #[cfg(target_env = "msvc")]
14
- c_config.flag("-utf-8");
13
+ if c_config.get_compiler().is_like_msvc() {
14
+ c_config.flag("-utf-8");
15
+ }
15
16
 
16
17
  if let Some(headers) = wasm_headers {
17
18
  c_config.include(headers);
@@ -426,27 +426,86 @@ mod tests {
426
426
  {
427
427
  let mut parser = tree_sitter::Parser::new();
428
428
  parser.set_language(&language.into()).unwrap();
429
- for (name, source, start, row, column, normal_kind, allow_replacement) in [
429
+ for (name, source, start, row, column, normal_nodes, allow_replacement) in [
430
430
  (
431
431
  "initial comment text",
432
432
  &b"#xn\np\n"[..],
433
433
  1,
434
434
  0,
435
435
  1,
436
- "comment_text",
436
+ ("comment_text", None),
437
+ true,
438
+ ),
439
+ (
440
+ "label definition",
441
+ &b":axb\np\n"[..],
442
+ 2,
443
+ 0,
444
+ 2,
445
+ ("label_literal", Some("label")),
446
+ true,
447
+ ),
448
+ (
449
+ "branch label",
450
+ &b"b axb\np\n"[..],
451
+ 3,
452
+ 0,
453
+ 3,
454
+ ("label_literal", Some("label")),
455
+ true,
456
+ ),
457
+ (
458
+ "test label",
459
+ &b"t axb\np\n"[..],
460
+ 3,
461
+ 0,
462
+ 3,
463
+ ("label_literal", Some("label")),
464
+ true,
465
+ ),
466
+ (
467
+ "rfile",
468
+ &b"r axb\np\n"[..],
469
+ 3,
470
+ 0,
471
+ 3,
472
+ ("file_literal", Some("rfile")),
473
+ true,
474
+ ),
475
+ (
476
+ "wfile",
477
+ &b"w axb\np\n"[..],
478
+ 3,
479
+ 0,
480
+ 3,
481
+ ("file_literal", Some("wfile")),
482
+ true,
483
+ ),
484
+ (
485
+ "substitution wfile",
486
+ &b"s/a/b/w axb\np\n"[..],
487
+ 9,
488
+ 0,
489
+ 9,
490
+ ("file_literal", Some("wfile")),
491
+ true,
492
+ ),
493
+ (
494
+ "text",
495
+ &b"a\\\naxb\np\n"[..],
496
+ 4,
497
+ 1,
498
+ 1,
499
+ ("text_literal", None),
437
500
  true,
438
501
  ),
439
- ("label", &b": axb\np\n"[..], 3, 0, 3, "label", true),
440
- ("rfile", &b"r axb\np\n"[..], 3, 0, 3, "rfile", true),
441
- ("wfile", &b"w axb\np\n"[..], 3, 0, 3, "wfile", true),
442
- ("text", &b"a\\\naxb\np\n"[..], 4, 1, 1, "text_literal", true),
443
502
  (
444
503
  "replacement",
445
504
  &b"s/a/axb/\np\n"[..],
446
505
  5,
447
506
  0,
448
507
  5,
449
- "replacement_literal",
508
+ ("replacement_literal", None),
450
509
  true,
451
510
  ),
452
511
  (
@@ -455,7 +514,7 @@ mod tests {
455
514
  3,
456
515
  0,
457
516
  3,
458
- "translation_literal",
517
+ ("translation_literal", None),
459
518
  true,
460
519
  ),
461
520
  (
@@ -464,7 +523,7 @@ mod tests {
464
523
  7,
465
524
  0,
466
525
  7,
467
- "translation_literal",
526
+ ("translation_literal", None),
468
527
  true,
469
528
  ),
470
529
  (
@@ -473,7 +532,7 @@ mod tests {
473
532
  5,
474
533
  1,
475
534
  2,
476
- "text_backslash_escape",
535
+ ("text_backslash_escape", None),
477
536
  false,
478
537
  ),
479
538
  (
@@ -482,7 +541,7 @@ mod tests {
482
541
  6,
483
542
  0,
484
543
  6,
485
- "replacement_escape",
544
+ ("replacement_escape", None),
486
545
  false,
487
546
  ),
488
547
  (
@@ -491,7 +550,7 @@ mod tests {
491
550
  4,
492
551
  0,
493
552
  4,
494
- "translation_escape",
553
+ ("translation_escape", None),
495
554
  false,
496
555
  ),
497
556
  (
@@ -500,7 +559,7 @@ mod tests {
500
559
  8,
501
560
  0,
502
561
  8,
503
- "translation_escape",
562
+ ("translation_escape", None),
504
563
  false,
505
564
  ),
506
565
  (
@@ -509,7 +568,7 @@ mod tests {
509
568
  2,
510
569
  0,
511
570
  2,
512
- "ordinary_character",
571
+ ("ordinary_character", None),
513
572
  true,
514
573
  ),
515
574
  (
@@ -518,7 +577,7 @@ mod tests {
518
577
  3,
519
578
  0,
520
579
  3,
521
- "collating_element",
580
+ ("collating_element", None),
522
581
  true,
523
582
  ),
524
583
  (
@@ -527,7 +586,7 @@ mod tests {
527
586
  5,
528
587
  0,
529
588
  5,
530
- "coll_elem_multi",
589
+ ("coll_elem_multi", None),
531
590
  true,
532
591
  ),
533
592
  (
@@ -536,7 +595,7 @@ mod tests {
536
595
  5,
537
596
  0,
538
597
  5,
539
- "coll_elem_multi",
598
+ ("coll_elem_multi", None),
540
599
  true,
541
600
  ),
542
601
  (
@@ -545,16 +604,25 @@ mod tests {
545
604
  5,
546
605
  0,
547
606
  5,
548
- "class_name",
607
+ ("class_name", None),
549
608
  false,
550
609
  ),
551
610
  ] {
552
- for invalid in [&b"\xff"[..], &b"\xff\xfe"[..]] {
611
+ let (normal_kind, owner_kind) = normal_nodes;
612
+ let mut invalid_inputs = vec![&b"\xff"[..], &b"\xff\xfe"[..]];
613
+ if owner_kind.is_some() {
614
+ invalid_inputs.extend([&b"\0"[..], &b"\xff\0\xfe"[..]]);
615
+ }
616
+ for invalid in invalid_inputs {
553
617
  let mut tree = parser.parse(source, None).unwrap();
554
618
  assert!(!tree.root_node().has_error(), "{mode}, {name}");
555
619
  assert!(issue_signatures(&tree).is_empty(), "{mode}, {name}");
556
620
  let mut old_length = 1;
557
- let mut replacements = vec![invalid, &source[start..start + 1]];
621
+ let mut replacements = vec![invalid];
622
+ if owner_kind.is_some() {
623
+ replacements.push(&b""[..]);
624
+ }
625
+ replacements.push(&source[start..start + 1]);
558
626
  if allow_replacement {
559
627
  replacements.push("\u{fffd}".as_bytes());
560
628
  }
@@ -585,23 +653,83 @@ mod tests {
585
653
  };
586
654
  let expected: Vec<_> = ranges
587
655
  .iter()
588
- .map(|range| {
589
- (
590
- "invalid_syntax".to_owned(),
591
- "invalid_encoding".to_owned(),
592
- *range,
593
- )
656
+ .zip(invalid)
657
+ .map(|(range, byte)| {
658
+ let (outcome, reason) = if *byte == 0 {
659
+ ("nonconforming_syntax", "nul_character")
660
+ } else {
661
+ ("invalid_syntax", "invalid_encoding")
662
+ };
663
+ (outcome.to_owned(), reason.to_owned(), *range)
594
664
  })
595
665
  .collect();
666
+ let encoding_ranges: Vec<_> = expected
667
+ .iter()
668
+ .filter(|(_, reason, _)| reason == "invalid_encoding")
669
+ .map(|(_, _, range)| *range)
670
+ .collect();
596
671
  let context =
597
672
  format!("{mode}, {name}, invalid {invalid:?}, step {step}");
598
673
  for parsed in [&fresh, &incremental] {
599
674
  assert!(!parsed.root_node().has_error(), "{context}");
600
675
  assert_eq!(issue_signatures(parsed), expected, "{context}");
601
- assert_invalid_encoding_leaves(parsed, &ranges, &context);
676
+ assert_invalid_encoding_leaves(
677
+ parsed,
678
+ &encoding_ranges,
679
+ &context,
680
+ );
602
681
  let mut nodes = vec![parsed.root_node()];
603
682
  let mut repaired_leaf = false;
683
+ let mut owners = 0;
604
684
  while let Some(node) = nodes.pop() {
685
+ if Some(node.kind()) == owner_kind {
686
+ owners += 1;
687
+ let owner_range = Range {
688
+ start_byte: start - 1,
689
+ end_byte: start + replacement.len() + 1,
690
+ start_point: Point::new(row, column - 1),
691
+ end_point: Point::new(row, column + replacement.len() + 1),
692
+ };
693
+ assert_eq!(node.range(), owner_range, "{context}");
694
+ let expected_children = if step == 0 {
695
+ let mut children = vec![(
696
+ normal_kind,
697
+ Range {
698
+ end_byte: start,
699
+ end_point: Point::new(row, column),
700
+ ..owner_range
701
+ },
702
+ )];
703
+ children.extend(
704
+ ranges.iter().map(|range| ("syntax_issue", *range)),
705
+ );
706
+ children.push((
707
+ normal_kind,
708
+ Range {
709
+ start_byte: start + replacement.len(),
710
+ start_point: Point::new(
711
+ row,
712
+ column + replacement.len(),
713
+ ),
714
+ ..owner_range
715
+ },
716
+ ));
717
+ children
718
+ } else {
719
+ vec![(normal_kind, owner_range)]
720
+ };
721
+ let children: Vec<_> = (0..node.child_count())
722
+ .map(|index| {
723
+ let child = node.child(index).unwrap();
724
+ assert!(child.is_named(), "{context}");
725
+ if child.kind() == normal_kind {
726
+ assert_eq!(child.child_count(), 0, "{context}");
727
+ }
728
+ (child.kind(), child.range())
729
+ })
730
+ .collect();
731
+ assert_eq!(children, expected_children, "{context}");
732
+ }
605
733
  if name == "initial comment text" {
606
734
  assert_ne!(
607
735
  node.kind(),
@@ -624,6 +752,9 @@ mod tests {
624
752
  if step > 0 {
625
753
  assert!(repaired_leaf, "{context}: normal leaf must return");
626
754
  }
755
+ if owner_kind.is_some() {
756
+ assert_eq!(owners, 1, "{context}: operand must have one owner");
757
+ }
627
758
  }
628
759
  assert_eq!(
629
760
  incremental.root_node().to_sexp(),
package/common/grammar.js CHANGED
@@ -32,13 +32,13 @@ function lineOperand($, first, rest) {
32
32
  return prec.right(
33
33
  seq(
34
34
  choice(
35
- first,
35
+ namedExternal($, first, "file_literal"),
36
36
  issueField($, "nul_character"),
37
37
  issueField($, "invalid_encoding"),
38
38
  ),
39
39
  repeat(
40
40
  choice(
41
- rest,
41
+ namedExternal($, rest, "file_literal"),
42
42
  issueField($, "nul_character"),
43
43
  issueField($, "invalid_encoding"),
44
44
  ),
@@ -718,7 +718,7 @@ function functionRules() {
718
718
  prec.right(
719
719
  repeat1(
720
720
  choice(
721
- $._line_word,
721
+ namedExternal($, $._line_word, "label_literal"),
722
722
  issueField($, "nul_character"),
723
723
  issueField($, "invalid_encoding"),
724
724
  ),
@@ -746,7 +746,7 @@ function functionRules() {
746
746
  field("closing", $.closing_brace),
747
747
  issueField($, "missing_closing_brace"),
748
748
  ),
749
- optional($._blanks),
749
+ optional($._block_trailing_blanks),
750
750
  ],
751
751
  text: ($) => [
752
752
  choice(
@@ -1651,6 +1651,7 @@ function externalTokens($, mode) {
1651
1651
  $._line_word,
1652
1652
  $._argument_separator,
1653
1653
  $._right_brace,
1654
+ $._block_trailing_blanks,
1654
1655
  $._empty_command_marker,
1655
1656
  $._reserved_unknown_function_token,
1656
1657
  $._regex_incomplete_group,
package/common/scanner.h CHANGED
@@ -126,6 +126,7 @@ enum TokenType {
126
126
  LINE_WORD,
127
127
  ARGUMENT_SEPARATOR,
128
128
  RIGHT_BRACE,
129
+ BLOCK_TRAILING_BLANKS,
129
130
  EMPTY_COMMAND_MARKER,
130
131
  RESERVED_UNKNOWN_FUNCTION_TOKEN,
131
132
  REGEX_INCOMPLETE_GROUP,
@@ -2344,6 +2345,13 @@ static bool scan_command_token(
2344
2345
  const bool *valid_symbols,
2345
2346
  TSSymbol *symbol
2346
2347
  ) {
2348
+ if (valid_symbols[BLOCK_TRAILING_BLANKS] && is_blank(lexer->lookahead)) {
2349
+ advance_past_blanks(lexer);
2350
+ lexer->mark_end(lexer);
2351
+ *symbol = BLOCK_TRAILING_BLANKS;
2352
+ return true;
2353
+ }
2354
+
2347
2355
  if (
2348
2356
  valid_symbols[EMPTY_COMMAND_MARKER] &&
2349
2357
  (lexer->lookahead == ';' || lexer->lookahead == '\n')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-sed",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "description": "Tree-sitter grammars for POSIX sed.",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "tree-sitter.json"
24
24
  ],
25
25
  "scripts": {
26
- "check": "biome check . && node scripts/check-c.js && cargo fmt --check && cargo clippy --all-targets --locked -- -D warnings && node scripts/check-generated.js && npm test",
26
+ "check": "biome check . && node scripts/check-c.js && cargo fmt --check && cargo check --all-targets --locked && cargo clippy --all-targets --locked -- -D warnings && node scripts/check-generated.js && npm test",
27
27
  "format": "biome check --write . && node scripts/check-c.js --write && cargo fmt",
28
28
  "generate": "npm run tree-sitter -- generate-all",
29
29
  "parse": "npm run tree-sitter -- parse --scope source.sed",
@@ -41,7 +41,7 @@
41
41
  (text_escaped_newline)
42
42
  ] @punctuation.special
43
43
 
44
- (label) @label
44
+ (label_literal) @label
45
45
 
46
46
  (last_line_address) @constant.builtin
47
47
 
@@ -57,10 +57,7 @@
57
57
  (replacement_backreference)
58
58
  ] @string.special.symbol
59
59
 
60
- [
61
- (rfile)
62
- (wfile)
63
- ] @string.special.path
60
+ (file_literal) @string.special.path
64
61
 
65
62
  [
66
63
  (back_close_brace)
@@ -42,7 +42,7 @@
42
42
  (text_escaped_newline)
43
43
  ] @punctuation.special
44
44
 
45
- (label) @label
45
+ (label_literal) @label
46
46
 
47
47
  (last_line_address) @constant.builtin
48
48
 
@@ -57,10 +57,7 @@
57
57
  (replacement_backreference)
58
58
  ] @string.special.symbol
59
59
 
60
- [
61
- (rfile)
62
- (wfile)
63
- ] @string.special.path
60
+ (file_literal) @string.special.path
64
61
 
65
62
  [
66
63
  (close_brace)
@@ -2910,8 +2910,13 @@
2910
2910
  "type": "CHOICE",
2911
2911
  "members": [
2912
2912
  {
2913
- "type": "SYMBOL",
2914
- "name": "_file_argument"
2913
+ "type": "ALIAS",
2914
+ "content": {
2915
+ "type": "SYMBOL",
2916
+ "name": "_file_argument"
2917
+ },
2918
+ "named": true,
2919
+ "value": "file_literal"
2915
2920
  },
2916
2921
  {
2917
2922
  "type": "FIELD",
@@ -2947,8 +2952,13 @@
2947
2952
  "type": "CHOICE",
2948
2953
  "members": [
2949
2954
  {
2950
- "type": "SYMBOL",
2951
- "name": "_line_word"
2955
+ "type": "ALIAS",
2956
+ "content": {
2957
+ "type": "SYMBOL",
2958
+ "name": "_line_word"
2959
+ },
2960
+ "named": true,
2961
+ "value": "file_literal"
2952
2962
  },
2953
2963
  {
2954
2964
  "type": "FIELD",
@@ -2992,8 +3002,13 @@
2992
3002
  "type": "CHOICE",
2993
3003
  "members": [
2994
3004
  {
2995
- "type": "SYMBOL",
2996
- "name": "_file_argument"
3005
+ "type": "ALIAS",
3006
+ "content": {
3007
+ "type": "SYMBOL",
3008
+ "name": "_file_argument"
3009
+ },
3010
+ "named": true,
3011
+ "value": "file_literal"
2997
3012
  },
2998
3013
  {
2999
3014
  "type": "FIELD",
@@ -3029,8 +3044,13 @@
3029
3044
  "type": "CHOICE",
3030
3045
  "members": [
3031
3046
  {
3032
- "type": "SYMBOL",
3033
- "name": "_line_word"
3047
+ "type": "ALIAS",
3048
+ "content": {
3049
+ "type": "SYMBOL",
3050
+ "name": "_line_word"
3051
+ },
3052
+ "named": true,
3053
+ "value": "file_literal"
3034
3054
  },
3035
3055
  {
3036
3056
  "type": "FIELD",
@@ -3074,8 +3094,13 @@
3074
3094
  "type": "CHOICE",
3075
3095
  "members": [
3076
3096
  {
3077
- "type": "SYMBOL",
3078
- "name": "_substitution_wfile_argument"
3097
+ "type": "ALIAS",
3098
+ "content": {
3099
+ "type": "SYMBOL",
3100
+ "name": "_substitution_wfile_argument"
3101
+ },
3102
+ "named": true,
3103
+ "value": "file_literal"
3079
3104
  },
3080
3105
  {
3081
3106
  "type": "FIELD",
@@ -3111,8 +3136,13 @@
3111
3136
  "type": "CHOICE",
3112
3137
  "members": [
3113
3138
  {
3114
- "type": "SYMBOL",
3115
- "name": "_substitution_wfile_continuation"
3139
+ "type": "ALIAS",
3140
+ "content": {
3141
+ "type": "SYMBOL",
3142
+ "name": "_substitution_wfile_continuation"
3143
+ },
3144
+ "named": true,
3145
+ "value": "file_literal"
3116
3146
  },
3117
3147
  {
3118
3148
  "type": "FIELD",
@@ -3155,8 +3185,13 @@
3155
3185
  "type": "CHOICE",
3156
3186
  "members": [
3157
3187
  {
3158
- "type": "SYMBOL",
3159
- "name": "_line_word"
3188
+ "type": "ALIAS",
3189
+ "content": {
3190
+ "type": "SYMBOL",
3191
+ "name": "_line_word"
3192
+ },
3193
+ "named": true,
3194
+ "value": "label_literal"
3160
3195
  },
3161
3196
  {
3162
3197
  "type": "FIELD",
@@ -3519,7 +3554,7 @@
3519
3554
  "members": [
3520
3555
  {
3521
3556
  "type": "SYMBOL",
3522
- "name": "_blanks"
3557
+ "name": "_block_trailing_blanks"
3523
3558
  },
3524
3559
  {
3525
3560
  "type": "BLANK"
@@ -10442,6 +10477,10 @@
10442
10477
  "type": "SYMBOL",
10443
10478
  "name": "_right_brace"
10444
10479
  },
10480
+ {
10481
+ "type": "SYMBOL",
10482
+ "name": "_block_trailing_blanks"
10483
+ },
10445
10484
  {
10446
10485
  "type": "SYMBOL",
10447
10486
  "name": "_empty_command_marker"
@@ -1739,6 +1739,16 @@
1739
1739
  }
1740
1740
  ]
1741
1741
  }
1742
+ },
1743
+ "children": {
1744
+ "multiple": true,
1745
+ "required": false,
1746
+ "types": [
1747
+ {
1748
+ "type": "label_literal",
1749
+ "named": true
1750
+ }
1751
+ ]
1742
1752
  }
1743
1753
  },
1744
1754
  {
@@ -2450,6 +2460,16 @@
2450
2460
  }
2451
2461
  ]
2452
2462
  }
2463
+ },
2464
+ "children": {
2465
+ "multiple": true,
2466
+ "required": false,
2467
+ "types": [
2468
+ {
2469
+ "type": "file_literal",
2470
+ "named": true
2471
+ }
2472
+ ]
2453
2473
  }
2454
2474
  },
2455
2475
  {
@@ -3183,6 +3203,16 @@
3183
3203
  }
3184
3204
  ]
3185
3205
  }
3206
+ },
3207
+ "children": {
3208
+ "multiple": true,
3209
+ "required": false,
3210
+ "types": [
3211
+ {
3212
+ "type": "file_literal",
3213
+ "named": true
3214
+ }
3215
+ ]
3186
3216
  }
3187
3217
  },
3188
3218
  {
@@ -3359,6 +3389,10 @@
3359
3389
  "type": "delimiter",
3360
3390
  "named": true
3361
3391
  },
3392
+ {
3393
+ "type": "file_literal",
3394
+ "named": true
3395
+ },
3362
3396
  {
3363
3397
  "type": "function_verb",
3364
3398
  "named": true
@@ -3371,6 +3405,10 @@
3371
3405
  "type": "interval_separator",
3372
3406
  "named": true
3373
3407
  },
3408
+ {
3409
+ "type": "label_literal",
3410
+ "named": true
3411
+ },
3374
3412
  {
3375
3413
  "type": "last_line_address",
3376
3414
  "named": true