parseman 0.47.1 → 0.48.1

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 (126) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2964 -347
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2960 -343
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/choice.d.ts.map +1 -1
  7. package/dist/combinators/expect.d.ts +1 -0
  8. package/dist/combinators/expect.d.ts.map +1 -1
  9. package/dist/combinators/expected.d.ts +8 -0
  10. package/dist/combinators/expected.d.ts.map +1 -0
  11. package/dist/combinators/first-set.d.ts +8 -0
  12. package/dist/combinators/first-set.d.ts.map +1 -1
  13. package/dist/combinators/grammar.d.ts.map +1 -1
  14. package/dist/combinators/keywords.d.ts +4 -0
  15. package/dist/combinators/keywords.d.ts.map +1 -1
  16. package/dist/combinators/literal.d.ts.map +1 -1
  17. package/dist/combinators/not.d.ts.map +1 -1
  18. package/dist/combinators/peek.d.ts.map +1 -1
  19. package/dist/combinators/regex.d.ts.map +1 -1
  20. package/dist/combinators/repeat.d.ts.map +1 -1
  21. package/dist/combinators/sequence.d.ts.map +1 -1
  22. package/dist/combinators/trivia-skip.d.ts +16 -3
  23. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  24. package/dist/compiler/direct-projection.d.ts +12 -0
  25. package/dist/compiler/direct-projection.d.ts.map +1 -0
  26. package/dist/compiler/token-alphabet.d.ts +845 -5
  27. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  28. package/dist/compiler/token-capability.d.ts +3 -0
  29. package/dist/compiler/token-capability.d.ts.map +1 -0
  30. package/dist/compiler/token-capability.js +3192 -0
  31. package/dist/compiler/token-capability.js.map +6 -0
  32. package/dist/cst/trivia-charscan.d.ts +3 -0
  33. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  34. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  35. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  36. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  37. package/dist/index.js +2973 -343
  38. package/dist/index.js.map +3 -3
  39. package/dist/language-service/index.js +5 -1
  40. package/dist/language-service/index.js.map +1 -1
  41. package/dist/plugin/index.js +2982 -352
  42. package/dist/plugin/index.js.map +3 -3
  43. package/dist/spec/index.js +325 -47
  44. package/dist/spec/index.js.map +3 -3
  45. package/dist/table/assemble.d.ts.map +1 -1
  46. package/dist/table/child-slots.d.ts.map +1 -1
  47. package/dist/table/compile-rule-map.d.ts +3 -1
  48. package/dist/table/compile-rule-map.d.ts.map +1 -1
  49. package/dist/table/emit-assembly.d.ts +12 -13
  50. package/dist/table/emit-assembly.d.ts.map +1 -1
  51. package/dist/table/emit.d.ts.map +1 -1
  52. package/dist/table/encode.d.ts.map +1 -1
  53. package/dist/table/exec-baseline.d.ts.map +1 -1
  54. package/dist/table/exec.d.ts.map +1 -1
  55. package/dist/table/index.js +2937 -311
  56. package/dist/table/index.js.map +3 -3
  57. package/dist/table/lex-body.d.ts +9 -0
  58. package/dist/table/lex-body.d.ts.map +1 -0
  59. package/dist/table/lex-program.d.ts +25 -0
  60. package/dist/table/lex-program.d.ts.map +1 -0
  61. package/dist/table/ops.d.ts +47 -11
  62. package/dist/table/ops.d.ts.map +1 -1
  63. package/dist/table/program.d.ts +50 -2
  64. package/dist/table/program.d.ts.map +1 -1
  65. package/dist/table/scalar-terminal.d.ts +13 -0
  66. package/dist/table/scalar-terminal.d.ts.map +1 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/types.d.ts +2 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/version.d.ts +1 -1
  71. package/package.json +11 -11
  72. package/src/combinators/choice.ts +10 -1
  73. package/src/combinators/expect.ts +1 -0
  74. package/src/combinators/expected.ts +17 -0
  75. package/src/combinators/first-set.ts +58 -5
  76. package/src/combinators/grammar.ts +8 -3
  77. package/src/combinators/keywords.ts +22 -6
  78. package/src/combinators/literal.ts +2 -1
  79. package/src/combinators/not.ts +5 -1
  80. package/src/combinators/peek.ts +5 -1
  81. package/src/combinators/regex.ts +5 -3
  82. package/src/combinators/repeat.ts +4 -10
  83. package/src/combinators/sequence.ts +17 -14
  84. package/src/combinators/trivia-skip.ts +46 -13
  85. package/src/compiler/direct-projection.ts +43 -0
  86. package/src/compiler/token-alphabet.ts +4316 -12
  87. package/src/compiler/token-capability.ts +6 -0
  88. package/src/cst/trivia-charscan.ts +34 -0
  89. package/src/cst/trivia-css-scanner.ts +142 -0
  90. package/src/cst/trivia-kinds.ts +3 -1
  91. package/src/plugin/index.ts +4 -4
  92. package/src/table/assemble.ts +1253 -240
  93. package/src/table/child-slots.ts +2 -1
  94. package/src/table/compile-rule-map.ts +21 -3
  95. package/src/table/emit-assembly.ts +335 -87
  96. package/src/table/emit.ts +16 -2
  97. package/src/table/encode.ts +248 -60
  98. package/src/table/exec-baseline.ts +3 -7
  99. package/src/table/exec.ts +134 -25
  100. package/src/table/lex-body.ts +30 -0
  101. package/src/table/lex-program.ts +431 -0
  102. package/src/table/ops.ts +49 -11
  103. package/src/table/program.ts +46 -2
  104. package/src/table/scalar-terminal.ts +51 -0
  105. package/src/table/site-labels.ts +11 -1
  106. package/src/table/stamp.ts +1 -1
  107. package/src/types.ts +1 -1
  108. package/src/version.ts +1 -1
  109. package/dist/analysis/diagnostics.cjs +0 -13824
  110. package/dist/analysis/diagnostics.cjs.map +0 -6
  111. package/dist/cli/index.cjs +0 -14925
  112. package/dist/cli/index.cjs.map +0 -6
  113. package/dist/index.cjs +0 -16391
  114. package/dist/index.cjs.map +0 -6
  115. package/dist/language-service/index.cjs +0 -1304
  116. package/dist/language-service/index.cjs.map +0 -6
  117. package/dist/oracle/index.cjs +0 -254
  118. package/dist/oracle/index.cjs.map +0 -6
  119. package/dist/plugin/index.cjs +0 -16097
  120. package/dist/plugin/index.cjs.map +0 -6
  121. package/dist/run/index.cjs +0 -577
  122. package/dist/run/index.cjs.map +0 -6
  123. package/dist/spec/index.cjs +0 -6236
  124. package/dist/spec/index.cjs.map +0 -6
  125. package/dist/table/index.cjs +0 -11463
  126. package/dist/table/index.cjs.map +0 -6
@@ -817,6 +817,179 @@ function parseClassRanges(body) {
817
817
  return ranges.length ? ranges : null;
818
818
  }
819
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
+
820
993
  // src/cst/trivia-charscan.ts
821
994
  function inRanges(cp, ranges) {
822
995
  for (let i = 0; i < ranges.length; i++) {
@@ -970,6 +1143,35 @@ function classifyParser(p) {
970
1143
  if (d.tag !== "regex" || d.flags) return null;
971
1144
  return classifyArm(d.source);
972
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
+ }
973
1175
  var armSpec0;
974
1176
  var armSpec1;
975
1177
  var armSpec2;
@@ -1168,6 +1370,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1168
1370
  }
1169
1371
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1170
1372
  if (spec.minRepeats > 1) return void 0;
1373
+ const common = commonLabeledTriviaVisitor(spec);
1374
+ if (common !== null) return common(input, cur, visit);
1171
1375
  const chars = charArmsFor(spec);
1172
1376
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1173
1377
  let pos = cur;
@@ -1301,11 +1505,12 @@ function parser(opts, root) {
1301
1505
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1302
1506
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1303
1507
  const forceCaptureTrivia = opts.captureTrivia === true;
1304
- 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;
1305
1510
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1306
1511
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1307
1512
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1308
- return {
1513
+ const grammar = {
1309
1514
  _tag: "grammar",
1310
1515
  _meta: {
1311
1516
  ...root._meta,
@@ -1324,7 +1529,9 @@ function parser(opts, root) {
1324
1529
  clearTrivia,
1325
1530
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1326
1531
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1327
- trackLines: opts.trackLines ?? false
1532
+ trackLines: opts.trackLines ?? false,
1533
+ constructionTrackLines: trackLinesPolicy,
1534
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1328
1535
  },
1329
1536
  parse(input, pos, _ctx) {
1330
1537
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1353,6 +1560,7 @@ function parser(opts, root) {
1353
1560
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1354
1561
  }
1355
1562
  };
1563
+ return grammar;
1356
1564
  }
1357
1565
 
1358
1566
  // src/cst/reflection-symbols.ts
@@ -1831,6 +2039,21 @@ function firstSetFromRegex(source) {
1831
2039
  return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
1832
2040
  }
1833
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
+
1834
2057
  // src/combinators/regex.ts
1835
2058
  var SCAN_BAIL_AT = 64;
1836
2059
  function inRanges2(cp, ranges) {
@@ -1902,14 +2125,15 @@ function regex(pattern, flags = "") {
1902
2125
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1903
2126
  const canMatchNewline = raw.canMatchNewline;
1904
2127
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2128
+ const def = { tag: "regex", source, flags: resolvedFlags };
1905
2129
  return {
1906
2130
  _tag: "regex",
1907
2131
  _meta: meta,
1908
- _def: { tag: "regex", source, flags: resolvedFlags },
2132
+ _def: def,
1909
2133
  parse(input, pos, ctx) {
1910
2134
  const scanEnd = scan?.(input, pos);
1911
2135
  if (scanEnd !== void 0) {
1912
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2136
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1913
2137
  const value = input.slice(pos, scanEnd);
1914
2138
  const span2 = { start: pos, end: scanEnd };
1915
2139
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1919,7 +2143,7 @@ function regex(pattern, flags = "") {
1919
2143
  anchored.lastIndex = pos;
1920
2144
  const m = anchored.exec(input);
1921
2145
  if (m === null) {
1922
- return failAt(ctx, [`/${source}/`], pos);
2146
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1923
2147
  }
1924
2148
  const span = { start: pos, end: pos + m[0].length };
1925
2149
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -1960,7 +2184,7 @@ function literal(value, opts = {}) {
1960
2184
  { lo: firstUpper, hi: firstUpper }
1961
2185
  ] } : firstSet2;
1962
2186
  }
1963
- const expected = [JSON.stringify(value)];
2187
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
1964
2188
  const parse = !caseInsensitive && value.length === 1 ? (() => {
1965
2189
  const code = value.charCodeAt(0);
1966
2190
  return function parse2(input, pos, ctx) {
@@ -2033,12 +2257,14 @@ function caseFoldVariants(cp) {
2033
2257
  function escapeRe(s) {
2034
2258
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2035
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
+ }
2036
2265
  function keywords(words, opts = {}) {
2037
2266
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2038
- const alt = sorted.map(escapeRe).join("|");
2039
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2040
- const flags = opts.caseInsensitive ? "iy" : "uy";
2041
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2267
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2042
2268
  let firstSet2 = empty();
2043
2269
  for (const w of sorted) {
2044
2270
  if (w.length === 0) continue;
@@ -2049,15 +2275,21 @@ function keywords(words, opts = {}) {
2049
2275
  }
2050
2276
  }
2051
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
+ };
2052
2284
  return {
2053
2285
  _tag: "keywords",
2054
2286
  _meta: meta,
2055
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2287
+ _def: def,
2056
2288
  parse(input, pos, ctx) {
2057
2289
  re.lastIndex = pos;
2058
2290
  const m = re.exec(input);
2059
2291
  if (m === null || m.index !== pos) {
2060
- return failAt(ctx, ["keyword"], pos);
2292
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2061
2293
  }
2062
2294
  const value = m[0];
2063
2295
  const span = { start: pos, end: pos + value.length };
@@ -2070,6 +2302,14 @@ function keywords(words, opts = {}) {
2070
2302
  // src/combinators/trivia-skip.ts
2071
2303
  var NOOP_COMMIT = () => {
2072
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
+ }
2073
2313
  var fastTrivia0;
2074
2314
  var fastTrivia1;
2075
2315
  var fastTrivia2;
@@ -2134,7 +2374,7 @@ function rollbackLookahead(ctx, mark) {
2134
2374
  function scanWithLabels(input, cur, ctx) {
2135
2375
  const triviaP = ctx.trivia;
2136
2376
  const spec = analyzeLabeledTrivia(triviaP);
2137
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2377
+ if (!spec) return cur;
2138
2378
  const log = ctx._triviaLog;
2139
2379
  const rootLog = ctx._rootTriviaLog;
2140
2380
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2152,7 +2392,8 @@ function scanWithLabels(input, cur, ctx) {
2152
2392
  }
2153
2393
  });
2154
2394
  if (visitedEnd !== void 0) {
2155
- 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;
2156
2397
  return {
2157
2398
  end: visitedEnd,
2158
2399
  commit: () => {
@@ -2171,7 +2412,7 @@ function scanWithLabels(input, cur, ctx) {
2171
2412
  };
2172
2413
  }
2173
2414
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2174
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2415
+ if (end === cur) return cur;
2175
2416
  return {
2176
2417
  end,
2177
2418
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2212,7 +2453,7 @@ function advanceTrivia(input, cur, ctx) {
2212
2453
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2213
2454
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2214
2455
  }
2215
- function scanTrivia(input, cur, ctx) {
2456
+ function scanTriviaCompact(input, cur, ctx) {
2216
2457
  const triviaP = ctx.trivia;
2217
2458
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2218
2459
  const log = ctx._triviaLog;
@@ -2253,7 +2494,7 @@ function scanTrivia(input, cur, ctx) {
2253
2494
  }
2254
2495
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2255
2496
  const scan = scanWithLabels(input, cur, ctx);
2256
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2497
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2257
2498
  return scan;
2258
2499
  }
2259
2500
  if (ctx.triviaKindLabels) {
@@ -2285,14 +2526,12 @@ function scanTrivia(input, cur, ctx) {
2285
2526
  }
2286
2527
  function consumeTrivia(input, cur, ctx) {
2287
2528
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2288
- const scan = scanTrivia(input, cur, ctx);
2289
- scan.commit();
2290
- return scan.end;
2529
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2291
2530
  }
2292
2531
  function probeTriviaEnd(input, cur, ctx) {
2293
2532
  if (!ctx.trivia) return cur;
2294
2533
  const probeCtx = { ...ctx, trackLines: false };
2295
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2534
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2296
2535
  return advanceTrivia(input, cur, probeCtx);
2297
2536
  }
2298
2537
  function fastTriviaScanner(trivia2) {
@@ -2320,10 +2559,16 @@ function buildFastTriviaScanner(trivia2) {
2320
2559
  const one = regexTriviaScanner(repeat);
2321
2560
  if (one) return loopScanner([one]);
2322
2561
  if (repeat._def.tag !== "choice") return null;
2562
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2563
+ if (fused !== null) return fused;
2323
2564
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2324
2565
  if (arms.some((s) => s === null)) return null;
2325
2566
  return loopScanner(arms);
2326
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
+ }
2327
2572
  function loopScanner(arms) {
2328
2573
  return (input, cur) => {
2329
2574
  let pos = cur;
@@ -2813,9 +3058,7 @@ function sequence(...parsers) {
2813
3058
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2814
3059
  let scanEnd;
2815
3060
  if (needsDeferredTriviaCommit(ctx)) {
2816
- const scan = scanTrivia(input, cur, ctx);
2817
- scan.commit();
2818
- scanEnd = scan.end;
3061
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2819
3062
  } else {
2820
3063
  scanEnd = advanceTrivia(input, cur, ctx);
2821
3064
  }
@@ -2825,7 +3068,15 @@ function sequence(...parsers) {
2825
3068
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2826
3069
  if (!result2.ok) return result2;
2827
3070
  if (result2.span.end > scanEnd) cur = result2.span.end;
2828
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3071
+ else rollbackScannedTriviaAt(
3072
+ ctx,
3073
+ mTlog,
3074
+ scanTlog,
3075
+ mLog,
3076
+ scanLog,
3077
+ mRootLog,
3078
+ scanRootLog
3079
+ );
2829
3080
  if (values !== void 0) values.push(result2.value);
2830
3081
  continue;
2831
3082
  }
@@ -2860,9 +3111,7 @@ function sequence(...parsers) {
2860
3111
  const mLog = ctx._triviaLog?.length ?? 0;
2861
3112
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2862
3113
  if (needsDeferredTriviaCommit(ctx)) {
2863
- const scan = scanTrivia(input, cur, ctx);
2864
- scan.commit();
2865
- scanEnd = scan.end;
3114
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2866
3115
  } else {
2867
3116
  scanEnd = advanceTrivia(input, cur, ctx);
2868
3117
  }
@@ -2872,7 +3121,15 @@ function sequence(...parsers) {
2872
3121
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2873
3122
  if (!result2.ok) return result2;
2874
3123
  if (result2.span.end > scanEnd) cur = result2.span.end;
2875
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3124
+ else rollbackScannedTriviaAt(
3125
+ ctx,
3126
+ mTlog,
3127
+ scanTlog,
3128
+ mLog,
3129
+ scanLog,
3130
+ mRootLog,
3131
+ scanRootLog
3132
+ );
2876
3133
  if (values !== void 0) values.push(result2.value);
2877
3134
  continue;
2878
3135
  }
@@ -2904,9 +3161,7 @@ function sequence(...parsers) {
2904
3161
  const mLog = ctx._triviaLog?.length ?? 0;
2905
3162
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2906
3163
  if (needsDeferredTriviaCommit(ctx)) {
2907
- const scan = scanTrivia(input, cur, ctx);
2908
- scan.commit();
2909
- scanEnd = scan.end;
3164
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2910
3165
  } else {
2911
3166
  scanEnd = advanceTrivia(input, cur, ctx);
2912
3167
  }
@@ -2918,7 +3173,15 @@ function sequence(...parsers) {
2918
3173
  if (result2.span.end > scanEnd) {
2919
3174
  cur = result2.span.end;
2920
3175
  } else {
2921
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3176
+ rollbackScannedTriviaAt(
3177
+ ctx,
3178
+ mTlog,
3179
+ scanTlog,
3180
+ mLog,
3181
+ scanLog,
3182
+ mRootLog,
3183
+ scanRootLog
3184
+ );
2922
3185
  }
2923
3186
  if (values !== void 0) values.push(result2.value);
2924
3187
  continue;
@@ -3085,6 +3348,7 @@ function choice(...args) {
3085
3348
  },
3086
3349
  parse(input, pos, ctx) {
3087
3350
  const expected = [];
3351
+ let expectedAt = pos;
3088
3352
  if (disjoint) {
3089
3353
  const code = pos < input.length ? input.codePointAt(pos) : -1;
3090
3354
  let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
@@ -3142,7 +3406,12 @@ function choice(...args) {
3142
3406
  const result = parsers[i].parse(input, pos, ctx);
3143
3407
  if (!result.ok) {
3144
3408
  rollbackTrivia(ctx, mark);
3145
- expected.push(...result.expected);
3409
+ const at = result.span.start;
3410
+ if (at > expectedAt) {
3411
+ expectedAt = at;
3412
+ expected.length = 0;
3413
+ }
3414
+ if (at === expectedAt) expected.push(...result.expected);
3146
3415
  if (result.committed) return { ok: false, expected, span: result.span, committed: true };
3147
3416
  continue;
3148
3417
  }
@@ -3153,6 +3422,9 @@ function choice(...args) {
3153
3422
  }
3154
3423
  return result;
3155
3424
  }
3425
+ if (expected.length === 0) {
3426
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
3427
+ }
3156
3428
  return { ok: false, expected, span: { start: pos, end: pos } };
3157
3429
  }
3158
3430
  };
@@ -3610,9 +3882,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3610
3882
  let pos = cur;
3611
3883
  if (ctx.trivia) {
3612
3884
  if (needsDeferredTriviaCommit(ctx)) {
3613
- const scan = scanTrivia(input, cur, ctx);
3614
- scan.commit();
3615
- pos = scan.end;
3885
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3616
3886
  } else {
3617
3887
  pos = advanceTrivia(input, cur, ctx);
3618
3888
  }
@@ -3835,9 +4105,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3835
4105
  let sepPos = cur;
3836
4106
  if (ctx.trivia) {
3837
4107
  if (needsDeferredTriviaCommit(ctx)) {
3838
- const scan = scanTrivia(input, cur, ctx);
3839
- scan.commit();
3840
- sepPos = scan.end;
4108
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3841
4109
  } else {
3842
4110
  sepPos = advanceTrivia(input, cur, ctx);
3843
4111
  }
@@ -3853,9 +4121,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3853
4121
  let nextPos = sep.span.end;
3854
4122
  if (ctx.trivia) {
3855
4123
  if (needsDeferredTriviaCommit(ctx)) {
3856
- const scan = scanTrivia(input, sep.span.end, ctx);
3857
- scan.commit();
3858
- nextPos = scan.end;
4124
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3859
4125
  } else {
3860
4126
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3861
4127
  }
@@ -3906,7 +4172,11 @@ function not(combinator) {
3906
4172
  const result = combinator.parse(input, pos, ctx);
3907
4173
  rollbackLookahead(ctx, mark);
3908
4174
  if (result.ok) {
3909
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4175
+ return {
4176
+ ok: false,
4177
+ expected: assertionFailureExpected(false, combinator._tag),
4178
+ span: { start: pos, end: pos }
4179
+ };
3910
4180
  }
3911
4181
  return { ok: true, value: null, span: { start: pos, end: pos } };
3912
4182
  }
@@ -3930,7 +4200,11 @@ function peek(combinator) {
3930
4200
  const result = combinator.parse(input, pos, ctx);
3931
4201
  rollbackLookahead(ctx, mark);
3932
4202
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
3933
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
4203
+ return {
4204
+ ok: false,
4205
+ expected: assertionFailureExpected(true, combinator._tag),
4206
+ span: { start: pos, end: pos }
4207
+ };
3934
4208
  }
3935
4209
  };
3936
4210
  }
@@ -4857,6 +5131,8 @@ var OP_ATTEMPT = 38;
4857
5131
  var OP_LABEL = 39;
4858
5132
  var OP_COV = 40;
4859
5133
  var OP_SCOPE_PLAIN = 41;
5134
+ var OP_LEX_BODY = 42;
5135
+ var OP_LEX_PROGRAM = 43;
4860
5136
  var OP_DISPATCH = 25;
4861
5137
  var OP_ROUTED = 26;
4862
5138
  var OP_NAMES = {
@@ -4900,7 +5176,9 @@ var OP_NAMES = {
4900
5176
  [OP_ATTEMPT]: "ATTEMPT",
4901
5177
  [OP_LABEL]: "LABEL",
4902
5178
  [OP_COV]: "COV",
4903
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5179
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5180
+ [OP_LEX_BODY]: "LEX_BODY",
5181
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
4904
5182
  };
4905
5183
 
4906
5184
  // src/table/scan-shapes.ts