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.js
CHANGED
|
@@ -93,6 +93,151 @@ function failAt(ctx, expected, pos) {
|
|
|
93
93
|
return r;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// src/cst/capture-buffer.ts
|
|
97
|
+
var EMPTY = [];
|
|
98
|
+
var EMPTY_TL = [];
|
|
99
|
+
function cstCaptureActive(ctx) {
|
|
100
|
+
return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
|
|
101
|
+
}
|
|
102
|
+
function beginCstNodeCapture(ctx) {
|
|
103
|
+
const saved = {
|
|
104
|
+
ch: ctx._cstChildren,
|
|
105
|
+
lv: ctx._cstLeaves,
|
|
106
|
+
raw: ctx._cstRawChildren,
|
|
107
|
+
tl: ctx._cstTriviaLog,
|
|
108
|
+
cap: ctx.captureTrivia,
|
|
109
|
+
buf: ctx._cstBuf
|
|
110
|
+
};
|
|
111
|
+
ctx._cstBuf = {};
|
|
112
|
+
ctx._cstChildren = void 0;
|
|
113
|
+
ctx._cstLeaves = void 0;
|
|
114
|
+
ctx._cstRawChildren = void 0;
|
|
115
|
+
ctx._cstTriviaLog = void 0;
|
|
116
|
+
ctx.captureTrivia = true;
|
|
117
|
+
return saved;
|
|
118
|
+
}
|
|
119
|
+
function finishCstBuf(buf) {
|
|
120
|
+
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
121
|
+
const children = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
122
|
+
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
123
|
+
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
124
|
+
return { children, rawChildren, triviaLog };
|
|
125
|
+
}
|
|
126
|
+
function endCstNodeCapture(ctx, saved) {
|
|
127
|
+
const materialized = finishCstBuf(ctx._cstBuf);
|
|
128
|
+
ctx._cstBuf = saved.buf;
|
|
129
|
+
ctx._cstChildren = saved.ch;
|
|
130
|
+
ctx._cstLeaves = saved.lv;
|
|
131
|
+
ctx._cstRawChildren = saved.raw;
|
|
132
|
+
ctx._cstTriviaLog = saved.tl;
|
|
133
|
+
ctx.captureTrivia = saved.cap;
|
|
134
|
+
return materialized;
|
|
135
|
+
}
|
|
136
|
+
function pushCstLeaf(ctx, leaf) {
|
|
137
|
+
pushCstChild(ctx, leaf, leaf);
|
|
138
|
+
}
|
|
139
|
+
function pushCstChild(ctx, built, rawEntry) {
|
|
140
|
+
const b = ctx._cstBuf;
|
|
141
|
+
if (b) {
|
|
142
|
+
if (b.ch) b.ch.push(built);
|
|
143
|
+
else if (b.single !== void 0) {
|
|
144
|
+
b.ch = [b.single, built];
|
|
145
|
+
b.single = void 0;
|
|
146
|
+
} else b.single = built;
|
|
147
|
+
if (b.raw) b.raw.push(rawEntry);
|
|
148
|
+
else if (b.rawSingle !== void 0) {
|
|
149
|
+
b.raw = [b.rawSingle, rawEntry];
|
|
150
|
+
b.rawSingle = void 0;
|
|
151
|
+
} else b.rawSingle = rawEntry;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (ctx._cstChildren) ctx._cstChildren.push(built);
|
|
155
|
+
else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
|
|
156
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry);
|
|
157
|
+
}
|
|
158
|
+
function cstRawLen(ctx) {
|
|
159
|
+
const b = ctx._cstBuf;
|
|
160
|
+
if (b) {
|
|
161
|
+
if (b.raw) return b.raw.length;
|
|
162
|
+
return b.rawSingle !== void 0 ? 1 : 0;
|
|
163
|
+
}
|
|
164
|
+
return ctx._cstRawChildren?.length ?? 0;
|
|
165
|
+
}
|
|
166
|
+
function cstLeavesLen(ctx) {
|
|
167
|
+
const b = ctx._cstBuf;
|
|
168
|
+
if (b) {
|
|
169
|
+
if (b.ch) return b.ch.length;
|
|
170
|
+
return b.single !== void 0 ? 1 : 0;
|
|
171
|
+
}
|
|
172
|
+
return ctx._cstLeaves?.length ?? 0;
|
|
173
|
+
}
|
|
174
|
+
function cstTlLen(ctx) {
|
|
175
|
+
const b = ctx._cstBuf;
|
|
176
|
+
if (b) return b.tl?.length ?? 0;
|
|
177
|
+
return ctx._cstTriviaLog?.length ?? 0;
|
|
178
|
+
}
|
|
179
|
+
function saveCstMark(ctx) {
|
|
180
|
+
return {
|
|
181
|
+
raw: cstRawLen(ctx),
|
|
182
|
+
tlog: cstTlLen(ctx),
|
|
183
|
+
leaves: cstLeavesLen(ctx)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
187
|
+
const arr = b[keyMulti];
|
|
188
|
+
if (arr) {
|
|
189
|
+
if (len === 0) b[keyMulti] = void 0;
|
|
190
|
+
else if (len === 1) {
|
|
191
|
+
b[keySingle] = arr[0];
|
|
192
|
+
b[keyMulti] = void 0;
|
|
193
|
+
} else arr.length = len;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (len === 0) b[keySingle] = void 0;
|
|
197
|
+
}
|
|
198
|
+
function rollbackCstCapture(ctx, mark) {
|
|
199
|
+
const b = ctx._cstBuf;
|
|
200
|
+
if (b) {
|
|
201
|
+
rollbackBufList(b, "raw", "rawSingle", mark.raw);
|
|
202
|
+
rollbackBufList(b, "ch", "single", mark.leaves);
|
|
203
|
+
if (b.tl) {
|
|
204
|
+
if (mark.tlog === 0) b.tl = void 0;
|
|
205
|
+
else b.tl.length = mark.tlog;
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
210
|
+
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
211
|
+
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
212
|
+
}
|
|
213
|
+
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
214
|
+
const insertIdx = cstRawLen(ctx);
|
|
215
|
+
const b = ctx._cstBuf;
|
|
216
|
+
const withKind = ctx.triviaKindLabels !== void 0 && kindIndex !== void 0;
|
|
217
|
+
if (b) {
|
|
218
|
+
if (!b.tl) {
|
|
219
|
+
b.tl = withKind ? [start, end, insertIdx, kindIndex] : [start, end, insertIdx];
|
|
220
|
+
} else if (withKind) {
|
|
221
|
+
b.tl.push(start, end, insertIdx, kindIndex);
|
|
222
|
+
} else {
|
|
223
|
+
b.tl.push(start, end, insertIdx);
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (ctx._cstTriviaLog) {
|
|
228
|
+
if (withKind) ctx._cstTriviaLog.push(start, end, insertIdx, kindIndex);
|
|
229
|
+
else ctx._cstTriviaLog.push(start, end, insertIdx);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function pushTriviaLogEntry(ctx, start, end, kindIndex) {
|
|
233
|
+
if (!ctx._triviaLog) return;
|
|
234
|
+
if (ctx.triviaKindLabels !== void 0 && kindIndex !== void 0) {
|
|
235
|
+
ctx._triviaLog.push(start, end, kindIndex);
|
|
236
|
+
} else {
|
|
237
|
+
ctx._triviaLog.push(start, end);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
96
241
|
// src/combinators/literal.ts
|
|
97
242
|
var _collatorCache = null;
|
|
98
243
|
function collator() {
|
|
@@ -132,8 +277,7 @@ function literal(value, opts = {}) {
|
|
|
132
277
|
if (matched) {
|
|
133
278
|
const span = { start: pos, end };
|
|
134
279
|
const leaf = { _tag: "leaf", value: slice, span };
|
|
135
|
-
if (ctx
|
|
136
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
280
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
137
281
|
return { ok: true, value: slice, span };
|
|
138
282
|
}
|
|
139
283
|
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
@@ -275,109 +419,60 @@ function regex(pattern, flags = "") {
|
|
|
275
419
|
}
|
|
276
420
|
const span = { start: pos, end: pos + m[0].length };
|
|
277
421
|
const leaf = { _tag: "leaf", value: m[0], span };
|
|
278
|
-
if (ctx
|
|
279
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
422
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
280
423
|
return { ok: true, value: m[0], span };
|
|
281
424
|
}
|
|
282
425
|
};
|
|
283
426
|
}
|
|
284
427
|
|
|
285
|
-
// src/combinators/
|
|
286
|
-
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const out = ctx._cstRawChildren;
|
|
312
|
-
return {
|
|
313
|
-
end: tr2.span.end,
|
|
314
|
-
commit: () => {
|
|
315
|
-
for (const tok of sink) {
|
|
316
|
-
if (tok._tag === "leaf" && tok.span.end > tok.span.start) {
|
|
317
|
-
out.push({ _tag: "trivia", value: tok.value, span: tok.span });
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
return { end: cur, commit: NOOP_COMMIT };
|
|
324
|
-
}
|
|
325
|
-
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
326
|
-
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
327
|
-
}
|
|
328
|
-
function consumeTrivia(input, cur, ctx) {
|
|
329
|
-
const scan = scanTrivia(input, cur, ctx);
|
|
330
|
-
scan.commit();
|
|
331
|
-
return scan.end;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// src/combinators/sequence.ts
|
|
335
|
-
function sequence(...parsers) {
|
|
336
|
-
const meta = {
|
|
337
|
-
firstSet: parsers[0]?._meta.firstSet ?? empty(),
|
|
338
|
-
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
339
|
-
isTrivia: false
|
|
340
|
-
};
|
|
428
|
+
// src/combinators/keywords.ts
|
|
429
|
+
function word(str, boundary = "_0-9A-Za-z") {
|
|
430
|
+
return keywords([str], { boundary });
|
|
431
|
+
}
|
|
432
|
+
function escapeRe(s) {
|
|
433
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
434
|
+
}
|
|
435
|
+
function keywords(words, opts = {}) {
|
|
436
|
+
const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
|
|
437
|
+
const alt = sorted.map(escapeRe).join("|");
|
|
438
|
+
const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
|
|
439
|
+
const flags = opts.caseInsensitive ? "iuy" : "uy";
|
|
440
|
+
const re = new RegExp(`(?:${alt})${boundary}`, flags);
|
|
441
|
+
let firstSet = empty();
|
|
442
|
+
for (const w of sorted) {
|
|
443
|
+
if (w.length === 0) continue;
|
|
444
|
+
const cp = w.codePointAt(0);
|
|
445
|
+
firstSet = union(firstSet, fromChar(cp));
|
|
446
|
+
if (opts.caseInsensitive) {
|
|
447
|
+
const u = String.fromCodePoint(cp).toUpperCase().codePointAt(0);
|
|
448
|
+
const l = String.fromCodePoint(cp).toLowerCase().codePointAt(0);
|
|
449
|
+
if (u !== void 0) firstSet = union(firstSet, fromChar(u));
|
|
450
|
+
if (l !== void 0) firstSet = union(firstSet, fromChar(l));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
const meta = { firstSet, canMatchNewline: false, isTrivia: false };
|
|
341
454
|
return {
|
|
342
|
-
_tag: "
|
|
455
|
+
_tag: "keywords",
|
|
343
456
|
_meta: meta,
|
|
344
|
-
_def: { tag: "
|
|
457
|
+
_def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
|
|
345
458
|
parse(input, pos, ctx) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const scan = scanTrivia(input, cur, ctx);
|
|
351
|
-
const raw = ctx._cstRawChildren;
|
|
352
|
-
const mark = raw ? raw.length : 0;
|
|
353
|
-
scan.commit();
|
|
354
|
-
const result2 = parsers[i].parse(input, scan.end, ctx);
|
|
355
|
-
if (!result2.ok) return result2;
|
|
356
|
-
if (result2.span.end > scan.end) {
|
|
357
|
-
cur = result2.span.end;
|
|
358
|
-
} else if (raw) {
|
|
359
|
-
raw.length = mark;
|
|
360
|
-
}
|
|
361
|
-
values.push(result2.value);
|
|
362
|
-
continue;
|
|
363
|
-
}
|
|
364
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
365
|
-
if (!result.ok) return result;
|
|
366
|
-
values.push(result.value);
|
|
367
|
-
cur = result.span.end;
|
|
459
|
+
re.lastIndex = pos;
|
|
460
|
+
const m = re.exec(input);
|
|
461
|
+
if (m === null || m.index !== pos) {
|
|
462
|
+
return failAt(ctx, ["keyword"], pos);
|
|
368
463
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
};
|
|
464
|
+
const value = m[0];
|
|
465
|
+
const span = { start: pos, end: pos + value.length };
|
|
466
|
+
const leaf = { _tag: "leaf", value, span };
|
|
467
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
|
|
468
|
+
return { ok: true, value, span };
|
|
374
469
|
}
|
|
375
470
|
};
|
|
376
471
|
}
|
|
377
472
|
|
|
378
473
|
// src/combinators/choice.ts
|
|
379
474
|
function choice(...args) {
|
|
380
|
-
const parsers = args.map((a) => "gate" in a ? a.
|
|
475
|
+
const parsers = args.map((a) => "gate" in a ? a.combinator : a);
|
|
381
476
|
const gates = args.map((a) => "gate" in a ? a.gate : null);
|
|
382
477
|
const hasGates = gates.some((g) => g !== null);
|
|
383
478
|
const disjoint = !hasGates && areDisjoint(parsers.map((p) => p._meta.firstSet));
|
|
@@ -461,19 +556,19 @@ function choice(...args) {
|
|
|
461
556
|
}
|
|
462
557
|
for (let i = 0; i < parsers.length; i++) {
|
|
463
558
|
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
464
|
-
const
|
|
465
|
-
const
|
|
559
|
+
const mark = saveCstMark(ctx);
|
|
560
|
+
const logLen = ctx._triviaLog?.length;
|
|
466
561
|
const result = parsers[i].parse(input, pos, ctx);
|
|
467
562
|
if (!result.ok) {
|
|
468
|
-
|
|
469
|
-
if (
|
|
563
|
+
rollbackCstCapture(ctx, mark);
|
|
564
|
+
if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
|
|
470
565
|
expected.push(...result.expected);
|
|
471
566
|
continue;
|
|
472
567
|
}
|
|
473
568
|
const checks = autoNot[i];
|
|
474
569
|
if (checks && autoNotFires(input, result.span.end, checks)) {
|
|
475
|
-
|
|
476
|
-
if (
|
|
570
|
+
rollbackCstCapture(ctx, mark);
|
|
571
|
+
if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
|
|
477
572
|
continue;
|
|
478
573
|
}
|
|
479
574
|
return result;
|
|
@@ -552,6 +647,7 @@ function getCoreRegexDef(p) {
|
|
|
552
647
|
const def = p._def;
|
|
553
648
|
if (def.tag === "regex") return { source: def.source, flags: def.flags };
|
|
554
649
|
if (def.tag === "transform") return getCoreRegexDef(def.parser);
|
|
650
|
+
if (def.tag === "label") return getCoreRegexDef(def.parser);
|
|
555
651
|
return null;
|
|
556
652
|
}
|
|
557
653
|
function applyTransforms(p, value, span) {
|
|
@@ -605,46 +701,275 @@ function areDisjoint(sets) {
|
|
|
605
701
|
return true;
|
|
606
702
|
}
|
|
607
703
|
|
|
704
|
+
// src/cst/trivia-kinds.ts
|
|
705
|
+
function unwrapTrivia(p) {
|
|
706
|
+
let cur = p;
|
|
707
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
708
|
+
return cur;
|
|
709
|
+
}
|
|
710
|
+
function peelLabel(p) {
|
|
711
|
+
if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
function analyzeLabeledTrivia(trivia2) {
|
|
715
|
+
let core = unwrapTrivia(trivia2);
|
|
716
|
+
let minRepeats = 1;
|
|
717
|
+
if (core._def.tag === "oneOrMore") {
|
|
718
|
+
core = core._def.parser;
|
|
719
|
+
minRepeats = 1;
|
|
720
|
+
} else if (core._def.tag === "many") {
|
|
721
|
+
core = core._def.parser;
|
|
722
|
+
minRepeats = 0;
|
|
723
|
+
}
|
|
724
|
+
const arms = [];
|
|
725
|
+
if (core._def.tag === "choice") {
|
|
726
|
+
for (let i = 0; i < core._def.parsers.length; i++) {
|
|
727
|
+
const peeled = peelLabel(core._def.parsers[i]);
|
|
728
|
+
if (!peeled) return null;
|
|
729
|
+
arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
const peeled = peelLabel(core);
|
|
733
|
+
if (!peeled) return null;
|
|
734
|
+
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
735
|
+
}
|
|
736
|
+
return { labels: arms.map((a) => a.label), arms, minRepeats };
|
|
737
|
+
}
|
|
738
|
+
function matchArmAt(input, pos, arm) {
|
|
739
|
+
const r = arm.parse(input, pos, { trackLines: false });
|
|
740
|
+
if (!r.ok || r.span.end <= pos) return null;
|
|
741
|
+
return { end: r.span.end };
|
|
742
|
+
}
|
|
743
|
+
function scanLabeledTriviaChunks(input, cur, spec) {
|
|
744
|
+
const chunks = [];
|
|
745
|
+
let pos = cur;
|
|
746
|
+
while (pos < input.length) {
|
|
747
|
+
let matched = null;
|
|
748
|
+
for (const arm of spec.arms) {
|
|
749
|
+
const m = matchArmAt(input, pos, arm.parser);
|
|
750
|
+
if (m) {
|
|
751
|
+
matched = { end: m.end, kindIndex: arm.kindIndex };
|
|
752
|
+
break;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
if (!matched) break;
|
|
756
|
+
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
757
|
+
pos = matched.end;
|
|
758
|
+
}
|
|
759
|
+
if (chunks.length < spec.minRepeats) {
|
|
760
|
+
return { end: cur, chunks: [] };
|
|
761
|
+
}
|
|
762
|
+
return { end: pos, chunks };
|
|
763
|
+
}
|
|
764
|
+
function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
|
|
765
|
+
const chunks = [];
|
|
766
|
+
let pos = cur;
|
|
767
|
+
while (pos < input.length) {
|
|
768
|
+
const c = input.charCodeAt(pos);
|
|
769
|
+
if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
|
|
770
|
+
const start = pos;
|
|
771
|
+
pos++;
|
|
772
|
+
while (pos < input.length) {
|
|
773
|
+
const c2 = input.charCodeAt(pos);
|
|
774
|
+
if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
|
|
775
|
+
else break;
|
|
776
|
+
}
|
|
777
|
+
chunks.push({ start, end: pos, kindIndex: wsKind });
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (c === 47 && input.charCodeAt(pos + 1) === 42) {
|
|
781
|
+
const start = pos;
|
|
782
|
+
let j = pos + 2;
|
|
783
|
+
while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++;
|
|
784
|
+
pos = j + 2 <= input.length ? j + 2 : input.length;
|
|
785
|
+
chunks.push({ start, end: pos, kindIndex: commentKind });
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
return { end: pos, chunks };
|
|
791
|
+
}
|
|
792
|
+
function tryFastLabeledScan(input, cur, trivia2) {
|
|
793
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
794
|
+
if (!spec || spec.arms.length !== 2) return null;
|
|
795
|
+
const wsArm = spec.arms.find((a) => {
|
|
796
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
797
|
+
return src != null && !src.includes("\\*");
|
|
798
|
+
});
|
|
799
|
+
const commentArm = spec.arms.find((a) => {
|
|
800
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
801
|
+
return src != null && src.includes("\\*");
|
|
802
|
+
});
|
|
803
|
+
if (!wsArm || !commentArm) return null;
|
|
804
|
+
const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
805
|
+
if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
|
|
806
|
+
return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
807
|
+
}
|
|
808
|
+
function recordTriviaChunks(ctx, chunks) {
|
|
809
|
+
const kinds = ctx.triviaKindLabels;
|
|
810
|
+
for (const ch of chunks) {
|
|
811
|
+
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
812
|
+
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
813
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/combinators/trivia-skip.ts
|
|
819
|
+
var NOOP_COMMIT = () => {
|
|
820
|
+
};
|
|
821
|
+
function needsDeferredTriviaCommit(ctx) {
|
|
822
|
+
return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
823
|
+
}
|
|
824
|
+
function saveTriviaMark(ctx) {
|
|
825
|
+
const m = saveCstMark(ctx);
|
|
826
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
827
|
+
}
|
|
828
|
+
function rollbackTrivia(ctx, mark) {
|
|
829
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
830
|
+
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
831
|
+
}
|
|
832
|
+
function scanWithLabels(input, cur, ctx) {
|
|
833
|
+
const triviaP = ctx.trivia;
|
|
834
|
+
const spec = analyzeLabeledTrivia(triviaP);
|
|
835
|
+
if (!spec) return { end: cur, commit: NOOP_COMMIT };
|
|
836
|
+
const fast = tryFastLabeledScan(input, cur, triviaP);
|
|
837
|
+
const { end, chunks } = fast ?? scanLabeledTriviaChunks(input, cur, spec);
|
|
838
|
+
if (end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
839
|
+
return {
|
|
840
|
+
end,
|
|
841
|
+
commit: () => recordTriviaChunks(ctx, chunks)
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
function advanceTrivia(input, cur, ctx) {
|
|
845
|
+
const triviaP = ctx.trivia;
|
|
846
|
+
if (!triviaP) return cur;
|
|
847
|
+
if (ctx.triviaKindLabels) {
|
|
848
|
+
const scan = scanWithLabels(input, cur, ctx);
|
|
849
|
+
return scan.end;
|
|
850
|
+
}
|
|
851
|
+
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
852
|
+
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
853
|
+
}
|
|
854
|
+
function scanTrivia(input, cur, ctx) {
|
|
855
|
+
const triviaP = ctx.trivia;
|
|
856
|
+
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
857
|
+
const log = ctx._triviaLog;
|
|
858
|
+
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
859
|
+
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
860
|
+
return scanWithLabels(input, cur, ctx);
|
|
861
|
+
}
|
|
862
|
+
if (log !== void 0 || captureTl) {
|
|
863
|
+
const tr2 = triviaP.parse(input, cur, {
|
|
864
|
+
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
865
|
+
state: ctx.state
|
|
866
|
+
});
|
|
867
|
+
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
868
|
+
const end = tr2.span.end;
|
|
869
|
+
return {
|
|
870
|
+
end,
|
|
871
|
+
commit: () => {
|
|
872
|
+
pushTriviaLogEntry(ctx, cur, end);
|
|
873
|
+
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
878
|
+
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// src/combinators/sequence.ts
|
|
882
|
+
function sequence(...parsers) {
|
|
883
|
+
const meta = {
|
|
884
|
+
firstSet: parsers[0]?._meta.firstSet ?? empty(),
|
|
885
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
886
|
+
isTrivia: false
|
|
887
|
+
};
|
|
888
|
+
return {
|
|
889
|
+
_tag: "sequence",
|
|
890
|
+
_meta: meta,
|
|
891
|
+
_def: { tag: "sequence", parsers },
|
|
892
|
+
parse(input, pos, ctx) {
|
|
893
|
+
const values = [];
|
|
894
|
+
let cur = pos;
|
|
895
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
896
|
+
if (ctx.trivia && i > 0) {
|
|
897
|
+
let scanEnd;
|
|
898
|
+
let mark = saveTriviaMark(ctx);
|
|
899
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
900
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
901
|
+
scan.commit();
|
|
902
|
+
scanEnd = scan.end;
|
|
903
|
+
} else {
|
|
904
|
+
scanEnd = advanceTrivia(input, cur, ctx);
|
|
905
|
+
}
|
|
906
|
+
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
907
|
+
if (!result2.ok) return result2;
|
|
908
|
+
if (result2.span.end > scanEnd) {
|
|
909
|
+
cur = result2.span.end;
|
|
910
|
+
} else {
|
|
911
|
+
rollbackTrivia(ctx, mark);
|
|
912
|
+
}
|
|
913
|
+
values.push(result2.value);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const result = parsers[i].parse(input, cur, ctx);
|
|
917
|
+
if (!result.ok) return result;
|
|
918
|
+
values.push(result.value);
|
|
919
|
+
cur = result.span.end;
|
|
920
|
+
}
|
|
921
|
+
return {
|
|
922
|
+
ok: true,
|
|
923
|
+
value: values,
|
|
924
|
+
span: { start: pos, end: cur }
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
|
|
608
930
|
// src/combinators/repeat.ts
|
|
609
|
-
function repItem(
|
|
610
|
-
const
|
|
611
|
-
const mark = raw ? raw.length : 0;
|
|
931
|
+
function repItem(combinator, input, cur, ctx) {
|
|
932
|
+
const mark = saveTriviaMark(ctx);
|
|
612
933
|
let pos = cur;
|
|
613
934
|
if (ctx.trivia) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
935
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
936
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
937
|
+
scan.commit();
|
|
938
|
+
pos = scan.end;
|
|
939
|
+
} else {
|
|
940
|
+
pos = advanceTrivia(input, cur, ctx);
|
|
941
|
+
}
|
|
617
942
|
}
|
|
618
943
|
if (pos >= input.length) {
|
|
619
|
-
|
|
944
|
+
rollbackTrivia(ctx, mark);
|
|
620
945
|
return "stop";
|
|
621
946
|
}
|
|
622
|
-
const result =
|
|
947
|
+
const result = combinator.parse(input, pos, ctx);
|
|
623
948
|
if (!result.ok) {
|
|
624
|
-
|
|
949
|
+
rollbackTrivia(ctx, mark);
|
|
625
950
|
return { fail: result };
|
|
626
951
|
}
|
|
627
952
|
if (result.span.end === pos) {
|
|
628
|
-
|
|
953
|
+
rollbackTrivia(ctx, mark);
|
|
629
954
|
return "stop";
|
|
630
955
|
}
|
|
631
956
|
return { value: result.value, end: result.span.end };
|
|
632
957
|
}
|
|
633
|
-
function many(
|
|
958
|
+
function many(combinator) {
|
|
634
959
|
const meta = {
|
|
635
|
-
firstSet:
|
|
636
|
-
canMatchNewline:
|
|
960
|
+
firstSet: combinator._meta.firstSet,
|
|
961
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
637
962
|
isTrivia: false
|
|
638
963
|
};
|
|
639
964
|
return {
|
|
640
965
|
_tag: "many",
|
|
641
966
|
_meta: meta,
|
|
642
|
-
_def: { tag: "many", parser:
|
|
967
|
+
_def: { tag: "many", parser: combinator, min: 0 },
|
|
643
968
|
parse(input, pos, ctx) {
|
|
644
969
|
const values = [];
|
|
645
970
|
let cur = pos;
|
|
646
971
|
while (cur < input.length) {
|
|
647
|
-
const item = repItem(
|
|
972
|
+
const item = repItem(combinator, input, cur, ctx);
|
|
648
973
|
if (item === "stop" || "fail" in item) break;
|
|
649
974
|
values.push(item.value);
|
|
650
975
|
cur = item.end;
|
|
@@ -653,23 +978,23 @@ function many(parser2) {
|
|
|
653
978
|
}
|
|
654
979
|
};
|
|
655
980
|
}
|
|
656
|
-
function oneOrMore(
|
|
981
|
+
function oneOrMore(combinator) {
|
|
657
982
|
const meta = {
|
|
658
|
-
firstSet:
|
|
659
|
-
canMatchNewline:
|
|
983
|
+
firstSet: combinator._meta.firstSet,
|
|
984
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
660
985
|
isTrivia: false
|
|
661
986
|
};
|
|
662
987
|
return {
|
|
663
988
|
_tag: "oneOrMore",
|
|
664
989
|
_meta: meta,
|
|
665
|
-
_def: { tag: "oneOrMore", parser:
|
|
990
|
+
_def: { tag: "oneOrMore", parser: combinator, min: 1 },
|
|
666
991
|
parse(input, pos, ctx) {
|
|
667
|
-
const first =
|
|
992
|
+
const first = combinator.parse(input, pos, ctx);
|
|
668
993
|
if (!first.ok) return first;
|
|
669
994
|
const values = [first.value];
|
|
670
995
|
let cur = first.span.end;
|
|
671
996
|
while (cur < input.length) {
|
|
672
|
-
const item = repItem(
|
|
997
|
+
const item = repItem(combinator, input, cur, ctx);
|
|
673
998
|
if (item === "stop" || "fail" in item) break;
|
|
674
999
|
values.push(item.value);
|
|
675
1000
|
cur = item.end;
|
|
@@ -678,45 +1003,71 @@ function oneOrMore(parser2) {
|
|
|
678
1003
|
}
|
|
679
1004
|
};
|
|
680
1005
|
}
|
|
681
|
-
function optional(
|
|
1006
|
+
function optional(combinator) {
|
|
682
1007
|
const meta = {
|
|
683
|
-
firstSet:
|
|
684
|
-
canMatchNewline:
|
|
1008
|
+
firstSet: combinator._meta.firstSet,
|
|
1009
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
685
1010
|
isTrivia: false
|
|
686
1011
|
};
|
|
687
1012
|
return {
|
|
688
1013
|
_tag: "optional",
|
|
689
1014
|
_meta: meta,
|
|
690
|
-
_def: { tag: "optional", parser:
|
|
1015
|
+
_def: { tag: "optional", parser: combinator },
|
|
691
1016
|
parse(input, pos, ctx) {
|
|
692
|
-
const result =
|
|
1017
|
+
const result = combinator.parse(input, pos, ctx);
|
|
693
1018
|
if (result.ok) return result;
|
|
694
1019
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
695
1020
|
}
|
|
696
1021
|
};
|
|
697
1022
|
}
|
|
698
|
-
function sepBy(
|
|
1023
|
+
function sepBy(combinator, separator) {
|
|
699
1024
|
const meta = {
|
|
700
|
-
firstSet:
|
|
701
|
-
canMatchNewline:
|
|
1025
|
+
firstSet: combinator._meta.firstSet,
|
|
1026
|
+
canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
|
|
702
1027
|
isTrivia: false
|
|
703
1028
|
};
|
|
704
1029
|
return {
|
|
705
1030
|
_tag: "sepBy",
|
|
706
1031
|
_meta: meta,
|
|
707
|
-
_def: { tag: "sepBy", parser:
|
|
1032
|
+
_def: { tag: "sepBy", parser: combinator, separator },
|
|
708
1033
|
parse(input, pos, ctx) {
|
|
709
|
-
const first =
|
|
1034
|
+
const first = combinator.parse(input, pos, ctx);
|
|
710
1035
|
if (!first.ok) return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
711
1036
|
const values = [first.value];
|
|
712
1037
|
let cur = first.span.end;
|
|
713
1038
|
while (cur < input.length) {
|
|
714
|
-
|
|
1039
|
+
let mark = saveTriviaMark(ctx);
|
|
1040
|
+
let sepPos = cur;
|
|
1041
|
+
if (ctx.trivia) {
|
|
1042
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
1043
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
1044
|
+
scan.commit();
|
|
1045
|
+
sepPos = scan.end;
|
|
1046
|
+
} else {
|
|
1047
|
+
sepPos = advanceTrivia(input, cur, ctx);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
715
1050
|
const sep = separator.parse(input, sepPos, ctx);
|
|
716
|
-
if (!sep.ok)
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1051
|
+
if (!sep.ok) {
|
|
1052
|
+
rollbackTrivia(ctx, mark);
|
|
1053
|
+
break;
|
|
1054
|
+
}
|
|
1055
|
+
mark = saveTriviaMark(ctx);
|
|
1056
|
+
let nextPos = sep.span.end;
|
|
1057
|
+
if (ctx.trivia) {
|
|
1058
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
1059
|
+
const scan = scanTrivia(input, sep.span.end, ctx);
|
|
1060
|
+
scan.commit();
|
|
1061
|
+
nextPos = scan.end;
|
|
1062
|
+
} else {
|
|
1063
|
+
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const next = combinator.parse(input, nextPos, ctx);
|
|
1067
|
+
if (!next.ok) {
|
|
1068
|
+
rollbackTrivia(ctx, mark);
|
|
1069
|
+
break;
|
|
1070
|
+
}
|
|
720
1071
|
values.push(next.value);
|
|
721
1072
|
cur = next.span.end;
|
|
722
1073
|
}
|
|
@@ -726,7 +1077,7 @@ function sepBy(parser2, separator) {
|
|
|
726
1077
|
}
|
|
727
1078
|
|
|
728
1079
|
// src/combinators/not.ts
|
|
729
|
-
function not(
|
|
1080
|
+
function not(combinator) {
|
|
730
1081
|
const meta = {
|
|
731
1082
|
firstSet: any(),
|
|
732
1083
|
// we don't know what NOT matches
|
|
@@ -736,11 +1087,11 @@ function not(parser2) {
|
|
|
736
1087
|
return {
|
|
737
1088
|
_tag: "not",
|
|
738
1089
|
_meta: meta,
|
|
739
|
-
_def: { tag: "not", parser:
|
|
1090
|
+
_def: { tag: "not", parser: combinator },
|
|
740
1091
|
parse(input, pos, ctx) {
|
|
741
|
-
const result =
|
|
1092
|
+
const result = combinator.parse(input, pos, ctx);
|
|
742
1093
|
if (result.ok) {
|
|
743
|
-
return { ok: false, expected: [`not(${
|
|
1094
|
+
return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
|
|
744
1095
|
}
|
|
745
1096
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
746
1097
|
}
|
|
@@ -748,37 +1099,27 @@ function not(parser2) {
|
|
|
748
1099
|
}
|
|
749
1100
|
|
|
750
1101
|
// src/combinators/node.ts
|
|
751
|
-
function node(type,
|
|
1102
|
+
function node(type, combinator, build) {
|
|
752
1103
|
const meta = {
|
|
753
|
-
firstSet:
|
|
754
|
-
canMatchNewline:
|
|
1104
|
+
firstSet: combinator._meta.firstSet,
|
|
1105
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
755
1106
|
isTrivia: false
|
|
756
1107
|
};
|
|
757
1108
|
return {
|
|
758
1109
|
_tag: "node",
|
|
759
1110
|
_meta: meta,
|
|
760
|
-
_def: { tag: "node", type, parser:
|
|
1111
|
+
_def: { tag: "node", type, parser: combinator, build },
|
|
761
1112
|
parse(input, pos, ctx) {
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
const
|
|
765
|
-
...ctx,
|
|
766
|
-
// A node() always records the trivia between its terms — the library owns
|
|
767
|
-
// capture so grammar authors don't reconstruct it. (Matches the compiler.)
|
|
768
|
-
captureTrivia: true,
|
|
769
|
-
_cstChildren: children,
|
|
770
|
-
_cstLeaves: children,
|
|
771
|
-
_cstRawChildren: rawChildren
|
|
772
|
-
};
|
|
773
|
-
const r = parser2.parse(input, pos, innerCtx);
|
|
1113
|
+
const saved = beginCstNodeCapture(ctx);
|
|
1114
|
+
const r = combinator.parse(input, pos, ctx);
|
|
1115
|
+
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
774
1116
|
if (!r.ok) return r;
|
|
775
|
-
const
|
|
1117
|
+
const state = ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1118
|
+
const built = build(children, rawChildren, r.span, triviaLog, state);
|
|
776
1119
|
const isNodeLike = typeof built === "object" && built !== null && built._tag === "node";
|
|
777
|
-
|
|
778
|
-
if (
|
|
779
|
-
ctx
|
|
780
|
-
isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span }
|
|
781
|
-
);
|
|
1120
|
+
const rawEntry = isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1121
|
+
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1122
|
+
pushCstChild(ctx, built, rawEntry);
|
|
782
1123
|
}
|
|
783
1124
|
return { ok: true, value: built, span: r.span };
|
|
784
1125
|
}
|
|
@@ -786,24 +1127,37 @@ function node(type, parser2, build) {
|
|
|
786
1127
|
}
|
|
787
1128
|
|
|
788
1129
|
// src/combinators/map.ts
|
|
789
|
-
function transform(
|
|
1130
|
+
function transform(combinator, fn) {
|
|
790
1131
|
return {
|
|
791
1132
|
_tag: "transform",
|
|
792
|
-
_meta:
|
|
793
|
-
_def: { tag: "transform", parser:
|
|
1133
|
+
_meta: combinator._meta,
|
|
1134
|
+
_def: { tag: "transform", parser: combinator, fn },
|
|
794
1135
|
parse(input, pos, ctx) {
|
|
795
|
-
const result =
|
|
1136
|
+
const result = combinator.parse(input, pos, ctx);
|
|
796
1137
|
if (!result.ok) return result;
|
|
797
1138
|
return { ...result, value: fn(result.value, result.span) };
|
|
798
1139
|
}
|
|
799
1140
|
};
|
|
800
1141
|
}
|
|
801
|
-
function trivia(
|
|
1142
|
+
function trivia(combinator) {
|
|
1143
|
+
const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
|
|
1144
|
+
return {
|
|
1145
|
+
_tag: combinator._tag,
|
|
1146
|
+
_meta: {
|
|
1147
|
+
...combinator._meta,
|
|
1148
|
+
isTrivia: true,
|
|
1149
|
+
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
1150
|
+
},
|
|
1151
|
+
_def: { tag: "trivia", parser: combinator },
|
|
1152
|
+
parse: combinator.parse.bind(combinator)
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
function label(name, combinator) {
|
|
802
1156
|
return {
|
|
803
|
-
_tag:
|
|
804
|
-
_meta:
|
|
805
|
-
_def: { tag: "
|
|
806
|
-
parse:
|
|
1157
|
+
_tag: combinator._tag,
|
|
1158
|
+
_meta: combinator._meta,
|
|
1159
|
+
_def: { tag: "label", label: name, parser: combinator },
|
|
1160
|
+
parse: combinator.parse.bind(combinator)
|
|
807
1161
|
};
|
|
808
1162
|
}
|
|
809
1163
|
|
|
@@ -854,7 +1208,10 @@ function parser(opts, root) {
|
|
|
854
1208
|
const ctx = {
|
|
855
1209
|
..._ctx,
|
|
856
1210
|
trackLines,
|
|
857
|
-
...opts.trivia !== void 0 ? {
|
|
1211
|
+
...opts.trivia !== void 0 ? {
|
|
1212
|
+
trivia: opts.trivia,
|
|
1213
|
+
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1214
|
+
} : {},
|
|
858
1215
|
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {}
|
|
859
1216
|
};
|
|
860
1217
|
const result = root.parse(input, pos ?? 0, ctx);
|
|
@@ -867,6 +1224,320 @@ function parser(opts, root) {
|
|
|
867
1224
|
};
|
|
868
1225
|
}
|
|
869
1226
|
|
|
1227
|
+
// src/compiler/trivia-fast-path.ts
|
|
1228
|
+
var BLOCK_COMMENT = String.raw`\/\*(?:[^*]|\*(?!\/))*\*\/`;
|
|
1229
|
+
var WS_CLASS_SOURCES = /* @__PURE__ */ new Set([
|
|
1230
|
+
String.raw`[ \t\n\r\f]+`,
|
|
1231
|
+
String.raw`[ \t\n]+`,
|
|
1232
|
+
String.raw`[ \t]+`,
|
|
1233
|
+
String.raw`[\t\n\f\r ]+`
|
|
1234
|
+
]);
|
|
1235
|
+
function unwrapTrivia2(p) {
|
|
1236
|
+
let cur = p;
|
|
1237
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
1238
|
+
return cur;
|
|
1239
|
+
}
|
|
1240
|
+
function oneOrMoreInner(p) {
|
|
1241
|
+
const d = p._def;
|
|
1242
|
+
if (d.tag === "oneOrMore") return d.parser;
|
|
1243
|
+
if (d.tag === "many" && d.min >= 1) return d.parser;
|
|
1244
|
+
return null;
|
|
1245
|
+
}
|
|
1246
|
+
function choiceArms(p) {
|
|
1247
|
+
if (p._def.tag === "choice") return p._def.parsers;
|
|
1248
|
+
return null;
|
|
1249
|
+
}
|
|
1250
|
+
function isWsClassSource(source) {
|
|
1251
|
+
return WS_CLASS_SOURCES.has(source);
|
|
1252
|
+
}
|
|
1253
|
+
function isBlockCommentSource(source) {
|
|
1254
|
+
return source === BLOCK_COMMENT;
|
|
1255
|
+
}
|
|
1256
|
+
function analyzeTriviaFastPath(trivia2) {
|
|
1257
|
+
const core = unwrapTrivia2(trivia2);
|
|
1258
|
+
const direct = getCoreRegexDef(core)?.source;
|
|
1259
|
+
if (direct) {
|
|
1260
|
+
if (isWsClassSource(direct)) return "wsOnly";
|
|
1261
|
+
return null;
|
|
1262
|
+
}
|
|
1263
|
+
const inner = oneOrMoreInner(core);
|
|
1264
|
+
if (!inner) return null;
|
|
1265
|
+
const innerSrc = getCoreRegexDef(inner)?.source;
|
|
1266
|
+
if (innerSrc && isWsClassSource(innerSrc)) return "wsOnly";
|
|
1267
|
+
const arms = choiceArms(inner);
|
|
1268
|
+
if (!arms || arms.length !== 2) return null;
|
|
1269
|
+
let hasWs = false;
|
|
1270
|
+
let hasComment = false;
|
|
1271
|
+
for (const arm of arms) {
|
|
1272
|
+
const src = getCoreRegexDef(arm)?.source;
|
|
1273
|
+
if (!src) return null;
|
|
1274
|
+
if (isWsClassSource(src)) hasWs = true;
|
|
1275
|
+
else if (isBlockCommentSource(src)) hasComment = true;
|
|
1276
|
+
else return null;
|
|
1277
|
+
}
|
|
1278
|
+
if (hasWs && hasComment) return "wsComments";
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
var CAP_RECORD = [
|
|
1282
|
+
` if (_cap && _e > _pos) {`,
|
|
1283
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
1284
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
1285
|
+
` }`
|
|
1286
|
+
].join("\n");
|
|
1287
|
+
var WS_ONLY_LOOP = [
|
|
1288
|
+
` while (_e < input.length) {`,
|
|
1289
|
+
` const c = input.charCodeAt(_e)`,
|
|
1290
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) { _e++; continue }`,
|
|
1291
|
+
` break`,
|
|
1292
|
+
` }`
|
|
1293
|
+
].join("\n");
|
|
1294
|
+
var WS_COMMENTS_LOOP = [
|
|
1295
|
+
` while (_e < input.length) {`,
|
|
1296
|
+
` const c = input.charCodeAt(_e)`,
|
|
1297
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) { _e++; continue }`,
|
|
1298
|
+
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1299
|
+
` let j = _e + 2`,
|
|
1300
|
+
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1301
|
+
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1302
|
+
` continue`,
|
|
1303
|
+
` }`,
|
|
1304
|
+
` break`,
|
|
1305
|
+
` }`
|
|
1306
|
+
].join("\n");
|
|
1307
|
+
var CAP_CHUNK = (wsKind, commentKind) => [
|
|
1308
|
+
` if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {`,
|
|
1309
|
+
` const _cs = _e`,
|
|
1310
|
+
` _e++`,
|
|
1311
|
+
` while (_e < input.length) {`,
|
|
1312
|
+
` const c2 = input.charCodeAt(_e)`,
|
|
1313
|
+
` if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) _e++`,
|
|
1314
|
+
` else break`,
|
|
1315
|
+
` }`,
|
|
1316
|
+
` if (_cap) {`,
|
|
1317
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${wsKind})`,
|
|
1318
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${wsKind})`,
|
|
1319
|
+
` }`,
|
|
1320
|
+
` continue`,
|
|
1321
|
+
` }`,
|
|
1322
|
+
` if (c === 47 && input.charCodeAt(_e + 1) === 42) {`,
|
|
1323
|
+
` const _cs = _e`,
|
|
1324
|
+
` let j = _e + 2`,
|
|
1325
|
+
` while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++`,
|
|
1326
|
+
` _e = j + 2 <= input.length ? j + 2 : input.length`,
|
|
1327
|
+
` if (_cap) {`,
|
|
1328
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_cs, _e, ${commentKind})`,
|
|
1329
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_cs, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${commentKind})`,
|
|
1330
|
+
` }`,
|
|
1331
|
+
` continue`,
|
|
1332
|
+
` }`
|
|
1333
|
+
].join("\n");
|
|
1334
|
+
var WS_COMMENTS_LOOP_LABELED = (wsKind, commentKind) => [
|
|
1335
|
+
` while (_e < input.length) {`,
|
|
1336
|
+
` const c = input.charCodeAt(_e)`,
|
|
1337
|
+
CAP_CHUNK(wsKind, commentKind),
|
|
1338
|
+
` break`,
|
|
1339
|
+
` }`
|
|
1340
|
+
].join("\n");
|
|
1341
|
+
function buildFastTriviaFnDecl(fnName, kind, kindIndices) {
|
|
1342
|
+
const loop = kind === "wsComments" && kindIndices ? WS_COMMENTS_LOOP_LABELED(kindIndices.ws, kindIndices.comment) : kind === "wsComments" ? WS_COMMENTS_LOOP : WS_ONLY_LOOP;
|
|
1343
|
+
const cap = kindIndices ? "" : CAP_RECORD;
|
|
1344
|
+
const lines = [
|
|
1345
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1346
|
+
` let _e = _pos`,
|
|
1347
|
+
loop
|
|
1348
|
+
];
|
|
1349
|
+
if (cap) lines.push(cap);
|
|
1350
|
+
lines.push(` return _e`, `}`);
|
|
1351
|
+
return lines.join("\n");
|
|
1352
|
+
}
|
|
1353
|
+
function regexArmIndex(spec, isComment) {
|
|
1354
|
+
for (const arm of spec.arms) {
|
|
1355
|
+
const src = getCoreRegexDef(arm.parser)?.source;
|
|
1356
|
+
if (!src) return null;
|
|
1357
|
+
const comment = src.includes("\\*") || src.startsWith("\\/\\/");
|
|
1358
|
+
if (comment === isComment) return arm.kindIndex;
|
|
1359
|
+
}
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
|
|
1363
|
+
const tryArms = spec.arms.map((arm, i) => {
|
|
1364
|
+
const re = reNames[i];
|
|
1365
|
+
const k = arm.kindIndex;
|
|
1366
|
+
return [
|
|
1367
|
+
` ${re}.lastIndex = _e`,
|
|
1368
|
+
` const _m${i} = ${re}.exec(input)`,
|
|
1369
|
+
` if (_m${i} && _m${i}.index === _e) {`,
|
|
1370
|
+
` const _ce = _e + _m${i}[0].length`,
|
|
1371
|
+
` if (_cap) {`,
|
|
1372
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
1373
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
1374
|
+
` }`,
|
|
1375
|
+
` _e = _ce`,
|
|
1376
|
+
` _matched = true`,
|
|
1377
|
+
` continue`,
|
|
1378
|
+
` }`
|
|
1379
|
+
].join("\n");
|
|
1380
|
+
}).join("\n");
|
|
1381
|
+
return [
|
|
1382
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1383
|
+
` let _e = _pos`,
|
|
1384
|
+
` while (_e < input.length) {`,
|
|
1385
|
+
` let _matched = false`,
|
|
1386
|
+
tryArms,
|
|
1387
|
+
` if (!_matched) break`,
|
|
1388
|
+
` }`,
|
|
1389
|
+
` return _e`,
|
|
1390
|
+
`}`
|
|
1391
|
+
].join("\n");
|
|
1392
|
+
}
|
|
1393
|
+
function labeledTriviaKindIndices(trivia2) {
|
|
1394
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1395
|
+
if (!spec || spec.arms.length !== 2) return null;
|
|
1396
|
+
const ws = regexArmIndex(spec, false);
|
|
1397
|
+
const comment = regexArmIndex(spec, true);
|
|
1398
|
+
if (ws === null || comment === null) return null;
|
|
1399
|
+
return { ws, comment };
|
|
1400
|
+
}
|
|
1401
|
+
function labeledTriviaRegexArms(trivia2) {
|
|
1402
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1403
|
+
if (!spec) return null;
|
|
1404
|
+
for (const arm of spec.arms) {
|
|
1405
|
+
if (!getCoreRegexDef(arm.parser)) return null;
|
|
1406
|
+
}
|
|
1407
|
+
return spec;
|
|
1408
|
+
}
|
|
1409
|
+
function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
|
|
1410
|
+
const tryArms = spec.arms.map((arm, i) => {
|
|
1411
|
+
const k = arm.kindIndex;
|
|
1412
|
+
const ri = rpStartIndex + i;
|
|
1413
|
+
return [
|
|
1414
|
+
` const _r${i} = _rp[${ri}].parse(input, _e, _ctx)`,
|
|
1415
|
+
` if (_r${i}.ok && _r${i}.span.end > _e) {`,
|
|
1416
|
+
` const _ce = _r${i}.span.end`,
|
|
1417
|
+
` if (_cap) {`,
|
|
1418
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
|
|
1419
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
|
|
1420
|
+
` }`,
|
|
1421
|
+
` _e = _ce`,
|
|
1422
|
+
` _matched = true`,
|
|
1423
|
+
` continue`,
|
|
1424
|
+
` }`
|
|
1425
|
+
].join("\n");
|
|
1426
|
+
}).join("\n");
|
|
1427
|
+
return [
|
|
1428
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
1429
|
+
` let _e = _pos`,
|
|
1430
|
+
` while (_e < input.length) {`,
|
|
1431
|
+
` let _matched = false`,
|
|
1432
|
+
tryArms,
|
|
1433
|
+
` if (!_matched) break`,
|
|
1434
|
+
` }`,
|
|
1435
|
+
` return _e`,
|
|
1436
|
+
`}`
|
|
1437
|
+
].join("\n");
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// src/compiler/inline-build.ts
|
|
1441
|
+
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*$/;
|
|
1442
|
+
function escapeRegExp(s) {
|
|
1443
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1444
|
+
}
|
|
1445
|
+
function looseMkBuildRe(type) {
|
|
1446
|
+
return new RegExp(
|
|
1447
|
+
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*$`
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
function analyzeMkInlineBuild(def) {
|
|
1451
|
+
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
1452
|
+
const strict = src.match(MK_BUILD_RE);
|
|
1453
|
+
if (strict) {
|
|
1454
|
+
const mkType = strict[2];
|
|
1455
|
+
return mkType === def.type ? def.type : null;
|
|
1456
|
+
}
|
|
1457
|
+
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
1458
|
+
return null;
|
|
1459
|
+
}
|
|
1460
|
+
function emitInlineMkNodeExpr(type, chV, rawV, pos, endVar, tlV) {
|
|
1461
|
+
return `{ _tag: 'node', type: ${JSON.stringify(type)}, span: { start: ${pos}, end: ${endVar} }, children: ${chV}, rawCount: ${rawV}.length, localTriviaLen: ${tlV}.length }`;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
// src/compiler/inline-callback.ts
|
|
1465
|
+
var INLINE_BUILTINS = /* @__PURE__ */ new Set([
|
|
1466
|
+
"parseInt",
|
|
1467
|
+
"parseFloat",
|
|
1468
|
+
"String",
|
|
1469
|
+
"Number",
|
|
1470
|
+
"Boolean",
|
|
1471
|
+
"Object",
|
|
1472
|
+
"Array",
|
|
1473
|
+
"Math",
|
|
1474
|
+
"JSON",
|
|
1475
|
+
"undefined",
|
|
1476
|
+
"null",
|
|
1477
|
+
"true",
|
|
1478
|
+
"false",
|
|
1479
|
+
"NaN",
|
|
1480
|
+
"Infinity"
|
|
1481
|
+
]);
|
|
1482
|
+
function escapeRegExp2(s) {
|
|
1483
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1484
|
+
}
|
|
1485
|
+
function transformFnSource(fn, fnSrc) {
|
|
1486
|
+
if (fnSrc) return fnSrc.trim();
|
|
1487
|
+
const s = fn.toString().trim();
|
|
1488
|
+
if (s.includes("[native code]")) return null;
|
|
1489
|
+
return s;
|
|
1490
|
+
}
|
|
1491
|
+
function replaceParam(body, param, valueVar) {
|
|
1492
|
+
return body.replace(new RegExp(`\\b${escapeRegExp2(param)}\\b`, "g"), valueVar);
|
|
1493
|
+
}
|
|
1494
|
+
function stripForIdCheck(body) {
|
|
1495
|
+
return body.replace(/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/g, '""').replace(/\bas\s+const\b/g, "").replace(/\b[A-Za-z_$][\w$]*\s*:/g, ":");
|
|
1496
|
+
}
|
|
1497
|
+
function hasFreeIdentifiers(body, allowed) {
|
|
1498
|
+
const stripped = stripForIdCheck(body);
|
|
1499
|
+
const ids = stripped.match(/\b[A-Za-z_$][\w$]*\b/g) ?? [];
|
|
1500
|
+
for (const id of ids) {
|
|
1501
|
+
if (INLINE_BUILTINS.has(id)) continue;
|
|
1502
|
+
if (allowed.has(id)) continue;
|
|
1503
|
+
return true;
|
|
1504
|
+
}
|
|
1505
|
+
return false;
|
|
1506
|
+
}
|
|
1507
|
+
function tryInlineUnaryTransform(src, valueVar) {
|
|
1508
|
+
const allowed = /* @__PURE__ */ new Set([valueVar]);
|
|
1509
|
+
const nullary = src.match(/^\(\s*\)\s*=>\s*(.+)$/);
|
|
1510
|
+
if (nullary) {
|
|
1511
|
+
const body2 = nullary[1].trim();
|
|
1512
|
+
return hasFreeIdentifiers(body2, allowed) ? null : body2;
|
|
1513
|
+
}
|
|
1514
|
+
const m = src.match(/^(\w+)\s*=>\s*(.+)$/);
|
|
1515
|
+
if (!m) return null;
|
|
1516
|
+
const body = replaceParam(m[2].trim(), m[1], valueVar);
|
|
1517
|
+
return hasFreeIdentifiers(body, allowed) ? null : body;
|
|
1518
|
+
}
|
|
1519
|
+
function parseArrayDestructure(pattern, arity) {
|
|
1520
|
+
const slots = [];
|
|
1521
|
+
for (const part of pattern.split(",")) {
|
|
1522
|
+
const name = part.trim();
|
|
1523
|
+
slots.push(name === "" || name === "_" ? null : name);
|
|
1524
|
+
}
|
|
1525
|
+
while (slots.length < arity) slots.push(null);
|
|
1526
|
+
return slots.slice(0, arity);
|
|
1527
|
+
}
|
|
1528
|
+
function tryInlineDestructureTransform(src, valueVars) {
|
|
1529
|
+
const m = src.match(/^\(\s*\[([^\]]*)\]\s*\)\s*=>\s*(.+)$/s);
|
|
1530
|
+
if (!m) return null;
|
|
1531
|
+
const slots = parseArrayDestructure(m[1], valueVars.length);
|
|
1532
|
+
let body = m[2].trim();
|
|
1533
|
+
const allowed = new Set(valueVars);
|
|
1534
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1535
|
+
const name = slots[i];
|
|
1536
|
+
if (name) body = replaceParam(body, name, valueVars[i]);
|
|
1537
|
+
}
|
|
1538
|
+
return hasFreeIdentifiers(body, allowed) ? null : body;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
870
1541
|
// src/compiler/codegen.ts
|
|
871
1542
|
function v(ctx, prefix = "_v") {
|
|
872
1543
|
return `${prefix}${ctx.vars++}`;
|
|
@@ -874,12 +1545,42 @@ function v(ctx, prefix = "_v") {
|
|
|
874
1545
|
function ind(ctx) {
|
|
875
1546
|
return " ".repeat(ctx.indent);
|
|
876
1547
|
}
|
|
1548
|
+
var NAMED_FN_FAIL = "_pfFail";
|
|
1549
|
+
var NAMED_FN_END = "_pfEnd";
|
|
1550
|
+
function namedFnPrelude() {
|
|
1551
|
+
return [`const ${NAMED_FN_FAIL} = {}`, `let ${NAMED_FN_END}`];
|
|
1552
|
+
}
|
|
1553
|
+
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
1554
|
+
ctx.namedFnDecls.push([
|
|
1555
|
+
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1556
|
+
` let _pfok = false, _pfv, _pfe = _pos`,
|
|
1557
|
+
` _pfail: {`,
|
|
1558
|
+
...bodyStmts,
|
|
1559
|
+
` _pfv = ${valueVar}; _pfe = ${endVar}; _pfok = true`,
|
|
1560
|
+
` }`,
|
|
1561
|
+
` if (!_pfok) return ${NAMED_FN_FAIL}`,
|
|
1562
|
+
` ${NAMED_FN_END} = _pfe`,
|
|
1563
|
+
` return _pfv`,
|
|
1564
|
+
`}`
|
|
1565
|
+
].join("\n"));
|
|
1566
|
+
}
|
|
1567
|
+
function emitNamedFnCall(ctx, fnName, pos, failExpected) {
|
|
1568
|
+
const vv = v(ctx, "_pfv");
|
|
1569
|
+
const ev = v(ctx, "_pfe");
|
|
1570
|
+
return {
|
|
1571
|
+
stmts: [
|
|
1572
|
+
`${ind(ctx)}const ${vv} = ${fnName}(input, ${pos}, _ctx)`,
|
|
1573
|
+
`${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, failExpected, pos).trim()}`,
|
|
1574
|
+
`${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
|
|
1575
|
+
],
|
|
1576
|
+
valueVar: vv,
|
|
1577
|
+
endVar: ev
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
877
1580
|
function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
|
|
878
1581
|
if (!ctx.capturing) return [];
|
|
1582
|
+
if (ctx.capAsTrivia) return [];
|
|
879
1583
|
const i = ind(ctx);
|
|
880
|
-
if (ctx.capAsTrivia) {
|
|
881
|
-
return [`${i}if (_ctx._cstRawChildren) _ctx._cstRawChildren.push({ _tag: 'trivia', value: ${valExpr}, span: { start: ${startExpr}, end: ${endExpr} } })`];
|
|
882
|
-
}
|
|
883
1584
|
const lf = v(ctx, "_lf");
|
|
884
1585
|
return [
|
|
885
1586
|
`${i}if (_ctx._cstLeaves) {`,
|
|
@@ -889,35 +1590,84 @@ function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
|
|
|
889
1590
|
`${i}}`
|
|
890
1591
|
];
|
|
891
1592
|
}
|
|
892
|
-
function
|
|
1593
|
+
function ensureRegexDecl(ctx, optimizedSource, flags) {
|
|
1594
|
+
const f = "y" + flags.replace(/[gy]/g, "");
|
|
1595
|
+
const key = `${optimizedSource}/${f}`;
|
|
1596
|
+
let rName = ctx.regexMap.get(key);
|
|
1597
|
+
if (rName === void 0) {
|
|
1598
|
+
rName = `_re${ctx.regexDecls.length}`;
|
|
1599
|
+
ctx.regexDecls.push(`const ${rName} = /${optimizedSource}/${f}`);
|
|
1600
|
+
ctx.regexMap.set(key, rName);
|
|
1601
|
+
}
|
|
1602
|
+
return rName;
|
|
1603
|
+
}
|
|
1604
|
+
function ensureTriviaFn(ctx) {
|
|
893
1605
|
const trivia2 = ctx.activeTrivia;
|
|
894
|
-
const existing = ctx.
|
|
1606
|
+
const existing = ctx.triviaFnNames.get(trivia2);
|
|
895
1607
|
if (existing) return existing;
|
|
896
|
-
const fnName = `
|
|
1608
|
+
const fnName = `_tf${ctx.triviaFnNames.size}`;
|
|
1609
|
+
ctx.triviaFnNames.set(trivia2, fnName);
|
|
897
1610
|
ctx.triviaCaptureNames.set(trivia2, fnName);
|
|
898
|
-
const
|
|
1611
|
+
const fastKind = analyzeTriviaFastPath(trivia2);
|
|
1612
|
+
const kindIndices = labeledTriviaKindIndices(trivia2);
|
|
1613
|
+
if (fastKind) {
|
|
1614
|
+
ctx.namedFnDecls.push(buildFastTriviaFnDecl(fnName, fastKind, kindIndices ?? void 0));
|
|
1615
|
+
return fnName;
|
|
1616
|
+
}
|
|
1617
|
+
const labeledSpec = analyzeLabeledTrivia(trivia2);
|
|
1618
|
+
if (labeledSpec) {
|
|
1619
|
+
const regexSpec = labeledTriviaRegexArms(trivia2);
|
|
1620
|
+
if (regexSpec) {
|
|
1621
|
+
const reNames = [];
|
|
1622
|
+
for (const arm of regexSpec.arms) {
|
|
1623
|
+
const def = arm.parser._def;
|
|
1624
|
+
if (def.tag !== "regex") break;
|
|
1625
|
+
reNames.push(ensureRegexDecl(ctx, def.optimizedSource, def.flags));
|
|
1626
|
+
}
|
|
1627
|
+
if (reNames.length === regexSpec.arms.length) {
|
|
1628
|
+
ctx.namedFnDecls.push(buildLabeledRegexTriviaFnDecl(fnName, regexSpec, reNames));
|
|
1629
|
+
return fnName;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
const rpStart = ctx.runtimeParsers.length;
|
|
1633
|
+
for (const arm of labeledSpec.arms) {
|
|
1634
|
+
ctx.runtimeParsers.push(arm.parser);
|
|
1635
|
+
}
|
|
1636
|
+
ctx.namedFnDecls.push(buildLabeledRuntimeTriviaFnDecl(fnName, labeledSpec, rpStart));
|
|
1637
|
+
return fnName;
|
|
1638
|
+
}
|
|
1639
|
+
const savedIndent = ctx.indent;
|
|
1640
|
+
const savedFailLabel = ctx.failLabel;
|
|
1641
|
+
const savedTrivia = ctx.activeTrivia;
|
|
1642
|
+
const savedCapAsTrivia = ctx.capAsTrivia;
|
|
899
1643
|
ctx.indent = 2;
|
|
900
|
-
ctx.failLabel = "
|
|
1644
|
+
ctx.failLabel = "_triv";
|
|
901
1645
|
ctx.capAsTrivia = true;
|
|
902
|
-
|
|
1646
|
+
ctx.activeTrivia = void 0;
|
|
903
1647
|
const r = emit(trivia2, ctx, "_pos");
|
|
904
|
-
ctx.indent =
|
|
905
|
-
ctx.failLabel =
|
|
906
|
-
ctx.capAsTrivia =
|
|
907
|
-
|
|
1648
|
+
ctx.indent = savedIndent;
|
|
1649
|
+
ctx.failLabel = savedFailLabel;
|
|
1650
|
+
ctx.capAsTrivia = savedCapAsTrivia;
|
|
1651
|
+
ctx.activeTrivia = savedTrivia;
|
|
908
1652
|
ctx.namedFnDecls.push([
|
|
909
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1653
|
+
`function ${fnName}(input, _pos, _ctx, _cap) {`,
|
|
910
1654
|
` let _e = _pos`,
|
|
911
|
-
`
|
|
1655
|
+
` _triv: {`,
|
|
912
1656
|
...r.stmts,
|
|
913
1657
|
` _e = ${r.endVar}`,
|
|
914
1658
|
` }`,
|
|
915
|
-
` if (
|
|
1659
|
+
` if (_cap && _e > _pos) {`,
|
|
1660
|
+
` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
|
|
1661
|
+
` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
1662
|
+
` }`,
|
|
916
1663
|
` return _e`,
|
|
917
1664
|
`}`
|
|
918
1665
|
].join("\n"));
|
|
919
1666
|
return fnName;
|
|
920
1667
|
}
|
|
1668
|
+
function ensureTriviaCaptureFn(ctx) {
|
|
1669
|
+
return ensureTriviaFn(ctx);
|
|
1670
|
+
}
|
|
921
1671
|
function failStmt(ctx, expected, posExpr) {
|
|
922
1672
|
if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
|
|
923
1673
|
return `${ind(ctx)}return { ok: false, expected: [${expected}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
@@ -933,14 +1683,6 @@ function firstSetCond(codeVar, fs) {
|
|
|
933
1683
|
(r) => r.lo === r.hi ? `${codeVar} === ${r.lo}` : `(${codeVar} >= ${r.lo} && ${codeVar} <= ${r.hi})`
|
|
934
1684
|
).join(" || ");
|
|
935
1685
|
}
|
|
936
|
-
function asIIFE(stmts, valueVar, endVar, startPos, indent) {
|
|
937
|
-
return [
|
|
938
|
-
`(() => {`,
|
|
939
|
-
...stmts,
|
|
940
|
-
`${indent} return { ok: true, value: ${valueVar}, span: { start: ${startPos}, end: ${endVar} } }`,
|
|
941
|
-
`${indent}})()`
|
|
942
|
-
].join("\n");
|
|
943
|
-
}
|
|
944
1686
|
function emitFallible(inner, ctx, pos) {
|
|
945
1687
|
const lbl = v(ctx, "_lbl");
|
|
946
1688
|
const okV = `${lbl}ok`;
|
|
@@ -1006,6 +1748,33 @@ function emitLit(def, ctx, pos) {
|
|
|
1006
1748
|
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1007
1749
|
return { stmts, valueVar: vv, endVar };
|
|
1008
1750
|
}
|
|
1751
|
+
function escapeKeywordRe(s) {
|
|
1752
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1753
|
+
}
|
|
1754
|
+
function emitKeywords(def, ctx, pos) {
|
|
1755
|
+
const alt = def.words.map(escapeKeywordRe).join("|");
|
|
1756
|
+
const boundary = def.boundary ? `(?![${def.boundary}])` : "";
|
|
1757
|
+
const flags = def.caseInsensitive ? "iuy" : "uy";
|
|
1758
|
+
const source = `(?:${alt})${boundary}`;
|
|
1759
|
+
const key = `${source}/${flags}`;
|
|
1760
|
+
let rName = ctx.regexMap.get(key);
|
|
1761
|
+
if (rName === void 0) {
|
|
1762
|
+
rName = `_re${ctx.regexDecls.length}`;
|
|
1763
|
+
ctx.regexDecls.push(`const ${rName} = /${source}/${flags}`);
|
|
1764
|
+
ctx.regexMap.set(key, rName);
|
|
1765
|
+
}
|
|
1766
|
+
const mv = v(ctx, "_m");
|
|
1767
|
+
const vv = v(ctx);
|
|
1768
|
+
const stmts = [
|
|
1769
|
+
`${ind(ctx)}${rName}.lastIndex = ${pos}`,
|
|
1770
|
+
`${ind(ctx)}const ${mv} = ${rName}.exec(input)`,
|
|
1771
|
+
`${ind(ctx)}if (${mv} === null) ${failStmt({ ...ctx, indent: 0 }, '"keyword"', pos).trim()}`,
|
|
1772
|
+
`${ind(ctx)}const ${vv} = ${mv}[0]`
|
|
1773
|
+
];
|
|
1774
|
+
const endVar = `${pos} + ${vv}.length`;
|
|
1775
|
+
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1776
|
+
return { stmts, valueVar: vv, endVar };
|
|
1777
|
+
}
|
|
1009
1778
|
function emitRegex(def, ctx, pos) {
|
|
1010
1779
|
const flags = "y" + def.flags.replace(/[gy]/g, "");
|
|
1011
1780
|
const key = `${def.optimizedSource}/${flags}`;
|
|
@@ -1028,31 +1797,7 @@ function emitRegex(def, ctx, pos) {
|
|
|
1028
1797
|
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1029
1798
|
return { stmts, valueVar: vv, endVar };
|
|
1030
1799
|
}
|
|
1031
|
-
function
|
|
1032
|
-
const trivia2 = ctx.activeTrivia;
|
|
1033
|
-
if (!ctx.namedParsers.has(trivia2)) {
|
|
1034
|
-
const fnName = `_pf${ctx.namedParsers.size}`;
|
|
1035
|
-
ctx.namedParsers.set(trivia2, fnName);
|
|
1036
|
-
const savedIndent = ctx.indent;
|
|
1037
|
-
const savedFailLabel = ctx.failLabel;
|
|
1038
|
-
const savedTrivia = ctx.activeTrivia;
|
|
1039
|
-
ctx.indent = 1;
|
|
1040
|
-
ctx.failLabel = void 0;
|
|
1041
|
-
delete ctx.activeTrivia;
|
|
1042
|
-
const r = emit(trivia2, ctx, "_pos");
|
|
1043
|
-
ctx.indent = savedIndent;
|
|
1044
|
-
ctx.failLabel = savedFailLabel;
|
|
1045
|
-
if (savedTrivia) ctx.activeTrivia = savedTrivia;
|
|
1046
|
-
ctx.namedFnDecls.push([
|
|
1047
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1048
|
-
...r.stmts,
|
|
1049
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
1050
|
-
`}`
|
|
1051
|
-
].join("\n"));
|
|
1052
|
-
}
|
|
1053
|
-
return ctx.namedParsers.get(trivia2);
|
|
1054
|
-
}
|
|
1055
|
-
function emitSeq(def, ctx, pos) {
|
|
1800
|
+
function emitSeqValues(def, ctx, pos) {
|
|
1056
1801
|
const startV = v(ctx, "_start");
|
|
1057
1802
|
const curV = v(ctx, "_cur");
|
|
1058
1803
|
const stmts = [
|
|
@@ -1064,23 +1809,41 @@ function emitSeq(def, ctx, pos) {
|
|
|
1064
1809
|
if (i > 0 && ctx.activeTrivia) {
|
|
1065
1810
|
if (ctx.capturing) {
|
|
1066
1811
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
const
|
|
1070
|
-
const
|
|
1812
|
+
const markV = v(ctx, "_mk");
|
|
1813
|
+
const markTl = v(ctx, "_mktl");
|
|
1814
|
+
const markLog = v(ctx, "_mklg");
|
|
1815
|
+
const scanEndV = v(ctx, "_sne");
|
|
1071
1816
|
stmts.push(
|
|
1072
|
-
`${ind(ctx)}const ${
|
|
1073
|
-
`${ind(ctx)}
|
|
1817
|
+
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
1818
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
1819
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
1820
|
+
`${ind(ctx)}const ${scanEndV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1074
1821
|
);
|
|
1822
|
+
const r2 = emit(def.parsers[i], ctx, scanEndV);
|
|
1823
|
+
stmts.push(...r2.stmts);
|
|
1824
|
+
const endAfterV = v(ctx, "_sea");
|
|
1825
|
+
stmts.push(
|
|
1826
|
+
`${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
|
|
1827
|
+
`${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}; }`
|
|
1828
|
+
);
|
|
1829
|
+
valueVars.push(r2.valueVar);
|
|
1830
|
+
continue;
|
|
1831
|
+
} else {
|
|
1832
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1833
|
+
stmts.push(`${ind(ctx)}${curV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
1075
1834
|
}
|
|
1076
1835
|
}
|
|
1077
1836
|
const r = emit(def.parsers[i], ctx, curV);
|
|
1078
1837
|
stmts.push(...r.stmts, `${ind(ctx)}${curV} = ${r.endVar}`);
|
|
1079
1838
|
valueVars.push(r.valueVar);
|
|
1080
1839
|
}
|
|
1840
|
+
return { stmts, valueVar: valueVars[valueVars.length - 1] ?? "null", endVar: curV, valueVars };
|
|
1841
|
+
}
|
|
1842
|
+
function emitSeq(def, ctx, pos) {
|
|
1843
|
+
const { stmts, endVar, valueVars } = emitSeqValues(def, ctx, pos);
|
|
1081
1844
|
const arrV = v(ctx, "_arr");
|
|
1082
1845
|
stmts.push(`${ind(ctx)}const ${arrV} = [${valueVars.join(", ")}]`);
|
|
1083
|
-
return { stmts, valueVar: arrV, endVar
|
|
1846
|
+
return { stmts, valueVar: arrV, endVar };
|
|
1084
1847
|
}
|
|
1085
1848
|
function emitChoice(def, ctx, pos) {
|
|
1086
1849
|
const allExpected = JSON.stringify(
|
|
@@ -1131,29 +1894,39 @@ function emitGreedyClassify(def, superIndex, allExpected, ctx, pos) {
|
|
|
1131
1894
|
const matchV = v(ctx, "_gm");
|
|
1132
1895
|
const wordV = v(ctx, "_gw");
|
|
1133
1896
|
const endV = v(ctx, "_ge");
|
|
1897
|
+
const valV = v(ctx, "_gcv");
|
|
1134
1898
|
const stmts = [
|
|
1135
1899
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
1136
1900
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
1137
1901
|
`${ind(ctx)}if (${matchV} === null) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`,
|
|
1138
1902
|
`${ind(ctx)}const ${wordV} = ${matchV}[0]`,
|
|
1139
|
-
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length
|
|
1903
|
+
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`,
|
|
1904
|
+
`${ind(ctx)}let ${valV}`
|
|
1140
1905
|
];
|
|
1906
|
+
let first = true;
|
|
1141
1907
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
1142
1908
|
if (i === superIndex) continue;
|
|
1143
1909
|
const p = def.parsers[i];
|
|
1144
1910
|
const litVal = getCoreLiteralValue(p);
|
|
1145
1911
|
if (litVal === null) continue;
|
|
1146
|
-
|
|
1912
|
+
const kw = first ? "if" : "else if";
|
|
1913
|
+
first = false;
|
|
1914
|
+
stmts.push(`${ind(ctx)}${kw} (${wordV} === ${JSON.stringify(litVal)}) {`);
|
|
1147
1915
|
ctx.indent++;
|
|
1148
1916
|
const tR = emitTransformChain(p, JSON.stringify(litVal), endV, pos, ctx);
|
|
1149
|
-
stmts.push(...
|
|
1150
|
-
stmts.push(`${ind(ctx)}
|
|
1917
|
+
stmts.push(...emitLeafCapture(ctx, JSON.stringify(litVal), pos, endV));
|
|
1918
|
+
stmts.push(...tR.stmts, `${ind(ctx)}${valV} = ${tR.valueVar}`);
|
|
1151
1919
|
ctx.indent--;
|
|
1152
1920
|
stmts.push(`${ind(ctx)}}`);
|
|
1153
1921
|
}
|
|
1154
1922
|
const rR = emitTransformChain(superParser, wordV, endV, pos, ctx);
|
|
1155
|
-
|
|
1156
|
-
|
|
1923
|
+
const regexKw = first ? "if" : "else";
|
|
1924
|
+
stmts.push(`${ind(ctx)}${regexKw} {`);
|
|
1925
|
+
ctx.indent++;
|
|
1926
|
+
stmts.push(...emitLeafCapture(ctx, wordV, pos, endV), ...rR.stmts, `${ind(ctx)}${valV} = ${rR.valueVar}`);
|
|
1927
|
+
ctx.indent--;
|
|
1928
|
+
stmts.push(`${ind(ctx)}}`);
|
|
1929
|
+
return { stmts, valueVar: valV, endVar: endV };
|
|
1157
1930
|
}
|
|
1158
1931
|
function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
1159
1932
|
const valV = v(ctx, "_llv");
|
|
@@ -1167,10 +1940,15 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
1167
1940
|
const litCond = emitLiteralCondition(litVal, pos);
|
|
1168
1941
|
const kw = first ? "if" : "else if";
|
|
1169
1942
|
first = false;
|
|
1943
|
+
const litEnd = `${pos} + ${litLen}`;
|
|
1170
1944
|
stmts.push(`${ind(ctx)}${kw} (${litCond}) {`);
|
|
1171
1945
|
ctx.indent++;
|
|
1172
|
-
const tR = emitTransformChain(p, JSON.stringify(litVal),
|
|
1173
|
-
stmts.push(
|
|
1946
|
+
const tR = emitTransformChain(p, JSON.stringify(litVal), litEnd, pos, ctx);
|
|
1947
|
+
stmts.push(
|
|
1948
|
+
...emitLeafCapture(ctx, JSON.stringify(litVal), pos, litEnd),
|
|
1949
|
+
...tR.stmts,
|
|
1950
|
+
`${ind(ctx)}${valV} = ${tR.valueVar}; ${endV} = ${litEnd}`
|
|
1951
|
+
);
|
|
1174
1952
|
ctx.indent--;
|
|
1175
1953
|
stmts.push(`${ind(ctx)}}`);
|
|
1176
1954
|
}
|
|
@@ -1178,67 +1956,66 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
1178
1956
|
return { stmts, valueVar: valV, endVar: endV };
|
|
1179
1957
|
}
|
|
1180
1958
|
function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
1181
|
-
const
|
|
1182
|
-
const
|
|
1959
|
+
const resValV = v(ctx, "_crv");
|
|
1960
|
+
const resEndV = v(ctx, "_cre");
|
|
1961
|
+
const resOkV = v(ctx, "_crok");
|
|
1962
|
+
const ind0 = ind(ctx);
|
|
1963
|
+
const stmts = [
|
|
1964
|
+
`${ind0}let ${resValV}, ${resEndV} = ${pos}, ${resOkV} = false`
|
|
1965
|
+
];
|
|
1183
1966
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
1184
1967
|
const p = def.parsers[i];
|
|
1185
1968
|
const gate = def.gates[i];
|
|
1186
1969
|
const autoNot = def.autoNot[i];
|
|
1187
|
-
const savedIndent = ctx.indent;
|
|
1188
|
-
const savedFailLabel = ctx.failLabel;
|
|
1189
|
-
ctx.indent = 0;
|
|
1190
|
-
ctx.failLabel = void 0;
|
|
1191
|
-
const r = emit(p, ctx, pos);
|
|
1192
|
-
ctx.indent = savedIndent;
|
|
1193
|
-
ctx.failLabel = savedFailLabel;
|
|
1194
|
-
const iife = asIIFE(r.stmts, r.valueVar, r.endVar, pos, ind(ctx));
|
|
1195
1970
|
let gateCond = null;
|
|
1196
1971
|
if (gate) {
|
|
1197
1972
|
const gateIdx = ctx.mapFns.length;
|
|
1198
1973
|
ctx.mapFns.push(gate);
|
|
1199
1974
|
gateCond = `_mf[${gateIdx}](_ctx.state)`;
|
|
1200
1975
|
}
|
|
1201
|
-
const skipCond = gateCond ? `!${
|
|
1976
|
+
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
1202
1977
|
const markLeaves = ctx.capturing ? v(ctx, "_cml") : null;
|
|
1203
1978
|
const markRaw = ctx.capturing ? v(ctx, "_cmr") : null;
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
const
|
|
1979
|
+
const markTl = ctx.capturing ? v(ctx, "_cmtl") : null;
|
|
1980
|
+
const markLog = ctx.capturing ? v(ctx, "_cmlg") : null;
|
|
1981
|
+
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}` : "";
|
|
1982
|
+
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
1983
|
+
ctx.indent++;
|
|
1984
|
+
const ind1 = ind(ctx);
|
|
1985
|
+
if (markLeaves) {
|
|
1986
|
+
stmts.push(
|
|
1987
|
+
`${ind1}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
1988
|
+
`${ind1}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
1989
|
+
`${ind1}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
1990
|
+
`${ind1}const ${markLog} = _ctx._triviaLog?.length ?? 0`
|
|
1991
|
+
);
|
|
1992
|
+
}
|
|
1993
|
+
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos);
|
|
1994
|
+
stmts.push(...armStmts);
|
|
1995
|
+
ctx.indent--;
|
|
1210
1996
|
if (autoNot && autoNot.length > 0) {
|
|
1211
|
-
const tmp = v(ctx, "_ct");
|
|
1212
1997
|
const anCode = v(ctx, "_anc");
|
|
1213
1998
|
const rejectCond = autoNot.map(
|
|
1214
|
-
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${
|
|
1999
|
+
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${endVar})`
|
|
1215
2000
|
).join(" || ");
|
|
1216
|
-
stmts.push(`${ind(ctx)}if (${skipCond}) {`);
|
|
1217
|
-
stmts.push(...markStmts);
|
|
1218
2001
|
stmts.push(
|
|
1219
|
-
`${
|
|
1220
|
-
`${ind(ctx)} if (${tmp}?.ok) { const ${anCode} = ${tmp}.span.end < input.length ? input.charCodeAt(${tmp}.span.end) : -1; if (!(${rejectCond})) ${resV} = ${tmp} }`
|
|
2002
|
+
`${ind0} if (${okVar}) { const ${anCode} = ${endVar} < input.length ? input.charCodeAt(${endVar}) : -1; if (!(${rejectCond})) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true } }`
|
|
1221
2003
|
);
|
|
1222
|
-
if (
|
|
1223
|
-
stmts.push(`${ind(ctx)}}`);
|
|
2004
|
+
if (rollback) stmts.push(`${ind0} if (!${resOkV}) { ${rollback} }`);
|
|
1224
2005
|
} else {
|
|
1225
|
-
stmts.push(`${
|
|
1226
|
-
stmts.push(
|
|
1227
|
-
stmts.push(`${ind(ctx)} try { ${resV} = ${iife} } catch {}`);
|
|
1228
|
-
if (rollbackStmt) stmts.push(rollbackStmt);
|
|
1229
|
-
stmts.push(`${ind(ctx)}}`);
|
|
2006
|
+
stmts.push(`${ind0} if (${okVar}) { ${resValV} = ${valVar}; ${resEndV} = ${endVar}; ${resOkV} = true }`);
|
|
2007
|
+
if (rollback) stmts.push(`${ind0} else { ${rollback} }`);
|
|
1230
2008
|
}
|
|
2009
|
+
stmts.push(`${ind0}}`);
|
|
1231
2010
|
}
|
|
1232
|
-
stmts.push(`${
|
|
1233
|
-
return { stmts, valueVar:
|
|
2011
|
+
stmts.push(`${ind0}if (!${resOkV}) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
|
|
2012
|
+
return { stmts, valueVar: resValV, endVar: resEndV };
|
|
1234
2013
|
}
|
|
1235
2014
|
function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
1236
|
-
if (
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
1241
|
-
}
|
|
2015
|
+
if (strategy.tag === "greedyClassify")
|
|
2016
|
+
return emitGreedyClassify(def, strategy.superIndex, allExpected, ctx, pos);
|
|
2017
|
+
if (strategy.tag === "literalsLongestFirst")
|
|
2018
|
+
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
1242
2019
|
return emitFirstMatch(def, allExpected, ctx, pos);
|
|
1243
2020
|
}
|
|
1244
2021
|
function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
@@ -1291,27 +2068,28 @@ function emitMany(def, ctx, pos) {
|
|
|
1291
2068
|
if (ctx.capturing) {
|
|
1292
2069
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1293
2070
|
const markV = v(ctx, "_mk");
|
|
2071
|
+
const markTl = v(ctx, "_mktl");
|
|
2072
|
+
const markLog = v(ctx, "_mklg");
|
|
1294
2073
|
const npV = v(ctx, "_np");
|
|
1295
2074
|
stmts.push(
|
|
1296
2075
|
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
1297
|
-
`${ind(ctx)}const ${
|
|
2076
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2077
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2078
|
+
`${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1298
2079
|
);
|
|
1299
2080
|
itemPos = npV;
|
|
1300
|
-
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
2081
|
+
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
|
|
1301
2082
|
} else {
|
|
1302
2083
|
const trivFn = ensureTriviaFn(ctx);
|
|
1303
2084
|
const npV = v(ctx, "_np");
|
|
1304
|
-
stmts.push(
|
|
1305
|
-
`${ind(ctx)}let ${npV} = ${curV}`,
|
|
1306
|
-
`${ind(ctx)}{ const _trv = ${trivFn}(input, ${npV}, _ctx); if (_trv.ok) ${npV} = _trv.span.end }`
|
|
1307
|
-
);
|
|
2085
|
+
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
1308
2086
|
itemPos = npV;
|
|
1309
2087
|
}
|
|
1310
2088
|
}
|
|
1311
2089
|
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
1312
2090
|
stmts.push(
|
|
1313
2091
|
...iterStmts,
|
|
1314
|
-
`${ind(ctx)}if (!${iterOk} || ${iterEnd}
|
|
2092
|
+
`${ind(ctx)}if (!${iterOk} || ${iterEnd} <= ${itemPos}) { ${rollback}break }`,
|
|
1315
2093
|
`${ind(ctx)}${arrV}.push(${iterVal})`,
|
|
1316
2094
|
`${ind(ctx)}${curV} = ${iterEnd}`
|
|
1317
2095
|
);
|
|
@@ -1348,55 +2126,70 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
1348
2126
|
`${ind(ctx)}while (${curV} < input.length) {`
|
|
1349
2127
|
);
|
|
1350
2128
|
ctx.indent++;
|
|
1351
|
-
let rollback = "";
|
|
1352
|
-
if (ctx.capturing) {
|
|
1353
|
-
const markV = v(ctx, "_mk");
|
|
1354
|
-
stmts.push(`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`);
|
|
1355
|
-
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
1356
|
-
}
|
|
1357
2129
|
let sepAtPos = curV;
|
|
1358
2130
|
if (ctx.activeTrivia) {
|
|
1359
2131
|
if (ctx.capturing) {
|
|
1360
2132
|
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
} else {
|
|
1365
|
-
const trivFn = ensureTriviaFn(ctx);
|
|
2133
|
+
const markV = v(ctx, "_mk");
|
|
2134
|
+
const markTl = v(ctx, "_mktl");
|
|
2135
|
+
const markLog = v(ctx, "_mklg");
|
|
1366
2136
|
const spV = v(ctx, "_sp");
|
|
1367
2137
|
stmts.push(
|
|
1368
|
-
`${ind(ctx)}
|
|
1369
|
-
`${ind(ctx)}
|
|
2138
|
+
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
2139
|
+
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2140
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2141
|
+
`${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
|
|
1370
2142
|
);
|
|
1371
2143
|
sepAtPos = spV;
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
if (ctx.capturing) {
|
|
1379
|
-
const capFn = ensureTriviaCaptureFn(ctx);
|
|
2144
|
+
const sepRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
|
|
2145
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2146
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sepRollback}break }`);
|
|
2147
|
+
const mark2V = v(ctx, "_mk2");
|
|
2148
|
+
const mark2Tl = v(ctx, "_mktl2");
|
|
2149
|
+
const mark2Log = v(ctx, "_mklg2");
|
|
1380
2150
|
const npV = v(ctx, "_np");
|
|
1381
|
-
stmts.push(
|
|
1382
|
-
|
|
2151
|
+
stmts.push(
|
|
2152
|
+
`${ind(ctx)}const ${mark2V} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
2153
|
+
`${ind(ctx)}const ${mark2Tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
|
|
2154
|
+
`${ind(ctx)}const ${mark2Log} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
|
|
2155
|
+
`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx, 1)`
|
|
2156
|
+
);
|
|
2157
|
+
const nextRollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mark2V}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mark2Tl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mark2Log}; `;
|
|
2158
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
2159
|
+
stmts.push(
|
|
2160
|
+
...nextStmts,
|
|
2161
|
+
`${ind(ctx)}if (!${nextOk}) { ${nextRollback}break }`,
|
|
2162
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2163
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
2164
|
+
);
|
|
1383
2165
|
} else {
|
|
1384
2166
|
const trivFn = ensureTriviaFn(ctx);
|
|
2167
|
+
const spV = v(ctx, "_sp");
|
|
2168
|
+
stmts.push(`${ind(ctx)}const ${spV} = ${trivFn}(input, ${curV}, _ctx)`);
|
|
2169
|
+
sepAtPos = spV;
|
|
2170
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2171
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
1385
2172
|
const npV = v(ctx, "_np");
|
|
2173
|
+
stmts.push(`${ind(ctx)}const ${npV} = ${trivFn}(input, ${sepEnd}, _ctx)`);
|
|
2174
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, npV);
|
|
1386
2175
|
stmts.push(
|
|
1387
|
-
|
|
1388
|
-
`${ind(ctx)}
|
|
2176
|
+
...nextStmts,
|
|
2177
|
+
`${ind(ctx)}if (!${nextOk}) break`,
|
|
2178
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2179
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
1389
2180
|
);
|
|
1390
|
-
nextAtPos = npV;
|
|
1391
2181
|
}
|
|
2182
|
+
} else {
|
|
2183
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
2184
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
|
|
2185
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd);
|
|
2186
|
+
stmts.push(
|
|
2187
|
+
...nextStmts,
|
|
2188
|
+
`${ind(ctx)}if (!${nextOk}) break`,
|
|
2189
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
2190
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
2191
|
+
);
|
|
1392
2192
|
}
|
|
1393
|
-
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, nextAtPos);
|
|
1394
|
-
stmts.push(
|
|
1395
|
-
...nextStmts,
|
|
1396
|
-
`${ind(ctx)}if (!${nextOk}) { ${rollback}break }`,
|
|
1397
|
-
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
1398
|
-
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
1399
|
-
);
|
|
1400
2193
|
ctx.indent--;
|
|
1401
2194
|
stmts.push(`${ind(ctx)}}`);
|
|
1402
2195
|
ctx.indent--;
|
|
@@ -1458,27 +2251,33 @@ function emitNot(def, ctx, pos) {
|
|
|
1458
2251
|
};
|
|
1459
2252
|
}
|
|
1460
2253
|
function emitNode(def, ctx, pos) {
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
2254
|
+
const mkType = analyzeMkInlineBuild(def);
|
|
2255
|
+
let buildIdx = null;
|
|
2256
|
+
if (!mkType) {
|
|
2257
|
+
buildIdx = ctx.buildFns.length;
|
|
2258
|
+
ctx.buildFns.push(def.build);
|
|
2259
|
+
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
2260
|
+
}
|
|
1464
2261
|
const i = ind(ctx);
|
|
1465
2262
|
const chV = v(ctx, "_ch");
|
|
1466
2263
|
const rawV = v(ctx, "_raw");
|
|
1467
|
-
const
|
|
2264
|
+
const tlV = v(ctx, "_tl");
|
|
2265
|
+
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
1468
2266
|
const stmts = [
|
|
1469
|
-
`${i}const ${chV} = [], ${rawV} = []`,
|
|
1470
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia`,
|
|
1471
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true`
|
|
2267
|
+
`${i}const ${chV} = [], ${rawV} = [], ${tlV} = []`,
|
|
2268
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
2269
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${tlV}`
|
|
1472
2270
|
];
|
|
1473
2271
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
1474
2272
|
stmts.push(...innerStmts);
|
|
1475
|
-
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}`);
|
|
2273
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
|
|
1476
2274
|
stmts.push(`${i}if (!${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"node"', pos).trim()}`);
|
|
2275
|
+
const stV = v(ctx, "_nst");
|
|
2276
|
+
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
1477
2277
|
const ndV = v(ctx, "_nd");
|
|
2278
|
+
const ndExpr = mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `_build[${buildIdx}](${chV}, ${rawV}, { start: ${pos}, end: ${endVar} }, ${tlV}, ${stV})`;
|
|
1478
2279
|
stmts.push(
|
|
1479
|
-
`${i}const ${ndV} =
|
|
1480
|
-
// Record into the caller's collectors (the node in children; the node, or a
|
|
1481
|
-
// spanned leaf if build collapsed to a non-node value, in rawChildren).
|
|
2280
|
+
`${i}const ${ndV} = ${ndExpr}`,
|
|
1482
2281
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
1483
2282
|
`${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} } })`
|
|
1484
2283
|
);
|
|
@@ -1512,31 +2311,14 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
1512
2311
|
const savedIndent = ctx.indent;
|
|
1513
2312
|
const savedFailLabel = ctx.failLabel;
|
|
1514
2313
|
ctx.indent = 1;
|
|
1515
|
-
ctx.failLabel =
|
|
2314
|
+
ctx.failLabel = "_pfail";
|
|
1516
2315
|
const r = emit(resolved, ctx, "_pos");
|
|
1517
2316
|
ctx.indent = savedIndent;
|
|
1518
2317
|
ctx.failLabel = savedFailLabel;
|
|
1519
|
-
ctx.
|
|
1520
|
-
`function ${fnName2}(input, _pos, _ctx) {`,
|
|
1521
|
-
...r.stmts,
|
|
1522
|
-
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
1523
|
-
`}`
|
|
1524
|
-
].join("\n"));
|
|
2318
|
+
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar);
|
|
1525
2319
|
}
|
|
1526
2320
|
const fnName = ctx.namedParsers.get(p);
|
|
1527
|
-
|
|
1528
|
-
const vv = v(ctx, "_pfv");
|
|
1529
|
-
const ev = v(ctx, "_pfe");
|
|
1530
|
-
return {
|
|
1531
|
-
stmts: [
|
|
1532
|
-
`${ind(ctx)}const ${rv} = ${fnName}(input, ${pos}, _ctx)`,
|
|
1533
|
-
`${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"parser"', pos).trim()}`,
|
|
1534
|
-
`${ind(ctx)}const ${vv} = ${rv}.value`,
|
|
1535
|
-
`${ind(ctx)}const ${ev} = ${rv}.span.end`
|
|
1536
|
-
],
|
|
1537
|
-
valueVar: vv,
|
|
1538
|
-
endVar: ev
|
|
1539
|
-
};
|
|
2321
|
+
return emitNamedFnCall(ctx, fnName, pos, '"parser"');
|
|
1540
2322
|
}
|
|
1541
2323
|
function emitRecover(def, ctx, pos) {
|
|
1542
2324
|
const { stmts: innerStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
@@ -1572,6 +2354,8 @@ function emit(p, ctx, pos) {
|
|
|
1572
2354
|
return emitLit(def, ctx, pos);
|
|
1573
2355
|
case "regex":
|
|
1574
2356
|
return emitRegex(def, ctx, pos);
|
|
2357
|
+
case "keywords":
|
|
2358
|
+
return emitKeywords(def, ctx, pos);
|
|
1575
2359
|
case "sequence":
|
|
1576
2360
|
return emitSeq(def, ctx, pos);
|
|
1577
2361
|
case "choice":
|
|
@@ -1584,7 +2368,31 @@ function emit(p, ctx, pos) {
|
|
|
1584
2368
|
case "sepBy":
|
|
1585
2369
|
return emitSepBy(p, def, ctx, pos);
|
|
1586
2370
|
case "transform": {
|
|
2371
|
+
const fnSrc = transformFnSource(def.fn, def.fnSrc);
|
|
2372
|
+
if (fnSrc && def.parser._def.tag === "sequence") {
|
|
2373
|
+
const seqR = emitSeqValues(def.parser._def, ctx, pos);
|
|
2374
|
+
const inlined = tryInlineDestructureTransform(fnSrc, seqR.valueVars);
|
|
2375
|
+
if (inlined) {
|
|
2376
|
+
const mv2 = v(ctx, "_mapped");
|
|
2377
|
+
return {
|
|
2378
|
+
stmts: [...seqR.stmts, `${ind(ctx)}const ${mv2} = ${inlined}`],
|
|
2379
|
+
valueVar: mv2,
|
|
2380
|
+
endVar: seqR.endVar
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
1587
2384
|
const inner = emit(def.parser, ctx, pos);
|
|
2385
|
+
if (fnSrc) {
|
|
2386
|
+
const unary = tryInlineUnaryTransform(fnSrc, inner.valueVar);
|
|
2387
|
+
if (unary) {
|
|
2388
|
+
const mv2 = v(ctx, "_mapped");
|
|
2389
|
+
return {
|
|
2390
|
+
stmts: [...inner.stmts, `${ind(ctx)}const ${mv2} = ${unary}`],
|
|
2391
|
+
valueVar: mv2,
|
|
2392
|
+
endVar: inner.endVar
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
1588
2396
|
const fnIdx = ctx.mapFns.length;
|
|
1589
2397
|
ctx.mapFns.push(def.fn);
|
|
1590
2398
|
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
@@ -1620,12 +2428,20 @@ function emit(p, ctx, pos) {
|
|
|
1620
2428
|
return emitLazy(p, def, ctx, pos);
|
|
1621
2429
|
case "trivia":
|
|
1622
2430
|
return emit(def.parser, ctx, pos);
|
|
2431
|
+
case "label":
|
|
2432
|
+
return emit(def.parser, ctx, pos);
|
|
1623
2433
|
case "grammar": {
|
|
1624
2434
|
const savedTrivia = ctx.activeTrivia;
|
|
1625
|
-
|
|
2435
|
+
const savedKindLabels = ctx.triviaKindLabels;
|
|
2436
|
+
if (def.triviaParser) {
|
|
2437
|
+
ctx.activeTrivia = def.triviaParser;
|
|
2438
|
+
if (def.triviaParser._meta.triviaKindLabels) {
|
|
2439
|
+
ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
1626
2442
|
const r = emit(def.parser, ctx, pos);
|
|
1627
|
-
|
|
1628
|
-
|
|
2443
|
+
ctx.activeTrivia = savedTrivia;
|
|
2444
|
+
ctx.triviaKindLabels = savedKindLabels;
|
|
1629
2445
|
return r;
|
|
1630
2446
|
}
|
|
1631
2447
|
case "not":
|
|
@@ -1660,27 +2476,22 @@ function emit(p, ctx, pos) {
|
|
|
1660
2476
|
const savedIndent = ctx.indent;
|
|
1661
2477
|
const savedFailLabel = ctx.failLabel;
|
|
1662
2478
|
ctx.indent = 1;
|
|
1663
|
-
ctx.failLabel =
|
|
2479
|
+
ctx.failLabel = "_pfail";
|
|
1664
2480
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
1665
2481
|
ctx.indent = savedIndent;
|
|
1666
2482
|
ctx.failLabel = savedFailLabel;
|
|
1667
|
-
ctx.
|
|
1668
|
-
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1669
|
-
...innerR.stmts,
|
|
1670
|
-
` return { ok: true, value: ${innerR.valueVar}, span: { start: _pos, end: ${innerR.endVar} } }`,
|
|
1671
|
-
`}`
|
|
1672
|
-
].join("\n"));
|
|
2483
|
+
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
1673
2484
|
}
|
|
1674
2485
|
const fn = ctx.namedParsers.get(innerParser);
|
|
1675
2486
|
const rv = v(ctx, "_wcr");
|
|
1676
|
-
const vv = v(ctx);
|
|
2487
|
+
const vv = v(ctx, "_wcv");
|
|
1677
2488
|
const ev = v(ctx, "_wce");
|
|
1678
2489
|
return {
|
|
1679
2490
|
stmts: [
|
|
1680
|
-
`${ind(ctx)}const ${rv} =
|
|
1681
|
-
`${ind(ctx)}
|
|
1682
|
-
`${ind(ctx)}
|
|
1683
|
-
`${ind(ctx)}const ${ev} = ${
|
|
2491
|
+
`${ind(ctx)}const ${rv} = { ..._ctx, state: _mf[${evIdx}]() }`,
|
|
2492
|
+
`${ind(ctx)}const ${vv} = ${fn}(input, ${pos}, ${rv})`,
|
|
2493
|
+
`${ind(ctx)}if (${vv} === ${NAMED_FN_FAIL}) ${failStmt({ ...ctx, indent: 0 }, '"withCtx"', pos).trim()}`,
|
|
2494
|
+
`${ind(ctx)}const ${ev} = ${NAMED_FN_END}`
|
|
1684
2495
|
],
|
|
1685
2496
|
valueVar: vv,
|
|
1686
2497
|
endVar: ev
|
|
@@ -1706,6 +2517,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
1706
2517
|
}
|
|
1707
2518
|
case "grammar":
|
|
1708
2519
|
case "trivia":
|
|
2520
|
+
case "label":
|
|
1709
2521
|
case "optional":
|
|
1710
2522
|
case "many":
|
|
1711
2523
|
case "oneOrMore":
|
|
@@ -1729,7 +2541,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
1729
2541
|
return false;
|
|
1730
2542
|
}
|
|
1731
2543
|
}
|
|
1732
|
-
function compile(
|
|
2544
|
+
function compile(combinator, mapFnSources) {
|
|
1733
2545
|
const ctx = {
|
|
1734
2546
|
vars: 0,
|
|
1735
2547
|
indent: 1,
|
|
@@ -1743,15 +2555,18 @@ function compile(parser2, mapFnSources) {
|
|
|
1743
2555
|
needsCollator: false,
|
|
1744
2556
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
1745
2557
|
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
2558
|
+
triviaFnNames: /* @__PURE__ */ new Map(),
|
|
1746
2559
|
namedFnDecls: [],
|
|
1747
|
-
capturing: hasNodeDef(
|
|
2560
|
+
capturing: hasNodeDef(combinator)
|
|
1748
2561
|
};
|
|
1749
|
-
const r = emit(
|
|
2562
|
+
const r = emit(combinator, ctx, "_pos");
|
|
1750
2563
|
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
1751
2564
|
` : "";
|
|
2565
|
+
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
1752
2566
|
const source = [
|
|
1753
2567
|
...ctx.regexDecls,
|
|
1754
2568
|
"",
|
|
2569
|
+
...namedPrelude,
|
|
1755
2570
|
...ctx.namedFnDecls,
|
|
1756
2571
|
`${collatorDecl}function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
1757
2572
|
` let pos = _pos`,
|
|
@@ -1762,12 +2577,16 @@ function compile(parser2, mapFnSources) {
|
|
|
1762
2577
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
1763
2578
|
...ctx.regexDecls,
|
|
1764
2579
|
collatorDecl,
|
|
2580
|
+
...namedPrelude,
|
|
1765
2581
|
...ctx.namedFnDecls,
|
|
1766
2582
|
`let pos = _pos`,
|
|
1767
2583
|
...r.stmts,
|
|
1768
2584
|
`return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
1769
2585
|
].join("\n"));
|
|
1770
|
-
const defaultCtx = {
|
|
2586
|
+
const defaultCtx = {
|
|
2587
|
+
trackLines: false,
|
|
2588
|
+
...ctx.triviaKindLabels ? { triviaKindLabels: ctx.triviaKindLabels } : {}
|
|
2589
|
+
};
|
|
1771
2590
|
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
1772
2591
|
const effectiveSources = mapFnSources ?? derivedSrcs;
|
|
1773
2592
|
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
@@ -1781,6 +2600,9 @@ function compile(parser2, mapFnSources) {
|
|
|
1781
2600
|
parse(input, pos = 0) {
|
|
1782
2601
|
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
|
|
1783
2602
|
},
|
|
2603
|
+
parseWithContext(input, parseCtx, pos = 0) {
|
|
2604
|
+
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, parseCtx);
|
|
2605
|
+
},
|
|
1784
2606
|
parseWithErrors(input, pos = 0) {
|
|
1785
2607
|
const errors = [];
|
|
1786
2608
|
const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
|
|
@@ -1803,12 +2625,14 @@ function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources)
|
|
|
1803
2625
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
1804
2626
|
const needsWrapper = ctx.regexDecls.length > 0 || !!collatorDecl || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl;
|
|
1805
2627
|
if (!needsWrapper) return innerFn;
|
|
2628
|
+
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
1806
2629
|
return [
|
|
1807
2630
|
`/* @__PURE__ */ (() => {`,
|
|
1808
2631
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
1809
2632
|
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
1810
2633
|
mfDecl,
|
|
1811
2634
|
buildDecl,
|
|
2635
|
+
...namedPrelude.map((l) => ` ${l}`),
|
|
1812
2636
|
...ctx.namedFnDecls.flatMap((f) => f.split("\n").map((l) => ` ${l}`)),
|
|
1813
2637
|
` return ${innerFn}`,
|
|
1814
2638
|
`})()`
|
|
@@ -1830,10 +2654,9 @@ function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
|
1830
2654
|
let cur = pos;
|
|
1831
2655
|
const probeCtx = { trackLines: ctx.trackLines, state: ctx.state };
|
|
1832
2656
|
const emit2 = (end) => {
|
|
1833
|
-
if (end > pos && (ctx
|
|
2657
|
+
if (end > pos && cstCaptureActive(ctx)) {
|
|
1834
2658
|
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
1835
|
-
|
|
1836
|
-
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
2659
|
+
pushCstLeaf(ctx, leaf);
|
|
1837
2660
|
}
|
|
1838
2661
|
};
|
|
1839
2662
|
while (cur < input.length) {
|
|
@@ -1876,16 +2699,22 @@ function balanced(open, close, options = {}) {
|
|
|
1876
2699
|
}
|
|
1877
2700
|
|
|
1878
2701
|
// src/plugin/evaluator.ts
|
|
2702
|
+
function isWordFactory(v2) {
|
|
2703
|
+
return !!v2 && typeof v2 === "object" && v2.tag === "wordFactory";
|
|
2704
|
+
}
|
|
1879
2705
|
var SUPPORTED = {
|
|
1880
2706
|
literal: (...a) => literal(a[0], a[1]),
|
|
1881
2707
|
regex: (...a) => regex(a[0], a[1]),
|
|
2708
|
+
keywords: (...a) => keywords(a[0], a[1]),
|
|
2709
|
+
word: (...a) => word(a[0], a[1]),
|
|
1882
2710
|
sequence: (...a) => sequence(...a),
|
|
1883
2711
|
choice: (...a) => choice(...a),
|
|
1884
2712
|
many: (...a) => many(a[0]),
|
|
1885
2713
|
oneOrMore: (...a) => oneOrMore(a[0]),
|
|
1886
2714
|
optional: (...a) => optional(a[0]),
|
|
1887
2715
|
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
1888
|
-
trivia: (...a) => trivia(a[0])
|
|
2716
|
+
trivia: (...a) => trivia(a[0]),
|
|
2717
|
+
label: (...a) => label(a[0], a[1])
|
|
1889
2718
|
};
|
|
1890
2719
|
function isScopeEntry(v2) {
|
|
1891
2720
|
return !!v2 && typeof v2 === "object" && "combi" in v2 && "mfSrcs" in v2;
|
|
@@ -1907,6 +2736,33 @@ function exprToCombi(node2, scope, code, mfs) {
|
|
|
1907
2736
|
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
1908
2737
|
if (node2.type !== "CallExpression") return null;
|
|
1909
2738
|
const callee = node2.callee;
|
|
2739
|
+
if (callee.type === "CallExpression" && callee.callee.type === "Identifier" && callee.callee.name === "makeWord") {
|
|
2740
|
+
const boundaryArg = callee.arguments[0];
|
|
2741
|
+
const strArg = node2.arguments[0];
|
|
2742
|
+
if (!strArg || strArg.type === "SpreadElement") return null;
|
|
2743
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code, mfs) : "_0-9A-Za-z";
|
|
2744
|
+
const str = anyValue(strArg, scope, code, mfs);
|
|
2745
|
+
if (typeof boundary !== "string" || typeof str !== "string") return null;
|
|
2746
|
+
try {
|
|
2747
|
+
return word(str, boundary);
|
|
2748
|
+
} catch {
|
|
2749
|
+
return null;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
if (callee.type === "Identifier") {
|
|
2753
|
+
const factory2 = scope.get(callee.name);
|
|
2754
|
+
if (isWordFactory(factory2)) {
|
|
2755
|
+
const [strArg] = node2.arguments;
|
|
2756
|
+
if (!strArg || strArg.type === "SpreadElement") return null;
|
|
2757
|
+
const str = anyValue(strArg, scope, code, mfs);
|
|
2758
|
+
if (typeof str !== "string") return null;
|
|
2759
|
+
try {
|
|
2760
|
+
return word(str, factory2.boundary);
|
|
2761
|
+
} catch {
|
|
2762
|
+
return null;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
1910
2766
|
if (callee.type !== "Identifier") return null;
|
|
1911
2767
|
if (callee.name === "transform" && code !== void 0 && mfs !== void 0) {
|
|
1912
2768
|
const [parserArg, fnArg] = node2.arguments;
|
|
@@ -2083,9 +2939,27 @@ function anyValue(node2, scope, code, mfs) {
|
|
|
2083
2939
|
if (!propName) return null;
|
|
2084
2940
|
return obj[propName] ?? null;
|
|
2085
2941
|
}
|
|
2086
|
-
if (node2.type === "CallExpression")
|
|
2942
|
+
if (node2.type === "CallExpression") {
|
|
2943
|
+
const callee = node2.callee;
|
|
2944
|
+
if (callee.type === "Identifier" && callee.name === "makeWord") {
|
|
2945
|
+
const boundaryArg = node2.arguments[0];
|
|
2946
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code, mfs) : "_0-9A-Za-z";
|
|
2947
|
+
if (typeof boundary !== "string") return null;
|
|
2948
|
+
return { tag: "wordFactory", boundary };
|
|
2949
|
+
}
|
|
2950
|
+
return exprToCombi(node2, scope, code, mfs);
|
|
2951
|
+
}
|
|
2087
2952
|
return null;
|
|
2088
2953
|
}
|
|
2954
|
+
function evaluateWordFactory(node2, scope, code) {
|
|
2955
|
+
if (node2.type !== "CallExpression") return null;
|
|
2956
|
+
const callee = node2.callee;
|
|
2957
|
+
if (callee.type !== "Identifier" || callee.name !== "makeWord") return null;
|
|
2958
|
+
const boundaryArg = node2.arguments[0];
|
|
2959
|
+
const boundary = boundaryArg && boundaryArg.type !== "SpreadElement" ? anyValue(boundaryArg, scope, code) : "_0-9A-Za-z";
|
|
2960
|
+
if (typeof boundary !== "string") return null;
|
|
2961
|
+
return { tag: "wordFactory", boundary };
|
|
2962
|
+
}
|
|
2089
2963
|
function evaluateExpr(node2, scope, code, mapFnSources) {
|
|
2090
2964
|
return exprToCombi(node2, scope, code, mapFnSources);
|
|
2091
2965
|
}
|
|
@@ -2243,23 +3117,23 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
2243
3117
|
anyUnresolved = true;
|
|
2244
3118
|
warnings.push(`${id}:${lineOf(pos)} \u2014 ${msg} (running via the interpreter; add the plugin or simplify the declaration to compile it)`);
|
|
2245
3119
|
};
|
|
2246
|
-
const compileRulesFactory = (init,
|
|
3120
|
+
const compileRulesFactory = (init, label2) => {
|
|
2247
3121
|
const args = init.arguments;
|
|
2248
3122
|
const factoryArg = args[0];
|
|
2249
3123
|
if (!factoryArg) {
|
|
2250
|
-
warn(init.start, `${
|
|
3124
|
+
warn(init.start, `${label2}: rules() needs a factory argument`);
|
|
2251
3125
|
return null;
|
|
2252
3126
|
}
|
|
2253
3127
|
const ruleMap = evaluateParserFactory(factoryArg, scope, code, []);
|
|
2254
3128
|
if (!ruleMap) {
|
|
2255
|
-
warn(init.start, `${
|
|
3129
|
+
warn(init.start, `${label2}: rules(...) factory isn't statically evaluable`);
|
|
2256
3130
|
return null;
|
|
2257
3131
|
}
|
|
2258
3132
|
const entries = [];
|
|
2259
3133
|
for (const [ruleKey, rule] of ruleMap) {
|
|
2260
3134
|
const compiled = compile(rule);
|
|
2261
3135
|
if (compiled.inlineExpression === null) {
|
|
2262
|
-
warn(init.start, `${
|
|
3136
|
+
warn(init.start, `${label2}: rule "${ruleKey}" couldn't be inlined`);
|
|
2263
3137
|
return null;
|
|
2264
3138
|
}
|
|
2265
3139
|
entries.push([ruleKey, compiled.inlineExpression]);
|
|
@@ -2303,6 +3177,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
2303
3177
|
const mapFnSources = [];
|
|
2304
3178
|
const parser2 = evaluateExpr(init, scope, code, mapFnSources);
|
|
2305
3179
|
if (parser2 === null) {
|
|
3180
|
+
const wordFactory = evaluateWordFactory(init, scope, code);
|
|
3181
|
+
if (wordFactory) {
|
|
3182
|
+
;
|
|
3183
|
+
scope.set(varName, wordFactory);
|
|
3184
|
+
continue;
|
|
3185
|
+
}
|
|
2306
3186
|
warn(init.start, `"${varName}" references a parseman macro import but isn't a statically-evaluable combinator`);
|
|
2307
3187
|
continue;
|
|
2308
3188
|
}
|