parseman 0.4.0 → 0.6.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 +48 -17
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/completions.d.ts +1 -1
- package/dist/combinators/completions.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/keywords.d.ts +22 -0
- package/dist/combinators/keywords.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts +8 -2
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +10 -11
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/not.d.ts +3 -3
- package/dist/combinators/not.d.ts.map +1 -1
- package/dist/combinators/recover.d.ts +2 -2
- package/dist/combinators/recover.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts +4 -4
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +16 -10
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/combinators/withCtx.d.ts +2 -2
- package/dist/combinators/withCtx.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +4 -2
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/inline-build.d.ts +11 -0
- package/dist/compiler/inline-build.d.ts.map +1 -0
- package/dist/compiler/inline-callback.d.ts +12 -0
- package/dist/compiler/inline-callback.d.ts.map +1 -0
- package/dist/compiler/trivia-fast-path.d.ts +24 -0
- package/dist/compiler/trivia-fast-path.d.ts.map +1 -0
- package/dist/cst/capture-buffer.d.ts +46 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -0
- package/dist/cst/trivia-entries.d.ts +20 -0
- package/dist/cst/trivia-entries.d.ts.map +1 -0
- package/dist/cst/trivia-index.d.ts +11 -11
- package/dist/cst/trivia-index.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts +47 -0
- package/dist/cst/trivia-kinds.d.ts.map +1 -0
- package/dist/cst/types.d.ts +9 -13
- package/dist/cst/types.d.ts.map +1 -1
- package/dist/functional/doc.d.ts +2 -20
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/index.cjs +1238 -662
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1256 -6241
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts +7 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +1249 -369
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1249 -369
- package/dist/plugin/index.js.map +4 -4
- package/dist/types.d.ts +32 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -3
- package/dist/cst/grammar.d.ts +0 -115
- package/dist/cst/grammar.d.ts.map +0 -1
- package/dist/cst/incremental.d.ts +0 -40
- package/dist/cst/incremental.d.ts.map +0 -1
package/dist/plugin/index.cjs
CHANGED
|
@@ -128,6 +128,151 @@ function failAt(ctx, expected, pos) {
|
|
|
128
128
|
return r;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
// src/cst/capture-buffer.ts
|
|
132
|
+
var EMPTY = [];
|
|
133
|
+
var EMPTY_TL = [];
|
|
134
|
+
function cstCaptureActive(ctx) {
|
|
135
|
+
return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
|
|
136
|
+
}
|
|
137
|
+
function beginCstNodeCapture(ctx) {
|
|
138
|
+
const saved = {
|
|
139
|
+
ch: ctx._cstChildren,
|
|
140
|
+
lv: ctx._cstLeaves,
|
|
141
|
+
raw: ctx._cstRawChildren,
|
|
142
|
+
tl: ctx._cstTriviaLog,
|
|
143
|
+
cap: ctx.captureTrivia,
|
|
144
|
+
buf: ctx._cstBuf
|
|
145
|
+
};
|
|
146
|
+
ctx._cstBuf = {};
|
|
147
|
+
ctx._cstChildren = void 0;
|
|
148
|
+
ctx._cstLeaves = void 0;
|
|
149
|
+
ctx._cstRawChildren = void 0;
|
|
150
|
+
ctx._cstTriviaLog = void 0;
|
|
151
|
+
ctx.captureTrivia = true;
|
|
152
|
+
return saved;
|
|
153
|
+
}
|
|
154
|
+
function finishCstBuf(buf) {
|
|
155
|
+
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
156
|
+
const children = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
157
|
+
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
158
|
+
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
159
|
+
return { children, rawChildren, triviaLog };
|
|
160
|
+
}
|
|
161
|
+
function endCstNodeCapture(ctx, saved) {
|
|
162
|
+
const materialized = finishCstBuf(ctx._cstBuf);
|
|
163
|
+
ctx._cstBuf = saved.buf;
|
|
164
|
+
ctx._cstChildren = saved.ch;
|
|
165
|
+
ctx._cstLeaves = saved.lv;
|
|
166
|
+
ctx._cstRawChildren = saved.raw;
|
|
167
|
+
ctx._cstTriviaLog = saved.tl;
|
|
168
|
+
ctx.captureTrivia = saved.cap;
|
|
169
|
+
return materialized;
|
|
170
|
+
}
|
|
171
|
+
function pushCstLeaf(ctx, leaf) {
|
|
172
|
+
pushCstChild(ctx, leaf, leaf);
|
|
173
|
+
}
|
|
174
|
+
function pushCstChild(ctx, built, rawEntry) {
|
|
175
|
+
const b = ctx._cstBuf;
|
|
176
|
+
if (b) {
|
|
177
|
+
if (b.ch) b.ch.push(built);
|
|
178
|
+
else if (b.single !== void 0) {
|
|
179
|
+
b.ch = [b.single, built];
|
|
180
|
+
b.single = void 0;
|
|
181
|
+
} else b.single = built;
|
|
182
|
+
if (b.raw) b.raw.push(rawEntry);
|
|
183
|
+
else if (b.rawSingle !== void 0) {
|
|
184
|
+
b.raw = [b.rawSingle, rawEntry];
|
|
185
|
+
b.rawSingle = void 0;
|
|
186
|
+
} else b.rawSingle = rawEntry;
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (ctx._cstChildren) ctx._cstChildren.push(built);
|
|
190
|
+
else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
|
|
191
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry);
|
|
192
|
+
}
|
|
193
|
+
function cstRawLen(ctx) {
|
|
194
|
+
const b = ctx._cstBuf;
|
|
195
|
+
if (b) {
|
|
196
|
+
if (b.raw) return b.raw.length;
|
|
197
|
+
return b.rawSingle !== void 0 ? 1 : 0;
|
|
198
|
+
}
|
|
199
|
+
return ctx._cstRawChildren?.length ?? 0;
|
|
200
|
+
}
|
|
201
|
+
function cstLeavesLen(ctx) {
|
|
202
|
+
const b = ctx._cstBuf;
|
|
203
|
+
if (b) {
|
|
204
|
+
if (b.ch) return b.ch.length;
|
|
205
|
+
return b.single !== void 0 ? 1 : 0;
|
|
206
|
+
}
|
|
207
|
+
return ctx._cstLeaves?.length ?? 0;
|
|
208
|
+
}
|
|
209
|
+
function cstTlLen(ctx) {
|
|
210
|
+
const b = ctx._cstBuf;
|
|
211
|
+
if (b) return b.tl?.length ?? 0;
|
|
212
|
+
return ctx._cstTriviaLog?.length ?? 0;
|
|
213
|
+
}
|
|
214
|
+
function saveCstMark(ctx) {
|
|
215
|
+
return {
|
|
216
|
+
raw: cstRawLen(ctx),
|
|
217
|
+
tlog: cstTlLen(ctx),
|
|
218
|
+
leaves: cstLeavesLen(ctx)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
222
|
+
const arr = b[keyMulti];
|
|
223
|
+
if (arr) {
|
|
224
|
+
if (len === 0) b[keyMulti] = void 0;
|
|
225
|
+
else if (len === 1) {
|
|
226
|
+
b[keySingle] = arr[0];
|
|
227
|
+
b[keyMulti] = void 0;
|
|
228
|
+
} else arr.length = len;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (len === 0) b[keySingle] = void 0;
|
|
232
|
+
}
|
|
233
|
+
function rollbackCstCapture(ctx, mark) {
|
|
234
|
+
const b = ctx._cstBuf;
|
|
235
|
+
if (b) {
|
|
236
|
+
rollbackBufList(b, "raw", "rawSingle", mark.raw);
|
|
237
|
+
rollbackBufList(b, "ch", "single", mark.leaves);
|
|
238
|
+
if (b.tl) {
|
|
239
|
+
if (mark.tlog === 0) b.tl = void 0;
|
|
240
|
+
else b.tl.length = mark.tlog;
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
245
|
+
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
246
|
+
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
247
|
+
}
|
|
248
|
+
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
249
|
+
const insertIdx = cstRawLen(ctx);
|
|
250
|
+
const b = ctx._cstBuf;
|
|
251
|
+
const withKind = ctx.triviaKindLabels !== void 0 && kindIndex !== void 0;
|
|
252
|
+
if (b) {
|
|
253
|
+
if (!b.tl) {
|
|
254
|
+
b.tl = withKind ? [start, end, insertIdx, kindIndex] : [start, end, insertIdx];
|
|
255
|
+
} else if (withKind) {
|
|
256
|
+
b.tl.push(start, end, insertIdx, kindIndex);
|
|
257
|
+
} else {
|
|
258
|
+
b.tl.push(start, end, insertIdx);
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (ctx._cstTriviaLog) {
|
|
263
|
+
if (withKind) ctx._cstTriviaLog.push(start, end, insertIdx, kindIndex);
|
|
264
|
+
else ctx._cstTriviaLog.push(start, end, insertIdx);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function pushTriviaLogEntry(ctx, start, end, kindIndex) {
|
|
268
|
+
if (!ctx._triviaLog) return;
|
|
269
|
+
if (ctx.triviaKindLabels !== void 0 && kindIndex !== void 0) {
|
|
270
|
+
ctx._triviaLog.push(start, end, kindIndex);
|
|
271
|
+
} else {
|
|
272
|
+
ctx._triviaLog.push(start, end);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
131
276
|
// src/combinators/literal.ts
|
|
132
277
|
var _collatorCache = null;
|
|
133
278
|
function collator() {
|
|
@@ -167,8 +312,7 @@ function literal(value, opts = {}) {
|
|
|
167
312
|
if (matched) {
|
|
168
313
|
const span = { start: pos, end };
|
|
169
314
|
const leaf = { _tag: "leaf", value: slice, span };
|
|
170
|
-
if (ctx
|
|
171
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
315
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
172
316
|
return { ok: true, value: slice, span };
|
|
173
317
|
}
|
|
174
318
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
@@ -310,109 +454,60 @@ function regex(pattern, flags = "") {
|
|
|
310
454
|
}
|
|
311
455
|
const span = { start: pos, end: pos + m[0].length };
|
|
312
456
|
const leaf = { _tag: "leaf", value: m[0], span };
|
|
313
|
-
if (ctx
|
|
314
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
457
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
315
458
|
return { ok: true, value: m[0], span };
|
|
316
459
|
}
|
|
317
460
|
};
|
|
318
461
|
}
|
|
319
462
|
|
|
320
|
-
// src/combinators/
|
|
321
|
-
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const out = ctx._cstRawChildren;
|
|
347
|
-
return {
|
|
348
|
-
end: tr2.span.end,
|
|
349
|
-
commit: () => {
|
|
350
|
-
for (const tok of sink) {
|
|
351
|
-
if (tok._tag === "leaf" && tok.span.end > tok.span.start) {
|
|
352
|
-
out.push({ _tag: "trivia", value: tok.value, span: tok.span });
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
return { end: cur, commit: NOOP_COMMIT };
|
|
359
|
-
}
|
|
360
|
-
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
361
|
-
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
362
|
-
}
|
|
363
|
-
function consumeTrivia(input, cur, ctx) {
|
|
364
|
-
const scan = scanTrivia(input, cur, ctx);
|
|
365
|
-
scan.commit();
|
|
366
|
-
return scan.end;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// src/combinators/sequence.ts
|
|
370
|
-
function sequence(...parsers) {
|
|
371
|
-
const meta = {
|
|
372
|
-
firstSet: parsers[0]?._meta.firstSet ?? empty(),
|
|
373
|
-
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
374
|
-
isTrivia: false
|
|
375
|
-
};
|
|
463
|
+
// src/combinators/keywords.ts
|
|
464
|
+
function word(str, boundary = "_0-9A-Za-z") {
|
|
465
|
+
return keywords([str], { boundary });
|
|
466
|
+
}
|
|
467
|
+
function escapeRe(s) {
|
|
468
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
469
|
+
}
|
|
470
|
+
function keywords(words, opts = {}) {
|
|
471
|
+
const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
|
|
472
|
+
const alt = sorted.map(escapeRe).join("|");
|
|
473
|
+
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
474
|
+
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
475
|
+
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
476
|
+
let firstSet = empty();
|
|
477
|
+
for (const w of sorted) {
|
|
478
|
+
if (w.length === 0) continue;
|
|
479
|
+
const cp = w.codePointAt(0);
|
|
480
|
+
firstSet = union(firstSet, fromChar(cp));
|
|
481
|
+
if (opts.caseInsensitive) {
|
|
482
|
+
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
483
|
+
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
484
|
+
if (u !== void 0) firstSet = union(firstSet, fromChar(u));
|
|
485
|
+
if (l !== void 0) firstSet = union(firstSet, fromChar(l));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
376
489
|
return {
|
|
377
|
-
_tag: "
|
|
490
|
+
_tag: "keywords",
|
|
378
491
|
_meta: meta,
|
|
379
|
-
_def: { tag: "
|
|
492
|
+
_def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
|
|
380
493
|
parse(input, pos, ctx) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const scan = scanTrivia(input, cur, ctx);
|
|
386
|
-
const raw = ctx._cstRawChildren;
|
|
387
|
-
const mark = raw ? raw.length : 0;
|
|
388
|
-
scan.commit();
|
|
389
|
-
const result2 = parsers[i].parse(input, scan.end, ctx);
|
|
390
|
-
if (!result2.ok) return result2;
|
|
391
|
-
if (result2.span.end > scan.end) {
|
|
392
|
-
cur = result2.span.end;
|
|
393
|
-
} else if (raw) {
|
|
394
|
-
raw.length = mark;
|
|
395
|
-
}
|
|
396
|
-
values.push(result2.value);
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
400
|
-
if (!result.ok) return result;
|
|
401
|
-
values.push(result.value);
|
|
402
|
-
cur = result.span.end;
|
|
494
|
+
re.lastIndex = pos;
|
|
495
|
+
const m = re.exec(input);
|
|
496
|
+
if (m === null || m.index !== pos) {
|
|
497
|
+
return failAt(ctx, ["keyword"], pos);
|
|
403
498
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
};
|
|
499
|
+
const value = m[0];
|
|
500
|
+
const span = { start: pos, end: pos + value.length };
|
|
501
|
+
const leaf = { _tag: "leaf", value, span };
|
|
502
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
503
|
+
return { ok: true, value, span };
|
|
409
504
|
}
|
|
410
505
|
};
|
|
411
506
|
}
|
|
412
507
|
|
|
413
508
|
// src/combinators/choice.ts
|
|
414
509
|
function choice(...args) {
|
|
415
|
-
const parsers = args.map((a) => "gate" in a ? a.
|
|
510
|
+
const parsers = args.map((a) => "gate" in a ? a.combinator : a);
|
|
416
511
|
const gates = args.map((a) => "gate" in a ? a.gate : null);
|
|
417
512
|
const hasGates = gates.some((g) => g !== null);
|
|
418
513
|
const disjoint = !hasGates && areDisjoint(parsers.map((p) => p._meta.firstSet));
|
|
@@ -496,19 +591,19 @@ function choice(...args) {
|
|
|
496
591
|
}
|
|
497
592
|
for (let i = 0; i < parsers.length; i++) {
|
|
498
593
|
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
499
|
-
const
|
|
500
|
-
const
|
|
594
|
+
const mark = saveCstMark(ctx);
|
|
595
|
+
const logLen = ctx._triviaLog?.length;
|
|
501
596
|
const result = parsers[i].parse(input, pos, ctx);
|
|
502
597
|
if (!result.ok) {
|
|
503
|
-
|
|
504
|
-
if (
|
|
598
|
+
rollbackCstCapture(ctx, mark);
|
|
599
|
+
if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
|
|
505
600
|
expected.push(...result.expected);
|
|
506
601
|
continue;
|
|
507
602
|
}
|
|
508
603
|
const checks = autoNot[i];
|
|
509
604
|
if (checks && autoNotFires(input, result.span.end, checks)) {
|
|
510
|
-
|
|
511
|
-
if (
|
|
605
|
+
rollbackCstCapture(ctx, mark);
|
|
606
|
+
if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
|
|
512
607
|
continue;
|
|
513
608
|
}
|
|
514
609
|
return result;
|
|
@@ -587,6 +682,7 @@ function getCoreRegexDef(p) {
|
|
|
587
682
|
const def = p._def;
|
|
588
683
|
if (def.tag === "regex") return { source: def.source, flags: def.flags };
|
|
589
684
|
if (def.tag === "transform") return getCoreRegexDef(def.parser);
|
|
685
|
+
if (def.tag === "label") return getCoreRegexDef(def.parser);
|
|
590
686
|
return null;
|
|
591
687
|
}
|
|
592
688
|
function applyTransforms(p, value, span) {
|
|
@@ -640,46 +736,275 @@ function areDisjoint(sets) {
|
|
|
640
736
|
return true;
|
|
641
737
|
}
|
|
642
738
|
|
|
739
|
+
// src/cst/trivia-kinds.ts
|
|
740
|
+
function unwrapTrivia(p) {
|
|
741
|
+
let cur = p;
|
|
742
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
743
|
+
return cur;
|
|
744
|
+
}
|
|
745
|
+
function peelLabel(p) {
|
|
746
|
+
if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
function analyzeLabeledTrivia(trivia2) {
|
|
750
|
+
let core = unwrapTrivia(trivia2);
|
|
751
|
+
let minRepeats = 1;
|
|
752
|
+
if (core._def.tag === "oneOrMore") {
|
|
753
|
+
core = core._def.parser;
|
|
754
|
+
minRepeats = 1;
|
|
755
|
+
} else if (core._def.tag === "many") {
|
|
756
|
+
core = core._def.parser;
|
|
757
|
+
minRepeats = 0;
|
|
758
|
+
}
|
|
759
|
+
const arms = [];
|
|
760
|
+
if (core._def.tag === "choice") {
|
|
761
|
+
for (let i = 0; i < core._def.parsers.length; i++) {
|
|
762
|
+
const peeled = peelLabel(core._def.parsers[i]);
|
|
763
|
+
if (!peeled) return null;
|
|
764
|
+
arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
|
|
765
|
+
}
|
|
766
|
+
} else {
|
|
767
|
+
const peeled = peelLabel(core);
|
|
768
|
+
if (!peeled) return null;
|
|
769
|
+
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
770
|
+
}
|
|
771
|
+
return { labels: arms.map((a) => a.label), arms, minRepeats };
|
|
772
|
+
}
|
|
773
|
+
function matchArmAt(input, pos, arm) {
|
|
774
|
+
const r = arm.parse(input, pos, { trackLines: false });
|
|
775
|
+
if (!r.ok || r.span.end <= pos) return null;
|
|
776
|
+
return { end: r.span.end };
|
|
777
|
+
}
|
|
778
|
+
function scanLabeledTriviaChunks(input, cur, spec) {
|
|
779
|
+
const chunks = [];
|
|
780
|
+
let pos = cur;
|
|
781
|
+
while (pos < input.length) {
|
|
782
|
+
let matched = null;
|
|
783
|
+
for (const arm of spec.arms) {
|
|
784
|
+
const m = matchArmAt(input, pos, arm.parser);
|
|
785
|
+
if (m) {
|
|
786
|
+
matched = { end: m.end, kindIndex: arm.kindIndex };
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
if (!matched) break;
|
|
791
|
+
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
792
|
+
pos = matched.end;
|
|
793
|
+
}
|
|
794
|
+
if (chunks.length < spec.minRepeats) {
|
|
795
|
+
return { end: cur, chunks: [] };
|
|
796
|
+
}
|
|
797
|
+
return { end: pos, chunks };
|
|
798
|
+
}
|
|
799
|
+
function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
|
|
800
|
+
const chunks = [];
|
|
801
|
+
let pos = cur;
|
|
802
|
+
while (pos < input.length) {
|
|
803
|
+
const c = input.charCodeAt(pos);
|
|
804
|
+
if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
|
|
805
|
+
const start = pos;
|
|
806
|
+
pos++;
|
|
807
|
+
while (pos < input.length) {
|
|
808
|
+
const c2 = input.charCodeAt(pos);
|
|
809
|
+
if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
|
|
810
|
+
else break;
|
|
811
|
+
}
|
|
812
|
+
chunks.push({ start, end: pos, kindIndex: wsKind });
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
if (c === 47 && input.charCodeAt(pos + 1) === 42) {
|
|
816
|
+
const start = pos;
|
|
817
|
+
let j = pos + 2;
|
|
818
|
+
while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++;
|
|
819
|
+
pos = j + 2 <= input.length ? j + 2 : input.length;
|
|
820
|
+
chunks.push({ start, end: pos, kindIndex: commentKind });
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
return { end: pos, chunks };
|
|
826
|
+
}
|
|
827
|
+
function tryFastLabeledScan(input, cur, trivia2) {
|
|
828
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
829
|
+
if (!spec || spec.arms.length !== 2) return null;
|
|
830
|
+
const wsArm = spec.arms.find((a) => {
|
|
831
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
832
|
+
return src != null && !src.includes("\\*");
|
|
833
|
+
});
|
|
834
|
+
const commentArm = spec.arms.find((a) => {
|
|
835
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
836
|
+
return src != null && src.includes("\\*");
|
|
837
|
+
});
|
|
838
|
+
if (!wsArm || !commentArm) return null;
|
|
839
|
+
const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
840
|
+
if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
|
|
841
|
+
return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
842
|
+
}
|
|
843
|
+
function recordTriviaChunks(ctx, chunks) {
|
|
844
|
+
const kinds = ctx.triviaKindLabels;
|
|
845
|
+
for (const ch of chunks) {
|
|
846
|
+
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
847
|
+
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
848
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// src/combinators/trivia-skip.ts
|
|
854
|
+
var NOOP_COMMIT = () => {
|
|
855
|
+
};
|
|
856
|
+
function needsDeferredTriviaCommit(ctx) {
|
|
857
|
+
return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
858
|
+
}
|
|
859
|
+
function saveTriviaMark(ctx) {
|
|
860
|
+
const m = saveCstMark(ctx);
|
|
861
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
862
|
+
}
|
|
863
|
+
function rollbackTrivia(ctx, mark) {
|
|
864
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
865
|
+
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
866
|
+
}
|
|
867
|
+
function scanWithLabels(input, cur, ctx) {
|
|
868
|
+
const triviaP = ctx.trivia;
|
|
869
|
+
const spec = analyzeLabeledTrivia(triviaP);
|
|
870
|
+
if (!spec) return { end: cur, commit: NOOP_COMMIT };
|
|
871
|
+
const fast = tryFastLabeledScan(input, cur, triviaP);
|
|
872
|
+
const { end, chunks } = fast ?? scanLabeledTriviaChunks(input, cur, spec);
|
|
873
|
+
if (end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
874
|
+
return {
|
|
875
|
+
end,
|
|
876
|
+
commit: () => recordTriviaChunks(ctx, chunks)
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function advanceTrivia(input, cur, ctx) {
|
|
880
|
+
const triviaP = ctx.trivia;
|
|
881
|
+
if (!triviaP) return cur;
|
|
882
|
+
if (ctx.triviaKindLabels) {
|
|
883
|
+
const scan = scanWithLabels(input, cur, ctx);
|
|
884
|
+
return scan.end;
|
|
885
|
+
}
|
|
886
|
+
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
887
|
+
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
888
|
+
}
|
|
889
|
+
function scanTrivia(input, cur, ctx) {
|
|
890
|
+
const triviaP = ctx.trivia;
|
|
891
|
+
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
892
|
+
const log = ctx._triviaLog;
|
|
893
|
+
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
894
|
+
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
895
|
+
return scanWithLabels(input, cur, ctx);
|
|
896
|
+
}
|
|
897
|
+
if (log !== void 0 || captureTl) {
|
|
898
|
+
const tr2 = triviaP.parse(input, cur, {
|
|
899
|
+
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
900
|
+
state: ctx.state
|
|
901
|
+
});
|
|
902
|
+
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
903
|
+
const end = tr2.span.end;
|
|
904
|
+
return {
|
|
905
|
+
end,
|
|
906
|
+
commit: () => {
|
|
907
|
+
pushTriviaLogEntry(ctx, cur, end);
|
|
908
|
+
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
913
|
+
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/combinators/sequence.ts
|
|
917
|
+
function sequence(...parsers) {
|
|
918
|
+
const meta = {
|
|
919
|
+
firstSet: parsers[0]?._meta.firstSet ?? empty(),
|
|
920
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
921
|
+
isTrivia: false
|
|
922
|
+
};
|
|
923
|
+
return {
|
|
924
|
+
_tag: "sequence",
|
|
925
|
+
_meta: meta,
|
|
926
|
+
_def: { tag: "sequence", parsers },
|
|
927
|
+
parse(input, pos, ctx) {
|
|
928
|
+
const values = [];
|
|
929
|
+
let cur = pos;
|
|
930
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
931
|
+
if (ctx.trivia && i > 0) {
|
|
932
|
+
let scanEnd;
|
|
933
|
+
let mark = saveTriviaMark(ctx);
|
|
934
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
935
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
936
|
+
scan.commit();
|
|
937
|
+
scanEnd = scan.end;
|
|
938
|
+
} else {
|
|
939
|
+
scanEnd = advanceTrivia(input, cur, ctx);
|
|
940
|
+
}
|
|
941
|
+
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
942
|
+
if (!result2.ok) return result2;
|
|
943
|
+
if (result2.span.end > scanEnd) {
|
|
944
|
+
cur = result2.span.end;
|
|
945
|
+
} else {
|
|
946
|
+
rollbackTrivia(ctx, mark);
|
|
947
|
+
}
|
|
948
|
+
values.push(result2.value);
|
|
949
|
+
continue;
|
|
950
|
+
}
|
|
951
|
+
const result = parsers[i].parse(input, cur, ctx);
|
|
952
|
+
if (!result.ok) return result;
|
|
953
|
+
values.push(result.value);
|
|
954
|
+
cur = result.span.end;
|
|
955
|
+
}
|
|
956
|
+
return {
|
|
957
|
+
ok: true,
|
|
958
|
+
value: values,
|
|
959
|
+
span: { start: pos, end: cur }
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
|
|
643
965
|
// src/combinators/repeat.ts
|
|
644
|
-
function repItem(
|
|
645
|
-
const
|
|
646
|
-
const mark = raw ? raw.length : 0;
|
|
966
|
+
function repItem(combinator, input, cur, ctx) {
|
|
967
|
+
const mark = saveTriviaMark(ctx);
|
|
647
968
|
let pos = cur;
|
|
648
969
|
if (ctx.trivia) {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
970
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
971
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
972
|
+
scan.commit();
|
|
973
|
+
pos = scan.end;
|
|
974
|
+
} else {
|
|
975
|
+
pos = advanceTrivia(input, cur, ctx);
|
|
976
|
+
}
|
|
652
977
|
}
|
|
653
978
|
if (pos >= input.length) {
|
|
654
|
-
|
|
979
|
+
rollbackTrivia(ctx, mark);
|
|
655
980
|
return "stop";
|
|
656
981
|
}
|
|
657
|
-
const result =
|
|
982
|
+
const result = combinator.parse(input, pos, ctx);
|
|
658
983
|
if (!result.ok) {
|
|
659
|
-
|
|
984
|
+
rollbackTrivia(ctx, mark);
|
|
660
985
|
return { fail: result };
|
|
661
986
|
}
|
|
662
987
|
if (result.span.end === pos) {
|
|
663
|
-
|
|
988
|
+
rollbackTrivia(ctx, mark);
|
|
664
989
|
return "stop";
|
|
665
990
|
}
|
|
666
991
|
return { value: result.value, end: result.span.end };
|
|
667
992
|
}
|
|
668
|
-
function many(
|
|
993
|
+
function many(combinator) {
|
|
669
994
|
const meta = {
|
|
670
|
-
firstSet:
|
|
671
|
-
canMatchNewline:
|
|
995
|
+
firstSet: combinator._meta.firstSet,
|
|
996
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
672
997
|
isTrivia: false
|
|
673
998
|
};
|
|
674
999
|
return {
|
|
675
1000
|
_tag: "many",
|
|
676
1001
|
_meta: meta,
|
|
677
|
-
_def: { tag: "many", parser:
|
|
1002
|
+
_def: { tag: "many", parser: combinator, min: 0 },
|
|
678
1003
|
parse(input, pos, ctx) {
|
|
679
1004
|
const values = [];
|
|
680
1005
|
let cur = pos;
|
|
681
1006
|
while (cur < input.length) {
|
|
682
|
-
const item = repItem(
|
|
1007
|
+
const item = repItem(combinator, input, cur, ctx);
|
|
683
1008
|
if (item === "stop" || "fail" in item) break;
|
|
684
1009
|
values.push(item.value);
|
|
685
1010
|
cur = item.end;
|
|
@@ -688,23 +1013,23 @@ function many(parser2) {
|
|
|
688
1013
|
}
|
|
689
1014
|
};
|
|
690
1015
|
}
|
|
691
|
-
function oneOrMore(
|
|
1016
|
+
function oneOrMore(combinator) {
|
|
692
1017
|
const meta = {
|
|
693
|
-
firstSet:
|
|
694
|
-
canMatchNewline:
|
|
1018
|
+
firstSet: combinator._meta.firstSet,
|
|
1019
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
695
1020
|
isTrivia: false
|
|
696
1021
|
};
|
|
697
1022
|
return {
|
|
698
1023
|
_tag: "oneOrMore",
|
|
699
1024
|
_meta: meta,
|
|
700
|
-
_def: { tag: "oneOrMore", parser:
|
|
1025
|
+
_def: { tag: "oneOrMore", parser: combinator, min: 1 },
|
|
701
1026
|
parse(input, pos, ctx) {
|
|
702
|
-
const first =
|
|
1027
|
+
const first = combinator.parse(input, pos, ctx);
|
|
703
1028
|
if (!first.ok) return first;
|
|
704
1029
|
const values = [first.value];
|
|
705
1030
|
let cur = first.span.end;
|
|
706
1031
|
while (cur < input.length) {
|
|
707
|
-
const item = repItem(
|
|
1032
|
+
const item = repItem(combinator, input, cur, ctx);
|
|
708
1033
|
if (item === "stop" || "fail" in item) break;
|
|
709
1034
|
values.push(item.value);
|
|
710
1035
|
cur = item.end;
|
|
@@ -713,45 +1038,71 @@ function oneOrMore(parser2) {
|
|
|
713
1038
|
}
|
|
714
1039
|
};
|
|
715
1040
|
}
|
|
716
|
-
function optional(
|
|
1041
|
+
function optional(combinator) {
|
|
717
1042
|
const meta = {
|
|
718
|
-
firstSet:
|
|
719
|
-
canMatchNewline:
|
|
1043
|
+
firstSet: combinator._meta.firstSet,
|
|
1044
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
720
1045
|
isTrivia: false
|
|
721
1046
|
};
|
|
722
1047
|
return {
|
|
723
1048
|
_tag: "optional",
|
|
724
1049
|
_meta: meta,
|
|
725
|
-
_def: { tag: "optional", parser:
|
|
1050
|
+
_def: { tag: "optional", parser: combinator },
|
|
726
1051
|
parse(input, pos, ctx) {
|
|
727
|
-
const result =
|
|
1052
|
+
const result = combinator.parse(input, pos, ctx);
|
|
728
1053
|
if (result.ok) return result;
|
|
729
1054
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
730
1055
|
}
|
|
731
1056
|
};
|
|
732
1057
|
}
|
|
733
|
-
function sepBy(
|
|
1058
|
+
function sepBy(combinator, separator) {
|
|
734
1059
|
const meta = {
|
|
735
|
-
firstSet:
|
|
736
|
-
canMatchNewline:
|
|
1060
|
+
firstSet: combinator._meta.firstSet,
|
|
1061
|
+
canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
|
|
737
1062
|
isTrivia: false
|
|
738
1063
|
};
|
|
739
1064
|
return {
|
|
740
1065
|
_tag: "sepBy",
|
|
741
1066
|
_meta: meta,
|
|
742
|
-
_def: { tag: "sepBy", parser:
|
|
1067
|
+
_def: { tag: "sepBy", parser: combinator, separator },
|
|
743
1068
|
parse(input, pos, ctx) {
|
|
744
|
-
const first =
|
|
1069
|
+
const first = combinator.parse(input, pos, ctx);
|
|
745
1070
|
if (!first.ok) return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
746
1071
|
const values = [first.value];
|
|
747
1072
|
let cur = first.span.end;
|
|
748
1073
|
while (cur < input.length) {
|
|
749
|
-
|
|
1074
|
+
let mark = saveTriviaMark(ctx);
|
|
1075
|
+
let sepPos = cur;
|
|
1076
|
+
if (ctx.trivia) {
|
|
1077
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
1078
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
1079
|
+
scan.commit();
|
|
1080
|
+
sepPos = scan.end;
|
|
1081
|
+
} else {
|
|
1082
|
+
sepPos = advanceTrivia(input, cur, ctx);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
750
1085
|
const sep = separator.parse(input, sepPos, ctx);
|
|
751
|
-
if (!sep.ok)
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
1086
|
+
if (!sep.ok) {
|
|
1087
|
+
rollbackTrivia(ctx, mark);
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
mark = saveTriviaMark(ctx);
|
|
1091
|
+
let nextPos = sep.span.end;
|
|
1092
|
+
if (ctx.trivia) {
|
|
1093
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
1094
|
+
const scan = scanTrivia(input, sep.span.end, ctx);
|
|
1095
|
+
scan.commit();
|
|
1096
|
+
nextPos = scan.end;
|
|
1097
|
+
} else {
|
|
1098
|
+
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
const next = combinator.parse(input, nextPos, ctx);
|
|
1102
|
+
if (!next.ok) {
|
|
1103
|
+
rollbackTrivia(ctx, mark);
|
|
1104
|
+
break;
|
|
1105
|
+
}
|
|
755
1106
|
values.push(next.value);
|
|
756
1107
|
cur = next.span.end;
|
|
757
1108
|
}
|
|
@@ -761,7 +1112,7 @@ function sepBy(parser2, separator) {
|
|
|
761
1112
|
}
|
|
762
1113
|
|
|
763
1114
|
// src/combinators/not.ts
|
|
764
|
-
function not(
|
|
1115
|
+
function not(combinator) {
|
|
765
1116
|
const meta = {
|
|
766
1117
|
firstSet: any(),
|
|
767
1118
|
// we don't know what NOT matches
|
|
@@ -771,11 +1122,11 @@ function not(parser2) {
|
|
|
771
1122
|
return {
|
|
772
1123
|
_tag: "not",
|
|
773
1124
|
_meta: meta,
|
|
774
|
-
_def: { tag: "not", parser:
|
|
1125
|
+
_def: { tag: "not", parser: combinator },
|
|
775
1126
|
parse(input, pos, ctx) {
|
|
776
|
-
const result =
|
|
1127
|
+
const result = combinator.parse(input, pos, ctx);
|
|
777
1128
|
if (result.ok) {
|
|
778
|
-
return { ok: false, expected: [`not(${
|
|
1129
|
+
return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
|
|
779
1130
|
}
|
|
780
1131
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
781
1132
|
}
|
|
@@ -783,37 +1134,27 @@ function not(parser2) {
|
|
|
783
1134
|
}
|
|
784
1135
|
|
|
785
1136
|
// src/combinators/node.ts
|
|
786
|
-
function node(type,
|
|
1137
|
+
function node(type, combinator, build) {
|
|
787
1138
|
const meta = {
|
|
788
|
-
firstSet:
|
|
789
|
-
canMatchNewline:
|
|
1139
|
+
firstSet: combinator._meta.firstSet,
|
|
1140
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
790
1141
|
isTrivia: false
|
|
791
1142
|
};
|
|
792
1143
|
return {
|
|
793
1144
|
_tag: "node",
|
|
794
1145
|
_meta: meta,
|
|
795
|
-
_def: { tag: "node", type, parser:
|
|
1146
|
+
_def: { tag: "node", type, parser: combinator, build },
|
|
796
1147
|
parse(input, pos, ctx) {
|
|
797
|
-
const
|
|
798
|
-
const
|
|
799
|
-
const
|
|
800
|
-
...ctx,
|
|
801
|
-
// A node() always records the trivia between its terms — the library owns
|
|
802
|
-
// capture so grammar authors don't reconstruct it. (Matches the compiler.)
|
|
803
|
-
captureTrivia: true,
|
|
804
|
-
_cstChildren: children,
|
|
805
|
-
_cstLeaves: children,
|
|
806
|
-
_cstRawChildren: rawChildren
|
|
807
|
-
};
|
|
808
|
-
const r = parser2.parse(input, pos, innerCtx);
|
|
1148
|
+
const saved = beginCstNodeCapture(ctx);
|
|
1149
|
+
const r = combinator.parse(input, pos, ctx);
|
|
1150
|
+
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
809
1151
|
if (!r.ok) return r;
|
|
810
|
-
const
|
|
1152
|
+
const state = ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1153
|
+
const built = build(children, rawChildren, r.span, triviaLog, state);
|
|
811
1154
|
const isNodeLike = typeof built === "object" && built !== null && built._tag === "node";
|
|
812
|
-
|
|
813
|
-
if (
|
|
814
|
-
ctx
|
|
815
|
-
isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span }
|
|
816
|
-
);
|
|
1155
|
+
const rawEntry = isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1156
|
+
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1157
|
+
pushCstChild(ctx, built, rawEntry);
|
|
817
1158
|
}
|
|
818
1159
|
return { ok: true, value: built, span: r.span };
|
|
819
1160
|
}
|
|
@@ -821,24 +1162,37 @@ function node(type, parser2, build) {
|
|
|
821
1162
|
}
|
|
822
1163
|
|
|
823
1164
|
// src/combinators/map.ts
|
|
824
|
-
function transform(
|
|
1165
|
+
function transform(combinator, fn) {
|
|
825
1166
|
return {
|
|
826
1167
|
_tag: "transform",
|
|
827
|
-
_meta:
|
|
828
|
-
_def: { tag: "transform", parser:
|
|
1168
|
+
_meta: combinator._meta,
|
|
1169
|
+
_def: { tag: "transform", parser: combinator, fn },
|
|
829
1170
|
parse(input, pos, ctx) {
|
|
830
|
-
const result =
|
|
1171
|
+
const result = combinator.parse(input, pos, ctx);
|
|
831
1172
|
if (!result.ok) return result;
|
|
832
1173
|
return { ...result, value: fn(result.value, result.span) };
|
|
833
1174
|
}
|
|
834
1175
|
};
|
|
835
1176
|
}
|
|
836
|
-
function trivia(
|
|
1177
|
+
function trivia(combinator) {
|
|
1178
|
+
const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
|
|
1179
|
+
return {
|
|
1180
|
+
_tag: combinator._tag,
|
|
1181
|
+
_meta: {
|
|
1182
|
+
...combinator._meta,
|
|
1183
|
+
isTrivia: true,
|
|
1184
|
+
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
1185
|
+
},
|
|
1186
|
+
_def: { tag: "trivia", parser: combinator },
|
|
1187
|
+
parse: combinator.parse.bind(combinator)
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
function label(name, combinator) {
|
|
837
1191
|
return {
|
|
838
|
-
_tag:
|
|
839
|
-
_meta:
|
|
840
|
-
_def: { tag: "
|
|
841
|
-
parse:
|
|
1192
|
+
_tag: combinator._tag,
|
|
1193
|
+
_meta: combinator._meta,
|
|
1194
|
+
_def: { tag: "label", label: name, parser: combinator },
|
|
1195
|
+
parse: combinator.parse.bind(combinator)
|
|
842
1196
|
};
|
|
843
1197
|
}
|
|
844
1198
|
|
|
@@ -889,7 +1243,10 @@ function parser(opts, root) {
|
|
|
889
1243
|
const ctx = {
|
|
890
1244
|
..._ctx,
|
|
891
1245
|
trackLines,
|
|
892
|
-
...opts.trivia !== void 0 ? {
|
|
1246
|
+
...opts.trivia !== void 0 ? {
|
|
1247
|
+
trivia: opts.trivia,
|
|
1248
|
+
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1249
|
+
} : {},
|
|
893
1250
|
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {}
|
|
894
1251
|
};
|
|
895
1252
|
const result = root.parse(input, pos ?? 0, ctx);
|
|
@@ -902,6 +1259,320 @@ function parser(opts, root) {
|
|
|
902
1259
|
};
|
|
903
1260
|
}
|
|
904
1261
|
|
|
1262
|
+
// src/compiler/trivia-fast-path.ts
|
|
1263
|
+
var BLOCK_COMMENT = String.raw`\/\*(?:[^*]|\*(?!\/))*\*\/`;
|
|
1264
|
+
var WS_CLASS_SOURCES = /* @__PURE__ */ new Set([
|
|
1265
|
+
String.raw`[ \t\n\r\f]+`,
|
|
1266
|
+
String.raw`[ \t\n]+`,
|
|
1267
|
+
String.raw`[ \t]+`,
|
|
1268
|
+
String.raw`[\t\n\f\r ]+`
|
|
1269
|
+
]);
|
|
1270
|
+
function unwrapTrivia2(p) {
|
|
1271
|
+
let cur = p;
|
|
1272
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
1273
|
+
return cur;
|
|
1274
|
+
}
|
|
1275
|
+
function oneOrMoreInner(p) {
|
|
1276
|
+
const d = p._def;
|
|
1277
|
+
if (d.tag === "oneOrMore") return d.parser;
|
|
1278
|
+
if (d.tag === "many" && d.min >= 1) return d.parser;
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
function choiceArms(p) {
|
|
1282
|
+
if (p._def.tag === "choice") return p._def.parsers;
|
|
1283
|
+
return null;
|
|
1284
|
+
}
|
|
1285
|
+
function isWsClassSource(source) {
|
|
1286
|
+
return WS_CLASS_SOURCES.has(source);
|
|
1287
|
+
}
|
|
1288
|
+
function isBlockCommentSource(source) {
|
|
1289
|
+
return source === BLOCK_COMMENT;
|
|
1290
|
+
}
|
|
1291
|
+
function analyzeTriviaFastPath(trivia2) {
|
|
1292
|
+
const core = unwrapTrivia2(trivia2);
|
|
1293
|
+
const direct = getCoreRegexDef(core)?.source;
|
|
1294
|
+
if (direct) {
|
|
1295
|
+
if (isWsClassSource(direct)) return "wsOnly";
|
|
1296
|
+
return null;
|
|
1297
|
+
}
|
|
1298
|
+
const inner = oneOrMoreInner(core);
|
|
1299
|
+
if (!inner) return null;
|
|
1300
|
+
const innerSrc = getCoreRegexDef(inner)?.source;
|
|
1301
|
+
if (innerSrc && isWsClassSource(innerSrc)) return "wsOnly";
|
|
1302
|
+
const arms = choiceArms(inner);
|
|
1303
|
+
if (!arms || arms.length !== 2) return null;
|
|
1304
|
+
let hasWs = false;
|
|
1305
|
+
let hasComment = false;
|
|
1306
|
+
for (const arm of arms) {
|
|
1307
|
+
const src = getCoreRegexDef(arm)?.source;
|
|
1308
|
+
if (!src) return null;
|
|
1309
|
+
if (isWsClassSource(src)) hasWs = true;
|
|
1310
|
+
else if (isBlockCommentSource(src)) hasComment = true;
|
|
1311
|
+
else return null;
|
|
1312
|
+
}
|
|
1313
|
+
if (hasWs && hasComment) return "wsComments";
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
var CAP_RECORD = [
|
|
1317
|
+
` if (_cap && _e > _pos) {`,
|
|
1318
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
1319
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
1320
|
+
` }`
|
|
1321
|
+
].join("\n");
|
|
1322
|
+
var WS_ONLY_LOOP = [
|
|
1323
|
+
` while (_e < input.length) {`,
|
|
1324
|
+
` const c = input.charCodeAt(_e)`,
|
|
1325
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) { _e++; continue }`,
|
|
1326
|
+
` break`,
|
|
1327
|
+
` }`
|
|
1328
|
+
].join("\n");
|
|
1329
|
+
var WS_COMMENTS_LOOP = [
|
|
1330
|
+
` while (_e < input.length) {`,
|
|
1331
|
+
` const c = input.charCodeAt(_e)`,
|
|
1332
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) { _e++; continue }`,
|
|
1333
|
+
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1334
|
+
` let j = _e + 2`,
|
|
1335
|
+
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1336
|
+
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1337
|
+
` continue`,
|
|
1338
|
+
` }`,
|
|
1339
|
+
` break`,
|
|
1340
|
+
` }`
|
|
1341
|
+
].join("\n");
|
|
1342
|
+
var CAP_CHUNK = (wsKind, commentKind) => [
|
|
1343
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {`,
|
|
1344
|
+
` const _cs = _e`,
|
|
1345
|
+
` _e++`,
|
|
1346
|
+
` while (_e < input.length) {`,
|
|
1347
|
+
` const c2 = input.charCodeAt(_e)`,
|
|
1348
|
+
` if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) _e++`,
|
|
1349
|
+
` else break`,
|
|
1350
|
+
` }`,
|
|
1351
|
+
` if (_cap) {`,
|
|
1352
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${wsKind})`,
|
|
1353
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${wsKind})`,
|
|
1354
|
+
` }`,
|
|
1355
|
+
` continue`,
|
|
1356
|
+
` }`,
|
|
1357
|
+
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1358
|
+
` const _cs = _e`,
|
|
1359
|
+
` let j = _e + 2`,
|
|
1360
|
+
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1361
|
+
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1362
|
+
` if (_cap) {`,
|
|
1363
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${commentKind})`,
|
|
1364
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${commentKind})`,
|
|
1365
|
+
` }`,
|
|
1366
|
+
` continue`,
|
|
1367
|
+
` }`
|
|
1368
|
+
].join("\n");
|
|
1369
|
+
var WS_COMMENTS_LOOP_LABELED = (wsKind, commentKind) => [
|
|
1370
|
+
` while (_e < input.length) {`,
|
|
1371
|
+
` const c = input.charCodeAt(_e)`,
|
|
1372
|
+
CAP_CHUNK(wsKind, commentKind),
|
|
1373
|
+
` break`,
|
|
1374
|
+
` }`
|
|
1375
|
+
].join("\n");
|
|
1376
|
+
function buildFastTriviaFnDecl(fnName, kind, kindIndices) {
|
|
1377
|
+
const loop = kind === "wsComments" && kindIndices ? WS_COMMENTS_LOOP_LABELED(kindIndices.ws, kindIndices.comment) : kind === "wsComments" ? WS_COMMENTS_LOOP : WS_ONLY_LOOP;
|
|
1378
|
+
const cap = kindIndices ? "" : CAP_RECORD;
|
|
1379
|
+
const lines = [
|
|
1380
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1381
|
+
` let _e = _pos`,
|
|
1382
|
+
loop
|
|
1383
|
+
];
|
|
1384
|
+
if (cap) lines.push(cap);
|
|
1385
|
+
lines.push(` return _e`, `}`);
|
|
1386
|
+
return lines.join("\n");
|
|
1387
|
+
}
|
|
1388
|
+
function regexArmIndex(spec, isComment) {
|
|
1389
|
+
for (const arm of spec.arms) {
|
|
1390
|
+
const src = getCoreRegexDef(arm.parser)?.source;
|
|
1391
|
+
if (!src) return null;
|
|
1392
|
+
const comment = src.includes("\\*") || src.startsWith("\\/\\/");
|
|
1393
|
+
if (comment === isComment) return arm.kindIndex;
|
|
1394
|
+
}
|
|
1395
|
+
return null;
|
|
1396
|
+
}
|
|
1397
|
+
function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
1398
|
+
const tryArms = spec.arms.map((arm, i) => {
|
|
1399
|
+
const re = reNames[i];
|
|
1400
|
+
const k = arm.kindIndex;
|
|
1401
|
+
return [
|
|
1402
|
+
` ${re}.lastIndex = _e`,
|
|
1403
|
+
` const _m${i} = ${re}.exec(input)`,
|
|
1404
|
+
` if (_m${i} && _m${i}.index === _e) {`,
|
|
1405
|
+
` const _ce = _e + _m${i}[0].length`,
|
|
1406
|
+
` if (_cap) {`,
|
|
1407
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
1408
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
1409
|
+
` }`,
|
|
1410
|
+
` _e = _ce`,
|
|
1411
|
+
` _matched = true`,
|
|
1412
|
+
` continue`,
|
|
1413
|
+
` }`
|
|
1414
|
+
].join("\n");
|
|
1415
|
+
}).join("\n");
|
|
1416
|
+
return [
|
|
1417
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1418
|
+
` let _e = _pos`,
|
|
1419
|
+
` while (_e < input.length) {`,
|
|
1420
|
+
` let _matched = false`,
|
|
1421
|
+
tryArms,
|
|
1422
|
+
` if (!_matched) break`,
|
|
1423
|
+
` }`,
|
|
1424
|
+
` return _e`,
|
|
1425
|
+
`}`
|
|
1426
|
+
].join("\n");
|
|
1427
|
+
}
|
|
1428
|
+
function labeledTriviaKindIndices(trivia2) {
|
|
1429
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1430
|
+
if (!spec || spec.arms.length !== 2) return null;
|
|
1431
|
+
const ws = regexArmIndex(spec, false);
|
|
1432
|
+
const comment = regexArmIndex(spec, true);
|
|
1433
|
+
if (ws === null || comment === null) return null;
|
|
1434
|
+
return { ws, comment };
|
|
1435
|
+
}
|
|
1436
|
+
function labeledTriviaRegexArms(trivia2) {
|
|
1437
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1438
|
+
if (!spec) return null;
|
|
1439
|
+
for (const arm of spec.arms) {
|
|
1440
|
+
if (!getCoreRegexDef(arm.parser)) return null;
|
|
1441
|
+
}
|
|
1442
|
+
return spec;
|
|
1443
|
+
}
|
|
1444
|
+
function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
1445
|
+
const tryArms = spec.arms.map((arm, i) => {
|
|
1446
|
+
const k = arm.kindIndex;
|
|
1447
|
+
const ri = rpStartIndex + i;
|
|
1448
|
+
return [
|
|
1449
|
+
` const _r${i} = _rp[${ri}].parse(input, _e, _ctx)`,
|
|
1450
|
+
` if (_r${i}.ok && _r${i}.span.end > _e) {`,
|
|
1451
|
+
` const _ce = _r${i}.span.end`,
|
|
1452
|
+
` if (_cap) {`,
|
|
1453
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
1454
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
1455
|
+
` }`,
|
|
1456
|
+
` _e = _ce`,
|
|
1457
|
+
` _matched = true`,
|
|
1458
|
+
` continue`,
|
|
1459
|
+
` }`
|
|
1460
|
+
].join("\n");
|
|
1461
|
+
}).join("\n");
|
|
1462
|
+
return [
|
|
1463
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1464
|
+
` let _e = _pos`,
|
|
1465
|
+
` while (_e < input.length) {`,
|
|
1466
|
+
` let _matched = false`,
|
|
1467
|
+
tryArms,
|
|
1468
|
+
` if (!_matched) break`,
|
|
1469
|
+
` }`,
|
|
1470
|
+
` return _e`,
|
|
1471
|
+
`}`
|
|
1472
|
+
].join("\n");
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/compiler/inline-build.ts
|
|
1476
|
+
var MK_BUILD_RE = /^\(\s*(?:\w+\s*,\s*){3}\w+\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\1\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*$/;
|
|
1477
|
+
function escapeRegExp(s) {
|
|
1478
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1479
|
+
}
|
|
1480
|
+
function looseMkBuildRe(type) {
|
|
1481
|
+
return new RegExp(
|
|
1482
|
+
String.raw`^\(\s*(?:\w+\s*,\s*){3}\w+\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\1\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*$`
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
function analyzeMkInlineBuild(def) {
|
|
1486
|
+
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
1487
|
+
const strict = src.match(MK_BUILD_RE);
|
|
1488
|
+
if (strict) {
|
|
1489
|
+
const mkType = strict[2];
|
|
1490
|
+
return mkType === def.type ? def.type : null;
|
|
1491
|
+
}
|
|
1492
|
+
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
1493
|
+
return null;
|
|
1494
|
+
}
|
|
1495
|
+
function emitInlineMkNodeExpr(type, chV, rawV, pos, endVar, tlV) {
|
|
1496
|
+
return `{ _tag: 'node', type: ${JSON.stringify(type)}, span: { start: ${pos}, end: ${endVar} }, children: ${chV}, rawCount: ${rawV}.length, localTriviaLen: ${tlV}.length }`;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// src/compiler/inline-callback.ts
|
|
1500
|
+
var INLINE_BUILTINS = /* @__PURE__ */ new Set([
|
|
1501
|
+
"parseInt",
|
|
1502
|
+
"parseFloat",
|
|
1503
|
+
"String",
|
|
1504
|
+
"Number",
|
|
1505
|
+
"Boolean",
|
|
1506
|
+
"Object",
|
|
1507
|
+
"Array",
|
|
1508
|
+
"Math",
|
|
1509
|
+
"JSON",
|
|
1510
|
+
"undefined",
|
|
1511
|
+
"null",
|
|
1512
|
+
"true",
|
|
1513
|
+
"false",
|
|
1514
|
+
"NaN",
|
|
1515
|
+
"Infinity"
|
|
1516
|
+
]);
|
|
1517
|
+
function escapeRegExp2(s) {
|
|
1518
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1519
|
+
}
|
|
1520
|
+
function transformFnSource(fn, fnSrc) {
|
|
1521
|
+
if (fnSrc) return fnSrc.trim();
|
|
1522
|
+
const s = fn.toString().trim();
|
|
1523
|
+
if (s.includes("[native code]")) return null;
|
|
1524
|
+
return s;
|
|
1525
|
+
}
|
|
1526
|
+
function replaceParam(body, param, valueVar) {
|
|
1527
|
+
return body.replace(new RegExp(`\\b${escapeRegExp2(param)}\\b`, "g"), valueVar);
|
|
1528
|
+
}
|
|
1529
|
+
function stripForIdCheck(body) {
|
|
1530
|
+
return body.replace(/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/g, '""').replace(/\bas\s+const\b/g, "").replace(/\b[A-Za-z_$][\w$]*\s*:/g, ":");
|
|
1531
|
+
}
|
|
1532
|
+
function hasFreeIdentifiers(body, allowed) {
|
|
1533
|
+
const stripped = stripForIdCheck(body);
|
|
1534
|
+
const ids = stripped.match(/\b[A-Za-z_$][\w$]*\b/g) ?? [];
|
|
1535
|
+
for (const id of ids) {
|
|
1536
|
+
if (INLINE_BUILTINS.has(id)) continue;
|
|
1537
|
+
if (allowed.has(id)) continue;
|
|
1538
|
+
return true;
|
|
1539
|
+
}
|
|
1540
|
+
return false;
|
|
1541
|
+
}
|
|
1542
|
+
function tryInlineUnaryTransform(src, valueVar) {
|
|
1543
|
+
const allowed = /* @__PURE__ */ new Set([valueVar]);
|
|
1544
|
+
const nullary = src.match(/^\(\s*\)\s*=>\s*(.+)$/);
|
|
1545
|
+
if (nullary) {
|
|
1546
|
+
const body2 = nullary[1].trim();
|
|
1547
|
+
return hasFreeIdentifiers(body2, allowed) ? null : body2;
|
|
1548
|
+
}
|
|
1549
|
+
const m = src.match(/^(\w+)\s*=>\s*(.+)$/);
|
|
1550
|
+
if (!m) return null;
|
|
1551
|
+
const body = replaceParam(m[2].trim(), m[1], valueVar);
|
|
1552
|
+
return hasFreeIdentifiers(body, allowed) ? null : body;
|
|
1553
|
+
}
|
|
1554
|
+
function parseArrayDestructure(pattern, arity) {
|
|
1555
|
+
const slots = [];
|
|
1556
|
+
for (const part of pattern.split(",")) {
|
|
1557
|
+
const name = part.trim();
|
|
1558
|
+
slots.push(name === "" || name === "_" ? null : name);
|
|
1559
|
+
}
|
|
1560
|
+
while (slots.length < arity) slots.push(null);
|
|
1561
|
+
return slots.slice(0, arity);
|
|
1562
|
+
}
|
|
1563
|
+
function tryInlineDestructureTransform(src, valueVars) {
|
|
1564
|
+
const m = src.match(/^\(\s*\[([^\]]*)\]\s*\)\s*=>\s*(.+)$/s);
|
|
1565
|
+
if (!m) return null;
|
|
1566
|
+
const slots = parseArrayDestructure(m[1], valueVars.length);
|
|
1567
|
+
let body = m[2].trim();
|
|
1568
|
+
const allowed = new Set(valueVars);
|
|
1569
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1570
|
+
const name = slots[i];
|
|
1571
|
+
if (name) body = replaceParam(body, name, valueVars[i]);
|
|
1572
|
+
}
|
|
1573
|
+
return hasFreeIdentifiers(body, allowed) ? null : body;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
905
1576
|
// src/compiler/codegen.ts
|
|
906
1577
|
function v(ctx, prefix = "_v") {
|
|
907
1578
|
return `${prefix}${ctx.vars++}`;
|
|
@@ -909,12 +1580,42 @@ function v(ctx, prefix = "_v") {
|
|
|
909
1580
|
function ind(ctx) {
|
|
910
1581
|
return " ".repeat(ctx.indent);
|
|
911
1582
|
}
|
|
1583
|
+
var NAMED_FN_FAIL = "_pfFail";
|
|
1584
|
+
var NAMED_FN_END = "_pfEnd";
|
|
1585
|
+
function namedFnPrelude() {
|
|
1586
|
+
return [`const ${NAMED_FN_FAIL} = {}`, `let ${NAMED_FN_END}`];
|
|
1587
|
+
}
|
|
1588
|
+
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
1589
|
+
ctx.namedFnDecls.push([
|
|
1590
|
+
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1591
|
+
` let _pfok = false, _pfv, _pfe = _pos`,
|
|
1592
|
+
` _pfail: {`,
|
|
1593
|
+
...bodyStmts,
|
|
1594
|
+
` _pfv = ${valueVar}; _pfe = ${endVar}; _pfok = true`,
|
|
1595
|
+
` }`,
|
|
1596
|
+
` if (!_pfok) return ${NAMED_FN_FAIL}`,
|
|
1597
|
+
` ${NAMED_FN_END} = _pfe`,
|
|
1598
|
+
` return _pfv`,
|
|
1599
|
+
`}`
|
|
1600
|
+
].join("\n"));
|
|
1601
|
+
}
|
|
1602
|
+
function emitNamedFnCall(ctx, fnName, pos, failExpected) {
|
|
1603
|
+
const vv = v(ctx, "_pfv");
|
|
1604
|
+
const ev = v(ctx, "_pfe");
|
|
1605
|
+
return {
|
|
1606
|
+
stmts: [
|
|
1607
|
+
`${ind(ctx)}const ${vv} = ${fnName}(input, ${pos}, _ctx)`,
|
|
1608
|
+
`${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, failExpected, pos).trim()}`,
|
|
1609
|
+
`${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
|
|
1610
|
+
],
|
|
1611
|
+
valueVar: vv,
|
|
1612
|
+
endVar: ev
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
912
1615
|
function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
|
|
913
1616
|
if (!ctx.capturing) return [];
|
|
1617
|
+
if (ctx.capAsTrivia) return [];
|
|
914
1618
|
const i = ind(ctx);
|
|
915
|
-
if (ctx.capAsTrivia) {
|
|
916
|
-
return [`${i}if (_ctx._cstRawChildren) _ctx._cstRawChildren.push({ _tag: 'trivia', value: ${valExpr}, span: { start: ${startExpr}, end: ${endExpr} } })`];
|
|
917
|
-
}
|
|
918
1619
|
const lf = v(ctx, "_lf");
|
|
919
1620
|
return [
|
|
920
1621
|
`${i}if (_ctx._cstLeaves) {`,
|
|
@@ -924,35 +1625,84 @@ function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
|
|
|
924
1625
|
`${i}}`
|
|
925
1626
|
];
|
|
926
1627
|
}
|
|
927
|
-
function
|
|
1628
|
+
function ensureRegexDecl(ctx, optimizedSource, flags) {
|
|
1629
|
+
const f = "y" + flags.replace(/[gy]/g, "");
|
|
1630
|
+
const key = `${optimizedSource}/${f}`;
|
|
1631
|
+
let rName = ctx.regexMap.get(key);
|
|
1632
|
+
if (rName === void 0) {
|
|
1633
|
+
rName = `_re${ctx.regexDecls.length}`;
|
|
1634
|
+
ctx.regexDecls.push(`const ${rName} = /${optimizedSource}/${f}`);
|
|
1635
|
+
ctx.regexMap.set(key, rName);
|
|
1636
|
+
}
|
|
1637
|
+
return rName;
|
|
1638
|
+
}
|
|
1639
|
+
function ensureTriviaFn(ctx) {
|
|
928
1640
|
const trivia2 = ctx.activeTrivia;
|
|
929
|
-
const existing = ctx.
|
|
1641
|
+
const existing = ctx.triviaFnNames.get(trivia2);
|
|
930
1642
|
if (existing) return existing;
|
|
931
|
-
const fnName = `
|
|
1643
|
+
const fnName = `_tf${ctx.triviaFnNames.size}`;
|
|
1644
|
+
ctx.triviaFnNames.set(trivia2, fnName);
|
|
932
1645
|
ctx.triviaCaptureNames.set(trivia2, fnName);
|
|
933
|
-
const
|
|
1646
|
+
const fastKind = analyzeTriviaFastPath(trivia2);
|
|
1647
|
+
const kindIndices = labeledTriviaKindIndices(trivia2);
|
|
1648
|
+
if (fastKind) {
|
|
1649
|
+
ctx.namedFnDecls.push(buildFastTriviaFnDecl(fnName, fastKind, kindIndices ?? void 0));
|
|
1650
|
+
return fnName;
|
|
1651
|
+
}
|
|
1652
|
+
const labeledSpec = analyzeLabeledTrivia(trivia2);
|
|
1653
|
+
if (labeledSpec) {
|
|
1654
|
+
const regexSpec = labeledTriviaRegexArms(trivia2);
|
|
1655
|
+
if (regexSpec) {
|
|
1656
|
+
const reNames = [];
|
|
1657
|
+
for (const arm of regexSpec.arms) {
|
|
1658
|
+
const def = arm.parser._def;
|
|
1659
|
+
if (def.tag !== "regex") break;
|
|
1660
|
+
reNames.push(ensureRegexDecl(ctx, def.optimizedSource, def.flags));
|
|
1661
|
+
}
|
|
1662
|
+
if (reNames.length === regexSpec.arms.length) {
|
|
1663
|
+
ctx.namedFnDecls.push(buildLabeledRegexTriviaFnDecl(fnName, regexSpec, reNames));
|
|
1664
|
+
return fnName;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
const rpStart = ctx.runtimeParsers.length;
|
|
1668
|
+
for (const arm of labeledSpec.arms) {
|
|
1669
|
+
ctx.runtimeParsers.push(arm.parser);
|
|
1670
|
+
}
|
|
1671
|
+
ctx.namedFnDecls.push(buildLabeledRuntimeTriviaFnDecl(fnName, labeledSpec, rpStart));
|
|
1672
|
+
return fnName;
|
|
1673
|
+
}
|
|
1674
|
+
const savedIndent = ctx.indent;
|
|
1675
|
+
const savedFailLabel = ctx.failLabel;
|
|
1676
|
+
const savedTrivia = ctx.activeTrivia;
|
|
1677
|
+
const savedCapAsTrivia = ctx.capAsTrivia;
|
|
934
1678
|
ctx.indent = 2;
|
|
935
|
-
ctx.failLabel = "
|
|
1679
|
+
ctx.failLabel = "_triv";
|
|
936
1680
|
ctx.capAsTrivia = true;
|
|
937
|
-
|
|
1681
|
+
ctx.activeTrivia = void 0;
|
|
938
1682
|
const r = emit(trivia2, ctx, "_pos");
|
|
939
|
-
ctx.indent =
|
|
940
|
-
ctx.failLabel =
|
|
941
|
-
ctx.capAsTrivia =
|
|
942
|
-
|
|
1683
|
+
ctx.indent = savedIndent;
|
|
1684
|
+
ctx.failLabel = savedFailLabel;
|
|
1685
|
+
ctx.capAsTrivia = savedCapAsTrivia;
|
|
1686
|
+
ctx.activeTrivia = savedTrivia;
|
|
943
1687
|
ctx.namedFnDecls.push([
|
|
944
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1688
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
945
1689
|
` let _e = _pos`,
|
|
946
|
-
`
|
|
1690
|
+
` _triv: {`,
|
|
947
1691
|
...r.stmts,
|
|
948
1692
|
` _e = ${r.endVar}`,
|
|
949
1693
|
` }`,
|
|
950
|
-
` if (
|
|
1694
|
+
` if (_cap && _e > _pos) {`,
|
|
1695
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
1696
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
1697
|
+
` }`,
|
|
951
1698
|
` return _e`,
|
|
952
1699
|
`}`
|
|
953
1700
|
].join("\n"));
|
|
954
1701
|
return fnName;
|
|
955
1702
|
}
|
|
1703
|
+
function ensureTriviaCaptureFn(ctx) {
|
|
1704
|
+
return ensureTriviaFn(ctx);
|
|
1705
|
+
}
|
|
956
1706
|
function failStmt(ctx, expected, posExpr) {
|
|
957
1707
|
if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
|
|
958
1708
|
return `${ind(ctx)}return { ok: false, expected: [${expected}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
@@ -968,14 +1718,6 @@ function firstSetCond(codeVar, fs) {
|
|
|
968
1718
|
(r) => r.lo === r.hi ? `${codeVar} === ${r.lo}` : `(${codeVar} >= ${r.lo} && ${codeVar} <= ${r.hi})`
|
|
969
1719
|
).join(" || ");
|
|
970
1720
|
}
|
|
971
|
-
function asIIFE(stmts, valueVar, endVar, startPos, indent) {
|
|
972
|
-
return [
|
|
973
|
-
`(() => {`,
|
|
974
|
-
...stmts,
|
|
975
|
-
`${indent} return { ok: true, value: ${valueVar}, span: { start: ${startPos}, end: ${endVar} } }`,
|
|
976
|
-
`${indent}})()`
|
|
977
|
-
].join("\n");
|
|
978
|
-
}
|
|
979
1721
|
function emitFallible(inner, ctx, pos) {
|
|
980
1722
|
const lbl = v(ctx, "_lbl");
|
|
981
1723
|
const okV = `${lbl}ok`;
|
|
@@ -1041,6 +1783,33 @@ function emitLit(def, ctx, pos) {
|
|
|
1041
1783
|
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1042
1784
|
return { stmts, valueVar: vv, endVar };
|
|
1043
1785
|
}
|
|
1786
|
+
function escapeKeywordRe(s) {
|
|
1787
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1788
|
+
}
|
|
1789
|
+
function emitKeywords(def, ctx, pos) {
|
|
1790
|
+
const alt = def.words.map(escapeKeywordRe).join("|");
|
|
1791
|
+
const boundary = def.boundary ? `(?![${def.boundary}])` : "";
|
|
1792
|
+
const flags = def.caseInsensitive ? "iuy" : "uy";
|
|
1793
|
+
const source = `(?:${alt})${boundary}`;
|
|
1794
|
+
const key = `${source}/${flags}`;
|
|
1795
|
+
let rName = ctx.regexMap.get(key);
|
|
1796
|
+
if (rName === void 0) {
|
|
1797
|
+
rName = `_re${ctx.regexDecls.length}`;
|
|
1798
|
+
ctx.regexDecls.push(`const ${rName} = /${source}/${flags}`);
|
|
1799
|
+
ctx.regexMap.set(key, rName);
|
|
1800
|
+
}
|
|
1801
|
+
const mv = v(ctx, "_m");
|
|
1802
|
+
const vv = v(ctx);
|
|
1803
|
+
const stmts = [
|
|
1804
|
+
`${ind(ctx)}${rName}.lastIndex = ${pos}`,
|
|
1805
|
+
`${ind(ctx)}const ${mv} = ${rName}.exec(input)`,
|
|
1806
|
+
`${ind(ctx)}if (${mv} === null) ${failStmt({ ...ctx, indent: 0 }, '"keyword"', pos).trim()}`,
|
|
1807
|
+
`${ind(ctx)}const ${vv} = ${mv}[0]`
|
|
1808
|
+
];
|
|
1809
|
+
const endVar = `${pos} + ${vv}.length`;
|
|
1810
|
+
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1811
|
+
return { stmts, valueVar: vv, endVar };
|
|
1812
|
+
}
|
|
1044
1813
|
function emitRegex(def, ctx, pos) {
|
|
1045
1814
|
const flags = "y" + def.flags.replace(/[gy]/g, "");
|
|
1046
1815
|
const key = `${def.optimizedSource}/${flags}`;
|
|
@@ -1063,31 +1832,7 @@ function emitRegex(def, ctx, pos) {
|
|
|
1063
1832
|
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1064
1833
|
return { stmts, valueVar: vv, endVar };
|
|
1065
1834
|
}
|
|
1066
|
-
function
|
|
1067
|
-
const trivia2 = ctx.activeTrivia;
|
|
1068
|
-
if (!ctx.namedParsers.has(trivia2)) {
|
|
1069
|
-
const fnName = `_pf${ctx.namedParsers.size}`;
|
|
1070
|
-
ctx.namedParsers.set(trivia2, fnName);
|
|
1071
|
-
const savedIndent = ctx.indent;
|
|
1072
|
-
const savedFailLabel = ctx.failLabel;
|
|
1073
|
-
const savedTrivia = ctx.activeTrivia;
|
|
1074
|
-
ctx.indent = 1;
|
|
1075
|
-
ctx.failLabel = void 0;
|
|
1076
|
-
delete ctx.activeTrivia;
|
|
1077
|
-
const r = emit(trivia2, ctx, "_pos");
|
|
1078
|
-
ctx.indent = savedIndent;
|
|
1079
|
-
ctx.failLabel = savedFailLabel;
|
|
1080
|
-
if (savedTrivia) ctx.activeTrivia = savedTrivia;
|
|
1081
|
-
ctx.namedFnDecls.push([
|
|
1082
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1083
|
-
...r.stmts,
|
|
1084
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
1085
|
-
`}`
|
|
1086
|
-
].join("\n"));
|
|
1087
|
-
}
|
|
1088
|
-
return ctx.namedParsers.get(trivia2);
|
|
1089
|
-
}
|
|
1090
|
-
function emitSeq(def, ctx, pos) {
|
|
1835
|
+
function emitSeqValues(def, ctx, pos) {
|
|
1091
1836
|
const startV = v(ctx, "_start");
|
|
1092
1837
|
const curV = v(ctx, "_cur");
|
|
1093
1838
|
const stmts = [
|
|
@@ -1099,23 +1844,41 @@ function emitSeq(def, ctx, pos) {
|
|
|
1099
1844
|
if (i > 0 && ctx.activeTrivia) {
|
|
1100
1845
|
if (ctx.capturing) {
|
|
1101
1846
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
const
|
|
1105
|
-
const
|
|
1847
|
+
const markV = v(ctx, "_mk");
|
|
1848
|
+
const markTl = v(ctx, "_mktl");
|
|
1849
|
+
const markLog = v(ctx, "_mklg");
|
|
1850
|
+
const scanEndV = v(ctx, "_sne");
|
|
1106
1851
|
stmts.push(
|
|
1107
|
-
`${ind(ctx)}const ${
|
|
1108
|
-
`${ind(ctx)}
|
|
1852
|
+
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
1853
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
1854
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
1855
|
+
`${ind(ctx)}const ${scanEndV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1109
1856
|
);
|
|
1857
|
+
const r2 = emit(def.parsers[i], ctx, scanEndV);
|
|
1858
|
+
stmts.push(...r2.stmts);
|
|
1859
|
+
const endAfterV = v(ctx, "_sea");
|
|
1860
|
+
stmts.push(
|
|
1861
|
+
`${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
|
|
1862
|
+
`${ind(ctx)}if (${endAfterV} > ${scanEndV}) { ${curV} = ${endAfterV} } else { if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; }`
|
|
1863
|
+
);
|
|
1864
|
+
valueVars.push(r2.valueVar);
|
|
1865
|
+
continue;
|
|
1866
|
+
} else {
|
|
1867
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1868
|
+
stmts.push(`${ind(ctx)}${curV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
1110
1869
|
}
|
|
1111
1870
|
}
|
|
1112
1871
|
const r = emit(def.parsers[i], ctx, curV);
|
|
1113
1872
|
stmts.push(...r.stmts, `${ind(ctx)}${curV} = ${r.endVar}`);
|
|
1114
1873
|
valueVars.push(r.valueVar);
|
|
1115
1874
|
}
|
|
1875
|
+
return { stmts, valueVar: valueVars[valueVars.length - 1] ?? "null", endVar: curV, valueVars };
|
|
1876
|
+
}
|
|
1877
|
+
function emitSeq(def, ctx, pos) {
|
|
1878
|
+
const { stmts, endVar, valueVars } = emitSeqValues(def, ctx, pos);
|
|
1116
1879
|
const arrV = v(ctx, "_arr");
|
|
1117
1880
|
stmts.push(`${ind(ctx)}const ${arrV} = [${valueVars.join(", ")}]`);
|
|
1118
|
-
return { stmts, valueVar: arrV, endVar
|
|
1881
|
+
return { stmts, valueVar: arrV, endVar };
|
|
1119
1882
|
}
|
|
1120
1883
|
function emitChoice(def, ctx, pos) {
|
|
1121
1884
|
const allExpected = JSON.stringify(
|
|
@@ -1166,29 +1929,39 @@ function emitGreedyClassify(def, superIndex, allExpected, ctx, pos) {
|
|
|
1166
1929
|
const matchV = v(ctx, "_gm");
|
|
1167
1930
|
const wordV = v(ctx, "_gw");
|
|
1168
1931
|
const endV = v(ctx, "_ge");
|
|
1932
|
+
const valV = v(ctx, "_gcv");
|
|
1169
1933
|
const stmts = [
|
|
1170
1934
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
1171
1935
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
1172
1936
|
`${ind(ctx)}if (${matchV} === null) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`,
|
|
1173
1937
|
`${ind(ctx)}const ${wordV} = ${matchV}[0]`,
|
|
1174
|
-
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length
|
|
1938
|
+
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`,
|
|
1939
|
+
`${ind(ctx)}let ${valV}`
|
|
1175
1940
|
];
|
|
1941
|
+
let first = true;
|
|
1176
1942
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
1177
1943
|
if (i === superIndex) continue;
|
|
1178
1944
|
const p = def.parsers[i];
|
|
1179
1945
|
const litVal = getCoreLiteralValue(p);
|
|
1180
1946
|
if (litVal === null) continue;
|
|
1181
|
-
|
|
1947
|
+
const kw = first ? "if" : "else if";
|
|
1948
|
+
first = false;
|
|
1949
|
+
stmts.push(`${ind(ctx)}${kw} (${wordV} === ${JSON.stringify(litVal)}) {`);
|
|
1182
1950
|
ctx.indent++;
|
|
1183
1951
|
const tR = emitTransformChain(p, JSON.stringify(litVal), endV, pos, ctx);
|
|
1184
|
-
stmts.push(...
|
|
1185
|
-
stmts.push(`${ind(ctx)}
|
|
1952
|
+
stmts.push(...emitLeafCapture(ctx, JSON.stringify(litVal), pos, endV));
|
|
1953
|
+
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}`);
|
|
1186
1954
|
ctx.indent--;
|
|
1187
1955
|
stmts.push(`${ind(ctx)}}`);
|
|
1188
1956
|
}
|
|
1189
1957
|
const rR = emitTransformChain(superParser, wordV, endV, pos, ctx);
|
|
1190
|
-
|
|
1191
|
-
|
|
1958
|
+
const regexKw = first ? "if" : "else";
|
|
1959
|
+
stmts.push(`${ind(ctx)}${regexKw} {`);
|
|
1960
|
+
ctx.indent++;
|
|
1961
|
+
stmts.push(...emitLeafCapture(ctx, wordV, pos, endV), ...rR.stmts, `${ind(ctx)}${valV} = ${rR.valueVar}`);
|
|
1962
|
+
ctx.indent--;
|
|
1963
|
+
stmts.push(`${ind(ctx)}}`);
|
|
1964
|
+
return { stmts, valueVar: valV, endVar: endV };
|
|
1192
1965
|
}
|
|
1193
1966
|
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
1194
1967
|
const valV = v(ctx, "_llv");
|
|
@@ -1202,10 +1975,15 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
1202
1975
|
const litCond = emitLiteralCondition(litVal, pos);
|
|
1203
1976
|
const kw = first ? "if" : "else if";
|
|
1204
1977
|
first = false;
|
|
1978
|
+
const litEnd = `${pos} + ${litLen}`;
|
|
1205
1979
|
stmts.push(`${ind(ctx)}${kw} (${litCond}) {`);
|
|
1206
1980
|
ctx.indent++;
|
|
1207
|
-
const tR = emitTransformChain(p, JSON.stringify(litVal),
|
|
1208
|
-
stmts.push(
|
|
1981
|
+
const tR = emitTransformChain(p, JSON.stringify(litVal), litEnd, pos, ctx);
|
|
1982
|
+
stmts.push(
|
|
1983
|
+
...emitLeafCapture(ctx, JSON.stringify(litVal), pos, litEnd),
|
|
1984
|
+
...tR.stmts,
|
|
1985
|
+
`${ind(ctx)}${valV} = ${tR.valueVar}; ${endV} = ${litEnd}`
|
|
1986
|
+
);
|
|
1209
1987
|
ctx.indent--;
|
|
1210
1988
|
stmts.push(`${ind(ctx)}}`);
|
|
1211
1989
|
}
|
|
@@ -1213,67 +1991,66 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
1213
1991
|
return { stmts, valueVar: valV, endVar: endV };
|
|
1214
1992
|
}
|
|
1215
1993
|
function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
1216
|
-
const
|
|
1217
|
-
const
|
|
1994
|
+
const resValV = v(ctx, "_crv");
|
|
1995
|
+
const resEndV = v(ctx, "_cre");
|
|
1996
|
+
const resOkV = v(ctx, "_crok");
|
|
1997
|
+
const ind0 = ind(ctx);
|
|
1998
|
+
const stmts = [
|
|
1999
|
+
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`
|
|
2000
|
+
];
|
|
1218
2001
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
1219
2002
|
const p = def.parsers[i];
|
|
1220
2003
|
const gate = def.gates[i];
|
|
1221
2004
|
const autoNot = def.autoNot[i];
|
|
1222
|
-
const savedIndent = ctx.indent;
|
|
1223
|
-
const savedFailLabel = ctx.failLabel;
|
|
1224
|
-
ctx.indent = 0;
|
|
1225
|
-
ctx.failLabel = void 0;
|
|
1226
|
-
const r = emit(p, ctx, pos);
|
|
1227
|
-
ctx.indent = savedIndent;
|
|
1228
|
-
ctx.failLabel = savedFailLabel;
|
|
1229
|
-
const iife = asIIFE(r.stmts, r.valueVar, r.endVar, pos, ind(ctx));
|
|
1230
2005
|
let gateCond = null;
|
|
1231
2006
|
if (gate) {
|
|
1232
2007
|
const gateIdx = ctx.mapFns.length;
|
|
1233
2008
|
ctx.mapFns.push(gate);
|
|
1234
2009
|
gateCond = `_mf[${gateIdx}](_ctx.state)`;
|
|
1235
2010
|
}
|
|
1236
|
-
const skipCond = gateCond ? `!${
|
|
2011
|
+
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
1237
2012
|
const markLeaves = ctx.capturing ? v(ctx, "_cml") : null;
|
|
1238
2013
|
const markRaw = ctx.capturing ? v(ctx, "_cmr") : null;
|
|
1239
|
-
const
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
const
|
|
2014
|
+
const markTl = ctx.capturing ? v(ctx, "_cmtl") : null;
|
|
2015
|
+
const markLog = ctx.capturing ? v(ctx, "_cmlg") : null;
|
|
2016
|
+
const rollback = markLeaves ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLeaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRaw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}` : "";
|
|
2017
|
+
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
2018
|
+
ctx.indent++;
|
|
2019
|
+
const ind1 = ind(ctx);
|
|
2020
|
+
if (markLeaves) {
|
|
2021
|
+
stmts.push(
|
|
2022
|
+
`${ind1}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
2023
|
+
`${ind1}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
2024
|
+
`${ind1}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
2025
|
+
`${ind1}const ${markLog} = _ctx._triviaLog?.length ?? 0`
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
2029
|
+
stmts.push(...armStmts);
|
|
2030
|
+
ctx.indent--;
|
|
1245
2031
|
if (autoNot && autoNot.length > 0) {
|
|
1246
|
-
const tmp = v(ctx, "_ct");
|
|
1247
2032
|
const anCode = v(ctx, "_anc");
|
|
1248
2033
|
const rejectCond = autoNot.map(
|
|
1249
|
-
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${
|
|
2034
|
+
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
|
|
1250
2035
|
).join(" || ");
|
|
1251
|
-
stmts.push(`${ind(ctx)}if (${skipCond}) {`);
|
|
1252
|
-
stmts.push(...markStmts);
|
|
1253
2036
|
stmts.push(
|
|
1254
|
-
`${
|
|
1255
|
-
`${ind(ctx)} if (${tmp}?.ok) { const ${anCode} = ${tmp}.span.end < input.length ? input.charCodeAt(${tmp}.span.end) : -1; if (!(${rejectCond})) ${resV} = ${tmp} }`
|
|
2037
|
+
`${ind0} if (${okVar}) { const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1; if (!(${rejectCond})) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true } }`
|
|
1256
2038
|
);
|
|
1257
|
-
if (
|
|
1258
|
-
stmts.push(`${ind(ctx)}}`);
|
|
2039
|
+
if (rollback) stmts.push(`${ind0} if (!${resOkV}) { ${rollback} }`);
|
|
1259
2040
|
} else {
|
|
1260
|
-
stmts.push(`${
|
|
1261
|
-
stmts.push(
|
|
1262
|
-
stmts.push(`${ind(ctx)} try { ${resV} = ${iife} } catch {}`);
|
|
1263
|
-
if (rollbackStmt) stmts.push(rollbackStmt);
|
|
1264
|
-
stmts.push(`${ind(ctx)}}`);
|
|
2041
|
+
stmts.push(`${ind0} if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
2042
|
+
if (rollback) stmts.push(`${ind0} else { ${rollback} }`);
|
|
1265
2043
|
}
|
|
2044
|
+
stmts.push(`${ind0}}`);
|
|
1266
2045
|
}
|
|
1267
|
-
stmts.push(`${
|
|
1268
|
-
return { stmts, valueVar:
|
|
2046
|
+
stmts.push(`${ind0}if (!${resOkV}) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
|
|
2047
|
+
return { stmts, valueVar: resValV, endVar: resEndV };
|
|
1269
2048
|
}
|
|
1270
2049
|
function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
1271
|
-
if (
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
1276
|
-
}
|
|
2050
|
+
if (strategy.tag === "greedyClassify")
|
|
2051
|
+
return emitGreedyClassify(def, strategy.superIndex, allExpected, ctx, pos);
|
|
2052
|
+
if (strategy.tag === "literalsLongestFirst")
|
|
2053
|
+
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
1277
2054
|
return emitFirstMatch(def, allExpected, ctx, pos);
|
|
1278
2055
|
}
|
|
1279
2056
|
function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
@@ -1326,27 +2103,28 @@ function emitMany(def, ctx, pos) {
|
|
|
1326
2103
|
if (ctx.capturing) {
|
|
1327
2104
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1328
2105
|
const markV = v(ctx, "_mk");
|
|
2106
|
+
const markTl = v(ctx, "_mktl");
|
|
2107
|
+
const markLog = v(ctx, "_mklg");
|
|
1329
2108
|
const npV = v(ctx, "_np");
|
|
1330
2109
|
stmts.push(
|
|
1331
2110
|
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
1332
|
-
`${ind(ctx)}const ${
|
|
2111
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2112
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2113
|
+
`${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1333
2114
|
);
|
|
1334
2115
|
itemPos = npV;
|
|
1335
|
-
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
2116
|
+
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
|
|
1336
2117
|
} else {
|
|
1337
2118
|
const trivFn = ensureTriviaFn(ctx);
|
|
1338
2119
|
const npV = v(ctx, "_np");
|
|
1339
|
-
stmts.push(
|
|
1340
|
-
`${ind(ctx)}let ${npV} = ${curV}`,
|
|
1341
|
-
`${ind(ctx)}{ const _trv = ${trivFn}(input, ${npV}, _ctx); if (_trv.ok) ${npV} = _trv.span.end }`
|
|
1342
|
-
);
|
|
2120
|
+
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
1343
2121
|
itemPos = npV;
|
|
1344
2122
|
}
|
|
1345
2123
|
}
|
|
1346
2124
|
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
1347
2125
|
stmts.push(
|
|
1348
2126
|
...iterStmts,
|
|
1349
|
-
`${ind(ctx)}if (!${iterOk} || ${iterEnd}
|
|
2127
|
+
`${ind(ctx)}if (!${iterOk} || ${iterEnd} <= ${itemPos}) { ${rollback}break }`,
|
|
1350
2128
|
`${ind(ctx)}${arrV}.push(${iterVal})`,
|
|
1351
2129
|
`${ind(ctx)}${curV} = ${iterEnd}`
|
|
1352
2130
|
);
|
|
@@ -1383,55 +2161,70 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
1383
2161
|
`${ind(ctx)}while (${curV} < input.length) {`
|
|
1384
2162
|
);
|
|
1385
2163
|
ctx.indent++;
|
|
1386
|
-
let rollback = "";
|
|
1387
|
-
if (ctx.capturing) {
|
|
1388
|
-
const markV = v(ctx, "_mk");
|
|
1389
|
-
stmts.push(`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`);
|
|
1390
|
-
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
1391
|
-
}
|
|
1392
2164
|
let sepAtPos = curV;
|
|
1393
2165
|
if (ctx.activeTrivia) {
|
|
1394
2166
|
if (ctx.capturing) {
|
|
1395
2167
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
} else {
|
|
1400
|
-
const trivFn = ensureTriviaFn(ctx);
|
|
2168
|
+
const markV = v(ctx, "_mk");
|
|
2169
|
+
const markTl = v(ctx, "_mktl");
|
|
2170
|
+
const markLog = v(ctx, "_mklg");
|
|
1401
2171
|
const spV = v(ctx, "_sp");
|
|
1402
2172
|
stmts.push(
|
|
1403
|
-
`${ind(ctx)}
|
|
1404
|
-
`${ind(ctx)}
|
|
2173
|
+
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
2174
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2175
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2176
|
+
`${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1405
2177
|
);
|
|
1406
2178
|
sepAtPos = spV;
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
if (ctx.capturing) {
|
|
1414
|
-
const capFn = ensureTriviaCaptureFn(ctx);
|
|
2179
|
+
const sepRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
|
|
2180
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2181
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sepRollback}break }`);
|
|
2182
|
+
const mark2V = v(ctx, "_mk2");
|
|
2183
|
+
const mark2Tl = v(ctx, "_mktl2");
|
|
2184
|
+
const mark2Log = v(ctx, "_mklg2");
|
|
1415
2185
|
const npV = v(ctx, "_np");
|
|
1416
|
-
stmts.push(
|
|
1417
|
-
|
|
2186
|
+
stmts.push(
|
|
2187
|
+
`${ind(ctx)}const ${mark2V} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
2188
|
+
`${ind(ctx)}const ${mark2Tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2189
|
+
`${ind(ctx)}const ${mark2Log} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2190
|
+
`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`
|
|
2191
|
+
);
|
|
2192
|
+
const nextRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mark2V}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mark2Tl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mark2Log}; `;
|
|
2193
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
2194
|
+
stmts.push(
|
|
2195
|
+
...nextStmts,
|
|
2196
|
+
`${ind(ctx)}if (!${nextOk}) { ${nextRollback}break }`,
|
|
2197
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2198
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
2199
|
+
);
|
|
1418
2200
|
} else {
|
|
1419
2201
|
const trivFn = ensureTriviaFn(ctx);
|
|
2202
|
+
const spV = v(ctx, "_sp");
|
|
2203
|
+
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
2204
|
+
sepAtPos = spV;
|
|
2205
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2206
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
1420
2207
|
const npV = v(ctx, "_np");
|
|
2208
|
+
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
2209
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
1421
2210
|
stmts.push(
|
|
1422
|
-
|
|
1423
|
-
`${ind(ctx)}
|
|
2211
|
+
...nextStmts,
|
|
2212
|
+
`${ind(ctx)}if (!${nextOk}) break`,
|
|
2213
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2214
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
1424
2215
|
);
|
|
1425
|
-
nextAtPos = npV;
|
|
1426
2216
|
}
|
|
2217
|
+
} else {
|
|
2218
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2219
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2220
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
|
|
2221
|
+
stmts.push(
|
|
2222
|
+
...nextStmts,
|
|
2223
|
+
`${ind(ctx)}if (!${nextOk}) break`,
|
|
2224
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2225
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
2226
|
+
);
|
|
1427
2227
|
}
|
|
1428
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, nextAtPos);
|
|
1429
|
-
stmts.push(
|
|
1430
|
-
...nextStmts,
|
|
1431
|
-
`${ind(ctx)}if (!${nextOk}) { ${rollback}break }`,
|
|
1432
|
-
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
1433
|
-
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
1434
|
-
);
|
|
1435
2228
|
ctx.indent--;
|
|
1436
2229
|
stmts.push(`${ind(ctx)}}`);
|
|
1437
2230
|
ctx.indent--;
|
|
@@ -1493,27 +2286,33 @@ function emitNot(def, ctx, pos) {
|
|
|
1493
2286
|
};
|
|
1494
2287
|
}
|
|
1495
2288
|
function emitNode(def, ctx, pos) {
|
|
1496
|
-
const
|
|
1497
|
-
|
|
1498
|
-
|
|
2289
|
+
const mkType = analyzeMkInlineBuild(def);
|
|
2290
|
+
let buildIdx = null;
|
|
2291
|
+
if (!mkType) {
|
|
2292
|
+
buildIdx = ctx.buildFns.length;
|
|
2293
|
+
ctx.buildFns.push(def.build);
|
|
2294
|
+
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
2295
|
+
}
|
|
1499
2296
|
const i = ind(ctx);
|
|
1500
2297
|
const chV = v(ctx, "_ch");
|
|
1501
2298
|
const rawV = v(ctx, "_raw");
|
|
1502
|
-
const
|
|
2299
|
+
const tlV = v(ctx, "_tl");
|
|
2300
|
+
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
1503
2301
|
const stmts = [
|
|
1504
|
-
`${i}const ${chV} = [], ${rawV} = []`,
|
|
1505
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia`,
|
|
1506
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true`
|
|
2302
|
+
`${i}const ${chV} = [], ${rawV} = [], ${tlV} = []`,
|
|
2303
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
2304
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${tlV}`
|
|
1507
2305
|
];
|
|
1508
2306
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
1509
2307
|
stmts.push(...innerStmts);
|
|
1510
|
-
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}`);
|
|
2308
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
|
|
1511
2309
|
stmts.push(`${i}if (!${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"node"', pos).trim()}`);
|
|
2310
|
+
const stV = v(ctx, "_nst");
|
|
2311
|
+
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
1512
2312
|
const ndV = v(ctx, "_nd");
|
|
2313
|
+
const ndExpr = mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `_build[${buildIdx}](${chV}, ${rawV}, { start: ${pos}, end: ${endVar} }, ${tlV}, ${stV})`;
|
|
1513
2314
|
stmts.push(
|
|
1514
|
-
`${i}const ${ndV} =
|
|
1515
|
-
// Record into the caller's collectors (the node in children; the node, or a
|
|
1516
|
-
// spanned leaf if build collapsed to a non-node value, in rawChildren).
|
|
2315
|
+
`${i}const ${ndV} = ${ndExpr}`,
|
|
1517
2316
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
1518
2317
|
`${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} } })`
|
|
1519
2318
|
);
|
|
@@ -1547,31 +2346,14 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
1547
2346
|
const savedIndent = ctx.indent;
|
|
1548
2347
|
const savedFailLabel = ctx.failLabel;
|
|
1549
2348
|
ctx.indent = 1;
|
|
1550
|
-
ctx.failLabel =
|
|
2349
|
+
ctx.failLabel = "_pfail";
|
|
1551
2350
|
const r = emit(resolved, ctx, "_pos");
|
|
1552
2351
|
ctx.indent = savedIndent;
|
|
1553
2352
|
ctx.failLabel = savedFailLabel;
|
|
1554
|
-
ctx.
|
|
1555
|
-
`function ${fnName2}(input, _pos, _ctx) {`,
|
|
1556
|
-
...r.stmts,
|
|
1557
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
1558
|
-
`}`
|
|
1559
|
-
].join("\n"));
|
|
2353
|
+
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar);
|
|
1560
2354
|
}
|
|
1561
2355
|
const fnName = ctx.namedParsers.get(p);
|
|
1562
|
-
|
|
1563
|
-
const vv = v(ctx, "_pfv");
|
|
1564
|
-
const ev = v(ctx, "_pfe");
|
|
1565
|
-
return {
|
|
1566
|
-
stmts: [
|
|
1567
|
-
`${ind(ctx)}const ${rv} = ${fnName}(input, ${pos}, _ctx)`,
|
|
1568
|
-
`${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"parser"', pos).trim()}`,
|
|
1569
|
-
`${ind(ctx)}const ${vv} = ${rv}.value`,
|
|
1570
|
-
`${ind(ctx)}const ${ev} = ${rv}.span.end`
|
|
1571
|
-
],
|
|
1572
|
-
valueVar: vv,
|
|
1573
|
-
endVar: ev
|
|
1574
|
-
};
|
|
2356
|
+
return emitNamedFnCall(ctx, fnName, pos, '"parser"');
|
|
1575
2357
|
}
|
|
1576
2358
|
function emitRecover(def, ctx, pos) {
|
|
1577
2359
|
const { stmts: innerStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
@@ -1607,6 +2389,8 @@ function emit(p, ctx, pos) {
|
|
|
1607
2389
|
return emitLit(def, ctx, pos);
|
|
1608
2390
|
case "regex":
|
|
1609
2391
|
return emitRegex(def, ctx, pos);
|
|
2392
|
+
case "keywords":
|
|
2393
|
+
return emitKeywords(def, ctx, pos);
|
|
1610
2394
|
case "sequence":
|
|
1611
2395
|
return emitSeq(def, ctx, pos);
|
|
1612
2396
|
case "choice":
|
|
@@ -1619,7 +2403,31 @@ function emit(p, ctx, pos) {
|
|
|
1619
2403
|
case "sepBy":
|
|
1620
2404
|
return emitSepBy(p, def, ctx, pos);
|
|
1621
2405
|
case "transform": {
|
|
2406
|
+
const fnSrc = transformFnSource(def.fn, def.fnSrc);
|
|
2407
|
+
if (fnSrc && def.parser._def.tag === "sequence") {
|
|
2408
|
+
const seqR = emitSeqValues(def.parser._def, ctx, pos);
|
|
2409
|
+
const inlined = tryInlineDestructureTransform(fnSrc, seqR.valueVars);
|
|
2410
|
+
if (inlined) {
|
|
2411
|
+
const mv2 = v(ctx, "_mapped");
|
|
2412
|
+
return {
|
|
2413
|
+
stmts: [...seqR.stmts, `${ind(ctx)}const ${mv2} = ${inlined}`],
|
|
2414
|
+
valueVar: mv2,
|
|
2415
|
+
endVar: seqR.endVar
|
|
2416
|
+
};
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
1622
2419
|
const inner = emit(def.parser, ctx, pos);
|
|
2420
|
+
if (fnSrc) {
|
|
2421
|
+
const unary = tryInlineUnaryTransform(fnSrc, inner.valueVar);
|
|
2422
|
+
if (unary) {
|
|
2423
|
+
const mv2 = v(ctx, "_mapped");
|
|
2424
|
+
return {
|
|
2425
|
+
stmts: [...inner.stmts, `${ind(ctx)}const ${mv2} = ${unary}`],
|
|
2426
|
+
valueVar: mv2,
|
|
2427
|
+
endVar: inner.endVar
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
1623
2431
|
const fnIdx = ctx.mapFns.length;
|
|
1624
2432
|
ctx.mapFns.push(def.fn);
|
|
1625
2433
|
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
@@ -1655,12 +2463,20 @@ function emit(p, ctx, pos) {
|
|
|
1655
2463
|
return emitLazy(p, def, ctx, pos);
|
|
1656
2464
|
case "trivia":
|
|
1657
2465
|
return emit(def.parser, ctx, pos);
|
|
2466
|
+
case "label":
|
|
2467
|
+
return emit(def.parser, ctx, pos);
|
|
1658
2468
|
case "grammar": {
|
|
1659
2469
|
const savedTrivia = ctx.activeTrivia;
|
|
1660
|
-
|
|
2470
|
+
const savedKindLabels = ctx.triviaKindLabels;
|
|
2471
|
+
if (def.triviaParser) {
|
|
2472
|
+
ctx.activeTrivia = def.triviaParser;
|
|
2473
|
+
if (def.triviaParser._meta.triviaKindLabels) {
|
|
2474
|
+
ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
1661
2477
|
const r = emit(def.parser, ctx, pos);
|
|
1662
|
-
|
|
1663
|
-
|
|
2478
|
+
ctx.activeTrivia = savedTrivia;
|
|
2479
|
+
ctx.triviaKindLabels = savedKindLabels;
|
|
1664
2480
|
return r;
|
|
1665
2481
|
}
|
|
1666
2482
|
case "not":
|
|
@@ -1695,27 +2511,22 @@ function emit(p, ctx, pos) {
|
|
|
1695
2511
|
const savedIndent = ctx.indent;
|
|
1696
2512
|
const savedFailLabel = ctx.failLabel;
|
|
1697
2513
|
ctx.indent = 1;
|
|
1698
|
-
ctx.failLabel =
|
|
2514
|
+
ctx.failLabel = "_pfail";
|
|
1699
2515
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
1700
2516
|
ctx.indent = savedIndent;
|
|
1701
2517
|
ctx.failLabel = savedFailLabel;
|
|
1702
|
-
ctx.
|
|
1703
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1704
|
-
...innerR.stmts,
|
|
1705
|
-
` return { ok: true, value: ${innerR.valueVar}, span: { start: _pos, end: ${innerR.endVar} } }`,
|
|
1706
|
-
`}`
|
|
1707
|
-
].join("\n"));
|
|
2518
|
+
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
1708
2519
|
}
|
|
1709
2520
|
const fn = ctx.namedParsers.get(innerParser);
|
|
1710
2521
|
const rv = v(ctx, "_wcr");
|
|
1711
|
-
const vv = v(ctx);
|
|
2522
|
+
const vv = v(ctx, "_wcv");
|
|
1712
2523
|
const ev = v(ctx, "_wce");
|
|
1713
2524
|
return {
|
|
1714
2525
|
stmts: [
|
|
1715
|
-
`${ind(ctx)}const ${rv} =
|
|
1716
|
-
`${ind(ctx)}
|
|
1717
|
-
`${ind(ctx)}
|
|
1718
|
-
`${ind(ctx)}const ${ev} = ${
|
|
2526
|
+
`${ind(ctx)}const ${rv} = { ..._ctx, state: _mf[${evIdx}]() }`,
|
|
2527
|
+
`${ind(ctx)}const ${vv} = ${fn}(input, ${pos}, ${rv})`,
|
|
2528
|
+
`${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, '"withCtx"', pos).trim()}`,
|
|
2529
|
+
`${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
|
|
1719
2530
|
],
|
|
1720
2531
|
valueVar: vv,
|
|
1721
2532
|
endVar: ev
|
|
@@ -1741,6 +2552,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
1741
2552
|
}
|
|
1742
2553
|
case "grammar":
|
|
1743
2554
|
case "trivia":
|
|
2555
|
+
case "label":
|
|
1744
2556
|
case "optional":
|
|
1745
2557
|
case "many":
|
|
1746
2558
|
case "oneOrMore":
|
|
@@ -1764,7 +2576,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
1764
2576
|
return false;
|
|
1765
2577
|
}
|
|
1766
2578
|
}
|
|
1767
|
-
function compile(
|
|
2579
|
+
function compile(combinator, mapFnSources) {
|
|
1768
2580
|
const ctx = {
|
|
1769
2581
|
vars: 0,
|
|
1770
2582
|
indent: 1,
|
|
@@ -1778,15 +2590,18 @@ function compile(parser2, mapFnSources) {
|
|
|
1778
2590
|
needsCollator: false,
|
|
1779
2591
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
1780
2592
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
2593
|
+
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
1781
2594
|
namedFnDecls: [],
|
|
1782
|
-
capturing: hasNodeDef(
|
|
2595
|
+
capturing: hasNodeDef(combinator)
|
|
1783
2596
|
};
|
|
1784
|
-
const r = emit(
|
|
2597
|
+
const r = emit(combinator, ctx, "_pos");
|
|
1785
2598
|
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
1786
2599
|
` : "";
|
|
2600
|
+
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
1787
2601
|
const source = [
|
|
1788
2602
|
...ctx.regexDecls,
|
|
1789
2603
|
"",
|
|
2604
|
+
...namedPrelude,
|
|
1790
2605
|
...ctx.namedFnDecls,
|
|
1791
2606
|
`${collatorDecl}function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
1792
2607
|
` let pos = _pos`,
|
|
@@ -1797,12 +2612,16 @@ function compile(parser2, mapFnSources) {
|
|
|
1797
2612
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
1798
2613
|
...ctx.regexDecls,
|
|
1799
2614
|
collatorDecl,
|
|
2615
|
+
...namedPrelude,
|
|
1800
2616
|
...ctx.namedFnDecls,
|
|
1801
2617
|
`let pos = _pos`,
|
|
1802
2618
|
...r.stmts,
|
|
1803
2619
|
`return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
1804
2620
|
].join("\n"));
|
|
1805
|
-
const defaultCtx = {
|
|
2621
|
+
const defaultCtx = {
|
|
2622
|
+
trackLines: false,
|
|
2623
|
+
...ctx.triviaKindLabels ? { triviaKindLabels: ctx.triviaKindLabels } : {}
|
|
2624
|
+
};
|
|
1806
2625
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
1807
2626
|
const effectiveSources = mapFnSources ?? derivedSrcs;
|
|
1808
2627
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
@@ -1816,6 +2635,9 @@ function compile(parser2, mapFnSources) {
|
|
|
1816
2635
|
parse(input, pos = 0) {
|
|
1817
2636
|
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
|
|
1818
2637
|
},
|
|
2638
|
+
parseWithContext(input, parseCtx, pos = 0) {
|
|
2639
|
+
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
|
|
2640
|
+
},
|
|
1819
2641
|
parseWithErrors(input, pos = 0) {
|
|
1820
2642
|
const errors = [];
|
|
1821
2643
|
const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
|
|
@@ -1838,12 +2660,14 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
1838
2660
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
1839
2661
|
const needsWrapper = ctx.regexDecls.length > 0 || !!collatorDecl || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl;
|
|
1840
2662
|
if (!needsWrapper) return innerFn;
|
|
2663
|
+
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
1841
2664
|
return [
|
|
1842
2665
|
`/* @__PURE__ */ (() => {`,
|
|
1843
2666
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
1844
2667
|
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
1845
2668
|
mfDecl,
|
|
1846
2669
|
buildDecl,
|
|
2670
|
+
...namedPrelude.map((l) => ` ${l}`),
|
|
1847
2671
|
...ctx.namedFnDecls.flatMap((f) => f.split("\n").map((l) => ` ${l}`)),
|
|
1848
2672
|
` return ${innerFn}`,
|
|
1849
2673
|
`})()`
|
|
@@ -1865,10 +2689,9 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
1865
2689
|
let cur = pos;
|
|
1866
2690
|
const probeCtx = { trackLines: ctx.trackLines, state: ctx.state };
|
|
1867
2691
|
const emit2 = (end) => {
|
|
1868
|
-
if (end > pos && (ctx
|
|
2692
|
+
if (end > pos && cstCaptureActive(ctx)) {
|
|
1869
2693
|
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
1870
|
-
|
|
1871
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
2694
|
+
pushCstLeaf(ctx, leaf);
|
|
1872
2695
|
}
|
|
1873
2696
|
};
|
|
1874
2697
|
while (cur < input.length) {
|
|
@@ -1911,16 +2734,22 @@ function balanced(open, close, options = {}) {
|
|
|
1911
2734
|
}
|
|
1912
2735
|
|
|
1913
2736
|
// src/plugin/evaluator.ts
|
|
2737
|
+
function isWordFactory(v2) {
|
|
2738
|
+
return !!v2 && typeof v2 === "object" && v2.tag === "wordFactory";
|
|
2739
|
+
}
|
|
1914
2740
|
var SUPPORTED = {
|
|
1915
2741
|
literal: (...a) => literal(a[0], a[1]),
|
|
1916
2742
|
regex: (...a) => regex(a[0], a[1]),
|
|
2743
|
+
keywords: (...a) => keywords(a[0], a[1]),
|
|
2744
|
+
word: (...a) => word(a[0], a[1]),
|
|
1917
2745
|
sequence: (...a) => sequence(...a),
|
|
1918
2746
|
choice: (...a) => choice(...a),
|
|
1919
2747
|
many: (...a) => many(a[0]),
|
|
1920
2748
|
oneOrMore: (...a) => oneOrMore(a[0]),
|
|
1921
2749
|
optional: (...a) => optional(a[0]),
|
|
1922
2750
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
1923
|
-
trivia: (...a) => trivia(a[0])
|
|
2751
|
+
trivia: (...a) => trivia(a[0]),
|
|
2752
|
+
label: (...a) => label(a[0], a[1])
|
|
1924
2753
|
};
|
|
1925
2754
|
function isScopeEntry(v2) {
|
|
1926
2755
|
return !!v2 && typeof v2 === "object" && "combi" in v2 && "mfSrcs" in v2;
|
|
@@ -1942,6 +2771,33 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
1942
2771
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
1943
2772
|
if (node2.type !== "CallExpression") return null;
|
|
1944
2773
|
const callee = node2.callee;
|
|
2774
|
+
if (callee.type === "CallExpression" && callee.callee.type === "Identifier" && callee.callee.name === "makeWord") {
|
|
2775
|
+
const boundaryArg = callee.arguments[0];
|
|
2776
|
+
const strArg = node2.arguments[0];
|
|
2777
|
+
if (!strArg || strArg.type === "SpreadElement") return null;
|
|
2778
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code, mfs) : "_0-9A-Za-z";
|
|
2779
|
+
const str = anyValue(strArg, scope, code, mfs);
|
|
2780
|
+
if (typeof boundary !== "string" || typeof str !== "string") return null;
|
|
2781
|
+
try {
|
|
2782
|
+
return word(str, boundary);
|
|
2783
|
+
} catch {
|
|
2784
|
+
return null;
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
if (callee.type === "Identifier") {
|
|
2788
|
+
const factory2 = scope.get(callee.name);
|
|
2789
|
+
if (isWordFactory(factory2)) {
|
|
2790
|
+
const [strArg] = node2.arguments;
|
|
2791
|
+
if (!strArg || strArg.type === "SpreadElement") return null;
|
|
2792
|
+
const str = anyValue(strArg, scope, code, mfs);
|
|
2793
|
+
if (typeof str !== "string") return null;
|
|
2794
|
+
try {
|
|
2795
|
+
return word(str, factory2.boundary);
|
|
2796
|
+
} catch {
|
|
2797
|
+
return null;
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
1945
2801
|
if (callee.type !== "Identifier") return null;
|
|
1946
2802
|
if (callee.name === "transform" && code !== void 0 && mfs !== void 0) {
|
|
1947
2803
|
const [parserArg, fnArg] = node2.arguments;
|
|
@@ -2118,9 +2974,27 @@ function anyValue(node2, scope, code, mfs) {
|
|
|
2118
2974
|
if (!propName) return null;
|
|
2119
2975
|
return obj[propName] ?? null;
|
|
2120
2976
|
}
|
|
2121
|
-
if (node2.type === "CallExpression")
|
|
2977
|
+
if (node2.type === "CallExpression") {
|
|
2978
|
+
const callee = node2.callee;
|
|
2979
|
+
if (callee.type === "Identifier" && callee.name === "makeWord") {
|
|
2980
|
+
const boundaryArg = node2.arguments[0];
|
|
2981
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code, mfs) : "_0-9A-Za-z";
|
|
2982
|
+
if (typeof boundary !== "string") return null;
|
|
2983
|
+
return { tag: "wordFactory", boundary };
|
|
2984
|
+
}
|
|
2985
|
+
return exprToCombi(node2, scope, code, mfs);
|
|
2986
|
+
}
|
|
2122
2987
|
return null;
|
|
2123
2988
|
}
|
|
2989
|
+
function evaluateWordFactory(node2, scope, code) {
|
|
2990
|
+
if (node2.type !== "CallExpression") return null;
|
|
2991
|
+
const callee = node2.callee;
|
|
2992
|
+
if (callee.type !== "Identifier" || callee.name !== "makeWord") return null;
|
|
2993
|
+
const boundaryArg = node2.arguments[0];
|
|
2994
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code) : "_0-9A-Za-z";
|
|
2995
|
+
if (typeof boundary !== "string") return null;
|
|
2996
|
+
return { tag: "wordFactory", boundary };
|
|
2997
|
+
}
|
|
2124
2998
|
function evaluateExpr(node2, scope, code, mapFnSources) {
|
|
2125
2999
|
return exprToCombi(node2, scope, code, mapFnSources);
|
|
2126
3000
|
}
|
|
@@ -2278,23 +3152,23 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
2278
3152
|
anyUnresolved = true;
|
|
2279
3153
|
warnings.push(`${id}:${lineOf(pos)} \u2014 ${msg} (running via the interpreter; add the plugin or simplify the declaration to compile it)`);
|
|
2280
3154
|
};
|
|
2281
|
-
const compileRulesFactory = (init,
|
|
3155
|
+
const compileRulesFactory = (init, label2) => {
|
|
2282
3156
|
const args = init.arguments;
|
|
2283
3157
|
const factoryArg = args[0];
|
|
2284
3158
|
if (!factoryArg) {
|
|
2285
|
-
warn(init.start, `${
|
|
3159
|
+
warn(init.start, `${label2}: rules() needs a factory argument`);
|
|
2286
3160
|
return null;
|
|
2287
3161
|
}
|
|
2288
3162
|
const ruleMap = evaluateParserFactory(factoryArg, scope, code, []);
|
|
2289
3163
|
if (!ruleMap) {
|
|
2290
|
-
warn(init.start, `${
|
|
3164
|
+
warn(init.start, `${label2}: rules(...) factory isn't statically evaluable`);
|
|
2291
3165
|
return null;
|
|
2292
3166
|
}
|
|
2293
3167
|
const entries = [];
|
|
2294
3168
|
for (const [ruleKey, rule] of ruleMap) {
|
|
2295
3169
|
const compiled = compile(rule);
|
|
2296
3170
|
if (compiled.inlineExpression === null) {
|
|
2297
|
-
warn(init.start, `${
|
|
3171
|
+
warn(init.start, `${label2}: rule "${ruleKey}" couldn't be inlined`);
|
|
2298
3172
|
return null;
|
|
2299
3173
|
}
|
|
2300
3174
|
entries.push([ruleKey, compiled.inlineExpression]);
|
|
@@ -2338,6 +3212,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
2338
3212
|
const mapFnSources = [];
|
|
2339
3213
|
const parser2 = evaluateExpr(init, scope, code, mapFnSources);
|
|
2340
3214
|
if (parser2 === null) {
|
|
3215
|
+
const wordFactory = evaluateWordFactory(init, scope, code);
|
|
3216
|
+
if (wordFactory) {
|
|
3217
|
+
;
|
|
3218
|
+
scope.set(varName, wordFactory);
|
|
3219
|
+
continue;
|
|
3220
|
+
}
|
|
2341
3221
|
warn(init.start, `"${varName}" references a parseman macro import but isn't a statically-evaluable combinator`);
|
|
2342
3222
|
continue;
|
|
2343
3223
|
}
|