parseman 0.15.0 → 0.16.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/combinators/literal.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +16 -2
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/scannable-run.d.ts +2 -0
- package/dist/compiler/scannable-run.d.ts.map +1 -1
- package/dist/index.cjs +150 -49
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +150 -49
- package/dist/index.js.map +2 -2
- package/dist/plugin/index.cjs +169 -56
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.d.ts +9 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +169 -56
- package/dist/plugin/index.js.map +3 -3
- package/package.json +2 -2
package/dist/plugin/index.cjs
CHANGED
|
@@ -333,12 +333,16 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
|
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
// src/combinators/literal.ts
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
336
|
+
function asciiFoldEq(a, b) {
|
|
337
|
+
if (a.length !== b.length) return false;
|
|
338
|
+
for (let i = 0; i < a.length; i++) {
|
|
339
|
+
let ca = a.charCodeAt(i);
|
|
340
|
+
let cb = b.charCodeAt(i);
|
|
341
|
+
if (ca >= 65 && ca <= 90) ca += 32;
|
|
342
|
+
if (cb >= 65 && cb <= 90) cb += 32;
|
|
343
|
+
if (ca !== cb) return false;
|
|
340
344
|
}
|
|
341
|
-
return
|
|
345
|
+
return true;
|
|
342
346
|
}
|
|
343
347
|
function literal(value, opts = {}) {
|
|
344
348
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
@@ -353,8 +357,9 @@ function literal(value, opts = {}) {
|
|
|
353
357
|
const lower = value.toLowerCase();
|
|
354
358
|
const firstUpper = upper.codePointAt(0);
|
|
355
359
|
const firstLower = lower.codePointAt(0);
|
|
356
|
-
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? { kind: "ranges", ranges: [
|
|
357
|
-
{ lo:
|
|
360
|
+
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
361
|
+
{ lo: firstLower, hi: firstLower },
|
|
362
|
+
{ lo: firstUpper, hi: firstUpper }
|
|
358
363
|
] } : firstSet;
|
|
359
364
|
}
|
|
360
365
|
return {
|
|
@@ -367,7 +372,7 @@ function literal(value, opts = {}) {
|
|
|
367
372
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
368
373
|
}
|
|
369
374
|
const slice = input.slice(pos, end);
|
|
370
|
-
const matched = caseInsensitive ?
|
|
375
|
+
const matched = caseInsensitive ? asciiFoldEq(slice, value) : slice === value;
|
|
371
376
|
if (matched) {
|
|
372
377
|
const span = { start: pos, end };
|
|
373
378
|
const leaf = { _tag: "leaf", value: slice, span };
|
|
@@ -1596,8 +1601,8 @@ function classToRanges(cls) {
|
|
|
1596
1601
|
return parseClassRanges(body);
|
|
1597
1602
|
}
|
|
1598
1603
|
var foldEq = (cVar, cp) => {
|
|
1599
|
-
if (cp >= 65 && cp <= 90) return `(${cVar}
|
|
1600
|
-
if (cp >= 97 && cp <= 122) return `(${cVar}
|
|
1604
|
+
if (cp >= 65 && cp <= 90) return `(${cVar} | 32) === ${cp + 32}`;
|
|
1605
|
+
if (cp >= 97 && cp <= 122) return `(${cVar} | 32) === ${cp}`;
|
|
1601
1606
|
return `${cVar} === ${cp}`;
|
|
1602
1607
|
};
|
|
1603
1608
|
function literalCodePoints(frag) {
|
|
@@ -1848,6 +1853,12 @@ function firstSetsDisjoint(a, b) {
|
|
|
1848
1853
|
return classDisjoint(a, b);
|
|
1849
1854
|
}
|
|
1850
1855
|
function fixedClassSeq(shape) {
|
|
1856
|
+
if (shape.kind === "litFold") {
|
|
1857
|
+
return shape.open.map((cp) => {
|
|
1858
|
+
const other = cp >= 65 && cp <= 90 ? cp + 32 : cp >= 97 && cp <= 122 ? cp - 32 : cp;
|
|
1859
|
+
return other === cp ? { ranges: [[cp, cp]], negated: false } : { ranges: [[Math.min(cp, other), Math.min(cp, other)], [Math.max(cp, other), Math.max(cp, other)]], negated: false };
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1851
1862
|
if (shape.kind !== "seq") return null;
|
|
1852
1863
|
const out = [];
|
|
1853
1864
|
for (const p of shape.parts) {
|
|
@@ -2269,12 +2280,34 @@ function parseScanShapeCore(source) {
|
|
|
2269
2280
|
}
|
|
2270
2281
|
function scanShapeFromRegex(source, flags) {
|
|
2271
2282
|
if (/[msu]/.test(flags)) return null;
|
|
2272
|
-
if (/i/.test(flags))
|
|
2273
|
-
const open = literalCodePoints(source);
|
|
2274
|
-
return open ? { kind: "litFold", open } : null;
|
|
2275
|
-
}
|
|
2283
|
+
if (/i/.test(flags)) return caseFoldShape(source);
|
|
2276
2284
|
return parseScanShape(source);
|
|
2277
2285
|
}
|
|
2286
|
+
function caseFoldShape(source) {
|
|
2287
|
+
const la = stripTrailingLookahead(source);
|
|
2288
|
+
if (la) {
|
|
2289
|
+
const inner = caseFoldLiteralOrAlt(la.base);
|
|
2290
|
+
if (!inner) return null;
|
|
2291
|
+
const operand = { ranges: la.ranges, negated: la.classNegated };
|
|
2292
|
+
if (!lookaheadUnambiguous(inner, operand, la.negative)) return null;
|
|
2293
|
+
return { kind: "lookahead", inner, ranges: la.ranges, classNegated: la.classNegated, negative: la.negative };
|
|
2294
|
+
}
|
|
2295
|
+
return caseFoldLiteralOrAlt(source);
|
|
2296
|
+
}
|
|
2297
|
+
function caseFoldLiteralOrAlt(source) {
|
|
2298
|
+
const asciiOnly = (cps) => cps.every((cp) => cp <= 127);
|
|
2299
|
+
const open = literalCodePoints(source);
|
|
2300
|
+
if (open) return asciiOnly(open) ? { kind: "litFold", open } : null;
|
|
2301
|
+
const arms = splitTopLevelAlternation(source);
|
|
2302
|
+
if (!arms || arms.length < 2) return null;
|
|
2303
|
+
const litArms = [];
|
|
2304
|
+
for (const arm of arms) {
|
|
2305
|
+
const cp = literalCodePoints(arm);
|
|
2306
|
+
if (!cp || !asciiOnly(cp)) return null;
|
|
2307
|
+
litArms.push({ kind: "litFold", open: cp });
|
|
2308
|
+
}
|
|
2309
|
+
return { kind: "alt", arms: litArms, disjoint: false, firsts: litArms.map(() => null) };
|
|
2310
|
+
}
|
|
2278
2311
|
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
2279
2312
|
var litCond = (base, cps, firstVar) => cps.map(
|
|
2280
2313
|
(cp, k) => k === 0 && firstVar ? `${firstVar} === ${cp}` : `input.charCodeAt(${base}${k ? ` + ${k}` : ""}) === ${cp}`
|
|
@@ -2286,6 +2319,25 @@ function stringHardStop(shape) {
|
|
|
2286
2319
|
);
|
|
2287
2320
|
}
|
|
2288
2321
|
var codeAt = (start, firstChar) => firstChar ?? `input.charCodeAt(${start})`;
|
|
2322
|
+
var ALT_SWITCH_RANGE_LIMIT = 4;
|
|
2323
|
+
var ALT_SWITCH_MAX_CASES = 48;
|
|
2324
|
+
var ALT_SWITCH_MIN_CASES = 3;
|
|
2325
|
+
function planAltSwitch(firsts) {
|
|
2326
|
+
const cases = [];
|
|
2327
|
+
let total = 0;
|
|
2328
|
+
for (const fs2 of firsts) {
|
|
2329
|
+
if (!fs2 || fs2.negated) return { kind: "if" };
|
|
2330
|
+
const pts = [];
|
|
2331
|
+
for (const [lo, hi] of fs2.ranges) {
|
|
2332
|
+
if (hi - lo + 1 > ALT_SWITCH_RANGE_LIMIT) return { kind: "if" };
|
|
2333
|
+
for (let cp = lo; cp <= hi; cp++) pts.push(cp);
|
|
2334
|
+
}
|
|
2335
|
+
total += pts.length;
|
|
2336
|
+
if (total > ALT_SWITCH_MAX_CASES) return { kind: "if" };
|
|
2337
|
+
cases.push(pts);
|
|
2338
|
+
}
|
|
2339
|
+
return total >= ALT_SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
2340
|
+
}
|
|
2289
2341
|
function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
2290
2342
|
if (shape.kind === "lookahead") {
|
|
2291
2343
|
const inner = emitShapeMatch(shape.inner, start, mint, ind2, firstChar);
|
|
@@ -2310,18 +2362,57 @@ function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
|
2310
2362
|
const okV = mint("_ok");
|
|
2311
2363
|
const endV2 = mint("_end");
|
|
2312
2364
|
const lines = [`${ind2}let ${okV} = false`, `${ind2}let ${endV2} = ${start}`];
|
|
2365
|
+
if (shape.arms.length >= 2 && shape.arms.every((a) => a.kind === "litFold" && a.open.length >= 1)) {
|
|
2366
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2367
|
+
for (const a of shape.arms) {
|
|
2368
|
+
const open = a.open;
|
|
2369
|
+
const f = open[0];
|
|
2370
|
+
const lower = f >= 65 && f <= 90 ? f + 32 : f;
|
|
2371
|
+
(groups.get(lower) ?? groups.set(lower, []).get(lower)).push(open);
|
|
2372
|
+
}
|
|
2373
|
+
lines.push(`${ind2}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
2374
|
+
for (const [lower, arms] of groups) {
|
|
2375
|
+
const labels = lower >= 97 && lower <= 122 ? `case ${lower}: case ${lower - 32}:` : `case ${lower}:`;
|
|
2376
|
+
lines.push(`${ind2} ${labels} {`);
|
|
2377
|
+
for (const open of arms) {
|
|
2378
|
+
const tail = open.slice(1).map((cp, i) => foldEq(`input.charCodeAt(${start} + ${i + 1})`, cp));
|
|
2379
|
+
const cond = tail.length ? ` && ${tail.join(" && ")}` : "";
|
|
2380
|
+
lines.push(`${ind2} if (${start} + ${open.length} <= input.length${cond}) { ${okV} = true; ${endV2} = ${start} + ${open.length}; break }`);
|
|
2381
|
+
}
|
|
2382
|
+
lines.push(`${ind2} break`);
|
|
2383
|
+
lines.push(`${ind2} }`);
|
|
2384
|
+
}
|
|
2385
|
+
lines.push(`${ind2}}`);
|
|
2386
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2387
|
+
}
|
|
2313
2388
|
if (shape.disjoint) {
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2389
|
+
const plan = planAltSwitch(shape.firsts);
|
|
2390
|
+
if (plan.kind === "switch") {
|
|
2391
|
+
lines.push(`${ind2}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
2392
|
+
shape.arms.forEach((arm, k) => {
|
|
2393
|
+
const labels = plan.cases[k].map((cp) => `case ${cp}:`).join(" ");
|
|
2394
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2395
|
+
lines.push(`${ind2} ${labels} {`);
|
|
2396
|
+
lines.push(...m.setup);
|
|
2397
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2398
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2399
|
+
lines.push(`${ind2} break`);
|
|
2400
|
+
lines.push(`${ind2} }`);
|
|
2401
|
+
});
|
|
2323
2402
|
lines.push(`${ind2}}`);
|
|
2324
|
-
}
|
|
2403
|
+
} else {
|
|
2404
|
+
const c0 = codeAt(start, firstChar);
|
|
2405
|
+
shape.arms.forEach((arm, k) => {
|
|
2406
|
+
const fs2 = shape.firsts[k];
|
|
2407
|
+
const cond = fs2.negated ? `!(${classCond(c0, fs2.ranges)})` : `(${classCond(c0, fs2.ranges)})`;
|
|
2408
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2409
|
+
lines.push(`${ind2}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
2410
|
+
lines.push(...m.setup);
|
|
2411
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2412
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2413
|
+
lines.push(`${ind2}}`);
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2325
2416
|
} else {
|
|
2326
2417
|
const lbl = mint("_alt");
|
|
2327
2418
|
lines.push(`${ind2}${lbl}: {`);
|
|
@@ -2809,6 +2900,16 @@ function tryInlineDestructureTransform(src, valueVars) {
|
|
|
2809
2900
|
}
|
|
2810
2901
|
|
|
2811
2902
|
// src/compiler/codegen.ts
|
|
2903
|
+
var HOST_READS_DECL = "const _hostReads = (b, n) => { if (b === undefined) return false; let s; try { s = Function.prototype.toString.call(b) } catch (e) { return true } if (/\\barguments\\b/.test(s)) return true; const m = /^[^(]*\\(([\\s\\S]*?)\\)/.exec(s); if (m && /\\.\\.\\.|=/.test(m[1])) return true; return b.length > n }";
|
|
2904
|
+
var _loweringSink = null;
|
|
2905
|
+
function beginLoweringCapture() {
|
|
2906
|
+
_loweringSink = /* @__PURE__ */ new Set();
|
|
2907
|
+
}
|
|
2908
|
+
function endLoweringCapture() {
|
|
2909
|
+
const misses = _loweringSink ? [..._loweringSink] : [];
|
|
2910
|
+
_loweringSink = null;
|
|
2911
|
+
return misses;
|
|
2912
|
+
}
|
|
2812
2913
|
function v(ctx, prefix = "_v") {
|
|
2813
2914
|
return `${prefix}${ctx.vars++}`;
|
|
2814
2915
|
}
|
|
@@ -3207,13 +3308,14 @@ function emitLit(def, ctx, pos) {
|
|
|
3207
3308
|
const vv = v(ctx);
|
|
3208
3309
|
const expectedStr = JSON.stringify(JSON.stringify(value));
|
|
3209
3310
|
const stmts = [];
|
|
3210
|
-
if (caseInsensitive) {
|
|
3211
|
-
|
|
3311
|
+
if (caseInsensitive && len > 0) {
|
|
3312
|
+
const match = Array.from(
|
|
3313
|
+
{ length: len },
|
|
3314
|
+
(_, i) => `(${foldEq(`input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""})`, value.charCodeAt(i))})`
|
|
3315
|
+
).join(" && ");
|
|
3212
3316
|
stmts.push(
|
|
3213
|
-
...emitIfFail(ctx, `${pos} + ${len} > input.length`, failBody(ctx, expectedStr, pos)),
|
|
3214
|
-
`${ind(ctx)}const ${vv}
|
|
3215
|
-
...emitIfFail(ctx, `_collator.compare(${vv}_s, ${JSON.stringify(value)}) !== 0`, failBody(ctx, expectedStr, pos)),
|
|
3216
|
-
`${ind(ctx)}const ${vv} = ${vv}_s`
|
|
3317
|
+
...emitIfFail(ctx, `${pos} + ${len} > input.length || !(${match})`, failBody(ctx, expectedStr, pos)),
|
|
3318
|
+
`${ind(ctx)}const ${vv} = input.slice(${pos}, ${pos} + ${len})`
|
|
3217
3319
|
);
|
|
3218
3320
|
} else if (len === 0) {
|
|
3219
3321
|
stmts.push(`${ind(ctx)}const ${vv} = ''`);
|
|
@@ -3334,6 +3436,7 @@ function emitRegex(def, ctx, pos) {
|
|
|
3334
3436
|
return { stmts: stmts2, valueVar: vv2, endVar: scanned.endVar };
|
|
3335
3437
|
}
|
|
3336
3438
|
}
|
|
3439
|
+
_loweringSink?.add(`/${def.source}/${def.flags}`);
|
|
3337
3440
|
const flags = "y" + def.flags.replace(/[gy]/g, "");
|
|
3338
3441
|
const key = `${def.source}/${flags}`;
|
|
3339
3442
|
let rName = ctx.regexMap.get(key);
|
|
@@ -3914,15 +4017,19 @@ function emitNode(def, ctx, pos) {
|
|
|
3914
4017
|
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
3915
4018
|
}
|
|
3916
4019
|
const i = ind(ctx);
|
|
3917
|
-
const capturesTrivia = mkType !== null || structural
|
|
3918
|
-
const clonesState = structural
|
|
4020
|
+
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4021
|
+
const clonesState = !structural && buildReadsState(def);
|
|
3919
4022
|
const chV = v(ctx, "_ch");
|
|
3920
4023
|
const rawV = v(ctx, "_raw");
|
|
3921
|
-
const
|
|
4024
|
+
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4025
|
+
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4026
|
+
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
3922
4027
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
3923
4028
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
3924
|
-
|
|
3925
|
-
const
|
|
4029
|
+
if (structural) ctx.needsHostReads = true;
|
|
4030
|
+
const allocStmt = structural ? `${i}const ${capTLv} = _ctx._pmCapTL ??= _hostReads(_ctx.build, 4), ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 5))
|
|
4031
|
+
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4032
|
+
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
3926
4033
|
const stmts = [
|
|
3927
4034
|
allocStmt,
|
|
3928
4035
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
@@ -3933,7 +4040,10 @@ function emitNode(def, ctx, pos) {
|
|
|
3933
4040
|
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
|
|
3934
4041
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
3935
4042
|
let stV = "undefined";
|
|
3936
|
-
if (
|
|
4043
|
+
if (structural) {
|
|
4044
|
+
stV = v(ctx, "_nst");
|
|
4045
|
+
stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4046
|
+
} else if (clonesState) {
|
|
3937
4047
|
stV = v(ctx, "_nst");
|
|
3938
4048
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
3939
4049
|
}
|
|
@@ -4369,7 +4479,6 @@ function compile(combinator, mapFnSources) {
|
|
|
4369
4479
|
buildFns: [],
|
|
4370
4480
|
buildSrcs: [],
|
|
4371
4481
|
runtimeParsers: [],
|
|
4372
|
-
needsCollator: false,
|
|
4373
4482
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4374
4483
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4375
4484
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4378,18 +4487,18 @@ function compile(combinator, mapFnSources) {
|
|
|
4378
4487
|
lazyUsage: analyzeLazyUsage(combinator)
|
|
4379
4488
|
};
|
|
4380
4489
|
const r = emit(combinator, ctx, "_pos");
|
|
4381
|
-
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
4382
|
-
` : "";
|
|
4383
4490
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
4384
4491
|
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
4492
|
+
const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
|
|
4385
4493
|
const source = [
|
|
4386
4494
|
...emptyTlDecls,
|
|
4495
|
+
...hostReadsDecls,
|
|
4387
4496
|
...ctx.regexDecls,
|
|
4388
4497
|
...ctx.expectedDecls,
|
|
4389
4498
|
"",
|
|
4390
4499
|
...namedPrelude,
|
|
4391
4500
|
ctx.namedFnDecls.join("\n\n"),
|
|
4392
|
-
|
|
4501
|
+
`function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
4393
4502
|
` let pos = _pos`,
|
|
4394
4503
|
...r.stmts,
|
|
4395
4504
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
@@ -4397,9 +4506,9 @@ function compile(combinator, mapFnSources) {
|
|
|
4397
4506
|
].join("\n");
|
|
4398
4507
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
4399
4508
|
...emptyTlDecls,
|
|
4509
|
+
...hostReadsDecls,
|
|
4400
4510
|
...ctx.regexDecls,
|
|
4401
4511
|
...ctx.expectedDecls,
|
|
4402
|
-
collatorDecl,
|
|
4403
4512
|
...namedPrelude,
|
|
4404
4513
|
...ctx.namedFnDecls.flatMap((decl, i) => i > 0 ? ["", decl] : [decl]),
|
|
4405
4514
|
`let pos = _pos`,
|
|
@@ -4416,7 +4525,7 @@ function compile(combinator, mapFnSources) {
|
|
|
4416
4525
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
4417
4526
|
const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
|
|
4418
4527
|
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
4419
|
-
const inlineExpression = canInline ? buildInlineExpression(ctx, r,
|
|
4528
|
+
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources) : null;
|
|
4420
4529
|
return {
|
|
4421
4530
|
source,
|
|
4422
4531
|
inlineExpression,
|
|
@@ -4461,7 +4570,6 @@ function compileRuleMap(ruleMap) {
|
|
|
4461
4570
|
buildFns: [],
|
|
4462
4571
|
buildSrcs: [],
|
|
4463
4572
|
runtimeParsers: [],
|
|
4464
|
-
needsCollator: false,
|
|
4465
4573
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4466
4574
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4467
4575
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4480,8 +4588,6 @@ function compileRuleMap(ruleMap) {
|
|
|
4480
4588
|
}
|
|
4481
4589
|
ctx.ruleNames = ruleNames;
|
|
4482
4590
|
const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
|
|
4483
|
-
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
4484
|
-
` : "";
|
|
4485
4591
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
4486
4592
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
4487
4593
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
@@ -4493,9 +4599,9 @@ function compileRuleMap(ruleMap) {
|
|
|
4493
4599
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
4494
4600
|
const hoistedDecls = [
|
|
4495
4601
|
ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "",
|
|
4602
|
+
ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "",
|
|
4496
4603
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
4497
4604
|
...ctx.expectedDecls.map((d) => ` ${d}`),
|
|
4498
|
-
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
4499
4605
|
mfDecl,
|
|
4500
4606
|
buildDecl,
|
|
4501
4607
|
...namedPrelude.map((l) => ` ${l}`),
|
|
@@ -4548,7 +4654,6 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
4548
4654
|
buildFns: [],
|
|
4549
4655
|
buildSrcs: [],
|
|
4550
4656
|
runtimeParsers: [],
|
|
4551
|
-
needsCollator: false,
|
|
4552
4657
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4553
4658
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4554
4659
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4679,12 +4784,12 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
4679
4784
|
firstSets,
|
|
4680
4785
|
deps: ruleDependencies(ruleMap),
|
|
4681
4786
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
4682
|
-
|
|
4787
|
+
needsHostReads: !!ctx.needsHostReads,
|
|
4683
4788
|
mfFns: mfSrcs ? [] : ctx.mapFns,
|
|
4684
4789
|
buildFns: buildSrcs ? [] : ctx.buildFns
|
|
4685
4790
|
};
|
|
4686
4791
|
}
|
|
4687
|
-
function buildInlineExpression(ctx, r,
|
|
4792
|
+
function buildInlineExpression(ctx, r, mapFnSources, buildSources) {
|
|
4688
4793
|
const bodyLines = [
|
|
4689
4794
|
` let pos = _pos`,
|
|
4690
4795
|
...r.stmts,
|
|
@@ -4698,14 +4803,15 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
4698
4803
|
const mfDecl = mapFnSources?.length ? ` const _mf = [${mapFnSources.join(", ")}]` : "";
|
|
4699
4804
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
4700
4805
|
const emptyTlDecl = ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "";
|
|
4701
|
-
const
|
|
4806
|
+
const hostReadsDecl = ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "";
|
|
4807
|
+
const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl;
|
|
4702
4808
|
if (!needsWrapper) return innerFn;
|
|
4703
4809
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
4704
4810
|
const hoistedDecls = [
|
|
4705
4811
|
emptyTlDecl,
|
|
4812
|
+
hostReadsDecl,
|
|
4706
4813
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
4707
4814
|
...ctx.expectedDecls.map((d) => ` ${d}`),
|
|
4708
|
-
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
4709
4815
|
mfDecl,
|
|
4710
4816
|
buildDecl,
|
|
4711
4817
|
...namedPrelude.map((l) => ` ${l}`),
|
|
@@ -4733,13 +4839,13 @@ function fusedBody(pieces) {
|
|
|
4733
4839
|
}
|
|
4734
4840
|
const contributing = new Set(winner.values());
|
|
4735
4841
|
const needsEmptyTl = [...contributing].some((p) => p.needsEmptyTl);
|
|
4736
|
-
const
|
|
4842
|
+
const needsHostReads = [...contributing].some((p) => p.needsHostReads);
|
|
4737
4843
|
const lines = [
|
|
4738
4844
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
4739
4845
|
"const _pfFail = {}",
|
|
4740
4846
|
"let _pfEnd",
|
|
4741
4847
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
4742
|
-
...
|
|
4848
|
+
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
4743
4849
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
4744
4850
|
...[...contributing].flatMap((p) => p.prelude),
|
|
4745
4851
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
@@ -5385,7 +5491,7 @@ var plugin_default = (0, import_unplugin.createUnplugin)((opts = {}) => ({
|
|
|
5385
5491
|
if (!code.includes("parseman")) return null;
|
|
5386
5492
|
if (!code.includes("macro")) return null;
|
|
5387
5493
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
5388
|
-
const result = transformMacro(code, id, moduleAliases);
|
|
5494
|
+
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true);
|
|
5389
5495
|
if (result?.warnings.length) {
|
|
5390
5496
|
for (const w of result.warnings) {
|
|
5391
5497
|
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
@@ -5467,7 +5573,7 @@ function findCarriedPiecesLiteral(root) {
|
|
|
5467
5573
|
visit(root);
|
|
5468
5574
|
return found;
|
|
5469
5575
|
}
|
|
5470
|
-
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE])) {
|
|
5576
|
+
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false) {
|
|
5471
5577
|
let result;
|
|
5472
5578
|
try {
|
|
5473
5579
|
result = (0, import_oxc_parser.parseSync)(id, code);
|
|
@@ -5506,6 +5612,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5506
5612
|
const scope = /* @__PURE__ */ new Map();
|
|
5507
5613
|
const replacements = [];
|
|
5508
5614
|
const warnings = [];
|
|
5615
|
+
beginLoweringCapture();
|
|
5509
5616
|
let anyUnresolved = false;
|
|
5510
5617
|
let ruleMapHolderCounter = 0;
|
|
5511
5618
|
const lineOf = (pos) => {
|
|
@@ -5542,7 +5649,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5542
5649
|
const nsFor = (label2) => `_${(0, import_node_crypto.createHash)("sha1").update(`${id}#${label2}`).digest("hex").slice(0, 8)}_`;
|
|
5543
5650
|
const serializePieces = (p) => {
|
|
5544
5651
|
const mapLit = (m) => `new Map([${[...m].map(([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(v2)}]`).join(", ")}])`;
|
|
5545
|
-
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude)}, ruleFns: ${mapLit(p.ruleFns)}, wrappers: ${mapLit(p.wrappers)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl},
|
|
5652
|
+
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude)}, ruleFns: ${mapLit(p.ruleFns)}, wrappers: ${mapLit(p.wrappers)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, mfFns: [], buildFns: [] }`;
|
|
5546
5653
|
};
|
|
5547
5654
|
const serializeList = (list) => `[${list.map(serializePieces).join(", ")}]`;
|
|
5548
5655
|
const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ (() => { const _g = ${grammarExpr}; Object.defineProperty(_g, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)} }); return _g })()`;
|
|
@@ -5813,6 +5920,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5813
5920
|
for (const { start, end, replacement } of [...replacements].sort((a, b) => b.start - a.start)) {
|
|
5814
5921
|
ms.overwrite(start, end, replacement);
|
|
5815
5922
|
}
|
|
5923
|
+
const unlowered = endLoweringCapture();
|
|
5924
|
+
if (warnUnloweredRegex) {
|
|
5925
|
+
for (const src of unlowered) {
|
|
5926
|
+
warnings.push(`${id}: regex ${src} did not lower to a fast charCodeAt scan (RegExp.exec fallback)`);
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5816
5929
|
return {
|
|
5817
5930
|
code: ms.toString(),
|
|
5818
5931
|
map: ms.generateMap({ hires: true }),
|