parseman 0.23.0 → 0.25.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.
@@ -387,24 +387,35 @@ function literal(value, opts = {}) {
387
387
  { lo: firstUpper, hi: firstUpper }
388
388
  ] } : firstSet2;
389
389
  }
390
+ const expected = [JSON.stringify(value)];
391
+ const parse2 = !caseInsensitive && value.length === 1 ? (() => {
392
+ const code = value.charCodeAt(0);
393
+ return function parse3(input, pos, ctx) {
394
+ if (input.charCodeAt(pos) === code) {
395
+ const span = { start: pos, end: pos + 1 };
396
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
397
+ return { ok: true, value, span };
398
+ }
399
+ return failAt(ctx, expected, pos);
400
+ };
401
+ })() : function parse3(input, pos, ctx) {
402
+ const end = pos + value.length;
403
+ if (end > input.length) {
404
+ return failAt(ctx, expected, pos);
405
+ }
406
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
407
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
408
+ const span = { start: pos, end };
409
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
410
+ return { ok: true, value: matchedValue, span };
411
+ }
412
+ return failAt(ctx, expected, pos);
413
+ };
390
414
  return {
391
415
  _tag: "literal",
392
416
  _meta: meta,
393
417
  _def: { tag: "literal", value, caseInsensitive },
394
- parse(input, pos, ctx) {
395
- const end = pos + value.length;
396
- if (end > input.length) {
397
- return failAt(ctx, [JSON.stringify(value)], pos);
398
- }
399
- const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
400
- if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
401
- const span = { start: pos, end };
402
- const leaf = { _tag: "leaf", value: matchedValue, span };
403
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
404
- return { ok: true, value: matchedValue, span };
405
- }
406
- return failAt(ctx, [JSON.stringify(value)], pos);
407
- }
418
+ parse: parse2
408
419
  };
409
420
  }
410
421
 
@@ -539,8 +550,7 @@ function regex(pattern, flags = "") {
539
550
  if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
540
551
  const value = input.slice(pos, scanEnd);
541
552
  const span2 = { start: pos, end: scanEnd };
542
- const leaf2 = { _tag: "leaf", value, span: span2 };
543
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
553
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
544
554
  return { ok: true, value, span: span2 };
545
555
  }
546
556
  anchored.lastIndex = pos;
@@ -549,8 +559,7 @@ function regex(pattern, flags = "") {
549
559
  return failAt(ctx, [`/${source}/`], pos);
550
560
  }
551
561
  const span = { start: pos, end: pos + m[0].length };
552
- const leaf = { _tag: "leaf", value: m[0], span };
553
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
562
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
554
563
  return { ok: true, value: m[0], span };
555
564
  }
556
565
  };
@@ -855,8 +864,7 @@ function keywords(words, opts = {}) {
855
864
  }
856
865
  const value = m[0];
857
866
  const span = { start: pos, end: pos + value.length };
858
- const leaf = { _tag: "leaf", value, span };
859
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
867
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
860
868
  return { ok: true, value, span };
861
869
  }
862
870
  };
@@ -1346,33 +1354,136 @@ function loopScanner(arms) {
1346
1354
  }
1347
1355
  function regexTriviaScanner(parser2) {
1348
1356
  if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1349
- const ws = whitespaceSource(parser2._def.source);
1350
- if (ws) return ws;
1351
- return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
1357
+ const source = parser2._def.source;
1358
+ return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1352
1359
  }
1353
- function whitespaceSource(source) {
1354
- const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
1355
- if (!m) return null;
1356
- const chars = /* @__PURE__ */ new Set();
1357
- for (let i = 0; i < m[1].length; i++) {
1358
- const ch = m[1][i];
1359
- if (ch !== "\\") {
1360
- chars.add(ch.charCodeAt(0));
1361
- continue;
1360
+ function inRanges2(cp, ranges) {
1361
+ for (let i = 0; i < ranges.length; i++) {
1362
+ const r = ranges[i];
1363
+ if (cp >= r[0] && cp <= r[1]) return true;
1364
+ }
1365
+ return false;
1366
+ }
1367
+ function classScanner(classBody) {
1368
+ const ranges = parseClassRanges(classBody);
1369
+ if (!ranges) return null;
1370
+ return (input, cur) => {
1371
+ let pos = cur;
1372
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1373
+ return pos;
1374
+ };
1375
+ }
1376
+ function lineCommentScanner(commentCode) {
1377
+ return (input, cur) => {
1378
+ if (input.charCodeAt(cur) !== commentCode) return cur;
1379
+ let pos = cur + 1;
1380
+ while (pos < input.length) {
1381
+ const cc = input.charCodeAt(pos);
1382
+ if (cc === 10 || cc === 13) break;
1383
+ pos++;
1362
1384
  }
1363
- const esc = m[1][++i];
1364
- if (esc === "t") chars.add(9);
1365
- else if (esc === "n") chars.add(10);
1366
- else if (esc === "r") chars.add(13);
1367
- else if (esc === "f") chars.add(12);
1368
- else return null;
1385
+ return pos;
1386
+ };
1387
+ }
1388
+ function classRunSource(source) {
1389
+ const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1390
+ return m ? classScanner(m[1]) : null;
1391
+ }
1392
+ function classifyTriviaArm(arm) {
1393
+ const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1394
+ if (cls) {
1395
+ const ranges = parseClassRanges(cls[1]);
1396
+ return ranges ? { kind: "class", ranges } : null;
1397
+ }
1398
+ const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1399
+ if (lc) {
1400
+ const marker = lc[1];
1401
+ return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
1369
1402
  }
1403
+ return null;
1404
+ }
1405
+ function armScanner(arm) {
1406
+ if (arm.kind === "comment") return lineCommentScanner(arm.code);
1407
+ const ranges = arm.ranges;
1408
+ return (input, cur) => {
1409
+ let pos = cur;
1410
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1411
+ return pos;
1412
+ };
1413
+ }
1414
+ function fusedTriviaScanner(ranges, commentCodes) {
1415
+ const c0 = commentCodes[0];
1416
+ const single = commentCodes.length === 1;
1370
1417
  return (input, cur) => {
1371
1418
  let pos = cur;
1372
- while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
1419
+ const len = input.length;
1420
+ for (; ; ) {
1421
+ const c = input.charCodeAt(pos);
1422
+ if (pos < len && inRanges2(c, ranges)) {
1423
+ pos++;
1424
+ continue;
1425
+ }
1426
+ if (single ? c === c0 : commentCodes.includes(c)) {
1427
+ pos++;
1428
+ while (pos < len) {
1429
+ const cc = input.charCodeAt(pos);
1430
+ if (cc === 10 || cc === 13) break;
1431
+ pos++;
1432
+ }
1433
+ continue;
1434
+ }
1435
+ break;
1436
+ }
1373
1437
  return pos;
1374
1438
  };
1375
1439
  }
1440
+ function splitTopLevelAlts(body) {
1441
+ const arms = [];
1442
+ let inClass = false;
1443
+ let start = 0;
1444
+ for (let i = 0; i < body.length; i++) {
1445
+ const c = body[i];
1446
+ if (c === "\\") {
1447
+ i++;
1448
+ continue;
1449
+ }
1450
+ if (inClass) {
1451
+ if (c === "]") inClass = false;
1452
+ continue;
1453
+ }
1454
+ if (c === "[") inClass = true;
1455
+ else if (c === "(") return null;
1456
+ else if (c === "|") {
1457
+ arms.push(body.slice(start, i));
1458
+ start = i + 1;
1459
+ }
1460
+ }
1461
+ arms.push(body.slice(start));
1462
+ return arms;
1463
+ }
1464
+ function altStarSource(source) {
1465
+ const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1466
+ if (!m) return null;
1467
+ const armSrcs = splitTopLevelAlts(m[1]);
1468
+ if (!armSrcs || armSrcs.length < 2) return null;
1469
+ const arms = [];
1470
+ for (const src of armSrcs) {
1471
+ const arm = classifyTriviaArm(src);
1472
+ if (!arm) return null;
1473
+ arms.push(arm);
1474
+ }
1475
+ const ranges = [];
1476
+ const commentCodes = [];
1477
+ for (const arm of arms) {
1478
+ if (arm.kind === "class") ranges.push(...arm.ranges);
1479
+ else commentCodes.push(arm.code);
1480
+ }
1481
+ if (commentCodes.some((code) => inRanges2(code, ranges))) {
1482
+ return loopScanner(arms.map(armScanner));
1483
+ }
1484
+ if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
1485
+ return fusedTriviaScanner(ranges, commentCodes);
1486
+ }
1376
1487
  function blockCommentSource(source) {
1377
1488
  return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1378
1489
  }
@@ -1689,6 +1800,7 @@ function markUnusedValues(root) {
1689
1800
  }
1690
1801
 
1691
1802
  // src/combinators/parser.ts
1803
+ var RULE_ORDER = "__parsemanRuleOrder";
1692
1804
  function tagRule(r, key) {
1693
1805
  ;
1694
1806
  r._ruleName = key;
@@ -1733,6 +1845,11 @@ function rules(a, b) {
1733
1845
  for (const key of Object.keys(definitions)) {
1734
1846
  markUnusedValues(cache[key]);
1735
1847
  }
1848
+ Object.defineProperty(cache, RULE_ORDER, {
1849
+ value: Object.keys(definitions),
1850
+ enumerable: false,
1851
+ configurable: true
1852
+ });
1736
1853
  return cache;
1737
1854
  }
1738
1855