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/cli/index.js
CHANGED
|
@@ -206,8 +206,9 @@ function matchesEmptyBody(p, seen, resolve2) {
|
|
|
206
206
|
case "optional":
|
|
207
207
|
case "not":
|
|
208
208
|
case "peek":
|
|
209
|
+
case "expect":
|
|
209
210
|
return true;
|
|
210
|
-
// zero repetitions / absent / lookahead
|
|
211
|
+
// zero repetitions / absent / lookahead / recovered
|
|
211
212
|
// Default `sepBy` is `(item (sep item)*)?` — it MATCHES THE EMPTY STRING.
|
|
212
213
|
// Any `min >= 1` requires that many ITEMS, so it is nullable only when the
|
|
213
214
|
// item is. (Keying this off `min === 1` reported every `{ min: 2 }` list as
|
|
@@ -228,7 +229,6 @@ function matchesEmptyBody(p, seen, resolve2) {
|
|
|
228
229
|
case "trivia":
|
|
229
230
|
case "token":
|
|
230
231
|
case "leaf":
|
|
231
|
-
case "expect":
|
|
232
232
|
case "withCtx":
|
|
233
233
|
case "node":
|
|
234
234
|
case "grammar":
|
|
@@ -298,17 +298,17 @@ function sequenceSet(parsers, fs, empties, trivia2, consuming = true) {
|
|
|
298
298
|
function sequenceFirstSet(parsers) {
|
|
299
299
|
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty, void 0, false);
|
|
300
300
|
}
|
|
301
|
-
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2, activeTrivia, consuming = true) {
|
|
301
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2, activeTrivia, consuming = true, follow = false) {
|
|
302
302
|
if (seen.has(p)) return any();
|
|
303
303
|
seen.add(p);
|
|
304
304
|
try {
|
|
305
|
-
return firstSetBody(p, seen, resolve2, activeTrivia, consuming);
|
|
305
|
+
return firstSetBody(p, seen, resolve2, activeTrivia, consuming, follow);
|
|
306
306
|
} finally {
|
|
307
307
|
seen.delete(p);
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
-
function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
311
|
-
const fs = (c) => firstSetOf(c, seen, resolve2, activeTrivia, consuming);
|
|
310
|
+
function firstSetBody(p, seen, resolve2, activeTrivia, consuming, follow) {
|
|
311
|
+
const fs = (c) => firstSetOf(c, seen, resolve2, activeTrivia, consuming, follow);
|
|
312
312
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve2);
|
|
313
313
|
const d = p._def;
|
|
314
314
|
switch (d.tag) {
|
|
@@ -329,7 +329,7 @@ function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
const through = activeTrivia === null && resolve2 !== void 0;
|
|
332
|
-
return firstSetOf(target, seen, resolve2, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming);
|
|
332
|
+
return firstSetOf(target, seen, resolve2, through ? triviaThroughRef(p, target, null) : activeTrivia, consuming, follow);
|
|
333
333
|
}
|
|
334
334
|
case "choice": {
|
|
335
335
|
let out = empty();
|
|
@@ -339,6 +339,10 @@ function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
|
339
339
|
case "sequence": {
|
|
340
340
|
return sequenceSet(d.parsers, fs, empties, activeTrivia, consuming);
|
|
341
341
|
}
|
|
342
|
+
// Runs on any character: on one its child can't start, it reports the error. A
|
|
343
|
+
// resync sentinel still stops where the child could start.
|
|
344
|
+
case "expect":
|
|
345
|
+
return follow ? fs(d.parser) : any();
|
|
342
346
|
case "peek": {
|
|
343
347
|
const inner = d.parser;
|
|
344
348
|
return empties(inner) ? any() : fs(inner);
|
|
@@ -352,7 +356,6 @@ function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
|
352
356
|
case "leaf":
|
|
353
357
|
case "node":
|
|
354
358
|
case "sepBy":
|
|
355
|
-
case "expect":
|
|
356
359
|
// A transaction accepts exactly what its inner accepts. Its own `_meta` is
|
|
357
360
|
// the inner's construction-time set, which reads `any` when the inner opens
|
|
358
361
|
// with a rule reference — resolve through it like any other wrapper.
|
|
@@ -360,14 +363,15 @@ function firstSetBody(p, seen, resolve2, activeTrivia, consuming) {
|
|
|
360
363
|
return fs(d.parser);
|
|
361
364
|
// A token runs its body with trivia cleared (`token.ts`).
|
|
362
365
|
case "token":
|
|
363
|
-
return firstSetOf(d.parser, seen, resolve2, activeTrivia === void 0 ? void 0 : null, consuming);
|
|
366
|
+
return firstSetOf(d.parser, seen, resolve2, activeTrivia === void 0 ? void 0 : null, consuming, follow);
|
|
364
367
|
case "grammar":
|
|
365
368
|
return firstSetOf(
|
|
366
369
|
d.parser,
|
|
367
370
|
seen,
|
|
368
371
|
resolve2,
|
|
369
372
|
d.clearTrivia ? null : d.triviaParser ?? activeTrivia,
|
|
370
|
-
consuming
|
|
373
|
+
consuming,
|
|
374
|
+
follow
|
|
371
375
|
);
|
|
372
376
|
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
373
377
|
case "lines": {
|
|
@@ -2959,7 +2963,8 @@ function derive(c, seen) {
|
|
|
2959
2963
|
function expect(combinator, label2) {
|
|
2960
2964
|
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
2961
2965
|
const meta = {
|
|
2962
|
-
|
|
2966
|
+
// It runs on any character: on one its child can't start, it reports the error.
|
|
2967
|
+
firstSet: any(),
|
|
2963
2968
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
2964
2969
|
isTrivia: false
|
|
2965
2970
|
};
|
|
@@ -5708,7 +5713,7 @@ function regex(pattern, flags = "") {
|
|
|
5708
5713
|
}
|
|
5709
5714
|
|
|
5710
5715
|
// src/version.ts
|
|
5711
|
-
var PARSEMAN_VERSION = "0.61.
|
|
5716
|
+
var PARSEMAN_VERSION = "0.61.8";
|
|
5712
5717
|
|
|
5713
5718
|
// src/table/lex-body.ts
|
|
5714
5719
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -6677,7 +6682,7 @@ function sequence(...parsers) {
|
|
|
6677
6682
|
if (tolerant) {
|
|
6678
6683
|
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
6679
6684
|
parsers.slice(i + 1).reduce(
|
|
6680
|
-
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false)),
|
|
6685
|
+
(set, parser2) => union(set, firstSetOf(parser2, /* @__PURE__ */ new Set(), void 0, void 0, false, true)),
|
|
6681
6686
|
{ kind: "empty" }
|
|
6682
6687
|
)
|
|
6683
6688
|
));
|
|
@@ -8543,7 +8548,7 @@ var Encoder = class {
|
|
|
8543
8548
|
let fs = { kind: "empty" };
|
|
8544
8549
|
const rr = this.refResolver();
|
|
8545
8550
|
for (let j = i + 1; j < parsers.length; j++) {
|
|
8546
|
-
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false));
|
|
8551
|
+
fs = union(fs, firstSetOf(parsers[j], /* @__PURE__ */ new Set(), rr, void 0, false, true));
|
|
8547
8552
|
}
|
|
8548
8553
|
return this.charClass(fs);
|
|
8549
8554
|
}
|
|
@@ -11038,17 +11043,17 @@ var WRAPPERS = /* @__PURE__ */ new Set([
|
|
|
11038
11043
|
OP_SCOPE_PLAIN,
|
|
11039
11044
|
OP_FIELD,
|
|
11040
11045
|
OP_LABEL,
|
|
11041
|
-
OP_EXPECT,
|
|
11042
11046
|
OP_WITHCTX,
|
|
11043
11047
|
OP_RULE,
|
|
11044
11048
|
OP_ATTEMPT,
|
|
11045
11049
|
OP_COV,
|
|
11046
11050
|
OP_GAPGATE
|
|
11047
11051
|
]);
|
|
11048
|
-
function rowNullable(code, k, ip, memo) {
|
|
11049
|
-
const
|
|
11052
|
+
function rowNullable(code, k, ip, memo, recovers = true) {
|
|
11053
|
+
const key = recovers ? ip : ~ip;
|
|
11054
|
+
const hit = memo.get(key);
|
|
11050
11055
|
if (hit !== void 0) return hit;
|
|
11051
|
-
memo.set(
|
|
11056
|
+
memo.set(key, true);
|
|
11052
11057
|
const op = code[ip];
|
|
11053
11058
|
const kids = [];
|
|
11054
11059
|
let out = true;
|
|
@@ -11059,20 +11064,20 @@ function rowNullable(code, k, ip, memo) {
|
|
|
11059
11064
|
out = !(re instanceof RegExp) || regexCanMatchEmpty(re.source);
|
|
11060
11065
|
} else if (op === OP_SEQ || op === OP_SEQV || op === OP_SEQX) {
|
|
11061
11066
|
childSlots(code, ip, kids);
|
|
11062
|
-
out = kids.every((c) => rowNullable(code, k, c, memo));
|
|
11067
|
+
out = kids.every((c) => rowNullable(code, k, c, memo, recovers));
|
|
11063
11068
|
} else if (op === OP_CHOICE) {
|
|
11064
11069
|
childSlots(code, ip, kids);
|
|
11065
|
-
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
11070
|
+
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo, recovers));
|
|
11066
11071
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
11067
|
-
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
11072
|
+
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo, recovers);
|
|
11068
11073
|
} else if (op === OP_SEED) {
|
|
11069
|
-
out = rowNullable(code, k, code[ip + 1], memo);
|
|
11074
|
+
out = rowNullable(code, k, code[ip + 1], memo, recovers);
|
|
11070
11075
|
} else if (op === OP_CONT) {
|
|
11071
|
-
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
11072
|
-
} else if (WRAPPERS.has(op)) {
|
|
11073
|
-
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
11076
|
+
out = rowNullable(code, k, code[ip + 1], memo, recovers) && rowNullable(code, k, code[ip + 3], memo, recovers);
|
|
11077
|
+
} else if (WRAPPERS.has(op) || op === OP_EXPECT && !recovers) {
|
|
11078
|
+
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo, recovers);
|
|
11074
11079
|
}
|
|
11075
|
-
memo.set(
|
|
11080
|
+
memo.set(key, out);
|
|
11076
11081
|
return out;
|
|
11077
11082
|
}
|
|
11078
11083
|
function holdsGap(code, k, base, n, i, memo) {
|
|
@@ -11081,7 +11086,7 @@ function holdsGap(code, k, base, n, i, memo) {
|
|
|
11081
11086
|
if (code[term] !== OP_NOT && code[term] !== OP_PEEK) return false;
|
|
11082
11087
|
const next = code[base + i + 1];
|
|
11083
11088
|
if (code[next] === OP_ADJ || leadingTriviaFieldAt(code, k, next)) return false;
|
|
11084
|
-
return !rowNullable(code, k, next, memo);
|
|
11089
|
+
return !rowNullable(code, k, next, memo, false);
|
|
11085
11090
|
}
|
|
11086
11091
|
|
|
11087
11092
|
// src/table/gap-gate.ts
|
|
@@ -11403,11 +11408,35 @@ ${fast}
|
|
|
11403
11408
|
${scanned}
|
|
11404
11409
|
}`;
|
|
11405
11410
|
}
|
|
11406
|
-
|
|
11411
|
+
var TRIVIA_LOG_LENGTH = "ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)";
|
|
11412
|
+
function emitHoldTerm(callee, dst, t2, l, skip, recovers) {
|
|
11407
11413
|
const fast = `const ${t2}v=${callee}(input,cur,ctx)
|
|
11408
11414
|
if(${t2}v===FAIL)return FAIL
|
|
11409
11415
|
${dst}=${t2}v
|
|
11410
11416
|
cur=EC.e`;
|
|
11417
|
+
if (recovers) {
|
|
11418
|
+
const marked = `let ${t2}c=cur,${t2}s=cur,${t2}tl=0,${t2}stl=0,${t2}lg=0,${t2}slg=0,${t2}rt=0,${t2}srt=0`;
|
|
11419
|
+
if (l.tri === TRI_NONE) return `${marked}
|
|
11420
|
+
${fast}`;
|
|
11421
|
+
const held2 = `${t2}tl=${TRIVIA_LOG_LENGTH}
|
|
11422
|
+
${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11423
|
+
${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11424
|
+
${t2}s=${skip}(input,cur,ctx)
|
|
11425
|
+
${t2}stl=${TRIVIA_LOG_LENGTH}
|
|
11426
|
+
${t2}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11427
|
+
${t2}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11428
|
+
const ${t2}v=${callee}(input,${t2}s,ctx)
|
|
11429
|
+
if(${t2}v===FAIL)return FAIL
|
|
11430
|
+
${dst}=${t2}v
|
|
11431
|
+
cur=${t2}s`;
|
|
11432
|
+
return l.tri !== TRI_UNKNOWN ? `${marked}
|
|
11433
|
+
${held2}` : `${marked}
|
|
11434
|
+
if(ctx.trivia===undefined){
|
|
11435
|
+
${fast}
|
|
11436
|
+
}else{
|
|
11437
|
+
${held2}
|
|
11438
|
+
}`;
|
|
11439
|
+
}
|
|
11411
11440
|
if (l.tri === TRI_NONE) return fast;
|
|
11412
11441
|
const held = `const ${t2}s=${skip}(input,cur,ctx)
|
|
11413
11442
|
const ${t2}v=${callee}(input,${t2}s,ctx)
|
|
@@ -11421,6 +11450,9 @@ ${fast}
|
|
|
11421
11450
|
${held}
|
|
11422
11451
|
}`;
|
|
11423
11452
|
}
|
|
11453
|
+
function emitHeldGapUndo(t2) {
|
|
11454
|
+
return `if(cur===${t2}s&&${t2}s!==${t2}c){rollbackScannedTriviaAt(ctx,${t2}tl,${t2}stl,${t2}lg,${t2}slg,${t2}rt,${t2}srt);cur=${t2}c}`;
|
|
11455
|
+
}
|
|
11424
11456
|
function leadSkip(hasTrivia, leadTrivia, skip) {
|
|
11425
11457
|
if (hasTrivia === "false") return "{}";
|
|
11426
11458
|
const call = `itemStart=${skip}(input,itemStart,ctx)`;
|
|
@@ -12429,6 +12461,7 @@ return v
|
|
|
12429
12461
|
}
|
|
12430
12462
|
parts.push("let cur=EC.e");
|
|
12431
12463
|
const names = ["v0"];
|
|
12464
|
+
let heldUndo;
|
|
12432
12465
|
for (let i = 1; i < n; i++) {
|
|
12433
12466
|
const vn = `v${i}`;
|
|
12434
12467
|
parts.push(`let ${vn}`);
|
|
@@ -12445,7 +12478,16 @@ return v
|
|
|
12445
12478
|
);
|
|
12446
12479
|
} else {
|
|
12447
12480
|
const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
|
|
12448
|
-
|
|
12481
|
+
if (holdsGap(code, k, base, n, i, nullable2)) {
|
|
12482
|
+
const t3 = tmp();
|
|
12483
|
+
const recovers = rowNullable(code, k, code[base + i + 1], nullable2);
|
|
12484
|
+
parts.push(emitHoldTerm(callee, vn, t3, L, skipFor(L), recovers));
|
|
12485
|
+
heldUndo = recovers ? t3 : void 0;
|
|
12486
|
+
} else {
|
|
12487
|
+
parts.push(emitTerm(callee, vn, tmp(), L, skipFor(L), L.tri >= 0 ? triviaMiss(L.tri) : void 0));
|
|
12488
|
+
if (heldUndo !== void 0) parts.push(emitHeldGapUndo(heldUndo));
|
|
12489
|
+
heldUndo = void 0;
|
|
12490
|
+
}
|
|
12449
12491
|
}
|
|
12450
12492
|
names.push(vn);
|
|
12451
12493
|
}
|
|
@@ -13973,11 +14015,15 @@ function failCleanAnalysis(code) {
|
|
|
13973
14015
|
case OP_CONT:
|
|
13974
14016
|
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
13975
14017
|
break;
|
|
13976
|
-
// An arm's failure and
|
|
13977
|
-
// not
|
|
13978
|
-
|
|
13979
|
-
|
|
14018
|
+
// An arm's failure and a committing fallback's are committed; only the
|
|
14019
|
+
// selector's is not. An uncommitted fallback's failure leaves the selector's
|
|
14020
|
+
// capture, unless the fallback reads it through `routed()`, which rolls that
|
|
14021
|
+
// capture back first. With no fallback, the dispatch fails after the selector wrote.
|
|
14022
|
+
case OP_DISPATCH: {
|
|
14023
|
+
const flags = code[ip + 4];
|
|
14024
|
+
out = code[ip + 3] >= 0 && ((flags & 2) === 0 || (flags & 1) === 1) && clean(code[ip + 1]);
|
|
13980
14025
|
break;
|
|
14026
|
+
}
|
|
13981
14027
|
default: {
|
|
13982
14028
|
const c = passChild(code, ip);
|
|
13983
14029
|
out = c >= 0 && clean(c);
|
|
@@ -16018,8 +16064,46 @@ function assemble(t2, prog, cfg) {
|
|
|
16018
16064
|
}
|
|
16019
16065
|
if (hasAdj) {
|
|
16020
16066
|
const first2 = linkFirst();
|
|
16067
|
+
let heldFrom = 0, heldTl = 0, heldScanTl = 0, heldLog = 0, heldScanLog = 0, heldRoot = 0, heldScanRoot = 0;
|
|
16021
16068
|
const runnerAt = (i) => {
|
|
16022
16069
|
const kidIp = code[base + i];
|
|
16070
|
+
if (i > 1 && holdsGap(code, k, base, n, i - 1, NULLABLE) && rowNullable(code, k, kidIp, NULLABLE)) {
|
|
16071
|
+
const kid = link(kidIp);
|
|
16072
|
+
return (input, cur, ctx) => {
|
|
16073
|
+
const from = heldFrom, tl = heldTl, scanTl = heldScanTl, log = heldLog;
|
|
16074
|
+
const scanLog = heldScanLog, root = heldRoot, scanRoot = heldScanRoot;
|
|
16075
|
+
const next = step(kid, input, cur, ctx);
|
|
16076
|
+
if (next !== cur || from === cur) return next;
|
|
16077
|
+
rollbackScannedTriviaAt(ctx, tl, scanTl, log, scanLog, root, scanRoot);
|
|
16078
|
+
return from;
|
|
16079
|
+
};
|
|
16080
|
+
}
|
|
16081
|
+
if (holdsGap(code, k, base, n, i, NULLABLE) && rowNullable(code, k, code[base + i + 1], NULLABLE)) {
|
|
16082
|
+
const kid = link(kidIp);
|
|
16083
|
+
return (input, cur, ctx) => {
|
|
16084
|
+
if (ctx.trivia === void 0) {
|
|
16085
|
+
const v2 = kid(input, cur, ctx);
|
|
16086
|
+
if (v2 === FAIL) return -1;
|
|
16087
|
+
TERMV = v2;
|
|
16088
|
+
heldFrom = cur;
|
|
16089
|
+
return EC.e;
|
|
16090
|
+
}
|
|
16091
|
+
const tl = cstTlLen(ctx), log = ctx._triviaLog?.length ?? 0, root = ctx._rootTriviaLog?.length ?? 0;
|
|
16092
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
16093
|
+
const scanTl = cstTlLen(ctx), scanLog = ctx._triviaLog?.length ?? 0, scanRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
16094
|
+
const v = kid(input, scanEnd, ctx);
|
|
16095
|
+
if (v === FAIL) return -1;
|
|
16096
|
+
TERMV = v;
|
|
16097
|
+
heldFrom = cur;
|
|
16098
|
+
heldTl = tl;
|
|
16099
|
+
heldScanTl = scanTl;
|
|
16100
|
+
heldLog = log;
|
|
16101
|
+
heldScanLog = scanLog;
|
|
16102
|
+
heldRoot = root;
|
|
16103
|
+
heldScanRoot = scanRoot;
|
|
16104
|
+
return scanEnd;
|
|
16105
|
+
};
|
|
16106
|
+
}
|
|
16023
16107
|
if (holdsGap(code, k, base, n, i, NULLABLE)) {
|
|
16024
16108
|
const kid = link(kidIp);
|
|
16025
16109
|
return (input, cur, ctx) => {
|