parseman 0.17.0 → 0.18.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.
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);
@@ -1546,8 +1549,60 @@ function parse(combinator, input, opts = {}) {
1546
1549
  return withErrors;
1547
1550
  }
1548
1551
 
1552
+ // src/combinators/token.ts
1553
+ function token(root) {
1554
+ const meta = {
1555
+ firstSet: root._meta.firstSet,
1556
+ canMatchNewline: root._meta.canMatchNewline,
1557
+ isTrivia: false
1558
+ };
1559
+ return {
1560
+ _tag: "token",
1561
+ _meta: meta,
1562
+ _def: { tag: "token", parser: root },
1563
+ parse(input, pos, ctx) {
1564
+ const savedTrivia = ctx.trivia;
1565
+ const savedKinds = ctx.triviaKindLabels;
1566
+ const savedBuf = ctx._cstBuf;
1567
+ const savedChildren = ctx._cstChildren;
1568
+ const savedLeaves = ctx._cstLeaves;
1569
+ const savedRaw = ctx._cstRawChildren;
1570
+ const savedTriviaLog = ctx._cstTriviaLog;
1571
+ const savedOuterTriviaLog = ctx._triviaLog;
1572
+ const wasCapturing = cstCaptureActive(ctx);
1573
+ ctx.trivia = void 0;
1574
+ ctx.triviaKindLabels = void 0;
1575
+ ctx._cstBuf = void 0;
1576
+ ctx._cstChildren = void 0;
1577
+ ctx._cstLeaves = void 0;
1578
+ ctx._cstRawChildren = void 0;
1579
+ ctx._cstTriviaLog = void 0;
1580
+ delete ctx._triviaLog;
1581
+ let result;
1582
+ try {
1583
+ result = root.parse(input, pos, ctx);
1584
+ } finally {
1585
+ ctx.trivia = savedTrivia;
1586
+ ctx.triviaKindLabels = savedKinds;
1587
+ ctx._cstBuf = savedBuf;
1588
+ ctx._cstChildren = savedChildren;
1589
+ ctx._cstLeaves = savedLeaves;
1590
+ ctx._cstRawChildren = savedRaw;
1591
+ ctx._cstTriviaLog = savedTriviaLog;
1592
+ if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
1593
+ else ctx._triviaLog = savedOuterTriviaLog;
1594
+ }
1595
+ if (!result.ok) return result;
1596
+ const span = result.span;
1597
+ const value = input.slice(pos, span.end);
1598
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
1599
+ return { ok: true, value, span };
1600
+ }
1601
+ };
1602
+ }
1603
+
1549
1604
  // src/combinators/expect.ts
1550
- function staticExpected(c) {
1605
+ function deriveExpected(c) {
1551
1606
  const def = c._def;
1552
1607
  switch (def.tag) {
1553
1608
  case "literal":
@@ -1559,22 +1614,23 @@ function staticExpected(c) {
1559
1614
  case "label":
1560
1615
  return [def.label];
1561
1616
  case "choice":
1562
- return def.parsers.flatMap(staticExpected);
1617
+ return def.parsers.flatMap(deriveExpected);
1563
1618
  case "sequence":
1564
- return def.parsers.length > 0 ? staticExpected(def.parsers[0]) : [];
1619
+ return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1565
1620
  case "node":
1566
1621
  case "grammar":
1567
1622
  case "trivia":
1623
+ case "token":
1568
1624
  case "optional":
1569
1625
  case "many":
1570
1626
  case "oneOrMore":
1571
1627
  case "transform":
1572
1628
  case "not":
1573
- return staticExpected(def.parser);
1629
+ return deriveExpected(def.parser);
1574
1630
  case "lazy": {
1575
1631
  const name = c._ruleName;
1576
1632
  try {
1577
- return staticExpected(def.thunk());
1633
+ return deriveExpected(def.thunk());
1578
1634
  } catch {
1579
1635
  return name ? [name] : [];
1580
1636
  }
@@ -1584,7 +1640,7 @@ function staticExpected(c) {
1584
1640
  }
1585
1641
  }
1586
1642
  function expect(combinator, label2) {
1587
- const expected = label2 !== void 0 ? [label2] : staticExpected(combinator);
1643
+ const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
1588
1644
  const meta = {
1589
1645
  firstSet: combinator._meta.firstSet,
1590
1646
  canMatchNewline: combinator._meta.canMatchNewline,
@@ -3236,6 +3292,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
3236
3292
  case "guard":
3237
3293
  case "not":
3238
3294
  case "trivia":
3295
+ case "token":
3239
3296
  case "scanTo":
3240
3297
  case "unknown":
3241
3298
  return false;
@@ -3297,6 +3354,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
3297
3354
  case "regex":
3298
3355
  case "keywords":
3299
3356
  case "node":
3357
+ case "token":
3300
3358
  return true;
3301
3359
  case "not":
3302
3360
  case "guard":
@@ -3575,9 +3633,9 @@ function emitSeq(def, ctx, pos) {
3575
3633
  stmts.push(`${ind(ctx)}const ${arrV} = [${valueVars.join(", ")}]`);
3576
3634
  return { stmts, valueVar: arrV, endVar };
3577
3635
  }
3578
- function staticExpectedArr(parsers) {
3636
+ function deriveExpectedArr(parsers) {
3579
3637
  return JSON.stringify(parsers.flatMap((p) => {
3580
- const e = staticExpected(p);
3638
+ const e = deriveExpected(p);
3581
3639
  return e.length > 0 ? e : [p._tag];
3582
3640
  }));
3583
3641
  }
@@ -3598,7 +3656,7 @@ function failsAtStart(p) {
3598
3656
  }
3599
3657
  }
3600
3658
  function armStaticExpected(ctx, p) {
3601
- return hoistExpected(ctx, staticExpectedArr([p]));
3659
+ return hoistExpected(ctx, deriveExpectedArr([p]));
3602
3660
  }
3603
3661
  function canMatchEmptyAtStart(p) {
3604
3662
  const d = p._def;
@@ -3636,7 +3694,7 @@ function emitDisjointArm(p, ctx, pos, valV, endV) {
3636
3694
  ];
3637
3695
  }
3638
3696
  function emitChoice(def, ctx, pos) {
3639
- const allExpected = staticExpectedArr(def.parsers);
3697
+ const allExpected = deriveExpectedArr(def.parsers);
3640
3698
  if (def.disjoint) {
3641
3699
  const codeV = v(ctx, "_code");
3642
3700
  const valV = v(ctx, "_chv");
@@ -3697,7 +3755,7 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
3697
3755
  const wordV = v(ctx, "_gw");
3698
3756
  const endV = v(ctx, "_ge");
3699
3757
  const valV = v(ctx, "_gcv");
3700
- const regexExpected = JSON.stringify(staticExpected(superParser));
3758
+ const regexExpected = JSON.stringify(deriveExpected(superParser));
3701
3759
  const stmts = [
3702
3760
  `${ind(ctx)}${reVar}.lastIndex = ${pos}`,
3703
3761
  `${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
@@ -4089,6 +4147,116 @@ function emitNot(def, ctx, pos) {
4089
4147
  endVar: pos
4090
4148
  };
4091
4149
  }
4150
+ function escapeTokenLiteral(value) {
4151
+ return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
4152
+ }
4153
+ function regexMatchesEmpty(source, flags) {
4154
+ try {
4155
+ return new RegExp(`^(?:${source})$`, flags).test("");
4156
+ } catch {
4157
+ return true;
4158
+ }
4159
+ }
4160
+ function tokenTerminalSource(p) {
4161
+ const def = p._def;
4162
+ switch (def.tag) {
4163
+ case "literal":
4164
+ if (def.value.length === 0) return null;
4165
+ return {
4166
+ source: escapeTokenLiteral(def.value),
4167
+ caseInsensitive: def.caseInsensitive,
4168
+ rawCaseSensitive: def.caseInsensitive ? "" : def.value
4169
+ };
4170
+ case "regex": {
4171
+ if (def.flags.replace(/i/g, "") !== "") return null;
4172
+ if (regexMatchesEmpty(def.source, def.flags)) return null;
4173
+ return {
4174
+ source: `(?:${def.source})`,
4175
+ caseInsensitive: def.flags.includes("i"),
4176
+ rawCaseSensitive: def.flags.includes("i") ? "" : def.source
4177
+ };
4178
+ }
4179
+ default:
4180
+ return null;
4181
+ }
4182
+ }
4183
+ function tokenSequenceSource(p) {
4184
+ const def = p._def;
4185
+ const parts = def.tag === "sequence" ? def.parsers.map(tokenTerminalSource) : [tokenTerminalSource(p)];
4186
+ if (parts.some((part) => part === null)) return null;
4187
+ const typed = parts;
4188
+ const flags = typed.some((part) => part.caseInsensitive) ? "i" : "";
4189
+ if (flags.includes("i") && typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))) return null;
4190
+ return {
4191
+ source: typed.map((part) => part.source).join(""),
4192
+ flags,
4193
+ hasCaseSensitiveLetters: typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))
4194
+ };
4195
+ }
4196
+ function combineTokenRegexSources(parts) {
4197
+ const flags = parts.some((part) => part.flags.includes("i")) ? "i" : "";
4198
+ if (flags.includes("i") && parts.some((part) => part.flags === "" && part.hasCaseSensitiveLetters)) return null;
4199
+ return { source: parts.map((part) => part.source).join(""), flags };
4200
+ }
4201
+ function tokenNullableRegex(def) {
4202
+ const inner = def.parser._def;
4203
+ if (inner.tag === "many") {
4204
+ const seq = tokenSequenceSource(inner.parser);
4205
+ if (!seq) return null;
4206
+ return { tag: "regex", source: `(?:${seq.source})*`, flags: seq.flags };
4207
+ }
4208
+ if (inner.tag === "optional") {
4209
+ const seq = tokenSequenceSource(inner.parser);
4210
+ if (!seq) return null;
4211
+ return { tag: "regex", source: `(?:${seq.source})?`, flags: seq.flags };
4212
+ }
4213
+ if (inner.tag === "sepBy") {
4214
+ const item = tokenSequenceSource(inner.parser);
4215
+ const sep = tokenSequenceSource(inner.separator);
4216
+ if (!item || !sep) return null;
4217
+ const combined = combineTokenRegexSources([item, sep]);
4218
+ if (!combined) return null;
4219
+ return { tag: "regex", source: `(?:${item.source}(?:${sep.source}${item.source})*)?`, flags: combined.flags };
4220
+ }
4221
+ return null;
4222
+ }
4223
+ function emitToken(def, ctx, pos) {
4224
+ const lowered = tokenNullableRegex(def);
4225
+ if (lowered) return emitRegex(lowered, ctx, pos);
4226
+ const savedTrivia = ctx.activeTrivia;
4227
+ const savedKindLabels = ctx.triviaKindLabels;
4228
+ ctx.activeTrivia = void 0;
4229
+ ctx.triviaKindLabels = void 0;
4230
+ const inner = emitFallible(def.parser, ctx, pos);
4231
+ ctx.activeTrivia = savedTrivia;
4232
+ ctx.triviaKindLabels = savedKindLabels;
4233
+ const i = ind(ctx);
4234
+ const sc = v(ctx, "_tokCh");
4235
+ const sl = v(ctx, "_tokLv");
4236
+ const sr = v(ctx, "_tokRaw");
4237
+ const sv = v(ctx, "_tokTr");
4238
+ const sk = v(ctx, "_tokKinds");
4239
+ const stl = v(ctx, "_tokTl");
4240
+ const sol = v(ctx, "_tokLog");
4241
+ const sb = v(ctx, "_tokBuf");
4242
+ const valV = v(ctx, "_tok");
4243
+ return {
4244
+ stmts: [
4245
+ `${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`,
4246
+ `${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`,
4247
+ `${i}try {`,
4248
+ ...reindentStmts(inner.stmts, ctx.indent + 1).map((stmt) => stmt.replace(/^(\s*)(?:const|let)\s+/, "$1var ")),
4249
+ `${i}} finally {`,
4250
+ `${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}`,
4251
+ `${i}}`,
4252
+ ...emitIfFail(ctx, `!${inner.okVar}`, propagateFailBody(ctx)),
4253
+ `${i}const ${valV} = input.slice(${pos}, ${inner.endVar})`,
4254
+ ...emitLeafCapture(ctx, valV, pos, inner.endVar)
4255
+ ],
4256
+ valueVar: valV,
4257
+ endVar: inner.endVar
4258
+ };
4259
+ }
4092
4260
  function emitNode(def, ctx, pos) {
4093
4261
  const structural = def.build === void 0;
4094
4262
  const mkType = structural ? null : analyzeMkInlineBuild(def);
@@ -4208,7 +4376,7 @@ function emitRecover(def, ctx, pos) {
4208
4376
  `${ind0} if (${sentOk}) break`,
4209
4377
  `${ind0} ${scanV}++`,
4210
4378
  `${ind0} }`,
4211
- `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(staticExpected(def.parser))} }`,
4379
+ `${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(deriveExpected(def.parser))} }`,
4212
4380
  `${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
4213
4381
  `${ind0} ${valVar} = ${errV}`,
4214
4382
  `${ind0} ${endVar} = ${scanV}`,
@@ -4338,6 +4506,8 @@ function emitDispatch(p, ctx, pos) {
4338
4506
  return emitLazy(p, def, ctx, pos);
4339
4507
  case "trivia":
4340
4508
  return emit(def.parser, ctx, pos);
4509
+ case "token":
4510
+ return emitToken(def, ctx, pos);
4341
4511
  case "label":
4342
4512
  return emit(def.parser, ctx, pos);
4343
4513
  case "grammar": {
@@ -4439,6 +4609,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
4439
4609
  }
4440
4610
  case "grammar":
4441
4611
  case "trivia":
4612
+ case "token":
4442
4613
  case "label":
4443
4614
  case "optional":
4444
4615
  case "many":
@@ -4474,6 +4645,7 @@ function childrenOf(def) {
4474
4645
  case "optional":
4475
4646
  case "transform":
4476
4647
  case "trivia":
4648
+ case "token":
4477
4649
  case "label":
4478
4650
  case "grammar":
4479
4651
  case "not":
@@ -4984,7 +5156,7 @@ function balanced(open, close, options = {}) {
4984
5156
  const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
4985
5157
  const inner = many(choice(self, ...skips, content));
4986
5158
  const combi = transform(
4987
- sequence(literal(open), inner, expect(literal(close), close)),
5159
+ sequence(literal(open), inner, expect(literal(close))),
4988
5160
  // parts: strings (content/self) or arrays (a sequence-shaped skip) or a
4989
5161
  // ParseError (recovered close). `c` is the close string or a ParseError.
4990
5162
  ([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
@@ -5046,6 +5218,7 @@ function evalRuleMapIR(ir) {
5046
5218
  "node",
5047
5219
  "parser",
5048
5220
  "scanTo",
5221
+ "token",
5049
5222
  "transform",
5050
5223
  "skip",
5051
5224
  "trivia",
@@ -5071,6 +5244,7 @@ function evalRuleMapIR(ir) {
5071
5244
  node,
5072
5245
  parser,
5073
5246
  scanTo,
5247
+ token,
5074
5248
  transform,
5075
5249
  skip,
5076
5250
  trivia,
@@ -5231,7 +5405,7 @@ function recover(combinator, sentinel) {
5231
5405
  canMatchNewline: true,
5232
5406
  isTrivia: false
5233
5407
  };
5234
- const expected = staticExpected(combinator);
5408
+ const expected = deriveExpected(combinator);
5235
5409
  return {
5236
5410
  _tag: "recover",
5237
5411
  _meta: meta,
@@ -5944,7 +6118,7 @@ export {
5944
6118
  sequence,
5945
6119
  shiftAbsolute,
5946
6120
  skip,
5947
- staticExpected,
6121
+ token,
5948
6122
  transform,
5949
6123
  trivia,
5950
6124
  triviaEntries,