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.
package/dist/index.js CHANGED
@@ -343,24 +343,35 @@ function literal(value, opts = {}) {
343
343
  { lo: firstUpper, hi: firstUpper }
344
344
  ] } : firstSet2;
345
345
  }
346
+ const expected = [JSON.stringify(value)];
347
+ const parse2 = !caseInsensitive && value.length === 1 ? (() => {
348
+ const code = value.charCodeAt(0);
349
+ return function parse3(input, pos, ctx) {
350
+ if (input.charCodeAt(pos) === code) {
351
+ const span = { start: pos, end: pos + 1 };
352
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
353
+ return { ok: true, value, span };
354
+ }
355
+ return failAt(ctx, expected, pos);
356
+ };
357
+ })() : function parse3(input, pos, ctx) {
358
+ const end = pos + value.length;
359
+ if (end > input.length) {
360
+ return failAt(ctx, expected, pos);
361
+ }
362
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
363
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
364
+ const span = { start: pos, end };
365
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
366
+ return { ok: true, value: matchedValue, span };
367
+ }
368
+ return failAt(ctx, expected, pos);
369
+ };
346
370
  return {
347
371
  _tag: "literal",
348
372
  _meta: meta,
349
373
  _def: { tag: "literal", value, caseInsensitive },
350
- parse(input, pos, ctx) {
351
- const end = pos + value.length;
352
- if (end > input.length) {
353
- return failAt(ctx, [JSON.stringify(value)], pos);
354
- }
355
- const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
356
- if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
357
- const span = { start: pos, end };
358
- const leaf = { _tag: "leaf", value: matchedValue, span };
359
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
360
- return { ok: true, value: matchedValue, span };
361
- }
362
- return failAt(ctx, [JSON.stringify(value)], pos);
363
- }
374
+ parse: parse2
364
375
  };
365
376
  }
366
377
 
@@ -495,8 +506,7 @@ function regex(pattern, flags = "") {
495
506
  if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
496
507
  const value = input.slice(pos, scanEnd);
497
508
  const span2 = { start: pos, end: scanEnd };
498
- const leaf2 = { _tag: "leaf", value, span: span2 };
499
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
509
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
500
510
  return { ok: true, value, span: span2 };
501
511
  }
502
512
  anchored.lastIndex = pos;
@@ -505,8 +515,7 @@ function regex(pattern, flags = "") {
505
515
  return failAt(ctx, [`/${source}/`], pos);
506
516
  }
507
517
  const span = { start: pos, end: pos + m[0].length };
508
- const leaf = { _tag: "leaf", value: m[0], span };
509
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
518
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
510
519
  return { ok: true, value: m[0], span };
511
520
  }
512
521
  };
@@ -814,8 +823,7 @@ function keywords(words, opts = {}) {
814
823
  }
815
824
  const value = m[0];
816
825
  const span = { start: pos, end: pos + value.length };
817
- const leaf = { _tag: "leaf", value, span };
818
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
826
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
819
827
  return { ok: true, value, span };
820
828
  }
821
829
  };
@@ -1305,33 +1313,136 @@ function loopScanner(arms) {
1305
1313
  }
1306
1314
  function regexTriviaScanner(parser2) {
1307
1315
  if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1308
- const ws = whitespaceSource(parser2._def.source);
1309
- if (ws) return ws;
1310
- return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
1316
+ const source = parser2._def.source;
1317
+ return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1311
1318
  }
1312
- function whitespaceSource(source) {
1313
- const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
1314
- if (!m) return null;
1315
- const chars = /* @__PURE__ */ new Set();
1316
- for (let i = 0; i < m[1].length; i++) {
1317
- const ch = m[1][i];
1318
- if (ch !== "\\") {
1319
- chars.add(ch.charCodeAt(0));
1320
- continue;
1319
+ function inRanges2(cp, ranges) {
1320
+ for (let i = 0; i < ranges.length; i++) {
1321
+ const r = ranges[i];
1322
+ if (cp >= r[0] && cp <= r[1]) return true;
1323
+ }
1324
+ return false;
1325
+ }
1326
+ function classScanner(classBody) {
1327
+ const ranges = parseClassRanges(classBody);
1328
+ if (!ranges) return null;
1329
+ return (input, cur) => {
1330
+ let pos = cur;
1331
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1332
+ return pos;
1333
+ };
1334
+ }
1335
+ function lineCommentScanner(commentCode) {
1336
+ return (input, cur) => {
1337
+ if (input.charCodeAt(cur) !== commentCode) return cur;
1338
+ let pos = cur + 1;
1339
+ while (pos < input.length) {
1340
+ const cc = input.charCodeAt(pos);
1341
+ if (cc === 10 || cc === 13) break;
1342
+ pos++;
1321
1343
  }
1322
- const esc = m[1][++i];
1323
- if (esc === "t") chars.add(9);
1324
- else if (esc === "n") chars.add(10);
1325
- else if (esc === "r") chars.add(13);
1326
- else if (esc === "f") chars.add(12);
1327
- else return null;
1344
+ return pos;
1345
+ };
1346
+ }
1347
+ function classRunSource(source) {
1348
+ const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1349
+ return m ? classScanner(m[1]) : null;
1350
+ }
1351
+ function classifyTriviaArm(arm) {
1352
+ const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1353
+ if (cls) {
1354
+ const ranges = parseClassRanges(cls[1]);
1355
+ return ranges ? { kind: "class", ranges } : null;
1356
+ }
1357
+ const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1358
+ if (lc) {
1359
+ const marker = lc[1];
1360
+ return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
1328
1361
  }
1362
+ return null;
1363
+ }
1364
+ function armScanner(arm) {
1365
+ if (arm.kind === "comment") return lineCommentScanner(arm.code);
1366
+ const ranges = arm.ranges;
1367
+ return (input, cur) => {
1368
+ let pos = cur;
1369
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1370
+ return pos;
1371
+ };
1372
+ }
1373
+ function fusedTriviaScanner(ranges, commentCodes) {
1374
+ const c0 = commentCodes[0];
1375
+ const single = commentCodes.length === 1;
1329
1376
  return (input, cur) => {
1330
1377
  let pos = cur;
1331
- while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
1378
+ const len = input.length;
1379
+ for (; ; ) {
1380
+ const c = input.charCodeAt(pos);
1381
+ if (pos < len && inRanges2(c, ranges)) {
1382
+ pos++;
1383
+ continue;
1384
+ }
1385
+ if (single ? c === c0 : commentCodes.includes(c)) {
1386
+ pos++;
1387
+ while (pos < len) {
1388
+ const cc = input.charCodeAt(pos);
1389
+ if (cc === 10 || cc === 13) break;
1390
+ pos++;
1391
+ }
1392
+ continue;
1393
+ }
1394
+ break;
1395
+ }
1332
1396
  return pos;
1333
1397
  };
1334
1398
  }
1399
+ function splitTopLevelAlts(body) {
1400
+ const arms = [];
1401
+ let inClass = false;
1402
+ let start = 0;
1403
+ for (let i = 0; i < body.length; i++) {
1404
+ const c = body[i];
1405
+ if (c === "\\") {
1406
+ i++;
1407
+ continue;
1408
+ }
1409
+ if (inClass) {
1410
+ if (c === "]") inClass = false;
1411
+ continue;
1412
+ }
1413
+ if (c === "[") inClass = true;
1414
+ else if (c === "(") return null;
1415
+ else if (c === "|") {
1416
+ arms.push(body.slice(start, i));
1417
+ start = i + 1;
1418
+ }
1419
+ }
1420
+ arms.push(body.slice(start));
1421
+ return arms;
1422
+ }
1423
+ function altStarSource(source) {
1424
+ const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1425
+ if (!m) return null;
1426
+ const armSrcs = splitTopLevelAlts(m[1]);
1427
+ if (!armSrcs || armSrcs.length < 2) return null;
1428
+ const arms = [];
1429
+ for (const src of armSrcs) {
1430
+ const arm = classifyTriviaArm(src);
1431
+ if (!arm) return null;
1432
+ arms.push(arm);
1433
+ }
1434
+ const ranges = [];
1435
+ const commentCodes = [];
1436
+ for (const arm of arms) {
1437
+ if (arm.kind === "class") ranges.push(...arm.ranges);
1438
+ else commentCodes.push(arm.code);
1439
+ }
1440
+ if (commentCodes.some((code) => inRanges2(code, ranges))) {
1441
+ return loopScanner(arms.map(armScanner));
1442
+ }
1443
+ if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
1444
+ return fusedTriviaScanner(ranges, commentCodes);
1445
+ }
1335
1446
  function blockCommentSource(source) {
1336
1447
  return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1337
1448
  }
@@ -1685,6 +1796,7 @@ function markUnusedValues(root) {
1685
1796
  }
1686
1797
 
1687
1798
  // src/combinators/parser.ts
1799
+ var RULE_ORDER = "__parsemanRuleOrder";
1688
1800
  function tagRule(r, key) {
1689
1801
  ;
1690
1802
  r._ruleName = key;
@@ -1729,6 +1841,11 @@ function rules(a, b) {
1729
1841
  for (const key of Object.keys(definitions)) {
1730
1842
  markUnusedValues(cache[key]);
1731
1843
  }
1844
+ Object.defineProperty(cache, RULE_ORDER, {
1845
+ value: Object.keys(definitions),
1846
+ enumerable: false,
1847
+ configurable: true
1848
+ });
1732
1849
  return cache;
1733
1850
  }
1734
1851