parseman 0.47.0 → 0.48.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.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2955 -357
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2946 -348
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +19 -1
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2959 -348
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +7 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2969 -358
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +366 -49
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +13 -14
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +4839 -2232
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +47 -4
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +53 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +12 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +82 -3
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +35 -16
  82. package/src/combinators/trivia-skip.ts +75 -11
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1224 -222
  91. package/src/table/child-slots.ts +4 -3
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +363 -109
  94. package/src/table/emit.ts +26 -1
  95. package/src/table/encode.ts +246 -54
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +140 -18
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +50 -4
  101. package/src/table/program.ts +67 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +13 -3
  104. package/src/table/stamp.ts +3 -3
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13736
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14837
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16303
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1302
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16009
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6188
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11375
  124. package/dist/table/index.cjs.map +0 -6
@@ -44,6 +44,13 @@ function empty() {
44
44
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
45
45
  if (seen.has(p)) return true;
46
46
  seen.add(p);
47
+ try {
48
+ return matchesEmptyBody(p, seen, resolve);
49
+ } finally {
50
+ seen.delete(p);
51
+ }
52
+ }
53
+ function matchesEmptyBody(p, seen, resolve) {
47
54
  const me = (c) => matchesEmpty(c, seen, resolve);
48
55
  const d = p._def;
49
56
  switch (d.tag) {
@@ -145,6 +152,13 @@ function sequenceFirstSet(parsers) {
145
152
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve) {
146
153
  if (seen.has(p)) return any();
147
154
  seen.add(p);
155
+ try {
156
+ return firstSetBody(p, seen, resolve);
157
+ } finally {
158
+ seen.delete(p);
159
+ }
160
+ }
161
+ function firstSetBody(p, seen, resolve) {
148
162
  const fs = (c) => firstSetOf(c, seen, resolve);
149
163
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
150
164
  const d = p._def;
@@ -803,6 +817,179 @@ function parseClassRanges(body) {
803
817
  return ranges.length ? ranges : null;
804
818
  }
805
819
 
820
+ // src/cst/trivia-css-scanner.ts
821
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
822
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
823
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
824
+ function scanWhitespace(input, cur) {
825
+ let pos = cur;
826
+ while (pos < input.length) {
827
+ const c = input.charCodeAt(pos);
828
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
829
+ pos++;
830
+ }
831
+ return pos;
832
+ }
833
+ function scanLineComment(input, cur) {
834
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
835
+ let pos = cur + 2;
836
+ while (pos < input.length) {
837
+ const c = input.charCodeAt(pos);
838
+ if (c === 10 || c === 13) break;
839
+ pos++;
840
+ }
841
+ return pos;
842
+ }
843
+ function scanBlockComment(input, cur) {
844
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
845
+ const close = input.indexOf("*/", cur + 2);
846
+ return close < 0 ? cur : close + 2;
847
+ }
848
+ function scanWsLineBlockTrivia(input, cur) {
849
+ let pos = cur;
850
+ for (; ; ) {
851
+ const ws = scanWhitespace(input, pos);
852
+ if (ws !== pos) {
853
+ pos = ws;
854
+ continue;
855
+ }
856
+ const line = scanLineComment(input, pos);
857
+ if (line !== pos) {
858
+ pos = line;
859
+ continue;
860
+ }
861
+ const block = scanBlockComment(input, pos);
862
+ if (block !== pos) {
863
+ pos = block;
864
+ continue;
865
+ }
866
+ return pos;
867
+ }
868
+ }
869
+ function scanWsBlockTrivia(input, cur) {
870
+ let pos = cur;
871
+ for (; ; ) {
872
+ const ws = scanWhitespace(input, pos);
873
+ if (ws !== pos) {
874
+ pos = ws;
875
+ continue;
876
+ }
877
+ const block = scanBlockComment(input, pos);
878
+ if (block !== pos) {
879
+ pos = block;
880
+ continue;
881
+ }
882
+ return pos;
883
+ }
884
+ }
885
+ function scanLineBlockTrivia(input, cur) {
886
+ let pos = cur;
887
+ for (; ; ) {
888
+ const line = scanLineComment(input, pos);
889
+ if (line !== pos) {
890
+ pos = line;
891
+ continue;
892
+ }
893
+ const block = scanBlockComment(input, pos);
894
+ if (block !== pos) {
895
+ pos = block;
896
+ continue;
897
+ }
898
+ return pos;
899
+ }
900
+ }
901
+ function scanBlockTrivia(input, cur) {
902
+ let pos = cur;
903
+ for (; ; ) {
904
+ const block = scanBlockComment(input, pos);
905
+ if (block === pos) return pos;
906
+ pos = block;
907
+ }
908
+ }
909
+ function visitWsLineBlock(input, cur, visit) {
910
+ let pos = cur;
911
+ for (; ; ) {
912
+ let end = scanWhitespace(input, pos);
913
+ if (end !== pos) {
914
+ visit(pos, end, 0);
915
+ pos = end;
916
+ continue;
917
+ }
918
+ end = scanLineComment(input, pos);
919
+ if (end !== pos) {
920
+ visit(pos, end, 1);
921
+ pos = end;
922
+ continue;
923
+ }
924
+ end = scanBlockComment(input, pos);
925
+ if (end !== pos) {
926
+ visit(pos, end, 2);
927
+ pos = end;
928
+ continue;
929
+ }
930
+ return pos;
931
+ }
932
+ }
933
+ function visitWsBlock(input, cur, visit) {
934
+ let pos = cur;
935
+ for (; ; ) {
936
+ let end = scanWhitespace(input, pos);
937
+ if (end !== pos) {
938
+ visit(pos, end, 0);
939
+ pos = end;
940
+ continue;
941
+ }
942
+ end = scanBlockComment(input, pos);
943
+ if (end !== pos) {
944
+ visit(pos, end, 1);
945
+ pos = end;
946
+ continue;
947
+ }
948
+ return pos;
949
+ }
950
+ }
951
+ function visitLineBlock(input, cur, visit) {
952
+ let pos = cur;
953
+ for (; ; ) {
954
+ let end = scanLineComment(input, pos);
955
+ if (end !== pos) {
956
+ visit(pos, end, 0);
957
+ pos = end;
958
+ continue;
959
+ }
960
+ end = scanBlockComment(input, pos);
961
+ if (end !== pos) {
962
+ visit(pos, end, 1);
963
+ pos = end;
964
+ continue;
965
+ }
966
+ return pos;
967
+ }
968
+ }
969
+ function visitBlock(input, cur, visit) {
970
+ let pos = cur;
971
+ for (; ; ) {
972
+ const end = scanBlockComment(input, pos);
973
+ if (end === pos) return pos;
974
+ visit(pos, end, 0);
975
+ pos = end;
976
+ }
977
+ }
978
+ function commonCssTriviaScanner(sources) {
979
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
980
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
981
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
982
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
983
+ return null;
984
+ }
985
+ function commonCssTriviaVisitor(sources) {
986
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
987
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
988
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
989
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
990
+ return null;
991
+ }
992
+
806
993
  // src/cst/trivia-charscan.ts
807
994
  function inRanges(cp, ranges) {
808
995
  for (let i = 0; i < ranges.length; i++) {
@@ -956,6 +1143,35 @@ function classifyParser(p) {
956
1143
  if (d.tag !== "regex" || d.flags) return null;
957
1144
  return classifyArm(d.source);
958
1145
  }
1146
+ function plainRegexSource(p) {
1147
+ const d = p._def;
1148
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1149
+ }
1150
+ var visitSpec0;
1151
+ var visitSpec1;
1152
+ var visitSpec2;
1153
+ var visitSpec3;
1154
+ var visitValue0;
1155
+ var visitValue1;
1156
+ var visitValue2;
1157
+ var visitValue3;
1158
+ function commonLabeledTriviaVisitor(spec) {
1159
+ if (spec === visitSpec0) return visitValue0;
1160
+ if (spec === visitSpec1) return visitValue1;
1161
+ if (spec === visitSpec2) return visitValue2;
1162
+ if (spec === visitSpec3) return visitValue3;
1163
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1164
+ const visitor = commonCssTriviaVisitor(sources);
1165
+ visitSpec3 = visitSpec2;
1166
+ visitValue3 = visitValue2;
1167
+ visitSpec2 = visitSpec1;
1168
+ visitValue2 = visitValue1;
1169
+ visitSpec1 = visitSpec0;
1170
+ visitValue1 = visitValue0;
1171
+ visitSpec0 = spec;
1172
+ visitValue0 = visitor;
1173
+ return visitor;
1174
+ }
959
1175
  var armSpec0;
960
1176
  var armSpec1;
961
1177
  var armSpec2;
@@ -1154,6 +1370,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1154
1370
  }
1155
1371
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1156
1372
  if (spec.minRepeats > 1) return void 0;
1373
+ const common = commonLabeledTriviaVisitor(spec);
1374
+ if (common !== null) return common(input, cur, visit);
1157
1375
  const chars = charArmsFor(spec);
1158
1376
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1159
1377
  let pos = cur;
@@ -1287,11 +1505,12 @@ function parser(opts, root) {
1287
1505
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1288
1506
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1289
1507
  const forceCaptureTrivia = opts.captureTrivia === true;
1290
- const trackLinesOf = opts.trackLines === true ? TRACK_LINES_ON : opts.trackLines === false ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1508
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
1509
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1291
1510
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1292
1511
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1293
1512
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1294
- return {
1513
+ const grammar = {
1295
1514
  _tag: "grammar",
1296
1515
  _meta: {
1297
1516
  ...root._meta,
@@ -1310,7 +1529,9 @@ function parser(opts, root) {
1310
1529
  clearTrivia,
1311
1530
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1312
1531
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1313
- trackLines: opts.trackLines ?? false
1532
+ trackLines: opts.trackLines ?? false,
1533
+ constructionTrackLines: trackLinesPolicy,
1534
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1314
1535
  },
1315
1536
  parse(input, pos, _ctx) {
1316
1537
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1339,6 +1560,7 @@ function parser(opts, root) {
1339
1560
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1340
1561
  }
1341
1562
  };
1563
+ return grammar;
1342
1564
  }
1343
1565
 
1344
1566
  // src/cst/reflection-symbols.ts
@@ -1817,6 +2039,21 @@ function firstSetFromRegex(source) {
1817
2039
  return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
1818
2040
  }
1819
2041
 
2042
+ // src/combinators/expected.ts
2043
+ function directTerminalFailureExpected(def) {
2044
+ switch (def.tag) {
2045
+ case "literal":
2046
+ return [JSON.stringify(def.value)];
2047
+ case "regex":
2048
+ return [`/${def.source}/`];
2049
+ case "keywords":
2050
+ return ["keyword"];
2051
+ }
2052
+ }
2053
+ function assertionFailureExpected(positive, childTag) {
2054
+ return [`${positive ? "peek" : "not"}(${childTag})`];
2055
+ }
2056
+
1820
2057
  // src/combinators/regex.ts
1821
2058
  var SCAN_BAIL_AT = 64;
1822
2059
  function inRanges2(cp, ranges) {
@@ -1888,14 +2125,15 @@ function regex(pattern, flags = "") {
1888
2125
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1889
2126
  const canMatchNewline = raw.canMatchNewline;
1890
2127
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2128
+ const def = { tag: "regex", source, flags: resolvedFlags };
1891
2129
  return {
1892
2130
  _tag: "regex",
1893
2131
  _meta: meta,
1894
- _def: { tag: "regex", source, flags: resolvedFlags },
2132
+ _def: def,
1895
2133
  parse(input, pos, ctx) {
1896
2134
  const scanEnd = scan?.(input, pos);
1897
2135
  if (scanEnd !== void 0) {
1898
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2136
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1899
2137
  const value = input.slice(pos, scanEnd);
1900
2138
  const span2 = { start: pos, end: scanEnd };
1901
2139
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1905,7 +2143,7 @@ function regex(pattern, flags = "") {
1905
2143
  anchored.lastIndex = pos;
1906
2144
  const m = anchored.exec(input);
1907
2145
  if (m === null) {
1908
- return failAt(ctx, [`/${source}/`], pos);
2146
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1909
2147
  }
1910
2148
  const span = { start: pos, end: pos + m[0].length };
1911
2149
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -1946,7 +2184,7 @@ function literal(value, opts = {}) {
1946
2184
  { lo: firstUpper, hi: firstUpper }
1947
2185
  ] } : firstSet2;
1948
2186
  }
1949
- const expected = [JSON.stringify(value)];
2187
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
1950
2188
  const parse = !caseInsensitive && value.length === 1 ? (() => {
1951
2189
  const code = value.charCodeAt(0);
1952
2190
  return function parse2(input, pos, ctx) {
@@ -2019,12 +2257,14 @@ function caseFoldVariants(cp) {
2019
2257
  function escapeRe(s) {
2020
2258
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2021
2259
  }
2260
+ function keywordsRegExp(words, boundary, caseInsensitive) {
2261
+ const alt = words.map(escapeRe).join("|");
2262
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
2263
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
2264
+ }
2022
2265
  function keywords(words, opts = {}) {
2023
2266
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2024
- const alt = sorted.map(escapeRe).join("|");
2025
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2026
- const flags = opts.caseInsensitive ? "iy" : "uy";
2027
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2267
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2028
2268
  let firstSet2 = empty();
2029
2269
  for (const w of sorted) {
2030
2270
  if (w.length === 0) continue;
@@ -2035,15 +2275,21 @@ function keywords(words, opts = {}) {
2035
2275
  }
2036
2276
  }
2037
2277
  const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
2278
+ const def = {
2279
+ tag: "keywords",
2280
+ words: sorted,
2281
+ caseInsensitive: opts.caseInsensitive ?? false,
2282
+ boundary: opts.boundary
2283
+ };
2038
2284
  return {
2039
2285
  _tag: "keywords",
2040
2286
  _meta: meta,
2041
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2287
+ _def: def,
2042
2288
  parse(input, pos, ctx) {
2043
2289
  re.lastIndex = pos;
2044
2290
  const m = re.exec(input);
2045
2291
  if (m === null || m.index !== pos) {
2046
- return failAt(ctx, ["keyword"], pos);
2292
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2047
2293
  }
2048
2294
  const value = m[0];
2049
2295
  const span = { start: pos, end: pos + value.length };
@@ -2056,6 +2302,14 @@ function keywords(words, opts = {}) {
2056
2302
  // src/combinators/trivia-skip.ts
2057
2303
  var NOOP_COMMIT = () => {
2058
2304
  };
2305
+ function triviaScanEnd(scan) {
2306
+ return typeof scan === "number" ? scan : scan.end;
2307
+ }
2308
+ function commitTriviaScan(scan) {
2309
+ if (typeof scan === "number") return scan;
2310
+ scan.commit();
2311
+ return scan.end;
2312
+ }
2059
2313
  var fastTrivia0;
2060
2314
  var fastTrivia1;
2061
2315
  var fastTrivia2;
@@ -2084,6 +2338,23 @@ function rollbackTrivia(ctx, mark) {
2084
2338
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
2085
2339
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
2086
2340
  }
2341
+ function removeNumberRange(values, start, end) {
2342
+ if (values === void 0 || end <= start) return;
2343
+ if (values.length > end) values.copyWithin(start, end);
2344
+ values.length -= end - start;
2345
+ }
2346
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
2347
+ const b = ctx._cstBuf;
2348
+ if (b !== void 0) {
2349
+ const tlog = b.tl;
2350
+ removeNumberRange(tlog, tlogStart, tlogEnd);
2351
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
2352
+ } else {
2353
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
2354
+ }
2355
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
2356
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
2357
+ }
2087
2358
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
2088
2359
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
2089
2360
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2103,7 +2374,7 @@ function rollbackLookahead(ctx, mark) {
2103
2374
  function scanWithLabels(input, cur, ctx) {
2104
2375
  const triviaP = ctx.trivia;
2105
2376
  const spec = analyzeLabeledTrivia(triviaP);
2106
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2377
+ if (!spec) return cur;
2107
2378
  const log = ctx._triviaLog;
2108
2379
  const rootLog = ctx._rootTriviaLog;
2109
2380
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2121,7 +2392,8 @@ function scanWithLabels(input, cur, ctx) {
2121
2392
  }
2122
2393
  });
2123
2394
  if (visitedEnd !== void 0) {
2124
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
2395
+ if (visitedEnd === cur) return cur;
2396
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
2125
2397
  return {
2126
2398
  end: visitedEnd,
2127
2399
  commit: () => {
@@ -2140,7 +2412,7 @@ function scanWithLabels(input, cur, ctx) {
2140
2412
  };
2141
2413
  }
2142
2414
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2143
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2415
+ if (end === cur) return cur;
2144
2416
  return {
2145
2417
  end,
2146
2418
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2181,7 +2453,7 @@ function advanceTrivia(input, cur, ctx) {
2181
2453
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2182
2454
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2183
2455
  }
2184
- function scanTrivia(input, cur, ctx) {
2456
+ function scanTriviaCompact(input, cur, ctx) {
2185
2457
  const triviaP = ctx.trivia;
2186
2458
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2187
2459
  const log = ctx._triviaLog;
@@ -2222,7 +2494,7 @@ function scanTrivia(input, cur, ctx) {
2222
2494
  }
2223
2495
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2224
2496
  const scan = scanWithLabels(input, cur, ctx);
2225
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2497
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2226
2498
  return scan;
2227
2499
  }
2228
2500
  if (ctx.triviaKindLabels) {
@@ -2254,14 +2526,12 @@ function scanTrivia(input, cur, ctx) {
2254
2526
  }
2255
2527
  function consumeTrivia(input, cur, ctx) {
2256
2528
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2257
- const scan = scanTrivia(input, cur, ctx);
2258
- scan.commit();
2259
- return scan.end;
2529
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2260
2530
  }
2261
2531
  function probeTriviaEnd(input, cur, ctx) {
2262
2532
  if (!ctx.trivia) return cur;
2263
2533
  const probeCtx = { ...ctx, trackLines: false };
2264
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2534
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2265
2535
  return advanceTrivia(input, cur, probeCtx);
2266
2536
  }
2267
2537
  function fastTriviaScanner(trivia2) {
@@ -2289,10 +2559,16 @@ function buildFastTriviaScanner(trivia2) {
2289
2559
  const one = regexTriviaScanner(repeat);
2290
2560
  if (one) return loopScanner([one]);
2291
2561
  if (repeat._def.tag !== "choice") return null;
2562
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2563
+ if (fused !== null) return fused;
2292
2564
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2293
2565
  if (arms.some((s) => s === null)) return null;
2294
2566
  return loopScanner(arms);
2295
2567
  }
2568
+ function triviaRegexSource(parser2) {
2569
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2570
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
2571
+ }
2296
2572
  function loopScanner(arms) {
2297
2573
  return (input, cur) => {
2298
2574
  let pos = cur;
@@ -2777,19 +3053,30 @@ function sequence(...parsers) {
2777
3053
  continue;
2778
3054
  }
2779
3055
  if (ctx.trivia && i > 0) {
2780
- const mark = saveTriviaMark(ctx);
3056
+ const mTlog = cstTlLen(ctx);
3057
+ const mLog = ctx._triviaLog?.length ?? 0;
3058
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2781
3059
  let scanEnd;
2782
3060
  if (needsDeferredTriviaCommit(ctx)) {
2783
- const scan = scanTrivia(input, cur, ctx);
2784
- scan.commit();
2785
- scanEnd = scan.end;
3061
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2786
3062
  } else {
2787
3063
  scanEnd = advanceTrivia(input, cur, ctx);
2788
3064
  }
3065
+ const scanTlog = cstTlLen(ctx);
3066
+ const scanLog = ctx._triviaLog?.length ?? 0;
3067
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2789
3068
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2790
3069
  if (!result2.ok) return result2;
2791
3070
  if (result2.span.end > scanEnd) cur = result2.span.end;
2792
- else rollbackTrivia(ctx, mark);
3071
+ else rollbackScannedTriviaAt(
3072
+ ctx,
3073
+ mTlog,
3074
+ scanTlog,
3075
+ mLog,
3076
+ scanLog,
3077
+ mRootLog,
3078
+ scanRootLog
3079
+ );
2793
3080
  if (values !== void 0) values.push(result2.value);
2794
3081
  continue;
2795
3082
  }
@@ -2820,18 +3107,29 @@ function sequence(...parsers) {
2820
3107
  }
2821
3108
  if (ctx.trivia && i > 0) {
2822
3109
  let scanEnd;
2823
- const mark = saveTriviaMark(ctx);
3110
+ const mTlog = cstTlLen(ctx);
3111
+ const mLog = ctx._triviaLog?.length ?? 0;
3112
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2824
3113
  if (needsDeferredTriviaCommit(ctx)) {
2825
- const scan = scanTrivia(input, cur, ctx);
2826
- scan.commit();
2827
- scanEnd = scan.end;
3114
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2828
3115
  } else {
2829
3116
  scanEnd = advanceTrivia(input, cur, ctx);
2830
3117
  }
3118
+ const scanTlog = cstTlLen(ctx);
3119
+ const scanLog = ctx._triviaLog?.length ?? 0;
3120
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2831
3121
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2832
3122
  if (!result2.ok) return result2;
2833
3123
  if (result2.span.end > scanEnd) cur = result2.span.end;
2834
- else rollbackTrivia(ctx, mark);
3124
+ else rollbackScannedTriviaAt(
3125
+ ctx,
3126
+ mTlog,
3127
+ scanTlog,
3128
+ mLog,
3129
+ scanLog,
3130
+ mRootLog,
3131
+ scanRootLog
3132
+ );
2835
3133
  if (values !== void 0) values.push(result2.value);
2836
3134
  continue;
2837
3135
  }
@@ -2859,20 +3157,31 @@ function sequence(...parsers) {
2859
3157
  for (let i = 0; i < parsers.length; i++) {
2860
3158
  if (ctx.trivia && i > 0) {
2861
3159
  let scanEnd;
2862
- let mark = saveTriviaMark(ctx);
3160
+ const mTlog = cstTlLen(ctx);
3161
+ const mLog = ctx._triviaLog?.length ?? 0;
3162
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2863
3163
  if (needsDeferredTriviaCommit(ctx)) {
2864
- const scan = scanTrivia(input, cur, ctx);
2865
- scan.commit();
2866
- scanEnd = scan.end;
3164
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2867
3165
  } else {
2868
3166
  scanEnd = advanceTrivia(input, cur, ctx);
2869
3167
  }
3168
+ const scanTlog = cstTlLen(ctx);
3169
+ const scanLog = ctx._triviaLog?.length ?? 0;
3170
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2870
3171
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2871
3172
  if (!result2.ok) return result2;
2872
3173
  if (result2.span.end > scanEnd) {
2873
3174
  cur = result2.span.end;
2874
3175
  } else {
2875
- rollbackTrivia(ctx, mark);
3176
+ rollbackScannedTriviaAt(
3177
+ ctx,
3178
+ mTlog,
3179
+ scanTlog,
3180
+ mLog,
3181
+ scanLog,
3182
+ mRootLog,
3183
+ scanRootLog
3184
+ );
2876
3185
  }
2877
3186
  if (values !== void 0) values.push(result2.value);
2878
3187
  continue;
@@ -3564,9 +3873,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3564
3873
  let pos = cur;
3565
3874
  if (ctx.trivia) {
3566
3875
  if (needsDeferredTriviaCommit(ctx)) {
3567
- const scan = scanTrivia(input, cur, ctx);
3568
- scan.commit();
3569
- pos = scan.end;
3876
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3570
3877
  } else {
3571
3878
  pos = advanceTrivia(input, cur, ctx);
3572
3879
  }
@@ -3789,9 +4096,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3789
4096
  let sepPos = cur;
3790
4097
  if (ctx.trivia) {
3791
4098
  if (needsDeferredTriviaCommit(ctx)) {
3792
- const scan = scanTrivia(input, cur, ctx);
3793
- scan.commit();
3794
- sepPos = scan.end;
4099
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3795
4100
  } else {
3796
4101
  sepPos = advanceTrivia(input, cur, ctx);
3797
4102
  }
@@ -3807,9 +4112,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3807
4112
  let nextPos = sep.span.end;
3808
4113
  if (ctx.trivia) {
3809
4114
  if (needsDeferredTriviaCommit(ctx)) {
3810
- const scan = scanTrivia(input, sep.span.end, ctx);
3811
- scan.commit();
3812
- nextPos = scan.end;
4115
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3813
4116
  } else {
3814
4117
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3815
4118
  }
@@ -3860,7 +4163,11 @@ function not(combinator) {
3860
4163
  const result = combinator.parse(input, pos, ctx);
3861
4164
  rollbackLookahead(ctx, mark);
3862
4165
  if (result.ok) {
3863
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4166
+ return {
4167
+ ok: false,
4168
+ expected: assertionFailureExpected(false, combinator._tag),
4169
+ span: { start: pos, end: pos }
4170
+ };
3864
4171
  }
3865
4172
  return { ok: true, value: null, span: { start: pos, end: pos } };
3866
4173
  }
@@ -3884,7 +4191,11 @@ function peek(combinator) {
3884
4191
  const result = combinator.parse(input, pos, ctx);
3885
4192
  rollbackLookahead(ctx, mark);
3886
4193
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
3887
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
4194
+ return {
4195
+ ok: false,
4196
+ expected: assertionFailureExpected(true, combinator._tag),
4197
+ span: { start: pos, end: pos }
4198
+ };
3888
4199
  }
3889
4200
  };
3890
4201
  }
@@ -4810,6 +5121,9 @@ var OP_LIVE = 37;
4810
5121
  var OP_ATTEMPT = 38;
4811
5122
  var OP_LABEL = 39;
4812
5123
  var OP_COV = 40;
5124
+ var OP_SCOPE_PLAIN = 41;
5125
+ var OP_LEX_BODY = 42;
5126
+ var OP_LEX_PROGRAM = 43;
4813
5127
  var OP_DISPATCH = 25;
4814
5128
  var OP_ROUTED = 26;
4815
5129
  var OP_NAMES = {
@@ -4852,7 +5166,10 @@ var OP_NAMES = {
4852
5166
  [OP_LIVE]: "LIVE",
4853
5167
  [OP_ATTEMPT]: "ATTEMPT",
4854
5168
  [OP_LABEL]: "LABEL",
4855
- [OP_COV]: "COV"
5169
+ [OP_COV]: "COV",
5170
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5171
+ [OP_LEX_BODY]: "LEX_BODY",
5172
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
4856
5173
  };
4857
5174
 
4858
5175
  // src/table/scan-shapes.ts