parseman 0.23.0 → 0.24.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.
@@ -422,24 +422,35 @@ function literal(value, opts = {}) {
422
422
  { lo: firstUpper, hi: firstUpper }
423
423
  ] } : firstSet2;
424
424
  }
425
+ const expected = [JSON.stringify(value)];
426
+ const parse2 = !caseInsensitive && value.length === 1 ? (() => {
427
+ const code = value.charCodeAt(0);
428
+ return function parse3(input, pos, ctx) {
429
+ if (input.charCodeAt(pos) === code) {
430
+ const span = { start: pos, end: pos + 1 };
431
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
432
+ return { ok: true, value, span };
433
+ }
434
+ return failAt(ctx, expected, pos);
435
+ };
436
+ })() : function parse3(input, pos, ctx) {
437
+ const end = pos + value.length;
438
+ if (end > input.length) {
439
+ return failAt(ctx, expected, pos);
440
+ }
441
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
442
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
443
+ const span = { start: pos, end };
444
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
445
+ return { ok: true, value: matchedValue, span };
446
+ }
447
+ return failAt(ctx, expected, pos);
448
+ };
425
449
  return {
426
450
  _tag: "literal",
427
451
  _meta: meta,
428
452
  _def: { tag: "literal", value, caseInsensitive },
429
- parse(input, pos, ctx) {
430
- const end = pos + value.length;
431
- if (end > input.length) {
432
- return failAt(ctx, [JSON.stringify(value)], pos);
433
- }
434
- const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
435
- if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
436
- const span = { start: pos, end };
437
- const leaf = { _tag: "leaf", value: matchedValue, span };
438
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
439
- return { ok: true, value: matchedValue, span };
440
- }
441
- return failAt(ctx, [JSON.stringify(value)], pos);
442
- }
453
+ parse: parse2
443
454
  };
444
455
  }
445
456
 
@@ -574,8 +585,7 @@ function regex(pattern, flags = "") {
574
585
  if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
575
586
  const value = input.slice(pos, scanEnd);
576
587
  const span2 = { start: pos, end: scanEnd };
577
- const leaf2 = { _tag: "leaf", value, span: span2 };
578
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
588
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
579
589
  return { ok: true, value, span: span2 };
580
590
  }
581
591
  anchored.lastIndex = pos;
@@ -584,8 +594,7 @@ function regex(pattern, flags = "") {
584
594
  return failAt(ctx, [`/${source}/`], pos);
585
595
  }
586
596
  const span = { start: pos, end: pos + m[0].length };
587
- const leaf = { _tag: "leaf", value: m[0], span };
588
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
597
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
589
598
  return { ok: true, value: m[0], span };
590
599
  }
591
600
  };
@@ -890,8 +899,7 @@ function keywords(words, opts = {}) {
890
899
  }
891
900
  const value = m[0];
892
901
  const span = { start: pos, end: pos + value.length };
893
- const leaf = { _tag: "leaf", value, span };
894
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
902
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
895
903
  return { ok: true, value, span };
896
904
  }
897
905
  };
@@ -1381,33 +1389,136 @@ function loopScanner(arms) {
1381
1389
  }
1382
1390
  function regexTriviaScanner(parser2) {
1383
1391
  if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1384
- const ws = whitespaceSource(parser2._def.source);
1385
- if (ws) return ws;
1386
- return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
1392
+ const source = parser2._def.source;
1393
+ return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1387
1394
  }
1388
- function whitespaceSource(source) {
1389
- const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
1390
- if (!m) return null;
1391
- const chars = /* @__PURE__ */ new Set();
1392
- for (let i = 0; i < m[1].length; i++) {
1393
- const ch = m[1][i];
1394
- if (ch !== "\\") {
1395
- chars.add(ch.charCodeAt(0));
1396
- continue;
1395
+ function inRanges2(cp, ranges) {
1396
+ for (let i = 0; i < ranges.length; i++) {
1397
+ const r = ranges[i];
1398
+ if (cp >= r[0] && cp <= r[1]) return true;
1399
+ }
1400
+ return false;
1401
+ }
1402
+ function classScanner(classBody) {
1403
+ const ranges = parseClassRanges(classBody);
1404
+ if (!ranges) return null;
1405
+ return (input, cur) => {
1406
+ let pos = cur;
1407
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1408
+ return pos;
1409
+ };
1410
+ }
1411
+ function lineCommentScanner(commentCode) {
1412
+ return (input, cur) => {
1413
+ if (input.charCodeAt(cur) !== commentCode) return cur;
1414
+ let pos = cur + 1;
1415
+ while (pos < input.length) {
1416
+ const cc = input.charCodeAt(pos);
1417
+ if (cc === 10 || cc === 13) break;
1418
+ pos++;
1397
1419
  }
1398
- const esc = m[1][++i];
1399
- if (esc === "t") chars.add(9);
1400
- else if (esc === "n") chars.add(10);
1401
- else if (esc === "r") chars.add(13);
1402
- else if (esc === "f") chars.add(12);
1403
- else return null;
1420
+ return pos;
1421
+ };
1422
+ }
1423
+ function classRunSource(source) {
1424
+ const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1425
+ return m ? classScanner(m[1]) : null;
1426
+ }
1427
+ function classifyTriviaArm(arm) {
1428
+ const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1429
+ if (cls) {
1430
+ const ranges = parseClassRanges(cls[1]);
1431
+ return ranges ? { kind: "class", ranges } : null;
1432
+ }
1433
+ const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1434
+ if (lc) {
1435
+ const marker = lc[1];
1436
+ return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
1404
1437
  }
1438
+ return null;
1439
+ }
1440
+ function armScanner(arm) {
1441
+ if (arm.kind === "comment") return lineCommentScanner(arm.code);
1442
+ const ranges = arm.ranges;
1443
+ return (input, cur) => {
1444
+ let pos = cur;
1445
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1446
+ return pos;
1447
+ };
1448
+ }
1449
+ function fusedTriviaScanner(ranges, commentCodes) {
1450
+ const c0 = commentCodes[0];
1451
+ const single = commentCodes.length === 1;
1405
1452
  return (input, cur) => {
1406
1453
  let pos = cur;
1407
- while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
1454
+ const len = input.length;
1455
+ for (; ; ) {
1456
+ const c = input.charCodeAt(pos);
1457
+ if (pos < len && inRanges2(c, ranges)) {
1458
+ pos++;
1459
+ continue;
1460
+ }
1461
+ if (single ? c === c0 : commentCodes.includes(c)) {
1462
+ pos++;
1463
+ while (pos < len) {
1464
+ const cc = input.charCodeAt(pos);
1465
+ if (cc === 10 || cc === 13) break;
1466
+ pos++;
1467
+ }
1468
+ continue;
1469
+ }
1470
+ break;
1471
+ }
1408
1472
  return pos;
1409
1473
  };
1410
1474
  }
1475
+ function splitTopLevelAlts(body) {
1476
+ const arms = [];
1477
+ let inClass = false;
1478
+ let start = 0;
1479
+ for (let i = 0; i < body.length; i++) {
1480
+ const c = body[i];
1481
+ if (c === "\\") {
1482
+ i++;
1483
+ continue;
1484
+ }
1485
+ if (inClass) {
1486
+ if (c === "]") inClass = false;
1487
+ continue;
1488
+ }
1489
+ if (c === "[") inClass = true;
1490
+ else if (c === "(") return null;
1491
+ else if (c === "|") {
1492
+ arms.push(body.slice(start, i));
1493
+ start = i + 1;
1494
+ }
1495
+ }
1496
+ arms.push(body.slice(start));
1497
+ return arms;
1498
+ }
1499
+ function altStarSource(source) {
1500
+ const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1501
+ if (!m) return null;
1502
+ const armSrcs = splitTopLevelAlts(m[1]);
1503
+ if (!armSrcs || armSrcs.length < 2) return null;
1504
+ const arms = [];
1505
+ for (const src of armSrcs) {
1506
+ const arm = classifyTriviaArm(src);
1507
+ if (!arm) return null;
1508
+ arms.push(arm);
1509
+ }
1510
+ const ranges = [];
1511
+ const commentCodes = [];
1512
+ for (const arm of arms) {
1513
+ if (arm.kind === "class") ranges.push(...arm.ranges);
1514
+ else commentCodes.push(arm.code);
1515
+ }
1516
+ if (commentCodes.some((code) => inRanges2(code, ranges))) {
1517
+ return loopScanner(arms.map(armScanner));
1518
+ }
1519
+ if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
1520
+ return fusedTriviaScanner(ranges, commentCodes);
1521
+ }
1411
1522
  function blockCommentSource(source) {
1412
1523
  return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1413
1524
  }
@@ -1724,6 +1835,7 @@ function markUnusedValues(root) {
1724
1835
  }
1725
1836
 
1726
1837
  // src/combinators/parser.ts
1838
+ var RULE_ORDER = "__parsemanRuleOrder";
1727
1839
  function tagRule(r, key) {
1728
1840
  ;
1729
1841
  r._ruleName = key;
@@ -1768,6 +1880,11 @@ function rules(a, b) {
1768
1880
  for (const key of Object.keys(definitions)) {
1769
1881
  markUnusedValues(cache[key]);
1770
1882
  }
1883
+ Object.defineProperty(cache, RULE_ORDER, {
1884
+ value: Object.keys(definitions),
1885
+ enumerable: false,
1886
+ configurable: true
1887
+ });
1771
1888
  return cache;
1772
1889
  }
1773
1890