parseman 0.17.0 → 0.18.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.
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export type { BuildNode, NodeOptions } from './combinators/node.ts';
15
15
  export { transform, skip, trivia, label } from './combinators/map.ts';
16
16
  export { parse, parser, noTrivia } from './combinators/grammar.ts';
17
17
  export type { ParseOptions, ParserOptions, ParsemanParser } from './combinators/grammar.ts';
18
+ export { token } from './combinators/token.ts';
18
19
  export { compile } from './compiler/codegen.ts';
19
20
  export type { CompiledParser, LinkablePieces } from './compiler/codegen.ts';
20
21
  export { compose, pick, cstBuildHost } from './compiler/linker.ts';
@@ -24,7 +25,7 @@ export type { LineIndex } from './compiler/line-index.ts';
24
25
  export { guard } from './combinators/guard.ts';
25
26
  export { withCtx } from './combinators/withCtx.ts';
26
27
  export { recover, isParseError } from './combinators/recover.ts';
27
- export { expect, staticExpected } from './combinators/expect.ts';
28
+ export { expect } from './combinators/expect.ts';
28
29
  export { completionsAt } from './combinators/completions.ts';
29
30
  export { scanTo, balanced } from './combinators/scanTo.ts';
30
31
  export type { ScanToOptions } from './combinators/scanTo.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -58,6 +58,7 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set()) {
58
58
  case "transform":
59
59
  case "label":
60
60
  case "trivia":
61
+ case "token":
61
62
  case "expect":
62
63
  case "withCtx":
63
64
  case "node":
@@ -120,6 +121,7 @@ function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
120
121
  case "transform":
121
122
  case "label":
122
123
  case "trivia":
124
+ case "token":
123
125
  case "node":
124
126
  case "grammar":
125
127
  case "expect":
@@ -1246,6 +1248,7 @@ function markUnusedValues(root) {
1246
1248
  return;
1247
1249
  case "label":
1248
1250
  case "trivia":
1251
+ case "token":
1249
1252
  case "withCtx":
1250
1253
  case "expect":
1251
1254
  visit(def.parser, consumed);
@@ -1447,7 +1450,11 @@ function label(name, combinator) {
1447
1450
  _tag: combinator._tag,
1448
1451
  _meta: combinator._meta,
1449
1452
  _def: { tag: "label", label: name, parser: combinator },
1450
- parse: combinator.parse.bind(combinator)
1453
+ parse(input, pos, ctx) {
1454
+ const result = combinator.parse(input, pos, ctx);
1455
+ if (!result.ok) return { ...result, expected: [name] };
1456
+ return result;
1457
+ }
1451
1458
  };
1452
1459
  }
1453
1460
 
@@ -1546,8 +1553,60 @@ function parse(combinator, input, opts = {}) {
1546
1553
  return withErrors;
1547
1554
  }
1548
1555
 
1556
+ // src/combinators/token.ts
1557
+ function token(root) {
1558
+ const meta = {
1559
+ firstSet: root._meta.firstSet,
1560
+ canMatchNewline: root._meta.canMatchNewline,
1561
+ isTrivia: false
1562
+ };
1563
+ return {
1564
+ _tag: "token",
1565
+ _meta: meta,
1566
+ _def: { tag: "token", parser: root },
1567
+ parse(input, pos, ctx) {
1568
+ const savedTrivia = ctx.trivia;
1569
+ const savedKinds = ctx.triviaKindLabels;
1570
+ const savedBuf = ctx._cstBuf;
1571
+ const savedChildren = ctx._cstChildren;
1572
+ const savedLeaves = ctx._cstLeaves;
1573
+ const savedRaw = ctx._cstRawChildren;
1574
+ const savedTriviaLog = ctx._cstTriviaLog;
1575
+ const savedOuterTriviaLog = ctx._triviaLog;
1576
+ const wasCapturing = cstCaptureActive(ctx);
1577
+ ctx.trivia = void 0;
1578
+ ctx.triviaKindLabels = void 0;
1579
+ ctx._cstBuf = void 0;
1580
+ ctx._cstChildren = void 0;
1581
+ ctx._cstLeaves = void 0;
1582
+ ctx._cstRawChildren = void 0;
1583
+ ctx._cstTriviaLog = void 0;
1584
+ delete ctx._triviaLog;
1585
+ let result;
1586
+ try {
1587
+ result = root.parse(input, pos, ctx);
1588
+ } finally {
1589
+ ctx.trivia = savedTrivia;
1590
+ ctx.triviaKindLabels = savedKinds;
1591
+ ctx._cstBuf = savedBuf;
1592
+ ctx._cstChildren = savedChildren;
1593
+ ctx._cstLeaves = savedLeaves;
1594
+ ctx._cstRawChildren = savedRaw;
1595
+ ctx._cstTriviaLog = savedTriviaLog;
1596
+ if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
1597
+ else ctx._triviaLog = savedOuterTriviaLog;
1598
+ }
1599
+ if (!result.ok) return result;
1600
+ const span = result.span;
1601
+ const value = input.slice(pos, span.end);
1602
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
1603
+ return { ok: true, value, span };
1604
+ }
1605
+ };
1606
+ }
1607
+
1549
1608
  // src/combinators/expect.ts
1550
- function staticExpected(c) {
1609
+ function deriveExpected(c) {
1551
1610
  const def = c._def;
1552
1611
  switch (def.tag) {
1553
1612
  case "literal":
@@ -1559,22 +1618,23 @@ function staticExpected(c) {
1559
1618
  case "label":
1560
1619
  return [def.label];
1561
1620
  case "choice":
1562
- return def.parsers.flatMap(staticExpected);
1621
+ return def.parsers.flatMap(deriveExpected);
1563
1622
  case "sequence":
1564
- return def.parsers.length > 0 ? staticExpected(def.parsers[0]) : [];
1623
+ return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1565
1624
  case "node":
1566
1625
  case "grammar":
1567
1626
  case "trivia":
1627
+ case "token":
1568
1628
  case "optional":
1569
1629
  case "many":
1570
1630
  case "oneOrMore":
1571
1631
  case "transform":
1572
1632
  case "not":
1573
- return staticExpected(def.parser);
1633
+ return deriveExpected(def.parser);
1574
1634
  case "lazy": {
1575
1635
  const name = c._ruleName;
1576
1636
  try {
1577
- return staticExpected(def.thunk());
1637
+ return deriveExpected(def.thunk());
1578
1638
  } catch {
1579
1639
  return name ? [name] : [];
1580
1640
  }
@@ -1584,7 +1644,7 @@ function staticExpected(c) {
1584
1644
  }
1585
1645
  }
1586
1646
  function expect(combinator, label2) {
1587
- const expected = label2 !== void 0 ? [label2] : staticExpected(combinator);
1647
+ const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
1588
1648
  const meta = {
1589
1649
  firstSet: combinator._meta.firstSet,
1590
1650
  canMatchNewline: combinator._meta.canMatchNewline,
@@ -3236,6 +3296,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
3236
3296
  case "guard":
3237
3297
  case "not":
3238
3298
  case "trivia":
3299
+ case "token":
3239
3300
  case "scanTo":
3240
3301
  case "unknown":
3241
3302
  return false;
@@ -3297,6 +3358,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
3297
3358
  case "regex":
3298
3359
  case "keywords":
3299
3360
  case "node":
3361
+ case "token":
3300
3362
  return true;
3301
3363
  case "not":
3302
3364
  case "guard":
@@ -3575,9 +3637,9 @@ function emitSeq(def, ctx, pos) {
3575
3637
  stmts.push(`${ind(ctx)}const ${arrV} = [${valueVars.join(", ")}]`);
3576
3638
  return { stmts, valueVar: arrV, endVar };
3577
3639
  }
3578
- function staticExpectedArr(parsers) {
3640
+ function deriveExpectedArr(parsers) {
3579
3641
  return JSON.stringify(parsers.flatMap((p) => {
3580
- const e = staticExpected(p);
3642
+ const e = deriveExpected(p);
3581
3643
  return e.length > 0 ? e : [p._tag];
3582
3644
  }));
3583
3645
  }
@@ -3598,7 +3660,7 @@ function failsAtStart(p) {
3598
3660
  }
3599
3661
  }
3600
3662
  function armStaticExpected(ctx, p) {
3601
- return hoistExpected(ctx, staticExpectedArr([p]));
3663
+ return hoistExpected(ctx, deriveExpectedArr([p]));
3602
3664
  }
3603
3665
  function canMatchEmptyAtStart(p) {
3604
3666
  const d = p._def;
@@ -3636,7 +3698,7 @@ function emitDisjointArm(p, ctx, pos, valV, endV) {
3636
3698
  ];
3637
3699
  }
3638
3700
  function emitChoice(def, ctx, pos) {
3639
- const allExpected = staticExpectedArr(def.parsers);
3701
+ const allExpected = deriveExpectedArr(def.parsers);
3640
3702
  if (def.disjoint) {
3641
3703
  const codeV = v(ctx, "_code");
3642
3704
  const valV = v(ctx, "_chv");
@@ -3697,7 +3759,7 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
3697
3759
  const wordV = v(ctx, "_gw");
3698
3760
  const endV = v(ctx, "_ge");
3699
3761
  const valV = v(ctx, "_gcv");
3700
- const regexExpected = JSON.stringify(staticExpected(superParser));
3762
+ const regexExpected = JSON.stringify(deriveExpected(superParser));
3701
3763
  const stmts = [
3702
3764
  `${ind(ctx)}${reVar}.lastIndex = ${pos}`,
3703
3765
  `${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
@@ -4089,6 +4151,116 @@ function emitNot(def, ctx, pos) {
4089
4151
  endVar: pos
4090
4152
  };
4091
4153
  }
4154
+ function escapeTokenLiteral(value) {
4155
+ return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
4156
+ }
4157
+ function regexMatchesEmpty(source, flags) {
4158
+ try {
4159
+ return new RegExp(`^(?:${source})$`, flags).test("");
4160
+ } catch {
4161
+ return true;
4162
+ }
4163
+ }
4164
+ function tokenTerminalSource(p) {
4165
+ const def = p._def;
4166
+ switch (def.tag) {
4167
+ case "literal":
4168
+ if (def.value.length === 0) return null;
4169
+ return {
4170
+ source: escapeTokenLiteral(def.value),
4171
+ caseInsensitive: def.caseInsensitive,
4172
+ rawCaseSensitive: def.caseInsensitive ? "" : def.value
4173
+ };
4174
+ case "regex": {
4175
+ if (def.flags.replace(/i/g, "") !== "") return null;
4176
+ if (regexMatchesEmpty(def.source, def.flags)) return null;
4177
+ return {
4178
+ source: `(?:${def.source})`,
4179
+ caseInsensitive: def.flags.includes("i"),
4180
+ rawCaseSensitive: def.flags.includes("i") ? "" : def.source
4181
+ };
4182
+ }
4183
+ default:
4184
+ return null;
4185
+ }
4186
+ }
4187
+ function tokenSequenceSource(p) {
4188
+ const def = p._def;
4189
+ const parts = def.tag === "sequence" ? def.parsers.map(tokenTerminalSource) : [tokenTerminalSource(p)];
4190
+ if (parts.some((part) => part === null)) return null;
4191
+ const typed = parts;
4192
+ const flags = typed.some((part) => part.caseInsensitive) ? "i" : "";
4193
+ if (flags.includes("i") && typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))) return null;
4194
+ return {
4195
+ source: typed.map((part) => part.source).join(""),
4196
+ flags,
4197
+ hasCaseSensitiveLetters: typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))
4198
+ };
4199
+ }
4200
+ function combineTokenRegexSources(parts) {
4201
+ const flags = parts.some((part) => part.flags.includes("i")) ? "i" : "";
4202
+ if (flags.includes("i") && parts.some((part) => part.flags === "" && part.hasCaseSensitiveLetters)) return null;
4203
+ return { source: parts.map((part) => part.source).join(""), flags };
4204
+ }
4205
+ function tokenNullableRegex(def) {
4206
+ const inner = def.parser._def;
4207
+ if (inner.tag === "many") {
4208
+ const seq = tokenSequenceSource(inner.parser);
4209
+ if (!seq) return null;
4210
+ return { tag: "regex", source: `(?:${seq.source})*`, flags: seq.flags };
4211
+ }
4212
+ if (inner.tag === "optional") {
4213
+ const seq = tokenSequenceSource(inner.parser);
4214
+ if (!seq) return null;
4215
+ return { tag: "regex", source: `(?:${seq.source})?`, flags: seq.flags };
4216
+ }
4217
+ if (inner.tag === "sepBy") {
4218
+ const item = tokenSequenceSource(inner.parser);
4219
+ const sep = tokenSequenceSource(inner.separator);
4220
+ if (!item || !sep) return null;
4221
+ const combined = combineTokenRegexSources([item, sep]);
4222
+ if (!combined) return null;
4223
+ return { tag: "regex", source: `(?:${item.source}(?:${sep.source}${item.source})*)?`, flags: combined.flags };
4224
+ }
4225
+ return null;
4226
+ }
4227
+ function emitToken(def, ctx, pos) {
4228
+ const lowered = tokenNullableRegex(def);
4229
+ if (lowered) return emitRegex(lowered, ctx, pos);
4230
+ const savedTrivia = ctx.activeTrivia;
4231
+ const savedKindLabels = ctx.triviaKindLabels;
4232
+ ctx.activeTrivia = void 0;
4233
+ ctx.triviaKindLabels = void 0;
4234
+ const inner = emitFallible(def.parser, ctx, pos);
4235
+ ctx.activeTrivia = savedTrivia;
4236
+ ctx.triviaKindLabels = savedKindLabels;
4237
+ const i = ind(ctx);
4238
+ const sc = v(ctx, "_tokCh");
4239
+ const sl = v(ctx, "_tokLv");
4240
+ const sr = v(ctx, "_tokRaw");
4241
+ const sv = v(ctx, "_tokTr");
4242
+ const sk = v(ctx, "_tokKinds");
4243
+ const stl = v(ctx, "_tokTl");
4244
+ const sol = v(ctx, "_tokLog");
4245
+ const sb = v(ctx, "_tokBuf");
4246
+ const valV = v(ctx, "_tok");
4247
+ return {
4248
+ stmts: [
4249
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${sv} = _ctx.trivia, ${sk} = _ctx.triviaKindLabels, ${stl} = _ctx._cstTriviaLog, ${sol} = _ctx._triviaLog, ${sb} = _ctx._cstBuf`,
4250
+ `${i}_ctx.trivia = undefined; _ctx.triviaKindLabels = undefined; _ctx._cstChildren = undefined; _ctx._cstLeaves = undefined; _ctx._cstRawChildren = undefined; _ctx._cstTriviaLog = undefined; _ctx._triviaLog = undefined; _ctx._cstBuf = undefined`,
4251
+ `${i}try {`,
4252
+ ...reindentStmts(inner.stmts, ctx.indent + 1).map((stmt) => stmt.replace(/^(\s*)(?:const|let)\s+/, "$1var ")),
4253
+ `${i}} finally {`,
4254
+ `${i} _ctx.trivia = ${sv}; _ctx.triviaKindLabels = ${sk}; _ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx._cstTriviaLog = ${stl}; _ctx._triviaLog = ${sol}; _ctx._cstBuf = ${sb}`,
4255
+ `${i}}`,
4256
+ ...emitIfFail(ctx, `!${inner.okVar}`, propagateFailBody(ctx)),
4257
+ `${i}const ${valV} = input.slice(${pos}, ${inner.endVar})`,
4258
+ ...emitLeafCapture(ctx, valV, pos, inner.endVar)
4259
+ ],
4260
+ valueVar: valV,
4261
+ endVar: inner.endVar
4262
+ };
4263
+ }
4092
4264
  function emitNode(def, ctx, pos) {
4093
4265
  const structural = def.build === void 0;
4094
4266
  const mkType = structural ? null : analyzeMkInlineBuild(def);
@@ -4208,7 +4380,7 @@ function emitRecover(def, ctx, pos) {
4208
4380
  `${ind0} if (${sentOk}) break`,
4209
4381
  `${ind0} ${scanV}++`,
4210
4382
  `${ind0} }`,
4211
- `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(staticExpected(def.parser))} }`,
4383
+ `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(deriveExpected(def.parser))} }`,
4212
4384
  `${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
4213
4385
  `${ind0} ${valVar} = ${errV}`,
4214
4386
  `${ind0} ${endVar} = ${scanV}`,
@@ -4338,8 +4510,19 @@ function emitDispatch(p, ctx, pos) {
4338
4510
  return emitLazy(p, def, ctx, pos);
4339
4511
  case "trivia":
4340
4512
  return emit(def.parser, ctx, pos);
4341
- case "label":
4342
- return emit(def.parser, ctx, pos);
4513
+ case "token":
4514
+ return emitToken(def, ctx, pos);
4515
+ case "label": {
4516
+ const inner = emitFallible(def.parser, ctx, pos);
4517
+ return {
4518
+ stmts: [
4519
+ ...inner.stmts,
4520
+ ...emitIfFail(ctx, `!${inner.okVar}`, failBody(ctx, JSON.stringify(def.label), "_ctx._fe"))
4521
+ ],
4522
+ valueVar: inner.valVar,
4523
+ endVar: inner.endVar
4524
+ };
4525
+ }
4343
4526
  case "grammar": {
4344
4527
  const savedTrivia = ctx.activeTrivia;
4345
4528
  const savedKindLabels = ctx.triviaKindLabels;
@@ -4439,6 +4622,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
4439
4622
  }
4440
4623
  case "grammar":
4441
4624
  case "trivia":
4625
+ case "token":
4442
4626
  case "label":
4443
4627
  case "optional":
4444
4628
  case "many":
@@ -4474,6 +4658,7 @@ function childrenOf(def) {
4474
4658
  case "optional":
4475
4659
  case "transform":
4476
4660
  case "trivia":
4661
+ case "token":
4477
4662
  case "label":
4478
4663
  case "grammar":
4479
4664
  case "not":
@@ -4984,7 +5169,7 @@ function balanced(open, close, options = {}) {
4984
5169
  const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
4985
5170
  const inner = many(choice(self, ...skips, content));
4986
5171
  const combi = transform(
4987
- sequence(literal(open), inner, expect(literal(close), close)),
5172
+ sequence(literal(open), inner, expect(literal(close))),
4988
5173
  // parts: strings (content/self) or arrays (a sequence-shaped skip) or a
4989
5174
  // ParseError (recovered close). `c` is the close string or a ParseError.
4990
5175
  ([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
@@ -5046,6 +5231,7 @@ function evalRuleMapIR(ir) {
5046
5231
  "node",
5047
5232
  "parser",
5048
5233
  "scanTo",
5234
+ "token",
5049
5235
  "transform",
5050
5236
  "skip",
5051
5237
  "trivia",
@@ -5071,6 +5257,7 @@ function evalRuleMapIR(ir) {
5071
5257
  node,
5072
5258
  parser,
5073
5259
  scanTo,
5260
+ token,
5074
5261
  transform,
5075
5262
  skip,
5076
5263
  trivia,
@@ -5231,7 +5418,7 @@ function recover(combinator, sentinel) {
5231
5418
  canMatchNewline: true,
5232
5419
  isTrivia: false
5233
5420
  };
5234
- const expected = staticExpected(combinator);
5421
+ const expected = deriveExpected(combinator);
5235
5422
  return {
5236
5423
  _tag: "recover",
5237
5424
  _meta: meta,
@@ -5944,7 +6131,7 @@ export {
5944
6131
  sequence,
5945
6132
  shiftAbsolute,
5946
6133
  skip,
5947
- staticExpected,
6134
+ token,
5948
6135
  transform,
5949
6136
  trivia,
5950
6137
  triviaEntries,