parseman 0.61.6 → 0.61.8
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/analysis/diagnostics.js +117 -33
- package/dist/analysis/diagnostics.js.map +2 -2
- package/dist/cli/index.js +117 -33
- package/dist/cli/index.js.map +2 -2
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts +3 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +14 -10
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/index.js +117 -33
- package/dist/index.js.map +2 -2
- package/dist/plugin/index.js +117 -33
- package/dist/plugin/index.js.map +2 -2
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/fail-clean.d.ts.map +1 -1
- package/dist/table/hold-gap.d.ts +3 -1
- package/dist/table/hold-gap.d.ts.map +1 -1
- package/dist/table/index.js +117 -33
- package/dist/table/index.js.map +2 -2
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/combinators/expect.ts +3 -2
- package/src/combinators/first-set.ts +14 -7
- package/src/combinators/sequence.ts +1 -1
- package/src/table/assemble.ts +38 -0
- package/src/table/emit-assembly.ts +42 -5
- package/src/table/encode.ts +1 -1
- package/src/table/fail-clean.ts +8 -4
- package/src/table/hold-gap.ts +22 -13
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -198,8 +198,9 @@ function matchesEmptyBody(p, seen, resolve) {
|
|
|
198
198
|
case "optional":
|
|
199
199
|
case "not":
|
|
200
200
|
case "peek":
|
|
201
|
+
case "expect":
|
|
201
202
|
return true;
|
|
202
|
-
// zero repetitions / absent / lookahead
|
|
203
|
+
// zero repetitions / absent / lookahead / recovered
|
|
203
204
|
// Default `sepBy` is `(item (sep item)*)?` — it MATCHES THE EMPTY STRING.
|
|
204
205
|
// Any `min >= 1` requires that many ITEMS, so it is nullable only when the
|
|
205
206
|
// item is. (Keying this off `min === 1` reported every `{ min: 2 }` list as
|
|
@@ -220,7 +221,6 @@ function matchesEmptyBody(p, seen, resolve) {
|
|
|
220
221
|
case "trivia":
|
|
221
222
|
case "token":
|
|
222
223
|
case "leaf":
|
|
223
|
-
case "expect":
|
|
224
224
|
case "withCtx":
|
|
225
225
|
case "node":
|
|
226
226
|
case "grammar":
|
|
@@ -290,17 +290,17 @@ function sequenceSet(parsers, fs, empties, trivia2, consuming = true) {
|
|
|
290
290
|
function sequenceFirstSet(parsers) {
|
|
291
291
|
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
292
292
|
}
|
|
293
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming = true) {
|
|
293
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia, consuming = true, follow = false) {
|
|
294
294
|
if (seen.has(p)) return any();
|
|
295
295
|
seen.add(p);
|
|
296
296
|
try {
|
|
297
|
-
return firstSetBody(p, seen, resolve, activeTrivia, consuming);
|
|
297
|
+
return firstSetBody(p, seen, resolve, activeTrivia, consuming, follow);
|
|
298
298
|
} finally {
|
|
299
299
|
seen.delete(p);
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
-
function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
303
|
-
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia, consuming);
|
|
302
|
+
function firstSetBody(p, seen, resolve, activeTrivia, consuming, follow) {
|
|
303
|
+
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia, consuming, follow);
|
|
304
304
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
|
|
305
305
|
const d = p._def;
|
|
306
306
|
switch (d.tag) {
|
|
@@ -321,7 +321,7 @@ function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
const through = activeTrivia === null && resolve !== void 0;
|
|
324
|
-
return firstSetOf(target, seen, resolve, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
324
|
+
return firstSetOf(target, seen, resolve, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming, follow);
|
|
325
325
|
}
|
|
326
326
|
case "choice": {
|
|
327
327
|
let out = empty();
|
|
@@ -331,6 +331,10 @@ function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
|
331
331
|
case "sequence": {
|
|
332
332
|
return sequenceSet(d.parsers, fs, empties, activeTrivia, consuming);
|
|
333
333
|
}
|
|
334
|
+
// Runs on any character: on one its child can't start, it reports the error. A
|
|
335
|
+
// resync sentinel still stops where the child could start.
|
|
336
|
+
case "expect":
|
|
337
|
+
return follow ? fs(d.parser) : any();
|
|
334
338
|
case "peek": {
|
|
335
339
|
const inner = d.parser;
|
|
336
340
|
return empties(inner) ? any() : fs(inner);
|
|
@@ -344,7 +348,6 @@ function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
|
344
348
|
case "leaf":
|
|
345
349
|
case "node":
|
|
346
350
|
case "sepBy":
|
|
347
|
-
case "expect":
|
|
348
351
|
// A transaction accepts exactly what its inner accepts. Its own `_meta` is
|
|
349
352
|
// the inner's construction-time set, which reads `any` when the inner opens
|
|
350
353
|
// with a rule reference — resolve through it like any other wrapper.
|
|
@@ -352,14 +355,15 @@ function firstSetBody(p, seen, resolve, activeTrivia, consuming) {
|
|
|
352
355
|
return fs(d.parser);
|
|
353
356
|
// A token runs its body with trivia cleared (`token.ts`).
|
|
354
357
|
case "token":
|
|
355
|
-
return firstSetOf(d.parser, seen, resolve, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
358
|
+
return firstSetOf(d.parser, seen, resolve, activeTrivia === void 0 ? void 0 : null, consuming, follow);
|
|
356
359
|
case "grammar":
|
|
357
360
|
return firstSetOf(
|
|
358
361
|
d.parser,
|
|
359
362
|
seen,
|
|
360
363
|
resolve,
|
|
361
364
|
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
362
|
-
consuming
|
|
365
|
+
consuming,
|
|
366
|
+
follow
|
|
363
367
|
);
|
|
364
368
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
365
369
|
case "lines": {
|
|
@@ -3094,7 +3098,7 @@ function sequence(...parsers) {
|
|
|
3094
3098
|
if (tolerant) {
|
|
3095
3099
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
3096
3100
|
parsers.slice(i + 1).reduce(
|
|
3097
|
-
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
3101
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false, true)),
|
|
3098
3102
|
{ kind: "empty" }
|
|
3099
3103
|
)
|
|
3100
3104
|
));
|
|
@@ -3244,7 +3248,8 @@ function derive(c, seen) {
|
|
|
3244
3248
|
function expect(combinator, label2) {
|
|
3245
3249
|
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
3246
3250
|
const meta = {
|
|
3247
|
-
|
|
3251
|
+
// It runs on any character: on one its child can't start, it reports the error.
|
|
3252
|
+
firstSet: any(),
|
|
3248
3253
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3249
3254
|
isTrivia: false
|
|
3250
3255
|
};
|
|
@@ -5661,7 +5666,7 @@ function sourceLeaf(root, fn) {
|
|
|
5661
5666
|
}
|
|
5662
5667
|
|
|
5663
5668
|
// src/version.ts
|
|
5664
|
-
var PARSEMAN_VERSION = "0.61.
|
|
5669
|
+
var PARSEMAN_VERSION = "0.61.8";
|
|
5665
5670
|
|
|
5666
5671
|
// src/table/lex-body.ts
|
|
5667
5672
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -8939,7 +8944,7 @@ var Encoder = class {
|
|
|
8939
8944
|
let fs = { kind: "empty" };
|
|
8940
8945
|
const rr = this.refResolver();
|
|
8941
8946
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
8942
|
-
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
8947
|
+
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false, true));
|
|
8943
8948
|
}
|
|
8944
8949
|
return this.charClass(fs);
|
|
8945
8950
|
}
|
|
@@ -11437,17 +11442,17 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
11437
11442
|
OP_SCOPE_PLAIN,
|
|
11438
11443
|
OP_FIELD,
|
|
11439
11444
|
OP_LABEL,
|
|
11440
|
-
OP_EXPECT,
|
|
11441
11445
|
OP_WITHCTX,
|
|
11442
11446
|
OP_RULE,
|
|
11443
11447
|
OP_ATTEMPT,
|
|
11444
11448
|
OP_COV,
|
|
11445
11449
|
OP_GAPGATE
|
|
11446
11450
|
]);
|
|
11447
|
-
function rowNullable(code, k, ip, memo) {
|
|
11448
|
-
const
|
|
11451
|
+
function rowNullable(code, k, ip, memo, recovers = true) {
|
|
11452
|
+
const key = recovers ? ip : ~ip;
|
|
11453
|
+
const hit = memo.get(key);
|
|
11449
11454
|
if (hit !== void 0) return hit;
|
|
11450
|
-
memo.set(
|
|
11455
|
+
memo.set(key, true);
|
|
11451
11456
|
const op = code[ip];
|
|
11452
11457
|
const kids = [];
|
|
11453
11458
|
let out = true;
|
|
@@ -11458,20 +11463,20 @@ function rowNullable(code, k, ip, memo) {
|
|
|
11458
11463
|
out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
|
|
11459
11464
|
} else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
|
|
11460
11465
|
childSlots(code, ip, kids);
|
|
11461
|
-
out = kids.every((c) => rowNullable(code, k, c, memo));
|
|
11466
|
+
out = kids.every((c) => rowNullable(code, k, c, memo, recovers));
|
|
11462
11467
|
} else if (op === OP_CHOICE) {
|
|
11463
11468
|
childSlots(code, ip, kids);
|
|
11464
|
-
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
11469
|
+
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo, recovers));
|
|
11465
11470
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
11466
|
-
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
11471
|
+
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo, recovers);
|
|
11467
11472
|
} else if (op === OP_SEED) {
|
|
11468
|
-
out = rowNullable(code, k, code[ip + 1], memo);
|
|
11473
|
+
out = rowNullable(code, k, code[ip + 1], memo, recovers);
|
|
11469
11474
|
} else if (op === OP_CONT) {
|
|
11470
|
-
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
11471
|
-
} else if (WRAPPERS.has(op)) {
|
|
11472
|
-
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
11475
|
+
out = rowNullable(code, k, code[ip + 1], memo, recovers) && rowNullable(code, k, code[ip + 3], memo, recovers);
|
|
11476
|
+
} else if (WRAPPERS.has(op) || op === OP_EXPECT && !recovers) {
|
|
11477
|
+
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo, recovers);
|
|
11473
11478
|
}
|
|
11474
|
-
memo.set(
|
|
11479
|
+
memo.set(key, out);
|
|
11475
11480
|
return out;
|
|
11476
11481
|
}
|
|
11477
11482
|
function holdsGap(code, k, base, n, i, memo) {
|
|
@@ -11480,7 +11485,7 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
11480
11485
|
if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
|
|
11481
11486
|
const next = code[base + i + 1];
|
|
11482
11487
|
if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
|
|
11483
|
-
return !rowNullable(code, k, next, memo);
|
|
11488
|
+
return !rowNullable(code, k, next, memo, false);
|
|
11484
11489
|
}
|
|
11485
11490
|
|
|
11486
11491
|
// src/table/gap-gate.ts
|
|
@@ -11802,11 +11807,35 @@ ${fast}
|
|
|
11802
11807
|
${scanned}
|
|
11803
11808
|
}`;
|
|
11804
11809
|
}
|
|
11805
|
-
|
|
11810
|
+
var TRIVIA_LOG_LENGTH = "ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)";
|
|
11811
|
+
function emitHoldTerm(callee, dst, t, l, skip, recovers) {
|
|
11806
11812
|
const fast = `const ${t}v=${callee}(input,cur,ctx)
|
|
11807
11813
|
if(${t}v===FAIL)return FAIL
|
|
11808
11814
|
${dst}=${t}v
|
|
11809
11815
|
cur=EC.e`;
|
|
11816
|
+
if (recovers) {
|
|
11817
|
+
const marked = `let ${t}c=cur,${t}s=cur,${t}tl=0,${t}stl=0,${t}lg=0,${t}slg=0,${t}rt=0,${t}srt=0`;
|
|
11818
|
+
if (l.tri === TRI_NONE) return `${marked}
|
|
11819
|
+
${fast}`;
|
|
11820
|
+
const held2 = `${t}tl=${TRIVIA_LOG_LENGTH}
|
|
11821
|
+
${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11822
|
+
${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11823
|
+
${t}s=${skip}(input,cur,ctx)
|
|
11824
|
+
${t}stl=${TRIVIA_LOG_LENGTH}
|
|
11825
|
+
${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11826
|
+
${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11827
|
+
const ${t}v=${callee}(input,${t}s,ctx)
|
|
11828
|
+
if(${t}v===FAIL)return FAIL
|
|
11829
|
+
${dst}=${t}v
|
|
11830
|
+
cur=${t}s`;
|
|
11831
|
+
return l.tri !== TRI_UNKNOWN ? `${marked}
|
|
11832
|
+
${held2}` : `${marked}
|
|
11833
|
+
if(ctx.trivia===undefined){
|
|
11834
|
+
${fast}
|
|
11835
|
+
}else{
|
|
11836
|
+
${held2}
|
|
11837
|
+
}`;
|
|
11838
|
+
}
|
|
11810
11839
|
if (l.tri === TRI_NONE) return fast;
|
|
11811
11840
|
const held = `const ${t}s=${skip}(input,cur,ctx)
|
|
11812
11841
|
const ${t}v=${callee}(input,${t}s,ctx)
|
|
@@ -11820,6 +11849,9 @@ ${fast}
|
|
|
11820
11849
|
${held}
|
|
11821
11850
|
}`;
|
|
11822
11851
|
}
|
|
11852
|
+
function emitHeldGapUndo(t) {
|
|
11853
|
+
return `if(cur===${t}s&&${t}s!==${t}c){rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt);cur=${t}c}`;
|
|
11854
|
+
}
|
|
11823
11855
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
11824
11856
|
if (hasTrivia === "false") return "{}";
|
|
11825
11857
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -12828,6 +12860,7 @@ return v
|
|
|
12828
12860
|
}
|
|
12829
12861
|
parts.push("let cur=EC.e");
|
|
12830
12862
|
const names = ["v0"];
|
|
12863
|
+
let heldUndo;
|
|
12831
12864
|
for (let i = 1; i < n; i++) {
|
|
12832
12865
|
const vn = `v${i}`;
|
|
12833
12866
|
parts.push(`let ${vn}`);
|
|
@@ -12844,7 +12877,16 @@ return v
|
|
|
12844
12877
|
);
|
|
12845
12878
|
} else {
|
|
12846
12879
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
12847
|
-
|
|
12880
|
+
if (holdsGap(code, k, base, n, i, nullable2)) {
|
|
12881
|
+
const t2 = tmp();
|
|
12882
|
+
const recovers = rowNullable(code, k, code[base + i + 1], nullable2);
|
|
12883
|
+
parts.push(emitHoldTerm(callee, vn, t2, L, skipFor(L), recovers));
|
|
12884
|
+
heldUndo = recovers ? t2 : void 0;
|
|
12885
|
+
} else {
|
|
12886
|
+
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L), L.tri >= 0 ? triviaMiss(L.tri) : void 0));
|
|
12887
|
+
if (heldUndo !== void 0) parts.push(emitHeldGapUndo(heldUndo));
|
|
12888
|
+
heldUndo = void 0;
|
|
12889
|
+
}
|
|
12848
12890
|
}
|
|
12849
12891
|
names.push(vn);
|
|
12850
12892
|
}
|
|
@@ -14283,11 +14325,15 @@ function failCleanAnalysis(code) {
|
|
|
14283
14325
|
case OP_CONT:
|
|
14284
14326
|
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
14285
14327
|
break;
|
|
14286
|
-
// An arm's failure and
|
|
14287
|
-
// not
|
|
14288
|
-
|
|
14289
|
-
|
|
14328
|
+
// An arm's failure and a committing fallback's are committed; only the
|
|
14329
|
+
// selector's is not. An uncommitted fallback's failure leaves the selector's
|
|
14330
|
+
// capture, unless the fallback reads it through `routed()`, which rolls that
|
|
14331
|
+
// capture back first. With no fallback, the dispatch fails after the selector wrote.
|
|
14332
|
+
case OP_DISPATCH: {
|
|
14333
|
+
const flags = code[ip + 4];
|
|
14334
|
+
out = code[ip + 3] >= 0 && ((flags & 2) === 0 || (flags & 1) === 1) && clean(code[ip + 1]);
|
|
14290
14335
|
break;
|
|
14336
|
+
}
|
|
14291
14337
|
default: {
|
|
14292
14338
|
const c = passChild(code, ip);
|
|
14293
14339
|
out = c >= 0 && clean(c);
|
|
@@ -16345,8 +16391,46 @@ function assemble(t, prog, cfg) {
|
|
|
16345
16391
|
}
|
|
16346
16392
|
if (hasAdj) {
|
|
16347
16393
|
const first2 = linkFirst();
|
|
16394
|
+
let heldFrom = 0, heldTl = 0, heldScanTl = 0, heldLog = 0, heldScanLog = 0, heldRoot = 0, heldScanRoot = 0;
|
|
16348
16395
|
const runnerAt = (i) => {
|
|
16349
16396
|
const kidIp = code[base + i];
|
|
16397
|
+
if (i > 1 && holdsGap(code, k, base, n, i - 1, NULLABLE) && rowNullable(code, k, kidIp, NULLABLE)) {
|
|
16398
|
+
const kid = link(kidIp);
|
|
16399
|
+
return (input, cur, ctx) => {
|
|
16400
|
+
const from = heldFrom, tl = heldTl, scanTl = heldScanTl, log = heldLog;
|
|
16401
|
+
const scanLog = heldScanLog, root = heldRoot, scanRoot = heldScanRoot;
|
|
16402
|
+
const next = step(kid, input, cur, ctx);
|
|
16403
|
+
if (next !== cur || from === cur) return next;
|
|
16404
|
+
rollbackScannedTriviaAt(ctx, tl, scanTl, log, scanLog, root, scanRoot);
|
|
16405
|
+
return from;
|
|
16406
|
+
};
|
|
16407
|
+
}
|
|
16408
|
+
if (holdsGap(code, k, base, n, i, NULLABLE) && rowNullable(code, k, code[base + i + 1], NULLABLE)) {
|
|
16409
|
+
const kid = link(kidIp);
|
|
16410
|
+
return (input, cur, ctx) => {
|
|
16411
|
+
if (ctx.trivia === void 0) {
|
|
16412
|
+
const v2 = kid(input, cur, ctx);
|
|
16413
|
+
if (v2 === FAIL) return -1;
|
|
16414
|
+
TERMV = v2;
|
|
16415
|
+
heldFrom = cur;
|
|
16416
|
+
return EC.e;
|
|
16417
|
+
}
|
|
16418
|
+
const tl = cstTlLen(ctx), log = ctx._triviaLog?.length ?? 0, root = ctx._rootTriviaLog?.length ?? 0;
|
|
16419
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
16420
|
+
const scanTl = cstTlLen(ctx), scanLog = ctx._triviaLog?.length ?? 0, scanRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
16421
|
+
const v = kid(input, scanEnd, ctx);
|
|
16422
|
+
if (v === FAIL) return -1;
|
|
16423
|
+
TERMV = v;
|
|
16424
|
+
heldFrom = cur;
|
|
16425
|
+
heldTl = tl;
|
|
16426
|
+
heldScanTl = scanTl;
|
|
16427
|
+
heldLog = log;
|
|
16428
|
+
heldScanLog = scanLog;
|
|
16429
|
+
heldRoot = root;
|
|
16430
|
+
heldScanRoot = scanRoot;
|
|
16431
|
+
return scanEnd;
|
|
16432
|
+
};
|
|
16433
|
+
}
|
|
16350
16434
|
if (holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
16351
16435
|
const kid = link(kidIp);
|
|
16352
16436
|
return (input, cur, ctx) => {
|