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.d.ts
CHANGED
|
@@ -2,6 +2,14 @@ import MagicString from 'magic-string';
|
|
|
2
2
|
export type ParsecraftPluginOptions = {
|
|
3
3
|
/** Extra module specifiers to treat as parseman re-exports */
|
|
4
4
|
moduleAliases?: string[];
|
|
5
|
+
/**
|
|
6
|
+
* Warn when a regex terminal can't LOWER to a fast `charCodeAt` scan and falls
|
|
7
|
+
* back to `RegExp.exec`. **Default `false` (opt-in).** `RegExp.exec` is an
|
|
8
|
+
* accepted, JIT-fast compiled path — most un-lowered regexes are perfectly fine
|
|
9
|
+
* and lowering them often shows no real gain — so this is a diagnostic you turn
|
|
10
|
+
* ON when specifically auditing lowering coverage, not a build-time nag.
|
|
11
|
+
*/
|
|
12
|
+
warnUnloweredRegex?: boolean;
|
|
5
13
|
};
|
|
6
14
|
declare const _default: import("unplugin").UnpluginInstance<ParsecraftPluginOptions, boolean>;
|
|
7
15
|
export default _default;
|
|
@@ -11,5 +19,5 @@ export type TransformMacroResult = {
|
|
|
11
19
|
/** Diagnostics for macro-referencing shapes that fell back to the interpreter. */
|
|
12
20
|
warnings: string[];
|
|
13
21
|
};
|
|
14
|
-
export declare function transformMacro(code: string, id: string, moduleAliases?: Set<string
|
|
22
|
+
export declare function transformMacro(code: string, id: string, moduleAliases?: Set<string>, warnUnloweredRegex?: boolean): TransformMacroResult | null;
|
|
15
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAgBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAgBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;;;AA+KD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,GACzB,oBAAoB,GAAG,IAAI,CA8hB7B"}
|
package/dist/plugin/index.js
CHANGED
|
@@ -298,12 +298,16 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
// src/combinators/literal.ts
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
301
|
+
function asciiFoldEq(a, b) {
|
|
302
|
+
if (a.length !== b.length) return false;
|
|
303
|
+
for (let i = 0; i < a.length; i++) {
|
|
304
|
+
let ca = a.charCodeAt(i);
|
|
305
|
+
let cb = b.charCodeAt(i);
|
|
306
|
+
if (ca >= 65 && ca <= 90) ca += 32;
|
|
307
|
+
if (cb >= 65 && cb <= 90) cb += 32;
|
|
308
|
+
if (ca !== cb) return false;
|
|
305
309
|
}
|
|
306
|
-
return
|
|
310
|
+
return true;
|
|
307
311
|
}
|
|
308
312
|
function literal(value, opts = {}) {
|
|
309
313
|
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
@@ -318,8 +322,9 @@ function literal(value, opts = {}) {
|
|
|
318
322
|
const lower = value.toLowerCase();
|
|
319
323
|
const firstUpper = upper.codePointAt(0);
|
|
320
324
|
const firstLower = lower.codePointAt(0);
|
|
321
|
-
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? { kind: "ranges", ranges: [
|
|
322
|
-
{ lo:
|
|
325
|
+
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
326
|
+
{ lo: firstLower, hi: firstLower },
|
|
327
|
+
{ lo: firstUpper, hi: firstUpper }
|
|
323
328
|
] } : firstSet;
|
|
324
329
|
}
|
|
325
330
|
return {
|
|
@@ -332,7 +337,7 @@ function literal(value, opts = {}) {
|
|
|
332
337
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
333
338
|
}
|
|
334
339
|
const slice = input.slice(pos, end);
|
|
335
|
-
const matched = caseInsensitive ?
|
|
340
|
+
const matched = caseInsensitive ? asciiFoldEq(slice, value) : slice === value;
|
|
336
341
|
if (matched) {
|
|
337
342
|
const span = { start: pos, end };
|
|
338
343
|
const leaf = { _tag: "leaf", value: slice, span };
|
|
@@ -1561,8 +1566,8 @@ function classToRanges(cls) {
|
|
|
1561
1566
|
return parseClassRanges(body);
|
|
1562
1567
|
}
|
|
1563
1568
|
var foldEq = (cVar, cp) => {
|
|
1564
|
-
if (cp >= 65 && cp <= 90) return `(${cVar}
|
|
1565
|
-
if (cp >= 97 && cp <= 122) return `(${cVar}
|
|
1569
|
+
if (cp >= 65 && cp <= 90) return `(${cVar} | 32) === ${cp + 32}`;
|
|
1570
|
+
if (cp >= 97 && cp <= 122) return `(${cVar} | 32) === ${cp}`;
|
|
1566
1571
|
return `${cVar} === ${cp}`;
|
|
1567
1572
|
};
|
|
1568
1573
|
function literalCodePoints(frag) {
|
|
@@ -1813,6 +1818,12 @@ function firstSetsDisjoint(a, b) {
|
|
|
1813
1818
|
return classDisjoint(a, b);
|
|
1814
1819
|
}
|
|
1815
1820
|
function fixedClassSeq(shape) {
|
|
1821
|
+
if (shape.kind === "litFold") {
|
|
1822
|
+
return shape.open.map((cp) => {
|
|
1823
|
+
const other = cp >= 65 && cp <= 90 ? cp + 32 : cp >= 97 && cp <= 122 ? cp - 32 : cp;
|
|
1824
|
+
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 };
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1816
1827
|
if (shape.kind !== "seq") return null;
|
|
1817
1828
|
const out = [];
|
|
1818
1829
|
for (const p of shape.parts) {
|
|
@@ -2234,12 +2245,34 @@ function parseScanShapeCore(source) {
|
|
|
2234
2245
|
}
|
|
2235
2246
|
function scanShapeFromRegex(source, flags) {
|
|
2236
2247
|
if (/[msu]/.test(flags)) return null;
|
|
2237
|
-
if (/i/.test(flags))
|
|
2238
|
-
const open = literalCodePoints(source);
|
|
2239
|
-
return open ? { kind: "litFold", open } : null;
|
|
2240
|
-
}
|
|
2248
|
+
if (/i/.test(flags)) return caseFoldShape(source);
|
|
2241
2249
|
return parseScanShape(source);
|
|
2242
2250
|
}
|
|
2251
|
+
function caseFoldShape(source) {
|
|
2252
|
+
const la = stripTrailingLookahead(source);
|
|
2253
|
+
if (la) {
|
|
2254
|
+
const inner = caseFoldLiteralOrAlt(la.base);
|
|
2255
|
+
if (!inner) return null;
|
|
2256
|
+
const operand = { ranges: la.ranges, negated: la.classNegated };
|
|
2257
|
+
if (!lookaheadUnambiguous(inner, operand, la.negative)) return null;
|
|
2258
|
+
return { kind: "lookahead", inner, ranges: la.ranges, classNegated: la.classNegated, negative: la.negative };
|
|
2259
|
+
}
|
|
2260
|
+
return caseFoldLiteralOrAlt(source);
|
|
2261
|
+
}
|
|
2262
|
+
function caseFoldLiteralOrAlt(source) {
|
|
2263
|
+
const asciiOnly = (cps) => cps.every((cp) => cp <= 127);
|
|
2264
|
+
const open = literalCodePoints(source);
|
|
2265
|
+
if (open) return asciiOnly(open) ? { kind: "litFold", open } : null;
|
|
2266
|
+
const arms = splitTopLevelAlternation(source);
|
|
2267
|
+
if (!arms || arms.length < 2) return null;
|
|
2268
|
+
const litArms = [];
|
|
2269
|
+
for (const arm of arms) {
|
|
2270
|
+
const cp = literalCodePoints(arm);
|
|
2271
|
+
if (!cp || !asciiOnly(cp)) return null;
|
|
2272
|
+
litArms.push({ kind: "litFold", open: cp });
|
|
2273
|
+
}
|
|
2274
|
+
return { kind: "alt", arms: litArms, disjoint: false, firsts: litArms.map(() => null) };
|
|
2275
|
+
}
|
|
2243
2276
|
var classCond = (cVar, ranges) => ranges.map(([lo, hi]) => lo === hi ? `${cVar} === ${lo}` : `(${cVar} >= ${lo} && ${cVar} <= ${hi})`).join(" || ");
|
|
2244
2277
|
var litCond = (base, cps, firstVar) => cps.map(
|
|
2245
2278
|
(cp, k) => k === 0 && firstVar ? `${firstVar} === ${cp}` : `input.charCodeAt(${base}${k ? ` + ${k}` : ""}) === ${cp}`
|
|
@@ -2251,6 +2284,25 @@ function stringHardStop(shape) {
|
|
|
2251
2284
|
);
|
|
2252
2285
|
}
|
|
2253
2286
|
var codeAt = (start, firstChar) => firstChar ?? `input.charCodeAt(${start})`;
|
|
2287
|
+
var ALT_SWITCH_RANGE_LIMIT = 4;
|
|
2288
|
+
var ALT_SWITCH_MAX_CASES = 48;
|
|
2289
|
+
var ALT_SWITCH_MIN_CASES = 3;
|
|
2290
|
+
function planAltSwitch(firsts) {
|
|
2291
|
+
const cases = [];
|
|
2292
|
+
let total = 0;
|
|
2293
|
+
for (const fs2 of firsts) {
|
|
2294
|
+
if (!fs2 || fs2.negated) return { kind: "if" };
|
|
2295
|
+
const pts = [];
|
|
2296
|
+
for (const [lo, hi] of fs2.ranges) {
|
|
2297
|
+
if (hi - lo + 1 > ALT_SWITCH_RANGE_LIMIT) return { kind: "if" };
|
|
2298
|
+
for (let cp = lo; cp <= hi; cp++) pts.push(cp);
|
|
2299
|
+
}
|
|
2300
|
+
total += pts.length;
|
|
2301
|
+
if (total > ALT_SWITCH_MAX_CASES) return { kind: "if" };
|
|
2302
|
+
cases.push(pts);
|
|
2303
|
+
}
|
|
2304
|
+
return total >= ALT_SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
2305
|
+
}
|
|
2254
2306
|
function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
2255
2307
|
if (shape.kind === "lookahead") {
|
|
2256
2308
|
const inner = emitShapeMatch(shape.inner, start, mint, ind2, firstChar);
|
|
@@ -2275,18 +2327,57 @@ function emitShapeMatch(shape, start, mint, ind2, firstChar) {
|
|
|
2275
2327
|
const okV = mint("_ok");
|
|
2276
2328
|
const endV2 = mint("_end");
|
|
2277
2329
|
const lines = [`${ind2}let ${okV} = false`, `${ind2}let ${endV2} = ${start}`];
|
|
2330
|
+
if (shape.arms.length >= 2 && shape.arms.every((a) => a.kind === "litFold" && a.open.length >= 1)) {
|
|
2331
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2332
|
+
for (const a of shape.arms) {
|
|
2333
|
+
const open = a.open;
|
|
2334
|
+
const f = open[0];
|
|
2335
|
+
const lower = f >= 65 && f <= 90 ? f + 32 : f;
|
|
2336
|
+
(groups.get(lower) ?? groups.set(lower, []).get(lower)).push(open);
|
|
2337
|
+
}
|
|
2338
|
+
lines.push(`${ind2}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
2339
|
+
for (const [lower, arms] of groups) {
|
|
2340
|
+
const labels = lower >= 97 && lower <= 122 ? `case ${lower}: case ${lower - 32}:` : `case ${lower}:`;
|
|
2341
|
+
lines.push(`${ind2} ${labels} {`);
|
|
2342
|
+
for (const open of arms) {
|
|
2343
|
+
const tail = open.slice(1).map((cp, i) => foldEq(`input.charCodeAt(${start} + ${i + 1})`, cp));
|
|
2344
|
+
const cond = tail.length ? ` && ${tail.join(" && ")}` : "";
|
|
2345
|
+
lines.push(`${ind2} if (${start} + ${open.length} <= input.length${cond}) { ${okV} = true; ${endV2} = ${start} + ${open.length}; break }`);
|
|
2346
|
+
}
|
|
2347
|
+
lines.push(`${ind2} break`);
|
|
2348
|
+
lines.push(`${ind2} }`);
|
|
2349
|
+
}
|
|
2350
|
+
lines.push(`${ind2}}`);
|
|
2351
|
+
return { setup: lines, ok: okV, end: endV2 };
|
|
2352
|
+
}
|
|
2278
2353
|
if (shape.disjoint) {
|
|
2279
|
-
const
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2354
|
+
const plan = planAltSwitch(shape.firsts);
|
|
2355
|
+
if (plan.kind === "switch") {
|
|
2356
|
+
lines.push(`${ind2}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
2357
|
+
shape.arms.forEach((arm, k) => {
|
|
2358
|
+
const labels = plan.cases[k].map((cp) => `case ${cp}:`).join(" ");
|
|
2359
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2360
|
+
lines.push(`${ind2} ${labels} {`);
|
|
2361
|
+
lines.push(...m.setup);
|
|
2362
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2363
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2364
|
+
lines.push(`${ind2} break`);
|
|
2365
|
+
lines.push(`${ind2} }`);
|
|
2366
|
+
});
|
|
2288
2367
|
lines.push(`${ind2}}`);
|
|
2289
|
-
}
|
|
2368
|
+
} else {
|
|
2369
|
+
const c0 = codeAt(start, firstChar);
|
|
2370
|
+
shape.arms.forEach((arm, k) => {
|
|
2371
|
+
const fs2 = shape.firsts[k];
|
|
2372
|
+
const cond = fs2.negated ? `!(${classCond(c0, fs2.ranges)})` : `(${classCond(c0, fs2.ranges)})`;
|
|
2373
|
+
const m = emitShapeMatch(arm, start, mint, `${ind2} `, firstChar);
|
|
2374
|
+
lines.push(`${ind2}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
2375
|
+
lines.push(...m.setup);
|
|
2376
|
+
lines.push(`${ind2} ${okV} = ${m.ok}`);
|
|
2377
|
+
lines.push(`${ind2} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
2378
|
+
lines.push(`${ind2}}`);
|
|
2379
|
+
});
|
|
2380
|
+
}
|
|
2290
2381
|
} else {
|
|
2291
2382
|
const lbl = mint("_alt");
|
|
2292
2383
|
lines.push(`${ind2}${lbl}: {`);
|
|
@@ -2774,6 +2865,16 @@ function tryInlineDestructureTransform(src, valueVars) {
|
|
|
2774
2865
|
}
|
|
2775
2866
|
|
|
2776
2867
|
// src/compiler/codegen.ts
|
|
2868
|
+
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 }";
|
|
2869
|
+
var _loweringSink = null;
|
|
2870
|
+
function beginLoweringCapture() {
|
|
2871
|
+
_loweringSink = /* @__PURE__ */ new Set();
|
|
2872
|
+
}
|
|
2873
|
+
function endLoweringCapture() {
|
|
2874
|
+
const misses = _loweringSink ? [..._loweringSink] : [];
|
|
2875
|
+
_loweringSink = null;
|
|
2876
|
+
return misses;
|
|
2877
|
+
}
|
|
2777
2878
|
function v(ctx, prefix = "_v") {
|
|
2778
2879
|
return `${prefix}${ctx.vars++}`;
|
|
2779
2880
|
}
|
|
@@ -3172,13 +3273,14 @@ function emitLit(def, ctx, pos) {
|
|
|
3172
3273
|
const vv = v(ctx);
|
|
3173
3274
|
const expectedStr = JSON.stringify(JSON.stringify(value));
|
|
3174
3275
|
const stmts = [];
|
|
3175
|
-
if (caseInsensitive) {
|
|
3176
|
-
|
|
3276
|
+
if (caseInsensitive && len > 0) {
|
|
3277
|
+
const match = Array.from(
|
|
3278
|
+
{ length: len },
|
|
3279
|
+
(_, i) => `(${foldEq(`input.charCodeAt(${pos}${i > 0 ? ` + ${i}` : ""})`, value.charCodeAt(i))})`
|
|
3280
|
+
).join(" && ");
|
|
3177
3281
|
stmts.push(
|
|
3178
|
-
...emitIfFail(ctx, `${pos} + ${len} > input.length`, failBody(ctx, expectedStr, pos)),
|
|
3179
|
-
`${ind(ctx)}const ${vv}
|
|
3180
|
-
...emitIfFail(ctx, `_collator.compare(${vv}_s, ${JSON.stringify(value)}) !== 0`, failBody(ctx, expectedStr, pos)),
|
|
3181
|
-
`${ind(ctx)}const ${vv} = ${vv}_s`
|
|
3282
|
+
...emitIfFail(ctx, `${pos} + ${len} > input.length || !(${match})`, failBody(ctx, expectedStr, pos)),
|
|
3283
|
+
`${ind(ctx)}const ${vv} = input.slice(${pos}, ${pos} + ${len})`
|
|
3182
3284
|
);
|
|
3183
3285
|
} else if (len === 0) {
|
|
3184
3286
|
stmts.push(`${ind(ctx)}const ${vv} = ''`);
|
|
@@ -3299,6 +3401,7 @@ function emitRegex(def, ctx, pos) {
|
|
|
3299
3401
|
return { stmts: stmts2, valueVar: vv2, endVar: scanned.endVar };
|
|
3300
3402
|
}
|
|
3301
3403
|
}
|
|
3404
|
+
_loweringSink?.add(`/${def.source}/${def.flags}`);
|
|
3302
3405
|
const flags = "y" + def.flags.replace(/[gy]/g, "");
|
|
3303
3406
|
const key = `${def.source}/${flags}`;
|
|
3304
3407
|
let rName = ctx.regexMap.get(key);
|
|
@@ -3879,15 +3982,19 @@ function emitNode(def, ctx, pos) {
|
|
|
3879
3982
|
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
3880
3983
|
}
|
|
3881
3984
|
const i = ind(ctx);
|
|
3882
|
-
const capturesTrivia = mkType !== null || structural
|
|
3883
|
-
const clonesState = structural
|
|
3985
|
+
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
3986
|
+
const clonesState = !structural && buildReadsState(def);
|
|
3884
3987
|
const chV = v(ctx, "_ch");
|
|
3885
3988
|
const rawV = v(ctx, "_raw");
|
|
3886
|
-
const
|
|
3989
|
+
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
3990
|
+
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
3991
|
+
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
3887
3992
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
3888
3993
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
3889
|
-
|
|
3890
|
-
const
|
|
3994
|
+
if (structural) ctx.needsHostReads = true;
|
|
3995
|
+
const allocStmt = structural ? `${i}const ${capTLv} = _ctx._pmCapTL ??= _hostReads(_ctx.build, 4), ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 5))
|
|
3996
|
+
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
3997
|
+
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
3891
3998
|
const stmts = [
|
|
3892
3999
|
allocStmt,
|
|
3893
4000
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
@@ -3898,7 +4005,10 @@ function emitNode(def, ctx, pos) {
|
|
|
3898
4005
|
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
|
|
3899
4006
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
3900
4007
|
let stV = "undefined";
|
|
3901
|
-
if (
|
|
4008
|
+
if (structural) {
|
|
4009
|
+
stV = v(ctx, "_nst");
|
|
4010
|
+
stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4011
|
+
} else if (clonesState) {
|
|
3902
4012
|
stV = v(ctx, "_nst");
|
|
3903
4013
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
3904
4014
|
}
|
|
@@ -4334,7 +4444,6 @@ function compile(combinator, mapFnSources) {
|
|
|
4334
4444
|
buildFns: [],
|
|
4335
4445
|
buildSrcs: [],
|
|
4336
4446
|
runtimeParsers: [],
|
|
4337
|
-
needsCollator: false,
|
|
4338
4447
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4339
4448
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4340
4449
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4343,18 +4452,18 @@ function compile(combinator, mapFnSources) {
|
|
|
4343
4452
|
lazyUsage: analyzeLazyUsage(combinator)
|
|
4344
4453
|
};
|
|
4345
4454
|
const r = emit(combinator, ctx, "_pos");
|
|
4346
|
-
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
4347
|
-
` : "";
|
|
4348
4455
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
4349
4456
|
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
4457
|
+
const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
|
|
4350
4458
|
const source = [
|
|
4351
4459
|
...emptyTlDecls,
|
|
4460
|
+
...hostReadsDecls,
|
|
4352
4461
|
...ctx.regexDecls,
|
|
4353
4462
|
...ctx.expectedDecls,
|
|
4354
4463
|
"",
|
|
4355
4464
|
...namedPrelude,
|
|
4356
4465
|
ctx.namedFnDecls.join("\n\n"),
|
|
4357
|
-
|
|
4466
|
+
`function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
4358
4467
|
` let pos = _pos`,
|
|
4359
4468
|
...r.stmts,
|
|
4360
4469
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
@@ -4362,9 +4471,9 @@ function compile(combinator, mapFnSources) {
|
|
|
4362
4471
|
].join("\n");
|
|
4363
4472
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
4364
4473
|
...emptyTlDecls,
|
|
4474
|
+
...hostReadsDecls,
|
|
4365
4475
|
...ctx.regexDecls,
|
|
4366
4476
|
...ctx.expectedDecls,
|
|
4367
|
-
collatorDecl,
|
|
4368
4477
|
...namedPrelude,
|
|
4369
4478
|
...ctx.namedFnDecls.flatMap((decl, i) => i > 0 ? ["", decl] : [decl]),
|
|
4370
4479
|
`let pos = _pos`,
|
|
@@ -4381,7 +4490,7 @@ function compile(combinator, mapFnSources) {
|
|
|
4381
4490
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
4382
4491
|
const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
|
|
4383
4492
|
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
4384
|
-
const inlineExpression = canInline ? buildInlineExpression(ctx, r,
|
|
4493
|
+
const inlineExpression = canInline ? buildInlineExpression(ctx, r, effectiveSources, buildSources) : null;
|
|
4385
4494
|
return {
|
|
4386
4495
|
source,
|
|
4387
4496
|
inlineExpression,
|
|
@@ -4426,7 +4535,6 @@ function compileRuleMap(ruleMap) {
|
|
|
4426
4535
|
buildFns: [],
|
|
4427
4536
|
buildSrcs: [],
|
|
4428
4537
|
runtimeParsers: [],
|
|
4429
|
-
needsCollator: false,
|
|
4430
4538
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4431
4539
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4432
4540
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4445,8 +4553,6 @@ function compileRuleMap(ruleMap) {
|
|
|
4445
4553
|
}
|
|
4446
4554
|
ctx.ruleNames = ruleNames;
|
|
4447
4555
|
const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
|
|
4448
|
-
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
4449
|
-
` : "";
|
|
4450
4556
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
4451
4557
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
4452
4558
|
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
@@ -4458,9 +4564,9 @@ function compileRuleMap(ruleMap) {
|
|
|
4458
4564
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
4459
4565
|
const hoistedDecls = [
|
|
4460
4566
|
ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "",
|
|
4567
|
+
ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "",
|
|
4461
4568
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
4462
4569
|
...ctx.expectedDecls.map((d) => ` ${d}`),
|
|
4463
|
-
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
4464
4570
|
mfDecl,
|
|
4465
4571
|
buildDecl,
|
|
4466
4572
|
...namedPrelude.map((l) => ` ${l}`),
|
|
@@ -4513,7 +4619,6 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
4513
4619
|
buildFns: [],
|
|
4514
4620
|
buildSrcs: [],
|
|
4515
4621
|
runtimeParsers: [],
|
|
4516
|
-
needsCollator: false,
|
|
4517
4622
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
4518
4623
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
4519
4624
|
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
@@ -4644,12 +4749,12 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
4644
4749
|
firstSets,
|
|
4645
4750
|
deps: ruleDependencies(ruleMap),
|
|
4646
4751
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
4647
|
-
|
|
4752
|
+
needsHostReads: !!ctx.needsHostReads,
|
|
4648
4753
|
mfFns: mfSrcs ? [] : ctx.mapFns,
|
|
4649
4754
|
buildFns: buildSrcs ? [] : ctx.buildFns
|
|
4650
4755
|
};
|
|
4651
4756
|
}
|
|
4652
|
-
function buildInlineExpression(ctx, r,
|
|
4757
|
+
function buildInlineExpression(ctx, r, mapFnSources, buildSources) {
|
|
4653
4758
|
const bodyLines = [
|
|
4654
4759
|
` let pos = _pos`,
|
|
4655
4760
|
...r.stmts,
|
|
@@ -4663,14 +4768,15 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
4663
4768
|
const mfDecl = mapFnSources?.length ? ` const _mf = [${mapFnSources.join(", ")}]` : "";
|
|
4664
4769
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
4665
4770
|
const emptyTlDecl = ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "";
|
|
4666
|
-
const
|
|
4771
|
+
const hostReadsDecl = ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "";
|
|
4772
|
+
const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl;
|
|
4667
4773
|
if (!needsWrapper) return innerFn;
|
|
4668
4774
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
4669
4775
|
const hoistedDecls = [
|
|
4670
4776
|
emptyTlDecl,
|
|
4777
|
+
hostReadsDecl,
|
|
4671
4778
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
4672
4779
|
...ctx.expectedDecls.map((d) => ` ${d}`),
|
|
4673
|
-
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
4674
4780
|
mfDecl,
|
|
4675
4781
|
buildDecl,
|
|
4676
4782
|
...namedPrelude.map((l) => ` ${l}`),
|
|
@@ -4698,13 +4804,13 @@ function fusedBody(pieces) {
|
|
|
4698
4804
|
}
|
|
4699
4805
|
const contributing = new Set(winner.values());
|
|
4700
4806
|
const needsEmptyTl = [...contributing].some((p) => p.needsEmptyTl);
|
|
4701
|
-
const
|
|
4807
|
+
const needsHostReads = [...contributing].some((p) => p.needsHostReads);
|
|
4702
4808
|
const lines = [
|
|
4703
4809
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
4704
4810
|
"const _pfFail = {}",
|
|
4705
4811
|
"let _pfEnd",
|
|
4706
4812
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
4707
|
-
...
|
|
4813
|
+
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
4708
4814
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
4709
4815
|
...[...contributing].flatMap((p) => p.prelude),
|
|
4710
4816
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
@@ -5350,7 +5456,7 @@ var plugin_default = createUnplugin((opts = {}) => ({
|
|
|
5350
5456
|
if (!code.includes("parseman")) return null;
|
|
5351
5457
|
if (!code.includes("macro")) return null;
|
|
5352
5458
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
5353
|
-
const result = transformMacro(code, id, moduleAliases);
|
|
5459
|
+
const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true);
|
|
5354
5460
|
if (result?.warnings.length) {
|
|
5355
5461
|
for (const w of result.warnings) {
|
|
5356
5462
|
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
@@ -5432,7 +5538,7 @@ function findCarriedPiecesLiteral(root) {
|
|
|
5432
5538
|
visit(root);
|
|
5433
5539
|
return found;
|
|
5434
5540
|
}
|
|
5435
|
-
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE])) {
|
|
5541
|
+
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false) {
|
|
5436
5542
|
let result;
|
|
5437
5543
|
try {
|
|
5438
5544
|
result = parseSync(id, code);
|
|
@@ -5471,6 +5577,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5471
5577
|
const scope = /* @__PURE__ */ new Map();
|
|
5472
5578
|
const replacements = [];
|
|
5473
5579
|
const warnings = [];
|
|
5580
|
+
beginLoweringCapture();
|
|
5474
5581
|
let anyUnresolved = false;
|
|
5475
5582
|
let ruleMapHolderCounter = 0;
|
|
5476
5583
|
const lineOf = (pos) => {
|
|
@@ -5507,7 +5614,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5507
5614
|
const nsFor = (label2) => `_${createHash("sha1").update(`${id}#${label2}`).digest("hex").slice(0, 8)}_`;
|
|
5508
5615
|
const serializePieces = (p) => {
|
|
5509
5616
|
const mapLit = (m) => `new Map([${[...m].map(([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(v2)}]`).join(", ")}])`;
|
|
5510
|
-
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},
|
|
5617
|
+
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: [] }`;
|
|
5511
5618
|
};
|
|
5512
5619
|
const serializeList = (list) => `[${list.map(serializePieces).join(", ")}]`;
|
|
5513
5620
|
const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ (() => { const _g = ${grammarExpr}; Object.defineProperty(_g, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)} }); return _g })()`;
|
|
@@ -5778,6 +5885,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
5778
5885
|
for (const { start, end, replacement } of [...replacements].sort((a, b) => b.start - a.start)) {
|
|
5779
5886
|
ms.overwrite(start, end, replacement);
|
|
5780
5887
|
}
|
|
5888
|
+
const unlowered = endLoweringCapture();
|
|
5889
|
+
if (warnUnloweredRegex) {
|
|
5890
|
+
for (const src of unlowered) {
|
|
5891
|
+
warnings.push(`${id}: regex ${src} did not lower to a fast charCodeAt scan (RegExp.exec fallback)`);
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5781
5894
|
return {
|
|
5782
5895
|
code: ms.toString(),
|
|
5783
5896
|
map: ms.generateMap({ hires: true }),
|