tree-sitter-sed 0.4.0 → 0.6.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/CMakeLists.txt CHANGED
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
2
2
 
3
3
  project(
4
4
  tree-sitter-sed
5
- VERSION 0.4.0
5
+ VERSION 0.6.0
6
6
  DESCRIPTION "Tree-sitter grammars for POSIX sed."
7
7
  HOMEPAGE_URL "https://github.com/konomanoasa/tree-sitter-sed"
8
8
  LANGUAGES C
package/Makefile CHANGED
@@ -1,6 +1,6 @@
1
1
  LANGUAGE_NAME := tree-sitter-sed
2
2
  HOMEPAGE_URL := https://github.com/konomanoasa/tree-sitter-sed
3
- VERSION := 0.4.0
3
+ VERSION := 0.6.0
4
4
  DESCRIPTION := Tree-sitter grammars for POSIX sed.
5
5
 
6
6
  PREFIX ?= /usr/local
package/README.md CHANGED
@@ -16,10 +16,18 @@ npm install tree-sitter-sed
16
16
 
17
17
  This repository contains the following two grammars.
18
18
 
19
- | Grammar | Regexp | C function |
20
- | --------- | ------ | ----------------------- |
21
- | `sed` | BRE | `tree_sitter_sed()` |
22
- | `sed_ere` | ERE | `tree_sitter_sed_ere()` |
19
+ | Grammar | Regexp | C function | Rust constant |
20
+ | --------- | ------ | ----------------------- | -------------- |
21
+ | `sed` | BRE | `tree_sitter_sed()` | `LANGUAGE` |
22
+ | `sed_ere` | ERE | `tree_sitter_sed_ere()` | `LANGUAGE_ERE` |
23
+
24
+ ## Development
25
+
26
+ ```sh
27
+ npm install
28
+ npm run parse -- script.sed
29
+ npm run parse:ere -- script.sed
30
+ ```
23
31
 
24
32
  ## Specifications
25
33
 
package/common/grammar.js CHANGED
@@ -551,29 +551,17 @@ function operandRules(mode) {
551
551
  }
552
552
 
553
553
  return {
554
- _substitute_function_without_write: ($) =>
554
+ _substitute_function: ($) =>
555
555
  choice(
556
556
  seq(
557
557
  $._complete_substitute_function,
558
558
  optional(
559
- field(
560
- "flags",
561
- alias($._substitution_flags_without_write, $.substitution_flags),
562
- ),
559
+ field("flags", alias($._substitution_flags, $.substitution_flags)),
563
560
  ),
564
561
  ),
565
562
  $._incomplete_substitute_function,
566
563
  ),
567
564
 
568
- _substitute_function_with_write: ($) =>
569
- seq(
570
- $._complete_substitute_function,
571
- field(
572
- "flags",
573
- alias($._substitution_flags_with_write, $.substitution_flags),
574
- ),
575
- ),
576
-
577
565
  _complete_substitute_function: ($) =>
578
566
  seq(
579
567
  functionVerb($, "s"),
@@ -659,6 +647,12 @@ function operandRules(mode) {
659
647
  escaped_newline: ($) =>
660
648
  namedExternal($, $._replacement_escaped_newline, "escaped_newline_token"),
661
649
 
650
+ _substitution_flags: ($) =>
651
+ choice(
652
+ $._substitution_flags_without_write,
653
+ seq(optional($._substitution_flags_without_write), $.write_flag),
654
+ ),
655
+
662
656
  _substitution_flags_without_write: ($) =>
663
657
  choice(
664
658
  substitutionFlagChoice($),
@@ -667,9 +661,6 @@ function operandRules(mode) {
667
661
  ),
668
662
  ),
669
663
 
670
- _substitution_flags_with_write: ($) =>
671
- seq(optional($._substitution_flags_without_write), $.write_flag),
672
-
673
664
  occurrence_flag: () => /[[:digit:]]+/,
674
665
 
675
666
  global_flag: () => "g",
@@ -684,8 +675,7 @@ function operandRules(mode) {
684
675
  choice(
685
676
  seq(
686
677
  $._flag_after_write_marker,
687
- issueField($, "flag_after_write_flag"),
688
- repeat(postWriteSubstitutionFlagChoice($)),
678
+ repeat1(postWriteSubstitutionFlagChoice($)),
689
679
  $._blanks,
690
680
  choice(
691
681
  field("wfile", alias($._substitution_wfile, $.wfile)),
@@ -955,39 +945,19 @@ function editingCommandRules() {
955
945
 
956
946
  _line_terminated_editing_command: ($) =>
957
947
  seq(
958
- choice(
959
- $._line_terminated_regular_editing_command_body,
960
- $._line_terminated_substitute_editing_command_body,
961
- ),
948
+ addressedForms($, lineTerminated, "line_terminated"),
962
949
  optional(issueField($, "unexpected_command_text")),
963
950
  ),
964
951
 
965
952
  _recovered_line_terminated_editing_command: ($) =>
966
- choice(
967
- prec.right(
968
- seq(
969
- $._line_terminated_regular_editing_command_body,
970
- optional(issueField($, "unexpected_command_text")),
971
- issueField($, "forbidden_command_separator"),
972
- optional($._blanks),
973
- ),
974
- ),
975
- prec.right(
976
- seq(
977
- $._line_terminated_substitute_editing_command_body,
978
- optional(issueField($, "unexpected_command_text")),
979
- issueField($, "command_after_write_flag"),
980
- optional($._blanks),
981
- ),
953
+ prec.right(
954
+ seq(
955
+ $._line_terminated_editing_command,
956
+ issueField($, "forbidden_command_separator"),
957
+ optional($._blanks),
982
958
  ),
983
959
  ),
984
960
 
985
- _line_terminated_regular_editing_command_body: ($) =>
986
- addressedForms($, lineTerminated, "line_terminated"),
987
-
988
- _line_terminated_substitute_editing_command_body: ($) =>
989
- addressedFunction($, $._line_terminated_substitute_function),
990
-
991
961
  _recovered_editing_command: ($) =>
992
962
  choice(
993
963
  addressedFunction($, $._unknown_function),
@@ -1034,10 +1004,7 @@ function editingCommandRules() {
1034
1004
  _missing_function: ($) => missingAtEndOrBoundary($, "missing_function"),
1035
1005
 
1036
1006
  _chainable_substitute_function: ($) =>
1037
- alias($._substitute_function_without_write, $.substitute_function),
1038
-
1039
- _line_terminated_substitute_function: ($) =>
1040
- alias($._substitute_function_with_write, $.substitute_function),
1007
+ alias($._substitute_function, $.substitute_function),
1041
1008
 
1042
1009
  negation: ($) =>
1043
1010
  seq(
@@ -1250,16 +1217,6 @@ function issueDefinitions(mode) {
1250
1217
  outcome: "undefined_syntax",
1251
1218
  rule: ($) => $._translate_nonportable_escape,
1252
1219
  },
1253
- {
1254
- reason: "command_after_write_flag",
1255
- outcome: "undefined_syntax",
1256
- rule: () => token.immediate(";"),
1257
- },
1258
- {
1259
- reason: "flag_after_write_flag",
1260
- outcome: "undefined_syntax",
1261
- rule: ($) => postWriteSubstitutionFlagChoice($),
1262
- },
1263
1220
  {
1264
1221
  reason: "equivalence_class_range_start",
1265
1222
  outcome: "unspecified_syntax",
package/common/regex.js CHANGED
@@ -64,24 +64,21 @@ function intervalExpression($, openingName, closingName) {
64
64
  function compoundBracketExpression(
65
65
  $,
66
66
  openingExternal,
67
- openingName,
67
+ marker,
68
68
  contentField,
69
69
  content,
70
70
  closingExternal,
71
- closingName,
72
71
  ) {
73
- const closing = namedExternal($, closingExternal, closingName);
72
+ const closing = seq(alias(closingExternal, marker), "]");
74
73
  return seq(
75
- field("opening", namedExternal($, openingExternal, openingName)),
74
+ alias(openingExternal, "["),
75
+ marker,
76
76
  choice(
77
77
  seq(
78
78
  field(contentField, content),
79
79
  choice(
80
- field("closing", closing),
81
- seq(
82
- issueField($, "malformed_bracket_term"),
83
- optional(field("closing", closing)),
84
- ),
80
+ closing,
81
+ seq(issueField($, "malformed_bracket_term"), optional(closing)),
85
82
  issueField($, "incomplete_bracket_term"),
86
83
  ),
87
84
  ),
@@ -90,7 +87,7 @@ function compoundBracketExpression(
90
87
  issueField($, "malformed_bracket_term"),
91
88
  issueField($, "incomplete_bracket_term"),
92
89
  ),
93
- optional(field("closing", closing)),
90
+ optional(closing),
94
91
  ),
95
92
  ),
96
93
  );
@@ -255,7 +252,7 @@ function bracketRules() {
255
252
  compoundBracketExpression(
256
253
  $,
257
254
  $._regex_open_dot,
258
- "open_dot",
255
+ ".",
259
256
  "element",
260
257
  choice(
261
258
  namedExternal($, $._regex_coll_elem_single, "coll_elem_single"),
@@ -263,32 +260,29 @@ function bracketRules() {
263
260
  namedExternal($, $._regex_meta_char, "meta_char"),
264
261
  ),
265
262
  $._regex_dot_close,
266
- "dot_close",
267
263
  ),
268
264
 
269
265
  equivalence_class: ($) =>
270
266
  compoundBracketExpression(
271
267
  $,
272
268
  $._regex_open_equal,
273
- "open_equal",
269
+ "=",
274
270
  "element",
275
271
  choice(
276
272
  namedExternal($, $._regex_coll_elem_single, "coll_elem_single"),
277
273
  namedExternal($, $._regex_coll_elem_multi, "coll_elem_multi"),
278
274
  ),
279
275
  $._regex_equal_close,
280
- "equal_close",
281
276
  ),
282
277
 
283
278
  character_class: ($) =>
284
279
  compoundBracketExpression(
285
280
  $,
286
281
  $._regex_open_colon,
287
- "open_colon",
282
+ ":",
288
283
  "name",
289
284
  namedExternal($, $._regex_class_name, "class_name"),
290
285
  $._regex_colon_close,
291
- "colon_close",
292
286
  ),
293
287
  };
294
288
  }
@@ -340,6 +334,14 @@ function breDuplicationSymbol($) {
340
334
  );
341
335
  }
342
336
 
337
+ function misplacedBreDuplSymbol($, reason) {
338
+ return choice(
339
+ seq(issueField($, reason), field("operator", $.bre_dupl_symbol)),
340
+ issueField($, "malformed_interval"),
341
+ issueField($, "incomplete_interval"),
342
+ );
343
+ }
344
+
343
345
  function breRules() {
344
346
  return {
345
347
  bre_extension_escape: ($) =>
@@ -483,24 +485,10 @@ function breRules() {
483
485
  intervalExpression($, "back_open_brace", "back_close_brace"),
484
486
 
485
487
  leading_bre_dupl_symbol: ($) =>
486
- choice(
487
- seq(
488
- issueField($, "leading_duplication_symbol"),
489
- field("operator", $.bre_dupl_symbol),
490
- ),
491
- issueField($, "malformed_interval"),
492
- issueField($, "incomplete_interval"),
493
- ),
488
+ misplacedBreDuplSymbol($, "leading_duplication_symbol"),
494
489
 
495
490
  adjacent_bre_dupl_symbol: ($) =>
496
- choice(
497
- seq(
498
- issueField($, "adjacent_duplication_symbol"),
499
- field("operator", $.bre_dupl_symbol),
500
- ),
501
- issueField($, "malformed_interval"),
502
- issueField($, "incomplete_interval"),
503
- ),
491
+ misplacedBreDuplSymbol($, "adjacent_duplication_symbol"),
504
492
  };
505
493
  }
506
494
 
package/common/scanner.h CHANGED
@@ -1234,7 +1234,6 @@ static bool scan_regex_bracket_opener(
1234
1234
  if (!valid_symbols[candidate]) {
1235
1235
  return false;
1236
1236
  }
1237
- consume(lexer);
1238
1237
  begin_compound_bracket_element(state);
1239
1238
  finish_first_bracket_element(state);
1240
1239
  state->regex_bracket_term_state = term_state;
@@ -1386,11 +1385,10 @@ static bool scan_regex_bracket_term_close(
1386
1385
  return false;
1387
1386
  }
1388
1387
 
1389
- advance(lexer);
1388
+ consume(lexer);
1390
1389
  if (lexer->lookahead != ']') {
1391
1390
  return false;
1392
1391
  }
1393
- consume(lexer);
1394
1392
  state->regex_bracket_term_state = REGEX_BRACKET_TERM_NONE;
1395
1393
  finish_compound_bracket_element(state);
1396
1394
  return emit_symbol(valid_symbols, candidate, symbol);
@@ -2851,16 +2849,26 @@ static bool scan_command_token(
2851
2849
  }
2852
2850
 
2853
2851
  if (at_command_boundary(lexer)) {
2854
- const TSSymbol first_marker = lexer->eof(lexer)
2855
- ? MISSING_FUNCTION_MARKER
2856
- : NONCONFORMING_MISSING_FUNCTION_MARKER;
2852
+ static const TSSymbol boundary_markers[][2] = {
2853
+ {MISSING_FUNCTION_MARKER, NONCONFORMING_MISSING_FUNCTION_MARKER},
2854
+ {MISSING_LABEL_MARKER, NONCONFORMING_MISSING_LABEL_MARKER},
2855
+ {MISSING_RFILE_MARKER, NONCONFORMING_MISSING_RFILE_MARKER},
2856
+ {MISSING_WFILE_MARKER, NONCONFORMING_MISSING_WFILE_MARKER},
2857
+ };
2858
+ const unsigned variant = lexer->eof(lexer) ? 0 : 1;
2857
2859
  for (
2858
- TSSymbol offset = 0;
2859
- offset <= MISSING_WFILE_MARKER - MISSING_FUNCTION_MARKER;
2860
- offset++
2860
+ unsigned index = 0;
2861
+ index < sizeof(boundary_markers) / sizeof(boundary_markers[0]);
2862
+ index++
2861
2863
  ) {
2862
- const TSSymbol marker = first_marker + offset;
2863
- if (emit_missing_marker(lexer, valid_symbols, marker, symbol)) {
2864
+ if (
2865
+ emit_missing_marker(
2866
+ lexer,
2867
+ valid_symbols,
2868
+ boundary_markers[index][variant],
2869
+ symbol
2870
+ )
2871
+ ) {
2864
2872
  return true;
2865
2873
  }
2866
2874
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-sed",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Tree-sitter grammars for POSIX sed.",
5
5
  "license": "MIT",
6
6
  "repository": "git+https://github.com/konomanoasa/tree-sitter-sed.git",
@@ -27,13 +27,15 @@
27
27
  "check": "biome check . && node scripts/check-c.js && node scripts/check-generated.js && npm test",
28
28
  "format": "biome check --write . && node scripts/check-c.js --write",
29
29
  "generate": "npm run tree-sitter -- generate-all",
30
+ "parse": "npm run tree-sitter -- parse --scope source.sed",
31
+ "parse:ere": "npm run tree-sitter -- parse --scope source.sed.ere",
30
32
  "test": "npm run tree-sitter -- test-corpus --rebuild && node --test",
31
33
  "test:fuzz": "npm run tree-sitter -- fuzz-all --iterations 100 --edits 5",
32
34
  "tree-sitter": "node scripts/tree-sitter.js"
33
35
  },
34
36
  "devDependencies": {
35
37
  "@biomejs/biome": "2.5.11",
36
- "tree-sitter-cli": "0.26.13"
38
+ "tree-sitter-cli": "0.27.0"
37
39
  },
38
40
  "allowScripts": {
39
41
  "tree-sitter-cli": true
@@ -65,11 +65,39 @@
65
65
  (back_open_parenthesis)
66
66
  (close_bracket_token)
67
67
  (closing_brace_token)
68
- (colon_close)
69
68
  (open_bracket)
70
- (open_colon)
71
69
  ] @punctuation.bracket
72
70
 
71
+ (character_class
72
+ "[" @punctuation.bracket
73
+ .
74
+ ":" @punctuation.delimiter)
75
+
76
+ (character_class
77
+ ":" @punctuation.delimiter
78
+ .
79
+ "]" @punctuation.bracket)
80
+
81
+ (collating_symbol
82
+ "[" @punctuation.bracket
83
+ .
84
+ "." @punctuation.delimiter)
85
+
86
+ (collating_symbol
87
+ "." @punctuation.delimiter
88
+ .
89
+ "]" @punctuation.bracket)
90
+
91
+ (equivalence_class
92
+ "[" @punctuation.bracket
93
+ .
94
+ "=" @punctuation.delimiter)
95
+
96
+ (equivalence_class
97
+ "=" @punctuation.delimiter
98
+ .
99
+ "]" @punctuation.bracket)
100
+
73
101
  [
74
102
  (nonmatching_list_operator)
75
103
  (range_operator)
@@ -85,11 +113,7 @@
85
113
  (coll_elem_multi)
86
114
  (coll_elem_single)
87
115
  (collating_element_token)
88
- (dot_close)
89
- (equal_close)
90
116
  (meta_char)
91
- (open_dot)
92
- (open_equal)
93
117
  (period_token)
94
118
  ] @character.special
95
119
 
@@ -63,13 +63,41 @@
63
63
  (close_bracket_token)
64
64
  (close_parenthesis_token)
65
65
  (closing_brace_token)
66
- (colon_close)
67
66
  (open_brace)
68
67
  (open_bracket)
69
- (open_colon)
70
68
  (open_parenthesis)
71
69
  ] @punctuation.bracket
72
70
 
71
+ (character_class
72
+ "[" @punctuation.bracket
73
+ .
74
+ ":" @punctuation.delimiter)
75
+
76
+ (character_class
77
+ ":" @punctuation.delimiter
78
+ .
79
+ "]" @punctuation.bracket)
80
+
81
+ (collating_symbol
82
+ "[" @punctuation.bracket
83
+ .
84
+ "." @punctuation.delimiter)
85
+
86
+ (collating_symbol
87
+ "." @punctuation.delimiter
88
+ .
89
+ "]" @punctuation.bracket)
90
+
91
+ (equivalence_class
92
+ "[" @punctuation.bracket
93
+ .
94
+ "=" @punctuation.delimiter)
95
+
96
+ (equivalence_class
97
+ "=" @punctuation.delimiter
98
+ .
99
+ "]" @punctuation.bracket)
100
+
73
101
  [
74
102
  (nonmatching_list_operator)
75
103
  (range_operator)
@@ -85,11 +113,7 @@
85
113
  (coll_elem_multi)
86
114
  (coll_elem_single)
87
115
  (collating_element_token)
88
- (dot_close)
89
- (equal_close)
90
116
  (meta_char)
91
- (open_dot)
92
- (open_equal)
93
117
  (period_token)
94
118
  ] @character.special
95
119