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
@@ -391,92 +391,6 @@ function markUnusedValues(root) {
391
391
  visit(resolveRoot(root), true);
392
392
  }
393
393
 
394
- // src/combinators/parser.ts
395
- var RULE_ORDER = "__parsemanRuleOrder";
396
- function tagRule(r, key) {
397
- ;
398
- r._ruleName = key;
399
- if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
400
- }
401
- function isDefinableRef(v) {
402
- return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
403
- }
404
- function ruleNameOf(r) {
405
- return r._ruleName;
406
- }
407
- function isNamedRuleRefForAnotherRule(r, key) {
408
- const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
409
- return name !== void 0 && name !== key;
410
- }
411
- function rules(a, b) {
412
- const factory = typeof a === "function" ? a : b;
413
- const options = typeof a === "function" ? b : a;
414
- const cache = {};
415
- const proxy = new Proxy(cache, {
416
- get(target, key) {
417
- if (typeof key !== "string") return void 0;
418
- const record = target;
419
- if (!(key in record)) {
420
- const r = ref();
421
- tagRule(r, key);
422
- record[key] = r;
423
- }
424
- return record[key];
425
- }
426
- });
427
- const definitions = factory(proxy);
428
- for (const key of Object.keys(definitions)) {
429
- const placeholder = cache[key];
430
- const parser2 = definitions[key];
431
- if (placeholder === parser2) {
432
- throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
433
- }
434
- if (isDefinableRef(placeholder)) {
435
- if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
436
- placeholder.define(parser2);
437
- placeholder._meta.firstSet = parser2._meta.firstSet;
438
- placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
439
- } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
440
- const alias = ref();
441
- tagRule(alias, key);
442
- alias.define(parser2);
443
- alias._meta.firstSet = parser2._meta.firstSet;
444
- alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
445
- cache[key] = alias;
446
- } else {
447
- tagRule(parser2, key);
448
- cache[key] = parser2;
449
- }
450
- }
451
- if (options?.trivia != null) {
452
- for (const key of Object.keys(definitions)) {
453
- const rule = cache[key];
454
- if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
455
- }
456
- }
457
- if (options?.scanSkip != null) {
458
- for (const key of Object.keys(definitions)) {
459
- const rule = cache[key];
460
- if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
461
- }
462
- }
463
- if (options?.hostMode === "cst") {
464
- for (const key of Object.keys(definitions)) {
465
- const rule = cache[key];
466
- if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
467
- }
468
- }
469
- for (const key of Object.keys(definitions)) {
470
- markUnusedValues(cache[key]);
471
- }
472
- Object.defineProperty(cache, RULE_ORDER, {
473
- value: Object.keys(definitions),
474
- enumerable: false,
475
- configurable: true
476
- });
477
- return cache;
478
- }
479
-
480
394
  // src/line-index.ts
481
395
  function createLineIndex() {
482
396
  return { lineStarts: [0] };
@@ -1144,38 +1058,432 @@ function codesToFirstSet(codes) {
1144
1058
  if (codes[i] === hi + 1) {
1145
1059
  hi = codes[i];
1146
1060
  } else {
1147
- ranges.push({ lo, hi });
1148
- lo = hi = codes[i];
1061
+ ranges.push({ lo, hi });
1062
+ lo = hi = codes[i];
1063
+ }
1064
+ }
1065
+ ranges.push({ lo, hi });
1066
+ return { kind: "ranges", ranges };
1067
+ }
1068
+ function inFirstSet(code, fs) {
1069
+ if (fs.kind === "any") return true;
1070
+ if (fs.kind === "empty") return false;
1071
+ for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1072
+ return false;
1073
+ }
1074
+ function areDisjoint(sets) {
1075
+ if (sets.some((s) => s.kind === "any")) return false;
1076
+ for (let i = 0; i < sets.length; i++)
1077
+ for (let j2 = i + 1; j2 < sets.length; j2++)
1078
+ if (intersects(sets[i], sets[j2])) return false;
1079
+ return true;
1080
+ }
1081
+ function buildAsciiDispatch(parsers) {
1082
+ const table = Array(128).fill(-1);
1083
+ for (let i = 0; i < parsers.length; i++) {
1084
+ const fs = parsers[i]._meta.firstSet;
1085
+ if (fs.kind !== "ranges") continue;
1086
+ for (const { lo, hi } of fs.ranges) {
1087
+ for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1088
+ table[code] = i;
1089
+ }
1090
+ }
1091
+ }
1092
+ return table;
1093
+ }
1094
+
1095
+ // src/cst/trivia-kinds.ts
1096
+ function unwrapTrivia(p) {
1097
+ let cur = p;
1098
+ while (cur._def.tag === "trivia") cur = cur._def.parser;
1099
+ return cur;
1100
+ }
1101
+ function peelLabel(p) {
1102
+ if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
1103
+ return null;
1104
+ }
1105
+ function analyzeLabeledTrivia(trivia2) {
1106
+ let core = unwrapTrivia(trivia2);
1107
+ let minRepeats = 1;
1108
+ if (core._def.tag === "oneOrMore") {
1109
+ core = core._def.parser;
1110
+ minRepeats = 1;
1111
+ } else if (core._def.tag === "many") {
1112
+ core = core._def.parser;
1113
+ minRepeats = 0;
1114
+ }
1115
+ const arms = [];
1116
+ if (core._def.tag === "choice") {
1117
+ for (let i = 0; i < core._def.parsers.length; i++) {
1118
+ const peeled = peelLabel(core._def.parsers[i]);
1119
+ if (!peeled) return null;
1120
+ arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
1121
+ }
1122
+ } else {
1123
+ const peeled = peelLabel(core);
1124
+ if (!peeled) return null;
1125
+ arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1126
+ }
1127
+ return { labels: arms.map((a) => a.label), arms, minRepeats };
1128
+ }
1129
+ function matchArmAt(input, pos, arm) {
1130
+ const r = arm.parse(input, pos, { trackLines: false });
1131
+ if (!r.ok || r.span.end <= pos) return null;
1132
+ return { end: r.span.end };
1133
+ }
1134
+ function scanLabeledTriviaChunks(input, cur, spec) {
1135
+ const chunks = [];
1136
+ let pos = cur;
1137
+ while (pos < input.length) {
1138
+ let matched = null;
1139
+ for (const arm of spec.arms) {
1140
+ const m = matchArmAt(input, pos, arm.parser);
1141
+ if (m) {
1142
+ matched = { end: m.end, kindIndex: arm.kindIndex };
1143
+ break;
1144
+ }
1145
+ }
1146
+ if (!matched) break;
1147
+ chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
1148
+ pos = matched.end;
1149
+ }
1150
+ if (chunks.length < spec.minRepeats) {
1151
+ return { end: cur, chunks: [] };
1152
+ }
1153
+ return { end: pos, chunks };
1154
+ }
1155
+ function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1156
+ const chunks = [];
1157
+ let pos = cur;
1158
+ while (pos < input.length) {
1159
+ const c = input.charCodeAt(pos);
1160
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1161
+ const start = pos;
1162
+ pos++;
1163
+ while (pos < input.length) {
1164
+ const c2 = input.charCodeAt(pos);
1165
+ if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1166
+ else break;
1167
+ }
1168
+ chunks.push({ start, end: pos, kindIndex: wsKind });
1169
+ continue;
1170
+ }
1171
+ if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1172
+ let j2 = pos + 2;
1173
+ while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
1174
+ if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
1175
+ const start = pos;
1176
+ pos = j2 + 2;
1177
+ chunks.push({ start, end: pos, kindIndex: commentKind });
1178
+ continue;
1179
+ }
1180
+ break;
1181
+ }
1182
+ break;
1183
+ }
1184
+ return { end: pos, chunks };
1185
+ }
1186
+ function tryFastLabeledScan(input, cur, trivia2) {
1187
+ const spec = analyzeLabeledTrivia(trivia2);
1188
+ if (!spec || spec.arms.length !== 2) return null;
1189
+ const wsArm = spec.arms.find((a) => {
1190
+ const src = getCoreRegexDef(a.parser)?.source;
1191
+ return src != null && !src.includes("\\*");
1192
+ });
1193
+ const commentArm = spec.arms.find((a) => {
1194
+ const src = getCoreRegexDef(a.parser)?.source;
1195
+ return src != null && src.includes("\\*");
1196
+ });
1197
+ if (!wsArm || !commentArm) return null;
1198
+ const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1199
+ if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
1200
+ return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1201
+ }
1202
+ function recordTriviaChunks(ctx, chunks) {
1203
+ const kinds = ctx.triviaKindLabels;
1204
+ const mask = ctx._triviaCaptureMask;
1205
+ for (const ch of chunks) {
1206
+ pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1207
+ if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1208
+ if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
1209
+ pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+ function triviaKindMask(labels, keep) {
1215
+ if (!labels) return void 0;
1216
+ let mask = 0;
1217
+ for (const name of keep) {
1218
+ const idx = labels.indexOf(name);
1219
+ if (idx >= 0) mask |= 1 << idx;
1220
+ }
1221
+ return mask;
1222
+ }
1223
+
1224
+ // src/combinators/grammar.ts
1225
+ function annotateResultLines(result, index) {
1226
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
1227
+ const errors = annotated.errors;
1228
+ if (errors) {
1229
+ ;
1230
+ annotated.errors = errors.map((error) => ({
1231
+ ...error,
1232
+ span: annotateSpan(error.span, index)
1233
+ }));
1234
+ }
1235
+ return annotated;
1236
+ }
1237
+ function createParseLineContext(input, pos) {
1238
+ const lineIndex = createLineIndex();
1239
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
1240
+ return { lineIndex, lineScannedTo: pos };
1241
+ }
1242
+ function parser(opts, root) {
1243
+ const clearTrivia = opts.trivia === null;
1244
+ return {
1245
+ _tag: "grammar",
1246
+ _meta: root._meta,
1247
+ _def: {
1248
+ tag: "grammar",
1249
+ parser: root,
1250
+ triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
1251
+ clearTrivia,
1252
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
1253
+ trackLines: opts.trackLines ?? false
1254
+ },
1255
+ parse(input, pos, _ctx) {
1256
+ const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
1257
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
1258
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
1259
+ const ctx = {
1260
+ ..._ctx,
1261
+ trackLines,
1262
+ ...lineIndex ? { _lineIndex: lineIndex } : {},
1263
+ ...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
1264
+ // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
1265
+ ...clearTrivia ? {
1266
+ trivia: void 0,
1267
+ triviaKindLabels: void 0
1268
+ } : opts.trivia != null ? {
1269
+ trivia: opts.trivia,
1270
+ ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
1271
+ } : {},
1272
+ ...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
1273
+ // Kind-filter for per-node capture. Resolve against this scope's trivia
1274
+ // labels — this parser's own trivia if it declares one, else the INHERITED
1275
+ // labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
1276
+ // trivia is inherited rather than re-declared here. No labels → undefined
1277
+ // (capture all).
1278
+ ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
1279
+ };
1280
+ const result = root.parse(input, pos ?? 0, ctx);
1281
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
1282
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
1283
+ }
1284
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1285
+ }
1286
+ };
1287
+ }
1288
+
1289
+ // src/cst/reflection.ts
1290
+ var GRAMMAR_REFLECTION = /* @__PURE__ */ Symbol.for("parseman.grammarReflection");
1291
+ function childrenOf(def) {
1292
+ switch (def.tag) {
1293
+ case "sequence":
1294
+ case "choice":
1295
+ return def.parsers;
1296
+ case "dispatch":
1297
+ return [
1298
+ def.selector,
1299
+ ...def.cases.map((c) => c.parser),
1300
+ ...def.matchers ? def.matchers.map((c) => c.parser) : [],
1301
+ ...def.otherwise ? [def.otherwise] : []
1302
+ ];
1303
+ case "many":
1304
+ case "oneOrMore":
1305
+ case "optional":
1306
+ case "attempt":
1307
+ case "transform":
1308
+ case "trivia":
1309
+ case "token":
1310
+ case "leaf":
1311
+ case "label":
1312
+ case "field":
1313
+ case "not":
1314
+ case "peek":
1315
+ case "node":
1316
+ case "withCtx":
1317
+ case "recover":
1318
+ case "expect":
1319
+ return [def.parser];
1320
+ case "grammar":
1321
+ return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
1322
+ case "sepBy":
1323
+ return [def.parser, def.separator];
1324
+ case "skip":
1325
+ return [def.main, def.skipped];
1326
+ case "scanTo":
1327
+ return [def.sentinel, ...def.skip];
1328
+ case "literal":
1329
+ case "regex":
1330
+ case "keywords":
1331
+ case "routed":
1332
+ case "guard":
1333
+ case "lazy":
1334
+ case "unknown":
1335
+ return [];
1336
+ }
1337
+ }
1338
+ function addNode(out, def) {
1339
+ if (def.type === void 0) return;
1340
+ const existing = out.get(def.type);
1341
+ if (existing === void 0) {
1342
+ out.set(def.type, def.tags === void 0 ? [] : [...def.tags]);
1343
+ return;
1344
+ }
1345
+ if (def.tags === void 0) return;
1346
+ for (const tag of def.tags) {
1347
+ if (!existing.includes(tag)) existing.push(tag);
1348
+ }
1349
+ }
1350
+ function collectFromCombinator(parser2, out, seen, followLazy = true) {
1351
+ if (seen.has(parser2)) return;
1352
+ seen.add(parser2);
1353
+ const def = parser2._def;
1354
+ if (def.tag === "lazy") {
1355
+ if (followLazy) {
1356
+ try {
1357
+ collectFromCombinator(def.thunk(), out, seen, followLazy);
1358
+ } catch {
1359
+ }
1360
+ }
1361
+ return;
1362
+ }
1363
+ if (def.tag === "node") addNode(out, def);
1364
+ for (const child of childrenOf(def)) collectFromCombinator(child, out, seen, followLazy);
1365
+ }
1366
+ function collectGrammarReflection(ruleMap, opts) {
1367
+ const byType = /* @__PURE__ */ new Map();
1368
+ const followLazy = opts?.followLazy !== false;
1369
+ for (const [, rule] of ruleMap) {
1370
+ if (!followLazy && rule._def.tag === "lazy") {
1371
+ try {
1372
+ const resolved = rule._def.thunk();
1373
+ if (resolved._def.tag !== "lazy") collectFromCombinator(resolved, byType, /* @__PURE__ */ new Set(), false);
1374
+ } catch {
1375
+ }
1376
+ continue;
1377
+ }
1378
+ collectFromCombinator(rule, byType, /* @__PURE__ */ new Set(), followLazy);
1379
+ }
1380
+ return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
1381
+ }
1382
+ function attachGrammarReflection(grammar, reflection) {
1383
+ Object.defineProperty(grammar, GRAMMAR_REFLECTION, { value: reflection, enumerable: false, configurable: true });
1384
+ return grammar;
1385
+ }
1386
+
1387
+ // src/combinators/parser.ts
1388
+ var RULE_ORDER = "__parsemanRuleOrder";
1389
+ function tagRule(r, key) {
1390
+ ;
1391
+ r._ruleName = key;
1392
+ if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
1393
+ }
1394
+ function isDefinableRef(v) {
1395
+ return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
1396
+ }
1397
+ function ruleNameOf(r) {
1398
+ return r._ruleName;
1399
+ }
1400
+ function isNamedRuleRefForAnotherRule(r, key) {
1401
+ const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
1402
+ return name !== void 0 && name !== key;
1403
+ }
1404
+ function rules(a, b) {
1405
+ const factory = typeof a === "function" ? a : b;
1406
+ const options = typeof a === "function" ? b : a;
1407
+ const cache = {};
1408
+ const proxy = new Proxy(cache, {
1409
+ get(target, key) {
1410
+ if (typeof key !== "string") return void 0;
1411
+ const record = target;
1412
+ if (!(key in record)) {
1413
+ const r = ref();
1414
+ tagRule(r, key);
1415
+ record[key] = r;
1416
+ }
1417
+ return record[key];
1418
+ }
1419
+ });
1420
+ const definitions = factory(proxy);
1421
+ for (const key of Object.keys(definitions)) {
1422
+ const placeholder = cache[key];
1423
+ const parser2 = definitions[key];
1424
+ if (placeholder === parser2) {
1425
+ throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
1426
+ }
1427
+ if (isDefinableRef(placeholder)) {
1428
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
1429
+ placeholder.define(parser2);
1430
+ placeholder._meta.firstSet = parser2._meta.firstSet;
1431
+ placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
1432
+ } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
1433
+ const alias = ref();
1434
+ tagRule(alias, key);
1435
+ alias.define(parser2);
1436
+ alias._meta.firstSet = parser2._meta.firstSet;
1437
+ alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
1438
+ cache[key] = alias;
1439
+ } else {
1440
+ tagRule(parser2, key);
1441
+ cache[key] = parser2;
1149
1442
  }
1150
1443
  }
1151
- ranges.push({ lo, hi });
1152
- return { kind: "ranges", ranges };
1153
- }
1154
- function inFirstSet(code, fs) {
1155
- if (fs.kind === "any") return true;
1156
- if (fs.kind === "empty") return false;
1157
- for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1158
- return false;
1159
- }
1160
- function areDisjoint(sets) {
1161
- if (sets.some((s) => s.kind === "any")) return false;
1162
- for (let i = 0; i < sets.length; i++)
1163
- for (let j2 = i + 1; j2 < sets.length; j2++)
1164
- if (intersects(sets[i], sets[j2])) return false;
1165
- return true;
1166
- }
1167
- function buildAsciiDispatch(parsers) {
1168
- const table = Array(128).fill(-1);
1169
- for (let i = 0; i < parsers.length; i++) {
1170
- const fs = parsers[i]._meta.firstSet;
1171
- if (fs.kind !== "ranges") continue;
1172
- for (const { lo, hi } of fs.ranges) {
1173
- for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1174
- table[code] = i;
1444
+ if (options?.trivia != null) {
1445
+ for (const key of Object.keys(definitions)) {
1446
+ const rule = cache[key];
1447
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
1448
+ }
1449
+ }
1450
+ if (options?.scanSkip != null) {
1451
+ for (const key of Object.keys(definitions)) {
1452
+ const rule = cache[key];
1453
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
1454
+ }
1455
+ }
1456
+ if (options?.hostMode === "cst") {
1457
+ for (const key of Object.keys(definitions)) {
1458
+ const rule = cache[key];
1459
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
1460
+ }
1461
+ }
1462
+ if (options?.trackLines === true) {
1463
+ for (const key of Object.keys(definitions)) {
1464
+ const rule = cache[key];
1465
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
1466
+ }
1467
+ for (const key of Object.keys(definitions)) {
1468
+ const rule = cache[key];
1469
+ if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
1470
+ const wrapped = parser({ trackLines: true }, rule);
1471
+ tagRule(wrapped, key);
1472
+ wrapped._meta.grammarTrackLines = true;
1473
+ cache[key] = wrapped;
1175
1474
  }
1176
1475
  }
1177
1476
  }
1178
- return table;
1477
+ for (const key of Object.keys(definitions)) {
1478
+ markUnusedValues(cache[key]);
1479
+ }
1480
+ Object.defineProperty(cache, RULE_ORDER, {
1481
+ value: Object.keys(definitions),
1482
+ enumerable: false,
1483
+ configurable: true
1484
+ });
1485
+ attachGrammarReflection(cache, collectGrammarReflection(Object.keys(definitions).map((key) => [key, cache[key]])));
1486
+ return cache;
1179
1487
  }
1180
1488
 
1181
1489
  // src/analysis/duplication.ts
@@ -1430,135 +1738,6 @@ function regex(pattern, flags = "") {
1430
1738
  };
1431
1739
  }
1432
1740
 
1433
- // src/cst/trivia-kinds.ts
1434
- function unwrapTrivia(p) {
1435
- let cur = p;
1436
- while (cur._def.tag === "trivia") cur = cur._def.parser;
1437
- return cur;
1438
- }
1439
- function peelLabel(p) {
1440
- if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
1441
- return null;
1442
- }
1443
- function analyzeLabeledTrivia(trivia2) {
1444
- let core = unwrapTrivia(trivia2);
1445
- let minRepeats = 1;
1446
- if (core._def.tag === "oneOrMore") {
1447
- core = core._def.parser;
1448
- minRepeats = 1;
1449
- } else if (core._def.tag === "many") {
1450
- core = core._def.parser;
1451
- minRepeats = 0;
1452
- }
1453
- const arms = [];
1454
- if (core._def.tag === "choice") {
1455
- for (let i = 0; i < core._def.parsers.length; i++) {
1456
- const peeled = peelLabel(core._def.parsers[i]);
1457
- if (!peeled) return null;
1458
- arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
1459
- }
1460
- } else {
1461
- const peeled = peelLabel(core);
1462
- if (!peeled) return null;
1463
- arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1464
- }
1465
- return { labels: arms.map((a) => a.label), arms, minRepeats };
1466
- }
1467
- function matchArmAt(input, pos, arm) {
1468
- const r = arm.parse(input, pos, { trackLines: false });
1469
- if (!r.ok || r.span.end <= pos) return null;
1470
- return { end: r.span.end };
1471
- }
1472
- function scanLabeledTriviaChunks(input, cur, spec) {
1473
- const chunks = [];
1474
- let pos = cur;
1475
- while (pos < input.length) {
1476
- let matched = null;
1477
- for (const arm of spec.arms) {
1478
- const m = matchArmAt(input, pos, arm.parser);
1479
- if (m) {
1480
- matched = { end: m.end, kindIndex: arm.kindIndex };
1481
- break;
1482
- }
1483
- }
1484
- if (!matched) break;
1485
- chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
1486
- pos = matched.end;
1487
- }
1488
- if (chunks.length < spec.minRepeats) {
1489
- return { end: cur, chunks: [] };
1490
- }
1491
- return { end: pos, chunks };
1492
- }
1493
- function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1494
- const chunks = [];
1495
- let pos = cur;
1496
- while (pos < input.length) {
1497
- const c = input.charCodeAt(pos);
1498
- if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1499
- const start = pos;
1500
- pos++;
1501
- while (pos < input.length) {
1502
- const c2 = input.charCodeAt(pos);
1503
- if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1504
- else break;
1505
- }
1506
- chunks.push({ start, end: pos, kindIndex: wsKind });
1507
- continue;
1508
- }
1509
- if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1510
- let j2 = pos + 2;
1511
- while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
1512
- if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
1513
- const start = pos;
1514
- pos = j2 + 2;
1515
- chunks.push({ start, end: pos, kindIndex: commentKind });
1516
- continue;
1517
- }
1518
- break;
1519
- }
1520
- break;
1521
- }
1522
- return { end: pos, chunks };
1523
- }
1524
- function tryFastLabeledScan(input, cur, trivia2) {
1525
- const spec = analyzeLabeledTrivia(trivia2);
1526
- if (!spec || spec.arms.length !== 2) return null;
1527
- const wsArm = spec.arms.find((a) => {
1528
- const src = getCoreRegexDef(a.parser)?.source;
1529
- return src != null && !src.includes("\\*");
1530
- });
1531
- const commentArm = spec.arms.find((a) => {
1532
- const src = getCoreRegexDef(a.parser)?.source;
1533
- return src != null && src.includes("\\*");
1534
- });
1535
- if (!wsArm || !commentArm) return null;
1536
- const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1537
- if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
1538
- return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1539
- }
1540
- function recordTriviaChunks(ctx, chunks) {
1541
- const kinds = ctx.triviaKindLabels;
1542
- const mask = ctx._triviaCaptureMask;
1543
- for (const ch of chunks) {
1544
- pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1545
- if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1546
- if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
1547
- pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1548
- }
1549
- }
1550
- }
1551
- }
1552
- function triviaKindMask(labels, keep) {
1553
- if (!labels) return void 0;
1554
- let mask = 0;
1555
- for (const name of keep) {
1556
- const idx = labels.indexOf(name);
1557
- if (idx >= 0) mask |= 1 << idx;
1558
- }
1559
- return mask;
1560
- }
1561
-
1562
1741
  // src/combinators/trivia-skip.ts
1563
1742
  var NOOP_COMMIT = () => {
1564
1743
  };
@@ -2930,13 +3109,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2930
3109
  const collapse = opts?.collapse === true;
2931
3110
  const captureTrivia = opts?.captureTrivia === true;
2932
3111
  const trailingTrivia = opts?.trailingTrivia === true;
3112
+ const tags = opts?.tags;
2933
3113
  if (unwrap && collapse) {
2934
3114
  throw new Error("node() options cannot set both unwrap and collapse");
2935
3115
  }
2936
3116
  if (project !== void 0 && (unwrap || collapse)) {
2937
3117
  throw new Error("node() options cannot combine project with unwrap or collapse");
2938
3118
  }
2939
- 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;
3119
+ 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;
2940
3120
  const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
2941
3121
  const clonesState = build ? buildReadsState(def) : project === void 0;
2942
3122
  const hasOwnFields = parserHasOwnFields(combinator);
@@ -2982,7 +3162,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2982
3162
  const cstOutput = cstOutputHost(ctx.build);
2983
3163
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
2984
3164
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2985
- 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 };
3165
+ 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 };
2986
3166
  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 };
2987
3167
  if (saved.buf !== void 0 || saved.ch !== void 0) {
2988
3168
  pushCstChild(ctx, built, rawEntry);
@@ -2992,71 +3172,6 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2992
3172
  };
2993
3173
  }
2994
3174
 
2995
- // src/combinators/grammar.ts
2996
- function annotateResultLines(result, index) {
2997
- const annotated = { ...result, span: annotateSpan(result.span, index) };
2998
- const errors = annotated.errors;
2999
- if (errors) {
3000
- ;
3001
- annotated.errors = errors.map((error) => ({
3002
- ...error,
3003
- span: annotateSpan(error.span, index)
3004
- }));
3005
- }
3006
- return annotated;
3007
- }
3008
- function createParseLineContext(input, pos) {
3009
- const lineIndex = createLineIndex();
3010
- if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
3011
- return { lineIndex, lineScannedTo: pos };
3012
- }
3013
- function parser(opts, root) {
3014
- const clearTrivia = opts.trivia === null;
3015
- return {
3016
- _tag: "grammar",
3017
- _meta: root._meta,
3018
- _def: {
3019
- tag: "grammar",
3020
- parser: root,
3021
- triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
3022
- clearTrivia,
3023
- ...opts.captureTrivia ? { captureTrivia: true } : {},
3024
- trackLines: opts.trackLines ?? false
3025
- },
3026
- parse(input, pos, _ctx) {
3027
- const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
3028
- const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
3029
- const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
3030
- const ctx = {
3031
- ..._ctx,
3032
- trackLines,
3033
- ...lineIndex ? { _lineIndex: lineIndex } : {},
3034
- ...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
3035
- // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
3036
- ...clearTrivia ? {
3037
- trivia: void 0,
3038
- triviaKindLabels: void 0
3039
- } : opts.trivia != null ? {
3040
- trivia: opts.trivia,
3041
- ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
3042
- } : {},
3043
- ...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
3044
- // Kind-filter for per-node capture. Resolve against this scope's trivia
3045
- // labels — this parser's own trivia if it declares one, else the INHERITED
3046
- // labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
3047
- // trivia is inherited rather than re-declared here. No labels → undefined
3048
- // (capture all).
3049
- ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
3050
- };
3051
- const result = root.parse(input, pos ?? 0, ctx);
3052
- if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
3053
- _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
3054
- }
3055
- return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
3056
- }
3057
- };
3058
- }
3059
-
3060
3175
  // src/combinators/token.ts
3061
3176
  function token(root) {
3062
3177
  const meta = {
@@ -3339,15 +3454,16 @@ function normalizeCstCollapse(collapse) {
3339
3454
  }
3340
3455
  return typeof collapse === "function" ? collapse : void 0;
3341
3456
  }
3342
- function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
3343
- return { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children] };
3457
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state, tags) {
3458
+ 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] };
3344
3459
  }
3345
- function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
3460
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state, _tags) {
3346
3461
  if (typeof typeOrOptions === "string") {
3347
3462
  return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
3348
3463
  }
3349
3464
  const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
3350
- const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2 ?? [], fields, span2, rawChildren2, triviaLog2, state2);
3465
+ const materializeTags = typeOrOptions?.tags === true;
3466
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children2 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
3351
3467
  host._parsemanCstOutput = true;
3352
3468
  if (collapse) host._parsemanCstCollapse = collapse;
3353
3469
  return host;