parseman 0.42.0 → 0.43.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 (42) hide show
  1. package/dist/combinators/node.d.ts +21 -7
  2. package/dist/combinators/node.d.ts.map +1 -1
  3. package/dist/combinators/parser.d.ts +23 -2
  4. package/dist/combinators/parser.d.ts.map +1 -1
  5. package/dist/compiler/codegen.d.ts +6 -0
  6. package/dist/compiler/codegen.d.ts.map +1 -1
  7. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  8. package/dist/compiler/linker.d.ts +7 -1
  9. package/dist/compiler/linker.d.ts.map +1 -1
  10. package/dist/cst/reflection.d.ts +24 -0
  11. package/dist/cst/reflection.d.ts.map +1 -0
  12. package/dist/cst/types.d.ts +2 -0
  13. package/dist/cst/types.d.ts.map +1 -1
  14. package/dist/cst/walk.d.ts +27 -62
  15. package/dist/cst/walk.d.ts.map +1 -1
  16. package/dist/index.cjs +375 -195
  17. package/dist/index.cjs.map +4 -4
  18. package/dist/index.d.ts +4 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +375 -195
  21. package/dist/index.js.map +4 -4
  22. package/dist/language-service/index.cjs +25 -33
  23. package/dist/language-service/index.cjs.map +4 -4
  24. package/dist/language-service/index.d.ts +1 -1
  25. package/dist/language-service/index.d.ts.map +1 -1
  26. package/dist/language-service/index.js +25 -33
  27. package/dist/language-service/index.js.map +4 -4
  28. package/dist/plugin/evaluator.d.ts +1 -0
  29. package/dist/plugin/evaluator.d.ts.map +1 -1
  30. package/dist/plugin/index.cjs +654 -173
  31. package/dist/plugin/index.cjs.map +4 -4
  32. package/dist/plugin/index.d.ts.map +1 -1
  33. package/dist/plugin/index.js +654 -173
  34. package/dist/plugin/index.js.map +4 -4
  35. package/dist/spec/index.cjs +429 -313
  36. package/dist/spec/index.cjs.map +4 -4
  37. package/dist/spec/index.js +429 -313
  38. package/dist/spec/index.js.map +4 -4
  39. package/dist/types.d.ts +8 -1
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/version.d.ts +1 -1
  42. package/package.json +1 -1
@@ -357,92 +357,6 @@ function markUnusedValues(root) {
357
357
  visit(resolveRoot(root), true);
358
358
  }
359
359
 
360
- // src/combinators/parser.ts
361
- var RULE_ORDER = "__parsemanRuleOrder";
362
- function tagRule(r, key) {
363
- ;
364
- r._ruleName = key;
365
- if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
366
- }
367
- function isDefinableRef(v) {
368
- return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
369
- }
370
- function ruleNameOf(r) {
371
- return r._ruleName;
372
- }
373
- function isNamedRuleRefForAnotherRule(r, key) {
374
- const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
375
- return name !== void 0 && name !== key;
376
- }
377
- function rules(a, b) {
378
- const factory = typeof a === "function" ? a : b;
379
- const options = typeof a === "function" ? b : a;
380
- const cache = {};
381
- const proxy = new Proxy(cache, {
382
- get(target, key) {
383
- if (typeof key !== "string") return void 0;
384
- const record = target;
385
- if (!(key in record)) {
386
- const r = ref();
387
- tagRule(r, key);
388
- record[key] = r;
389
- }
390
- return record[key];
391
- }
392
- });
393
- const definitions = factory(proxy);
394
- for (const key of Object.keys(definitions)) {
395
- const placeholder = cache[key];
396
- const parser2 = definitions[key];
397
- if (placeholder === parser2) {
398
- throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
399
- }
400
- if (isDefinableRef(placeholder)) {
401
- if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
402
- placeholder.define(parser2);
403
- placeholder._meta.firstSet = parser2._meta.firstSet;
404
- placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
405
- } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
406
- const alias = ref();
407
- tagRule(alias, key);
408
- alias.define(parser2);
409
- alias._meta.firstSet = parser2._meta.firstSet;
410
- alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
411
- cache[key] = alias;
412
- } else {
413
- tagRule(parser2, key);
414
- cache[key] = parser2;
415
- }
416
- }
417
- if (options?.trivia != null) {
418
- for (const key of Object.keys(definitions)) {
419
- const rule = cache[key];
420
- if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
421
- }
422
- }
423
- if (options?.scanSkip != null) {
424
- for (const key of Object.keys(definitions)) {
425
- const rule = cache[key];
426
- if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
427
- }
428
- }
429
- if (options?.hostMode === "cst") {
430
- for (const key of Object.keys(definitions)) {
431
- const rule = cache[key];
432
- if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
433
- }
434
- }
435
- for (const key of Object.keys(definitions)) {
436
- markUnusedValues(cache[key]);
437
- }
438
- Object.defineProperty(cache, RULE_ORDER, {
439
- value: Object.keys(definitions),
440
- enumerable: false,
441
- configurable: true
442
- });
443
- return cache;
444
- }
445
-
446
360
  // src/line-index.ts
447
361
  function createLineIndex() {
448
362
  return { lineStarts: [0] };
@@ -1110,38 +1024,432 @@ function codesToFirstSet(codes) {
1110
1024
  if (codes[i] === hi + 1) {
1111
1025
  hi = codes[i];
1112
1026
  } else {
1113
- ranges.push({ lo, hi });
1114
- lo = hi = codes[i];
1027
+ ranges.push({ lo, hi });
1028
+ lo = hi = codes[i];
1029
+ }
1030
+ }
1031
+ ranges.push({ lo, hi });
1032
+ return { kind: "ranges", ranges };
1033
+ }
1034
+ function inFirstSet(code, fs) {
1035
+ if (fs.kind === "any") return true;
1036
+ if (fs.kind === "empty") return false;
1037
+ for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1038
+ return false;
1039
+ }
1040
+ function areDisjoint(sets) {
1041
+ if (sets.some((s) => s.kind === "any")) return false;
1042
+ for (let i = 0; i < sets.length; i++)
1043
+ for (let j2 = i + 1; j2 < sets.length; j2++)
1044
+ if (intersects(sets[i], sets[j2])) return false;
1045
+ return true;
1046
+ }
1047
+ function buildAsciiDispatch(parsers) {
1048
+ const table = Array(128).fill(-1);
1049
+ for (let i = 0; i < parsers.length; i++) {
1050
+ const fs = parsers[i]._meta.firstSet;
1051
+ if (fs.kind !== "ranges") continue;
1052
+ for (const { lo, hi } of fs.ranges) {
1053
+ for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1054
+ table[code] = i;
1055
+ }
1056
+ }
1057
+ }
1058
+ return table;
1059
+ }
1060
+
1061
+ // src/cst/trivia-kinds.ts
1062
+ function unwrapTrivia(p) {
1063
+ let cur = p;
1064
+ while (cur._def.tag === "trivia") cur = cur._def.parser;
1065
+ return cur;
1066
+ }
1067
+ function peelLabel(p) {
1068
+ if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
1069
+ return null;
1070
+ }
1071
+ function analyzeLabeledTrivia(trivia2) {
1072
+ let core = unwrapTrivia(trivia2);
1073
+ let minRepeats = 1;
1074
+ if (core._def.tag === "oneOrMore") {
1075
+ core = core._def.parser;
1076
+ minRepeats = 1;
1077
+ } else if (core._def.tag === "many") {
1078
+ core = core._def.parser;
1079
+ minRepeats = 0;
1080
+ }
1081
+ const arms = [];
1082
+ if (core._def.tag === "choice") {
1083
+ for (let i = 0; i < core._def.parsers.length; i++) {
1084
+ const peeled = peelLabel(core._def.parsers[i]);
1085
+ if (!peeled) return null;
1086
+ arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
1087
+ }
1088
+ } else {
1089
+ const peeled = peelLabel(core);
1090
+ if (!peeled) return null;
1091
+ arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1092
+ }
1093
+ return { labels: arms.map((a) => a.label), arms, minRepeats };
1094
+ }
1095
+ function matchArmAt(input, pos, arm) {
1096
+ const r = arm.parse(input, pos, { trackLines: false });
1097
+ if (!r.ok || r.span.end <= pos) return null;
1098
+ return { end: r.span.end };
1099
+ }
1100
+ function scanLabeledTriviaChunks(input, cur, spec) {
1101
+ const chunks = [];
1102
+ let pos = cur;
1103
+ while (pos < input.length) {
1104
+ let matched = null;
1105
+ for (const arm of spec.arms) {
1106
+ const m = matchArmAt(input, pos, arm.parser);
1107
+ if (m) {
1108
+ matched = { end: m.end, kindIndex: arm.kindIndex };
1109
+ break;
1110
+ }
1111
+ }
1112
+ if (!matched) break;
1113
+ chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
1114
+ pos = matched.end;
1115
+ }
1116
+ if (chunks.length < spec.minRepeats) {
1117
+ return { end: cur, chunks: [] };
1118
+ }
1119
+ return { end: pos, chunks };
1120
+ }
1121
+ function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1122
+ const chunks = [];
1123
+ let pos = cur;
1124
+ while (pos < input.length) {
1125
+ const c = input.charCodeAt(pos);
1126
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1127
+ const start = pos;
1128
+ pos++;
1129
+ while (pos < input.length) {
1130
+ const c2 = input.charCodeAt(pos);
1131
+ if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1132
+ else break;
1133
+ }
1134
+ chunks.push({ start, end: pos, kindIndex: wsKind });
1135
+ continue;
1136
+ }
1137
+ if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1138
+ let j2 = pos + 2;
1139
+ while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
1140
+ if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
1141
+ const start = pos;
1142
+ pos = j2 + 2;
1143
+ chunks.push({ start, end: pos, kindIndex: commentKind });
1144
+ continue;
1145
+ }
1146
+ break;
1147
+ }
1148
+ break;
1149
+ }
1150
+ return { end: pos, chunks };
1151
+ }
1152
+ function tryFastLabeledScan(input, cur, trivia2) {
1153
+ const spec = analyzeLabeledTrivia(trivia2);
1154
+ if (!spec || spec.arms.length !== 2) return null;
1155
+ const wsArm = spec.arms.find((a) => {
1156
+ const src = getCoreRegexDef(a.parser)?.source;
1157
+ return src != null && !src.includes("\\*");
1158
+ });
1159
+ const commentArm = spec.arms.find((a) => {
1160
+ const src = getCoreRegexDef(a.parser)?.source;
1161
+ return src != null && src.includes("\\*");
1162
+ });
1163
+ if (!wsArm || !commentArm) return null;
1164
+ const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1165
+ if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
1166
+ return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1167
+ }
1168
+ function recordTriviaChunks(ctx, chunks) {
1169
+ const kinds = ctx.triviaKindLabels;
1170
+ const mask = ctx._triviaCaptureMask;
1171
+ for (const ch of chunks) {
1172
+ pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1173
+ if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1174
+ if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
1175
+ pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1176
+ }
1177
+ }
1178
+ }
1179
+ }
1180
+ function triviaKindMask(labels, keep) {
1181
+ if (!labels) return void 0;
1182
+ let mask = 0;
1183
+ for (const name of keep) {
1184
+ const idx = labels.indexOf(name);
1185
+ if (idx >= 0) mask |= 1 << idx;
1186
+ }
1187
+ return mask;
1188
+ }
1189
+
1190
+ // src/combinators/grammar.ts
1191
+ function annotateResultLines(result, index) {
1192
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
1193
+ const errors = annotated.errors;
1194
+ if (errors) {
1195
+ ;
1196
+ annotated.errors = errors.map((error) => ({
1197
+ ...error,
1198
+ span: annotateSpan(error.span, index)
1199
+ }));
1200
+ }
1201
+ return annotated;
1202
+ }
1203
+ function createParseLineContext(input, pos) {
1204
+ const lineIndex = createLineIndex();
1205
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
1206
+ return { lineIndex, lineScannedTo: pos };
1207
+ }
1208
+ function parser(opts, root) {
1209
+ const clearTrivia = opts.trivia === null;
1210
+ return {
1211
+ _tag: "grammar",
1212
+ _meta: root._meta,
1213
+ _def: {
1214
+ tag: "grammar",
1215
+ parser: root,
1216
+ triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
1217
+ clearTrivia,
1218
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
1219
+ trackLines: opts.trackLines ?? false
1220
+ },
1221
+ parse(input, pos, _ctx) {
1222
+ const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
1223
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
1224
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
1225
+ const ctx = {
1226
+ ..._ctx,
1227
+ trackLines,
1228
+ ...lineIndex ? { _lineIndex: lineIndex } : {},
1229
+ ...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
1230
+ // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
1231
+ ...clearTrivia ? {
1232
+ trivia: void 0,
1233
+ triviaKindLabels: void 0
1234
+ } : opts.trivia != null ? {
1235
+ trivia: opts.trivia,
1236
+ ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
1237
+ } : {},
1238
+ ...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
1239
+ // Kind-filter for per-node capture. Resolve against this scope's trivia
1240
+ // labels — this parser's own trivia if it declares one, else the INHERITED
1241
+ // labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
1242
+ // trivia is inherited rather than re-declared here. No labels → undefined
1243
+ // (capture all).
1244
+ ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
1245
+ };
1246
+ const result = root.parse(input, pos ?? 0, ctx);
1247
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
1248
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
1249
+ }
1250
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1251
+ }
1252
+ };
1253
+ }
1254
+
1255
+ // src/cst/reflection.ts
1256
+ var GRAMMAR_REFLECTION = /* @__PURE__ */ Symbol.for("parseman.grammarReflection");
1257
+ function childrenOf(def) {
1258
+ switch (def.tag) {
1259
+ case "sequence":
1260
+ case "choice":
1261
+ return def.parsers;
1262
+ case "dispatch":
1263
+ return [
1264
+ def.selector,
1265
+ ...def.cases.map((c) => c.parser),
1266
+ ...def.matchers ? def.matchers.map((c) => c.parser) : [],
1267
+ ...def.otherwise ? [def.otherwise] : []
1268
+ ];
1269
+ case "many":
1270
+ case "oneOrMore":
1271
+ case "optional":
1272
+ case "attempt":
1273
+ case "transform":
1274
+ case "trivia":
1275
+ case "token":
1276
+ case "leaf":
1277
+ case "label":
1278
+ case "field":
1279
+ case "not":
1280
+ case "peek":
1281
+ case "node":
1282
+ case "withCtx":
1283
+ case "recover":
1284
+ case "expect":
1285
+ return [def.parser];
1286
+ case "grammar":
1287
+ return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
1288
+ case "sepBy":
1289
+ return [def.parser, def.separator];
1290
+ case "skip":
1291
+ return [def.main, def.skipped];
1292
+ case "scanTo":
1293
+ return [def.sentinel, ...def.skip];
1294
+ case "literal":
1295
+ case "regex":
1296
+ case "keywords":
1297
+ case "routed":
1298
+ case "guard":
1299
+ case "lazy":
1300
+ case "unknown":
1301
+ return [];
1302
+ }
1303
+ }
1304
+ function addNode(out, def) {
1305
+ if (def.type === void 0) return;
1306
+ const existing = out.get(def.type);
1307
+ if (existing === void 0) {
1308
+ out.set(def.type, def.tags === void 0 ? [] : [...def.tags]);
1309
+ return;
1310
+ }
1311
+ if (def.tags === void 0) return;
1312
+ for (const tag of def.tags) {
1313
+ if (!existing.includes(tag)) existing.push(tag);
1314
+ }
1315
+ }
1316
+ function collectFromCombinator(parser2, out, seen, followLazy = true) {
1317
+ if (seen.has(parser2)) return;
1318
+ seen.add(parser2);
1319
+ const def = parser2._def;
1320
+ if (def.tag === "lazy") {
1321
+ if (followLazy) {
1322
+ try {
1323
+ collectFromCombinator(def.thunk(), out, seen, followLazy);
1324
+ } catch {
1325
+ }
1326
+ }
1327
+ return;
1328
+ }
1329
+ if (def.tag === "node") addNode(out, def);
1330
+ for (const child of childrenOf(def)) collectFromCombinator(child, out, seen, followLazy);
1331
+ }
1332
+ function collectGrammarReflection(ruleMap, opts) {
1333
+ const byType = /* @__PURE__ */ new Map();
1334
+ const followLazy = opts?.followLazy !== false;
1335
+ for (const [, rule] of ruleMap) {
1336
+ if (!followLazy && rule._def.tag === "lazy") {
1337
+ try {
1338
+ const resolved = rule._def.thunk();
1339
+ if (resolved._def.tag !== "lazy") collectFromCombinator(resolved, byType, /* @__PURE__ */ new Set(), false);
1340
+ } catch {
1341
+ }
1342
+ continue;
1343
+ }
1344
+ collectFromCombinator(rule, byType, /* @__PURE__ */ new Set(), followLazy);
1345
+ }
1346
+ return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
1347
+ }
1348
+ function attachGrammarReflection(grammar, reflection) {
1349
+ Object.defineProperty(grammar, GRAMMAR_REFLECTION, { value: reflection, enumerable: false, configurable: true });
1350
+ return grammar;
1351
+ }
1352
+
1353
+ // src/combinators/parser.ts
1354
+ var RULE_ORDER = "__parsemanRuleOrder";
1355
+ function tagRule(r, key) {
1356
+ ;
1357
+ r._ruleName = key;
1358
+ if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
1359
+ }
1360
+ function isDefinableRef(v) {
1361
+ return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
1362
+ }
1363
+ function ruleNameOf(r) {
1364
+ return r._ruleName;
1365
+ }
1366
+ function isNamedRuleRefForAnotherRule(r, key) {
1367
+ const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
1368
+ return name !== void 0 && name !== key;
1369
+ }
1370
+ function rules(a, b) {
1371
+ const factory = typeof a === "function" ? a : b;
1372
+ const options = typeof a === "function" ? b : a;
1373
+ const cache = {};
1374
+ const proxy = new Proxy(cache, {
1375
+ get(target, key) {
1376
+ if (typeof key !== "string") return void 0;
1377
+ const record = target;
1378
+ if (!(key in record)) {
1379
+ const r = ref();
1380
+ tagRule(r, key);
1381
+ record[key] = r;
1382
+ }
1383
+ return record[key];
1384
+ }
1385
+ });
1386
+ const definitions = factory(proxy);
1387
+ for (const key of Object.keys(definitions)) {
1388
+ const placeholder = cache[key];
1389
+ const parser2 = definitions[key];
1390
+ if (placeholder === parser2) {
1391
+ throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
1392
+ }
1393
+ if (isDefinableRef(placeholder)) {
1394
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
1395
+ placeholder.define(parser2);
1396
+ placeholder._meta.firstSet = parser2._meta.firstSet;
1397
+ placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
1398
+ } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
1399
+ const alias = ref();
1400
+ tagRule(alias, key);
1401
+ alias.define(parser2);
1402
+ alias._meta.firstSet = parser2._meta.firstSet;
1403
+ alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
1404
+ cache[key] = alias;
1405
+ } else {
1406
+ tagRule(parser2, key);
1407
+ cache[key] = parser2;
1115
1408
  }
1116
1409
  }
1117
- ranges.push({ lo, hi });
1118
- return { kind: "ranges", ranges };
1119
- }
1120
- function inFirstSet(code, fs) {
1121
- if (fs.kind === "any") return true;
1122
- if (fs.kind === "empty") return false;
1123
- for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1124
- return false;
1125
- }
1126
- function areDisjoint(sets) {
1127
- if (sets.some((s) => s.kind === "any")) return false;
1128
- for (let i = 0; i < sets.length; i++)
1129
- for (let j2 = i + 1; j2 < sets.length; j2++)
1130
- if (intersects(sets[i], sets[j2])) return false;
1131
- return true;
1132
- }
1133
- function buildAsciiDispatch(parsers) {
1134
- const table = Array(128).fill(-1);
1135
- for (let i = 0; i < parsers.length; i++) {
1136
- const fs = parsers[i]._meta.firstSet;
1137
- if (fs.kind !== "ranges") continue;
1138
- for (const { lo, hi } of fs.ranges) {
1139
- for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1140
- table[code] = i;
1410
+ if (options?.trivia != null) {
1411
+ for (const key of Object.keys(definitions)) {
1412
+ const rule = cache[key];
1413
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
1414
+ }
1415
+ }
1416
+ if (options?.scanSkip != null) {
1417
+ for (const key of Object.keys(definitions)) {
1418
+ const rule = cache[key];
1419
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
1420
+ }
1421
+ }
1422
+ if (options?.hostMode === "cst") {
1423
+ for (const key of Object.keys(definitions)) {
1424
+ const rule = cache[key];
1425
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
1426
+ }
1427
+ }
1428
+ if (options?.trackLines === true) {
1429
+ for (const key of Object.keys(definitions)) {
1430
+ const rule = cache[key];
1431
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
1432
+ }
1433
+ for (const key of Object.keys(definitions)) {
1434
+ const rule = cache[key];
1435
+ if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
1436
+ const wrapped = parser({ trackLines: true }, rule);
1437
+ tagRule(wrapped, key);
1438
+ wrapped._meta.grammarTrackLines = true;
1439
+ cache[key] = wrapped;
1141
1440
  }
1142
1441
  }
1143
1442
  }
1144
- return table;
1443
+ for (const key of Object.keys(definitions)) {
1444
+ markUnusedValues(cache[key]);
1445
+ }
1446
+ Object.defineProperty(cache, RULE_ORDER, {
1447
+ value: Object.keys(definitions),
1448
+ enumerable: false,
1449
+ configurable: true
1450
+ });
1451
+ attachGrammarReflection(cache, collectGrammarReflection(Object.keys(definitions).map((key) => [key, cache[key]])));
1452
+ return cache;
1145
1453
  }
1146
1454
 
1147
1455
  // src/analysis/duplication.ts
@@ -1396,135 +1704,6 @@ function regex(pattern, flags = "") {
1396
1704
  };
1397
1705
  }
1398
1706
 
1399
- // src/cst/trivia-kinds.ts
1400
- function unwrapTrivia(p) {
1401
- let cur = p;
1402
- while (cur._def.tag === "trivia") cur = cur._def.parser;
1403
- return cur;
1404
- }
1405
- function peelLabel(p) {
1406
- if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
1407
- return null;
1408
- }
1409
- function analyzeLabeledTrivia(trivia2) {
1410
- let core = unwrapTrivia(trivia2);
1411
- let minRepeats = 1;
1412
- if (core._def.tag === "oneOrMore") {
1413
- core = core._def.parser;
1414
- minRepeats = 1;
1415
- } else if (core._def.tag === "many") {
1416
- core = core._def.parser;
1417
- minRepeats = 0;
1418
- }
1419
- const arms = [];
1420
- if (core._def.tag === "choice") {
1421
- for (let i = 0; i < core._def.parsers.length; i++) {
1422
- const peeled = peelLabel(core._def.parsers[i]);
1423
- if (!peeled) return null;
1424
- arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
1425
- }
1426
- } else {
1427
- const peeled = peelLabel(core);
1428
- if (!peeled) return null;
1429
- arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1430
- }
1431
- return { labels: arms.map((a) => a.label), arms, minRepeats };
1432
- }
1433
- function matchArmAt(input, pos, arm) {
1434
- const r = arm.parse(input, pos, { trackLines: false });
1435
- if (!r.ok || r.span.end <= pos) return null;
1436
- return { end: r.span.end };
1437
- }
1438
- function scanLabeledTriviaChunks(input, cur, spec) {
1439
- const chunks = [];
1440
- let pos = cur;
1441
- while (pos < input.length) {
1442
- let matched = null;
1443
- for (const arm of spec.arms) {
1444
- const m = matchArmAt(input, pos, arm.parser);
1445
- if (m) {
1446
- matched = { end: m.end, kindIndex: arm.kindIndex };
1447
- break;
1448
- }
1449
- }
1450
- if (!matched) break;
1451
- chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
1452
- pos = matched.end;
1453
- }
1454
- if (chunks.length < spec.minRepeats) {
1455
- return { end: cur, chunks: [] };
1456
- }
1457
- return { end: pos, chunks };
1458
- }
1459
- function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1460
- const chunks = [];
1461
- let pos = cur;
1462
- while (pos < input.length) {
1463
- const c = input.charCodeAt(pos);
1464
- if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1465
- const start = pos;
1466
- pos++;
1467
- while (pos < input.length) {
1468
- const c2 = input.charCodeAt(pos);
1469
- if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1470
- else break;
1471
- }
1472
- chunks.push({ start, end: pos, kindIndex: wsKind });
1473
- continue;
1474
- }
1475
- if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1476
- let j2 = pos + 2;
1477
- while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
1478
- if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
1479
- const start = pos;
1480
- pos = j2 + 2;
1481
- chunks.push({ start, end: pos, kindIndex: commentKind });
1482
- continue;
1483
- }
1484
- break;
1485
- }
1486
- break;
1487
- }
1488
- return { end: pos, chunks };
1489
- }
1490
- function tryFastLabeledScan(input, cur, trivia2) {
1491
- const spec = analyzeLabeledTrivia(trivia2);
1492
- if (!spec || spec.arms.length !== 2) return null;
1493
- const wsArm = spec.arms.find((a) => {
1494
- const src = getCoreRegexDef(a.parser)?.source;
1495
- return src != null && !src.includes("\\*");
1496
- });
1497
- const commentArm = spec.arms.find((a) => {
1498
- const src = getCoreRegexDef(a.parser)?.source;
1499
- return src != null && src.includes("\\*");
1500
- });
1501
- if (!wsArm || !commentArm) return null;
1502
- const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1503
- if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
1504
- return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1505
- }
1506
- function recordTriviaChunks(ctx, chunks) {
1507
- const kinds = ctx.triviaKindLabels;
1508
- const mask = ctx._triviaCaptureMask;
1509
- for (const ch of chunks) {
1510
- pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1511
- if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1512
- if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
1513
- pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1514
- }
1515
- }
1516
- }
1517
- }
1518
- function triviaKindMask(labels, keep) {
1519
- if (!labels) return void 0;
1520
- let mask = 0;
1521
- for (const name of keep) {
1522
- const idx = labels.indexOf(name);
1523
- if (idx >= 0) mask |= 1 << idx;
1524
- }
1525
- return mask;
1526
- }
1527
-
1528
1707
  // src/combinators/trivia-skip.ts
1529
1708
  var NOOP_COMMIT = () => {
1530
1709
  };
@@ -2896,13 +3075,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2896
3075
  const collapse = opts?.collapse === true;
2897
3076
  const captureTrivia = opts?.captureTrivia === true;
2898
3077
  const trailingTrivia = opts?.trailingTrivia === true;
3078
+ const tags = opts?.tags;
2899
3079
  if (unwrap && collapse) {
2900
3080
  throw new Error("node() options cannot set both unwrap and collapse");
2901
3081
  }
2902
3082
  if (project !== void 0 && (unwrap || collapse)) {
2903
3083
  throw new Error("node() options cannot combine project with unwrap or collapse");
2904
3084
  }
2905
- const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
3085
+ const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
2906
3086
  const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
2907
3087
  const clonesState = build ? buildReadsState(def) : project === void 0;
2908
3088
  const hasOwnFields = parserHasOwnFields(combinator);
@@ -2948,7 +3128,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2948
3128
  const cstOutput = cstOutputHost(ctx.build);
2949
3129
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
2950
3130
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2951
- const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
3131
+ const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2952
3132
  const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
2953
3133
  if (saved.buf !== void 0 || saved.ch !== void 0) {
2954
3134
  pushCstChild(ctx, built, rawEntry);
@@ -2958,71 +3138,6 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2958
3138
  };
2959
3139
  }
2960
3140
 
2961
- // src/combinators/grammar.ts
2962
- function annotateResultLines(result, index) {
2963
- const annotated = { ...result, span: annotateSpan(result.span, index) };
2964
- const errors = annotated.errors;
2965
- if (errors) {
2966
- ;
2967
- annotated.errors = errors.map((error) => ({
2968
- ...error,
2969
- span: annotateSpan(error.span, index)
2970
- }));
2971
- }
2972
- return annotated;
2973
- }
2974
- function createParseLineContext(input, pos) {
2975
- const lineIndex = createLineIndex();
2976
- if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
2977
- return { lineIndex, lineScannedTo: pos };
2978
- }
2979
- function parser(opts, root) {
2980
- const clearTrivia = opts.trivia === null;
2981
- return {
2982
- _tag: "grammar",
2983
- _meta: root._meta,
2984
- _def: {
2985
- tag: "grammar",
2986
- parser: root,
2987
- triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
2988
- clearTrivia,
2989
- ...opts.captureTrivia ? { captureTrivia: true } : {},
2990
- trackLines: opts.trackLines ?? false
2991
- },
2992
- parse(input, pos, _ctx) {
2993
- const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
2994
- const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
2995
- const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
2996
- const ctx = {
2997
- ..._ctx,
2998
- trackLines,
2999
- ...lineIndex ? { _lineIndex: lineIndex } : {},
3000
- ...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
3001
- // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
3002
- ...clearTrivia ? {
3003
- trivia: void 0,
3004
- triviaKindLabels: void 0
3005
- } : opts.trivia != null ? {
3006
- trivia: opts.trivia,
3007
- ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
3008
- } : {},
3009
- ...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
3010
- // Kind-filter for per-node capture. Resolve against this scope's trivia
3011
- // labels — this parser's own trivia if it declares one, else the INHERITED
3012
- // labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
3013
- // trivia is inherited rather than re-declared here. No labels → undefined
3014
- // (capture all).
3015
- ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
3016
- };
3017
- const result = root.parse(input, pos ?? 0, ctx);
3018
- if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
3019
- _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
3020
- }
3021
- return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
3022
- }
3023
- };
3024
- }
3025
-
3026
3141
  // src/combinators/token.ts
3027
3142
  function token(root) {
3028
3143
  const meta = {
@@ -3305,15 +3420,16 @@ function normalizeCstCollapse(collapse) {
3305
3420
  }
3306
3421
  return typeof collapse === "function" ? collapse : void 0;
3307
3422
  }
3308
- function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
3309
- return { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children] };
3423
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state, tags) {
3424
+ return tags !== void 0 && tags.length > 0 ? { _tag: "node", type, tags, span: { ...span }, state: state ?? null, children: [...children] } : { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children] };
3310
3425
  }
3311
- function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
3426
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state, _tags) {
3312
3427
  if (typeof typeOrOptions === "string") {
3313
3428
  return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
3314
3429
  }
3315
3430
  const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
3316
- const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2 ?? [], fields, span2, rawChildren2, triviaLog2, state2);
3431
+ const materializeTags = typeOrOptions?.tags === true;
3432
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children2 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
3317
3433
  host._parsemanCstOutput = true;
3318
3434
  if (collapse) host._parsemanCstCollapse = collapse;
3319
3435
  return host;