parseman 0.9.0 → 0.10.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/README.md +33 -551
- package/dist/combinators/node.d.ts +15 -1
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +26 -0
- package/dist/compiler/build-arity.d.ts.map +1 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/index.cjs +102 -12
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -12
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +89 -13
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.js +89 -13
- package/dist/plugin/index.js.map +3 -3
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -1
package/dist/plugin/index.js
CHANGED
|
@@ -1099,24 +1099,70 @@ function not(combinator) {
|
|
|
1099
1099
|
};
|
|
1100
1100
|
}
|
|
1101
1101
|
|
|
1102
|
+
// src/compiler/build-arity.ts
|
|
1103
|
+
var PARAM_LIST_RE = (
|
|
1104
|
+
// (params) => ... | function name?(params) ... | single-ident arrow `x => ...`
|
|
1105
|
+
/^(?:function\b[^(]*\(([^)]*)\)|\(([^)]*)\)\s*=>|([A-Za-z_$][\w$]*)\s*=>)/
|
|
1106
|
+
);
|
|
1107
|
+
var CONFIRMABLE_PARAM_RE = /^[A-Za-z_$][\w$]*\s*\??\s*(?::[^,=]+)?$/;
|
|
1108
|
+
function confirmedBuildArity(src) {
|
|
1109
|
+
const s = src.trim();
|
|
1110
|
+
const m = PARAM_LIST_RE.exec(s);
|
|
1111
|
+
if (!m) return null;
|
|
1112
|
+
if (m[3] !== void 0) return 1;
|
|
1113
|
+
const inner = (m[1] ?? m[2] ?? "").trim();
|
|
1114
|
+
if (inner === "") return 0;
|
|
1115
|
+
const parts = inner.split(",");
|
|
1116
|
+
for (const part of parts) {
|
|
1117
|
+
if (!CONFIRMABLE_PARAM_RE.test(part.trim())) return null;
|
|
1118
|
+
}
|
|
1119
|
+
if (/\barguments\b/.test(s)) return null;
|
|
1120
|
+
return parts.length;
|
|
1121
|
+
}
|
|
1122
|
+
function buildReadsTrivia(def) {
|
|
1123
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1124
|
+
const arity = confirmedBuildArity(src);
|
|
1125
|
+
if (arity === null) return true;
|
|
1126
|
+
return arity >= 4;
|
|
1127
|
+
}
|
|
1128
|
+
function buildReadsState(def) {
|
|
1129
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1130
|
+
const arity = confirmedBuildArity(src);
|
|
1131
|
+
if (arity === null) return true;
|
|
1132
|
+
return arity >= 5;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1102
1135
|
// src/combinators/node.ts
|
|
1103
|
-
function
|
|
1136
|
+
function collapseChild(child) {
|
|
1137
|
+
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1138
|
+
}
|
|
1139
|
+
function node(type, combinator, build, opts) {
|
|
1104
1140
|
const meta = {
|
|
1105
1141
|
firstSet: combinator._meta.firstSet,
|
|
1106
1142
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1107
1143
|
isTrivia: false
|
|
1108
1144
|
};
|
|
1145
|
+
const collapse = opts?.collapse === true;
|
|
1146
|
+
const def = collapse ? { tag: "node", type, parser: combinator, build, collapse: true } : { tag: "node", type, parser: combinator, build };
|
|
1147
|
+
const capturesTrivia = buildReadsTrivia(def);
|
|
1148
|
+
const clonesState = buildReadsState(def);
|
|
1109
1149
|
return {
|
|
1110
1150
|
_tag: "node",
|
|
1111
1151
|
_meta: meta,
|
|
1112
|
-
_def:
|
|
1152
|
+
_def: def,
|
|
1113
1153
|
parse(input, pos, ctx) {
|
|
1114
1154
|
const saved = beginCstNodeCapture(ctx);
|
|
1155
|
+
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1115
1156
|
const r = combinator.parse(input, pos, ctx);
|
|
1116
1157
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1117
1158
|
if (!r.ok) return r;
|
|
1118
|
-
const
|
|
1119
|
-
|
|
1159
|
+
const built = collapse && children.length === 1 ? collapseChild(children[0]) : build(
|
|
1160
|
+
children,
|
|
1161
|
+
rawChildren,
|
|
1162
|
+
r.span,
|
|
1163
|
+
triviaLog,
|
|
1164
|
+
clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0
|
|
1165
|
+
);
|
|
1120
1166
|
const isNodeLike = typeof built === "object" && built !== null && built._tag === "node";
|
|
1121
1167
|
const rawEntry = isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1122
1168
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
@@ -2519,25 +2565,34 @@ function emitNode(def, ctx, pos) {
|
|
|
2519
2565
|
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
2520
2566
|
}
|
|
2521
2567
|
const i = ind(ctx);
|
|
2568
|
+
const capturesTrivia = mkType !== null || buildReadsTrivia(def);
|
|
2569
|
+
const clonesState = buildReadsState(def);
|
|
2522
2570
|
const chV = v(ctx, "_ch");
|
|
2523
2571
|
const rawV = v(ctx, "_raw");
|
|
2524
|
-
const tlV = v(ctx, "_tl");
|
|
2572
|
+
const tlV = capturesTrivia ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
2573
|
+
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
2525
2574
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
2575
|
+
const allocStmt = capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
2576
|
+
const innerTl = capturesTrivia ? tlV : "undefined";
|
|
2526
2577
|
const stmts = [
|
|
2527
|
-
|
|
2578
|
+
allocStmt,
|
|
2528
2579
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
2529
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${
|
|
2580
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
2530
2581
|
];
|
|
2531
2582
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
2532
2583
|
stmts.push(...innerStmts);
|
|
2533
2584
|
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
|
|
2534
2585
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, failBody(ctx, '"node"', pos)));
|
|
2535
|
-
|
|
2536
|
-
|
|
2586
|
+
let stV = "undefined";
|
|
2587
|
+
if (clonesState) {
|
|
2588
|
+
stV = v(ctx, "_nst");
|
|
2589
|
+
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
2590
|
+
}
|
|
2537
2591
|
const ndV = v(ctx, "_nd");
|
|
2538
2592
|
const ndExpr = mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `_build[${buildIdx}](${chV}, ${rawV}, { start: ${pos}, end: ${endVar} }, ${tlV}, ${stV})`;
|
|
2593
|
+
const finalExpr = def.collapse ? `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})` : ndExpr;
|
|
2539
2594
|
stmts.push(
|
|
2540
|
-
`${i}const ${ndV} = ${
|
|
2595
|
+
`${i}const ${ndV} = ${finalExpr}`,
|
|
2541
2596
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
2542
2597
|
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && ${ndV}._tag === 'node') ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
2543
2598
|
);
|
|
@@ -2929,7 +2984,9 @@ function compile(combinator, mapFnSources) {
|
|
|
2929
2984
|
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
2930
2985
|
` : "";
|
|
2931
2986
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
2987
|
+
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
2932
2988
|
const source = [
|
|
2989
|
+
...emptyTlDecls,
|
|
2933
2990
|
...ctx.regexDecls,
|
|
2934
2991
|
"",
|
|
2935
2992
|
...namedPrelude,
|
|
@@ -2941,6 +2998,7 @@ function compile(combinator, mapFnSources) {
|
|
|
2941
2998
|
`}`
|
|
2942
2999
|
].join("\n");
|
|
2943
3000
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
3001
|
+
...emptyTlDecls,
|
|
2944
3002
|
...ctx.regexDecls,
|
|
2945
3003
|
collatorDecl,
|
|
2946
3004
|
...namedPrelude,
|
|
@@ -3013,6 +3071,7 @@ function compileRuleMap(ruleMap) {
|
|
|
3013
3071
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
3014
3072
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
3015
3073
|
const hoistedDecls = [
|
|
3074
|
+
ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "",
|
|
3016
3075
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
3017
3076
|
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
3018
3077
|
mfDecl,
|
|
@@ -3054,10 +3113,12 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
3054
3113
|
].join("\n");
|
|
3055
3114
|
const mfDecl = mapFnSources?.length ? ` const _mf = [${mapFnSources.join(", ")}]` : "";
|
|
3056
3115
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
3057
|
-
const
|
|
3116
|
+
const emptyTlDecl = ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "";
|
|
3117
|
+
const needsWrapper = ctx.regexDecls.length > 0 || !!collatorDecl || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl;
|
|
3058
3118
|
if (!needsWrapper) return innerFn;
|
|
3059
3119
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
3060
3120
|
const hoistedDecls = [
|
|
3121
|
+
emptyTlDecl,
|
|
3061
3122
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
3062
3123
|
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
3063
3124
|
mfDecl,
|
|
@@ -3258,6 +3319,20 @@ function scopeGet(scope, name, mfs) {
|
|
|
3258
3319
|
if (isCombinator(entry)) return entry;
|
|
3259
3320
|
return null;
|
|
3260
3321
|
}
|
|
3322
|
+
function staticCollapseOption(expr) {
|
|
3323
|
+
if (expr.type !== "ObjectExpression") return false;
|
|
3324
|
+
for (const prop of expr.properties) {
|
|
3325
|
+
const p = prop;
|
|
3326
|
+
if (p.computed) continue;
|
|
3327
|
+
const key = p.key;
|
|
3328
|
+
const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
|
|
3329
|
+
if (name === "collapse") {
|
|
3330
|
+
const val = p.value;
|
|
3331
|
+
return (val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true;
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
return false;
|
|
3335
|
+
}
|
|
3261
3336
|
function exprToCombi(node2, scope, code, mfs) {
|
|
3262
3337
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
3263
3338
|
if (node2.type !== "CallExpression") return null;
|
|
@@ -3306,15 +3381,16 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
3306
3381
|
}
|
|
3307
3382
|
}
|
|
3308
3383
|
if (callee.name === "node" && code !== void 0) {
|
|
3309
|
-
const [typeArg, parserArg, buildArg] = node2.arguments;
|
|
3384
|
+
const [typeArg, parserArg, buildArg, optsArg] = node2.arguments;
|
|
3310
3385
|
if (!typeArg || !parserArg || !buildArg || typeArg.type === "SpreadElement" || parserArg.type === "SpreadElement" || buildArg.type === "SpreadElement") return null;
|
|
3311
3386
|
const typeVal = anyValue(typeArg, scope, code);
|
|
3312
3387
|
if (typeof typeVal !== "string") return null;
|
|
3313
3388
|
const inner = anyValue(parserArg, scope, code, mfs);
|
|
3314
3389
|
if (!isCombinator(inner)) return null;
|
|
3315
3390
|
const buildSrc = code.slice(buildArg.start, buildArg.end);
|
|
3391
|
+
const collapse = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticCollapseOption(optsArg) : false;
|
|
3316
3392
|
try {
|
|
3317
|
-
const combi = node(typeVal, inner, () => null);
|
|
3393
|
+
const combi = node(typeVal, inner, () => null, collapse ? { collapse: true } : void 0);
|
|
3318
3394
|
if (combi._def.tag === "node") combi._def.buildSrc = buildSrc;
|
|
3319
3395
|
return combi;
|
|
3320
3396
|
} catch {
|