parseman 0.2.0 → 0.3.1
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 +167 -126
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/completions.d.ts +17 -0
- package/dist/combinators/completions.d.ts.map +1 -0
- package/dist/combinators/grammar.d.ts +20 -4
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/guard.d.ts +2 -2
- package/dist/combinators/guard.d.ts.map +1 -1
- package/dist/combinators/keywords.d.ts +22 -0
- package/dist/combinators/keywords.d.ts.map +1 -0
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +24 -0
- package/dist/combinators/node.d.ts.map +1 -0
- package/dist/combinators/parser.d.ts +7 -7
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/probe.d.ts +13 -0
- package/dist/combinators/probe.d.ts.map +1 -0
- package/dist/combinators/recover.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- 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 +33 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -0
- package/dist/combinators/withCtx.d.ts +1 -1
- package/dist/compiler/codegen.d.ts +13 -4
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/cst/grammar.d.ts +33 -2
- package/dist/cst/grammar.d.ts.map +1 -1
- package/dist/cst/incremental.d.ts +4 -2
- package/dist/cst/incremental.d.ts.map +1 -1
- package/dist/cst/trivia-index.d.ts +50 -0
- package/dist/cst/trivia-index.d.ts.map +1 -0
- package/dist/cst/types.d.ts +7 -7
- package/dist/cst/types.d.ts.map +1 -1
- package/dist/functional/doc.d.ts +53 -0
- package/dist/functional/doc.d.ts.map +1 -0
- package/dist/index.cjs +953 -221
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6519 -226
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts +26 -6
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +1164 -215
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts +5 -2
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1164 -215
- package/dist/plugin/index.js.map +4 -4
- package/dist/types.d.ts +51 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/plugin/index.cjs
CHANGED
|
@@ -83,6 +83,51 @@ function mergeRanges(ranges) {
|
|
|
83
83
|
return out;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// src/combinators/ref.ts
|
|
87
|
+
function ref() {
|
|
88
|
+
let resolved = null;
|
|
89
|
+
const meta = {
|
|
90
|
+
firstSet: any(),
|
|
91
|
+
canMatchNewline: true,
|
|
92
|
+
isTrivia: false
|
|
93
|
+
};
|
|
94
|
+
const slot = {
|
|
95
|
+
_tag: "lazy",
|
|
96
|
+
_meta: meta,
|
|
97
|
+
_def: {
|
|
98
|
+
tag: "lazy",
|
|
99
|
+
thunk: () => {
|
|
100
|
+
if (!resolved) throw new Error("ref<T>() used before .define() was called");
|
|
101
|
+
return resolved;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
parse(input, pos, ctx) {
|
|
105
|
+
if (!resolved) throw new Error("ref<T>() used before .define() was called");
|
|
106
|
+
return resolved.parse(input, pos, ctx);
|
|
107
|
+
},
|
|
108
|
+
define(p) {
|
|
109
|
+
if (resolved) throw new Error("ref<T>() already defined");
|
|
110
|
+
resolved = p;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return slot;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/combinators/probe.ts
|
|
117
|
+
function failAt(ctx, expected, pos) {
|
|
118
|
+
const r = { ok: false, expected, span: { start: pos, end: pos } };
|
|
119
|
+
const probe = ctx._probe;
|
|
120
|
+
if (probe !== void 0 && pos <= probe.offset) {
|
|
121
|
+
const best = probe.best;
|
|
122
|
+
if (best === null || pos > best.span.start) {
|
|
123
|
+
probe.best = r;
|
|
124
|
+
} else if (pos === best.span.start) {
|
|
125
|
+
probe.best = { ...best, expected: [...best.expected, ...expected] };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return r;
|
|
129
|
+
}
|
|
130
|
+
|
|
86
131
|
// src/combinators/literal.ts
|
|
87
132
|
var _collatorCache = null;
|
|
88
133
|
function collator() {
|
|
@@ -112,21 +157,21 @@ function literal(value, opts = {}) {
|
|
|
112
157
|
_tag: "literal",
|
|
113
158
|
_meta: meta,
|
|
114
159
|
_def: { tag: "literal", value, caseInsensitive },
|
|
115
|
-
parse(input, pos,
|
|
160
|
+
parse(input, pos, ctx) {
|
|
116
161
|
const end = pos + value.length;
|
|
117
162
|
if (end > input.length) {
|
|
118
|
-
return
|
|
163
|
+
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
119
164
|
}
|
|
120
165
|
const slice = input.slice(pos, end);
|
|
121
166
|
const matched = caseInsensitive ? collator().compare(slice, value) === 0 : slice === value;
|
|
122
167
|
if (matched) {
|
|
123
168
|
const span = { start: pos, end };
|
|
124
169
|
const leaf = { _tag: "leaf", value: slice, span };
|
|
125
|
-
if (
|
|
126
|
-
if (
|
|
170
|
+
if (ctx._cstLeaves) ctx._cstLeaves.push(leaf);
|
|
171
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
127
172
|
return { ok: true, value: slice, span };
|
|
128
173
|
}
|
|
129
|
-
return
|
|
174
|
+
return failAt(ctx, [JSON.stringify(value)], pos);
|
|
130
175
|
}
|
|
131
176
|
};
|
|
132
177
|
}
|
|
@@ -141,38 +186,38 @@ function firstSetFromRegex(pattern) {
|
|
|
141
186
|
return { firstSet: any(), canMatchNewline: true };
|
|
142
187
|
}
|
|
143
188
|
}
|
|
144
|
-
function canBeEmpty(
|
|
145
|
-
if (!
|
|
146
|
-
switch (
|
|
189
|
+
function canBeEmpty(node2) {
|
|
190
|
+
if (!node2) return true;
|
|
191
|
+
switch (node2.type) {
|
|
147
192
|
case "Repetition": {
|
|
148
|
-
const q =
|
|
193
|
+
const q = node2.quantifier;
|
|
149
194
|
return q.kind === "*" || q.kind === "?" || q.kind === "Range" && (q.from ?? 1) === 0;
|
|
150
195
|
}
|
|
151
196
|
case "Alternative": {
|
|
152
|
-
const exprs =
|
|
197
|
+
const exprs = node2.expressions;
|
|
153
198
|
return !exprs || exprs.length === 0 || exprs.every((e) => canBeEmpty(e));
|
|
154
199
|
}
|
|
155
200
|
case "Group":
|
|
156
|
-
return canBeEmpty(
|
|
201
|
+
return canBeEmpty(node2.expression);
|
|
157
202
|
case "Disjunction":
|
|
158
|
-
return canBeEmpty(
|
|
203
|
+
return canBeEmpty(node2.left) || canBeEmpty(node2.right);
|
|
159
204
|
default:
|
|
160
205
|
return false;
|
|
161
206
|
}
|
|
162
207
|
}
|
|
163
|
-
function extractFirstSet(
|
|
164
|
-
if (!
|
|
165
|
-
switch (
|
|
208
|
+
function extractFirstSet(node2) {
|
|
209
|
+
if (!node2) return { firstSet: empty(), canMatchNewline: false };
|
|
210
|
+
switch (node2.type) {
|
|
166
211
|
case "Disjunction": {
|
|
167
|
-
const left = extractFirstSet(
|
|
168
|
-
const right = extractFirstSet(
|
|
212
|
+
const left = extractFirstSet(node2.left);
|
|
213
|
+
const right = extractFirstSet(node2.right);
|
|
169
214
|
return {
|
|
170
215
|
firstSet: union(left.firstSet, right.firstSet),
|
|
171
216
|
canMatchNewline: left.canMatchNewline || right.canMatchNewline
|
|
172
217
|
};
|
|
173
218
|
}
|
|
174
219
|
case "Alternative": {
|
|
175
|
-
const exprs =
|
|
220
|
+
const exprs = node2.expressions;
|
|
176
221
|
if (!exprs || exprs.length === 0) return { firstSet: empty(), canMatchNewline: false };
|
|
177
222
|
let fs = empty();
|
|
178
223
|
let canNL = false;
|
|
@@ -185,13 +230,13 @@ function extractFirstSet(node) {
|
|
|
185
230
|
return { firstSet: fs, canMatchNewline: canNL };
|
|
186
231
|
}
|
|
187
232
|
case "Char": {
|
|
188
|
-
const kind =
|
|
233
|
+
const kind = node2.kind;
|
|
189
234
|
if (kind === "simple") {
|
|
190
|
-
const code =
|
|
235
|
+
const code = node2.codePoint ?? node2.value.codePointAt(0) ?? 0;
|
|
191
236
|
return { firstSet: fromRange(code, code), canMatchNewline: code === 10 };
|
|
192
237
|
}
|
|
193
238
|
if (kind === "meta") {
|
|
194
|
-
const val =
|
|
239
|
+
const val = node2.value;
|
|
195
240
|
if (val === ".") return { firstSet: any(), canMatchNewline: false };
|
|
196
241
|
if (val === "d") return { firstSet: fromRange(48, 57), canMatchNewline: false };
|
|
197
242
|
if (val === "D") return { firstSet: any(), canMatchNewline: true };
|
|
@@ -208,7 +253,7 @@ function extractFirstSet(node) {
|
|
|
208
253
|
return { firstSet: any(), canMatchNewline: true };
|
|
209
254
|
}
|
|
210
255
|
case "CharacterClass": {
|
|
211
|
-
const expressions =
|
|
256
|
+
const expressions = node2.expressions;
|
|
212
257
|
let fs = empty();
|
|
213
258
|
let canNL = false;
|
|
214
259
|
for (const expr of expressions) {
|
|
@@ -223,14 +268,14 @@ function extractFirstSet(node) {
|
|
|
223
268
|
canNL = canNL || r.canMatchNewline;
|
|
224
269
|
}
|
|
225
270
|
}
|
|
226
|
-
if (
|
|
271
|
+
if (node2.negative) return { firstSet: any(), canMatchNewline: true };
|
|
227
272
|
return { firstSet: fs, canMatchNewline: canNL };
|
|
228
273
|
}
|
|
229
274
|
case "Repetition": {
|
|
230
|
-
return extractFirstSet(
|
|
275
|
+
return extractFirstSet(node2.expression);
|
|
231
276
|
}
|
|
232
277
|
case "Group": {
|
|
233
|
-
return extractFirstSet(
|
|
278
|
+
return extractFirstSet(node2.expression);
|
|
234
279
|
}
|
|
235
280
|
default:
|
|
236
281
|
return { firstSet: any(), canMatchNewline: true };
|
|
@@ -261,7 +306,7 @@ function regex(pattern, flags = "") {
|
|
|
261
306
|
anchored.lastIndex = pos;
|
|
262
307
|
const m = anchored.exec(input);
|
|
263
308
|
if (m === null) {
|
|
264
|
-
return
|
|
309
|
+
return failAt(ctx, [`/${source}/`], pos);
|
|
265
310
|
}
|
|
266
311
|
const span = { start: pos, end: pos + m[0].length };
|
|
267
312
|
const leaf = { _tag: "leaf", value: m[0], span };
|
|
@@ -272,6 +317,55 @@ function regex(pattern, flags = "") {
|
|
|
272
317
|
};
|
|
273
318
|
}
|
|
274
319
|
|
|
320
|
+
// src/combinators/trivia-skip.ts
|
|
321
|
+
var NOOP_COMMIT = () => {
|
|
322
|
+
};
|
|
323
|
+
function scanTrivia(input, cur, ctx) {
|
|
324
|
+
const triviaP = ctx.trivia;
|
|
325
|
+
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
326
|
+
const log = ctx._triviaLog;
|
|
327
|
+
if (log !== void 0) {
|
|
328
|
+
const tr2 = triviaP.parse(input, cur, { trackLines: false, state: ctx.state });
|
|
329
|
+
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
330
|
+
const end = tr2.span.end;
|
|
331
|
+
return {
|
|
332
|
+
end,
|
|
333
|
+
commit: () => {
|
|
334
|
+
log.push(cur, end);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
if (ctx.captureTrivia && ctx._cstRawChildren) {
|
|
339
|
+
const sink = [];
|
|
340
|
+
const tr2 = triviaP.parse(input, cur, {
|
|
341
|
+
trackLines: ctx.trackLines,
|
|
342
|
+
state: ctx.state,
|
|
343
|
+
_cstLeaves: sink
|
|
344
|
+
});
|
|
345
|
+
if (tr2.ok && tr2.span.end > cur) {
|
|
346
|
+
const out = ctx._cstRawChildren;
|
|
347
|
+
return {
|
|
348
|
+
end: tr2.span.end,
|
|
349
|
+
commit: () => {
|
|
350
|
+
for (const tok of sink) {
|
|
351
|
+
if (tok._tag === "leaf" && tok.span.end > tok.span.start) {
|
|
352
|
+
out.push({ _tag: "trivia", value: tok.value, span: tok.span });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return { end: cur, commit: NOOP_COMMIT };
|
|
359
|
+
}
|
|
360
|
+
const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
361
|
+
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
362
|
+
}
|
|
363
|
+
function consumeTrivia(input, cur, ctx) {
|
|
364
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
365
|
+
scan.commit();
|
|
366
|
+
return scan.end;
|
|
367
|
+
}
|
|
368
|
+
|
|
275
369
|
// src/combinators/sequence.ts
|
|
276
370
|
function sequence(...parsers) {
|
|
277
371
|
const meta = {
|
|
@@ -288,12 +382,19 @@ function sequence(...parsers) {
|
|
|
288
382
|
let cur = pos;
|
|
289
383
|
for (let i = 0; i < parsers.length; i++) {
|
|
290
384
|
if (ctx.trivia && i > 0) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
385
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
386
|
+
const raw = ctx._cstRawChildren;
|
|
387
|
+
const mark = raw ? raw.length : 0;
|
|
388
|
+
scan.commit();
|
|
389
|
+
const result2 = parsers[i].parse(input, scan.end, ctx);
|
|
390
|
+
if (!result2.ok) return result2;
|
|
391
|
+
if (result2.span.end > scan.end) {
|
|
392
|
+
cur = result2.span.end;
|
|
393
|
+
} else if (raw) {
|
|
394
|
+
raw.length = mark;
|
|
296
395
|
}
|
|
396
|
+
values.push(result2.value);
|
|
397
|
+
continue;
|
|
297
398
|
}
|
|
298
399
|
const result = parsers[i].parse(input, cur, ctx);
|
|
299
400
|
if (!result.ok) return result;
|
|
@@ -394,14 +495,22 @@ function choice(...args) {
|
|
|
394
495
|
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
395
496
|
}
|
|
396
497
|
for (let i = 0; i < parsers.length; i++) {
|
|
397
|
-
if (gates[i] && !gates[i](ctx.
|
|
498
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
499
|
+
const leavesLen = ctx._cstLeaves?.length;
|
|
500
|
+
const rawLen = ctx._cstRawChildren?.length;
|
|
398
501
|
const result = parsers[i].parse(input, pos, ctx);
|
|
399
502
|
if (!result.ok) {
|
|
503
|
+
if (leavesLen !== void 0 && ctx._cstLeaves) ctx._cstLeaves.length = leavesLen;
|
|
504
|
+
if (rawLen !== void 0 && ctx._cstRawChildren) ctx._cstRawChildren.length = rawLen;
|
|
400
505
|
expected.push(...result.expected);
|
|
401
506
|
continue;
|
|
402
507
|
}
|
|
403
508
|
const checks = autoNot[i];
|
|
404
|
-
if (checks && autoNotFires(input, result.span.end, checks))
|
|
509
|
+
if (checks && autoNotFires(input, result.span.end, checks)) {
|
|
510
|
+
if (leavesLen !== void 0 && ctx._cstLeaves) ctx._cstLeaves.length = leavesLen;
|
|
511
|
+
if (rawLen !== void 0 && ctx._cstRawChildren) ctx._cstRawChildren.length = rawLen;
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
405
514
|
return result;
|
|
406
515
|
}
|
|
407
516
|
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
@@ -532,6 +641,30 @@ function areDisjoint(sets) {
|
|
|
532
641
|
}
|
|
533
642
|
|
|
534
643
|
// src/combinators/repeat.ts
|
|
644
|
+
function repItem(parser2, input, cur, ctx) {
|
|
645
|
+
const raw = ctx._cstRawChildren;
|
|
646
|
+
const mark = raw ? raw.length : 0;
|
|
647
|
+
let pos = cur;
|
|
648
|
+
if (ctx.trivia) {
|
|
649
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
650
|
+
scan.commit();
|
|
651
|
+
pos = scan.end;
|
|
652
|
+
}
|
|
653
|
+
if (pos >= input.length) {
|
|
654
|
+
if (raw) raw.length = mark;
|
|
655
|
+
return "stop";
|
|
656
|
+
}
|
|
657
|
+
const result = parser2.parse(input, pos, ctx);
|
|
658
|
+
if (!result.ok) {
|
|
659
|
+
if (raw) raw.length = mark;
|
|
660
|
+
return { fail: result };
|
|
661
|
+
}
|
|
662
|
+
if (result.span.end === pos) {
|
|
663
|
+
if (raw) raw.length = mark;
|
|
664
|
+
return "stop";
|
|
665
|
+
}
|
|
666
|
+
return { value: result.value, end: result.span.end };
|
|
667
|
+
}
|
|
535
668
|
function many(parser2) {
|
|
536
669
|
const meta = {
|
|
537
670
|
firstSet: parser2._meta.firstSet,
|
|
@@ -546,11 +679,10 @@ function many(parser2) {
|
|
|
546
679
|
const values = [];
|
|
547
680
|
let cur = pos;
|
|
548
681
|
while (cur < input.length) {
|
|
549
|
-
const
|
|
550
|
-
if (
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
cur = result.span.end;
|
|
682
|
+
const item = repItem(parser2, input, cur, ctx);
|
|
683
|
+
if (item === "stop" || "fail" in item) break;
|
|
684
|
+
values.push(item.value);
|
|
685
|
+
cur = item.end;
|
|
554
686
|
}
|
|
555
687
|
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
556
688
|
}
|
|
@@ -572,11 +704,10 @@ function oneOrMore(parser2) {
|
|
|
572
704
|
const values = [first.value];
|
|
573
705
|
let cur = first.span.end;
|
|
574
706
|
while (cur < input.length) {
|
|
575
|
-
const
|
|
576
|
-
if (
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
cur = result.span.end;
|
|
707
|
+
const item = repItem(parser2, input, cur, ctx);
|
|
708
|
+
if (item === "stop" || "fail" in item) break;
|
|
709
|
+
values.push(item.value);
|
|
710
|
+
cur = item.end;
|
|
580
711
|
}
|
|
581
712
|
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
582
713
|
}
|
|
@@ -615,26 +746,10 @@ function sepBy(parser2, separator) {
|
|
|
615
746
|
const values = [first.value];
|
|
616
747
|
let cur = first.span.end;
|
|
617
748
|
while (cur < input.length) {
|
|
618
|
-
|
|
619
|
-
if (ctx.trivia) {
|
|
620
|
-
const triviaCtx = { trivia: ctx.trivia, trackLines: ctx.trackLines, user: ctx.user };
|
|
621
|
-
const tr = ctx.trivia.parse(input, sepPos, triviaCtx);
|
|
622
|
-
if (tr.ok) {
|
|
623
|
-
if (ctx._cstRawChildren && tr.span.end > tr.span.start) ctx._cstRawChildren.push({ _tag: "trivia", value: input.slice(tr.span.start, tr.span.end), span: tr.span });
|
|
624
|
-
sepPos = tr.span.end;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
749
|
+
const sepPos = ctx.trivia ? consumeTrivia(input, cur, ctx) : cur;
|
|
627
750
|
const sep = separator.parse(input, sepPos, ctx);
|
|
628
751
|
if (!sep.ok) break;
|
|
629
|
-
|
|
630
|
-
if (ctx.trivia) {
|
|
631
|
-
const triviaCtx = { trivia: ctx.trivia, trackLines: ctx.trackLines, user: ctx.user };
|
|
632
|
-
const tr = ctx.trivia.parse(input, nextPos, triviaCtx);
|
|
633
|
-
if (tr.ok) {
|
|
634
|
-
if (ctx._cstRawChildren && tr.span.end > tr.span.start) ctx._cstRawChildren.push({ _tag: "trivia", value: input.slice(tr.span.start, tr.span.end), span: tr.span });
|
|
635
|
-
nextPos = tr.span.end;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
752
|
+
const nextPos = ctx.trivia ? consumeTrivia(input, sep.span.end, ctx) : sep.span.end;
|
|
638
753
|
const next = parser2.parse(input, nextPos, ctx);
|
|
639
754
|
if (!next.ok) break;
|
|
640
755
|
values.push(next.value);
|
|
@@ -645,6 +760,148 @@ function sepBy(parser2, separator) {
|
|
|
645
760
|
};
|
|
646
761
|
}
|
|
647
762
|
|
|
763
|
+
// src/combinators/not.ts
|
|
764
|
+
function not(parser2) {
|
|
765
|
+
const meta = {
|
|
766
|
+
firstSet: any(),
|
|
767
|
+
// we don't know what NOT matches
|
|
768
|
+
canMatchNewline: false,
|
|
769
|
+
isTrivia: false
|
|
770
|
+
};
|
|
771
|
+
return {
|
|
772
|
+
_tag: "not",
|
|
773
|
+
_meta: meta,
|
|
774
|
+
_def: { tag: "not", parser: parser2 },
|
|
775
|
+
parse(input, pos, ctx) {
|
|
776
|
+
const result = parser2.parse(input, pos, ctx);
|
|
777
|
+
if (result.ok) {
|
|
778
|
+
return { ok: false, expected: [`not(${parser2._tag})`], span: { start: pos, end: pos } };
|
|
779
|
+
}
|
|
780
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/combinators/node.ts
|
|
786
|
+
function node(type, parser2, build) {
|
|
787
|
+
const meta = {
|
|
788
|
+
firstSet: parser2._meta.firstSet,
|
|
789
|
+
canMatchNewline: parser2._meta.canMatchNewline,
|
|
790
|
+
isTrivia: false
|
|
791
|
+
};
|
|
792
|
+
return {
|
|
793
|
+
_tag: "node",
|
|
794
|
+
_meta: meta,
|
|
795
|
+
_def: { tag: "node", type, parser: parser2, build },
|
|
796
|
+
parse(input, pos, ctx) {
|
|
797
|
+
const children = [];
|
|
798
|
+
const rawChildren = [];
|
|
799
|
+
const innerCtx = {
|
|
800
|
+
...ctx,
|
|
801
|
+
// A node() always records the trivia between its terms — the library owns
|
|
802
|
+
// capture so grammar authors don't reconstruct it. (Matches the compiler.)
|
|
803
|
+
captureTrivia: true,
|
|
804
|
+
_cstChildren: children,
|
|
805
|
+
_cstLeaves: children,
|
|
806
|
+
_cstRawChildren: rawChildren
|
|
807
|
+
};
|
|
808
|
+
const r = parser2.parse(input, pos, innerCtx);
|
|
809
|
+
if (!r.ok) return r;
|
|
810
|
+
const built = build(children, rawChildren, r.span);
|
|
811
|
+
const isNodeLike = typeof built === "object" && built !== null && built._tag === "node";
|
|
812
|
+
if (ctx._cstChildren) ctx._cstChildren.push(built);
|
|
813
|
+
if (ctx._cstRawChildren) {
|
|
814
|
+
ctx._cstRawChildren.push(
|
|
815
|
+
isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span }
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
return { ok: true, value: built, span: r.span };
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// src/combinators/map.ts
|
|
824
|
+
function transform(parser2, fn) {
|
|
825
|
+
return {
|
|
826
|
+
_tag: "transform",
|
|
827
|
+
_meta: parser2._meta,
|
|
828
|
+
_def: { tag: "transform", parser: parser2, fn },
|
|
829
|
+
parse(input, pos, ctx) {
|
|
830
|
+
const result = parser2.parse(input, pos, ctx);
|
|
831
|
+
if (!result.ok) return result;
|
|
832
|
+
return { ...result, value: fn(result.value, result.span) };
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
function trivia(parser2) {
|
|
837
|
+
return {
|
|
838
|
+
_tag: parser2._tag,
|
|
839
|
+
_meta: { ...parser2._meta, isTrivia: true },
|
|
840
|
+
_def: { tag: "trivia", parser: parser2 },
|
|
841
|
+
parse: parser2.parse.bind(parser2)
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// src/compiler/line-index.ts
|
|
846
|
+
function buildLineIndex(input) {
|
|
847
|
+
const lineStarts = [0];
|
|
848
|
+
for (let i = 0; i < input.length; i++) {
|
|
849
|
+
if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
|
|
850
|
+
}
|
|
851
|
+
return { lineStarts };
|
|
852
|
+
}
|
|
853
|
+
function offsetToLineCol(index, offset) {
|
|
854
|
+
const { lineStarts } = index;
|
|
855
|
+
let lo = 0;
|
|
856
|
+
let hi = lineStarts.length - 1;
|
|
857
|
+
while (lo < hi) {
|
|
858
|
+
const mid = lo + hi + 1 >> 1;
|
|
859
|
+
if (lineStarts[mid] <= offset) lo = mid;
|
|
860
|
+
else hi = mid - 1;
|
|
861
|
+
}
|
|
862
|
+
return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
|
|
863
|
+
}
|
|
864
|
+
function annotateSpan(span, index) {
|
|
865
|
+
const s = offsetToLineCol(index, span.start);
|
|
866
|
+
const e = offsetToLineCol(index, span.end);
|
|
867
|
+
return {
|
|
868
|
+
...span,
|
|
869
|
+
startLine: s.line,
|
|
870
|
+
startColumn: s.col,
|
|
871
|
+
endLine: e.line,
|
|
872
|
+
endColumn: e.col
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// src/combinators/grammar.ts
|
|
877
|
+
function parser(opts, root) {
|
|
878
|
+
return {
|
|
879
|
+
_tag: "grammar",
|
|
880
|
+
_meta: root._meta,
|
|
881
|
+
_def: {
|
|
882
|
+
tag: "grammar",
|
|
883
|
+
parser: root,
|
|
884
|
+
triviaParser: opts.trivia,
|
|
885
|
+
trackLines: opts.trackLines ?? false
|
|
886
|
+
},
|
|
887
|
+
parse(input, pos, _ctx) {
|
|
888
|
+
const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
|
|
889
|
+
const ctx = {
|
|
890
|
+
..._ctx,
|
|
891
|
+
trackLines,
|
|
892
|
+
...opts.trivia !== void 0 ? { trivia: opts.trivia } : {},
|
|
893
|
+
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {}
|
|
894
|
+
};
|
|
895
|
+
const result = root.parse(input, pos ?? 0, ctx);
|
|
896
|
+
if (trackLines) {
|
|
897
|
+
const idx = buildLineIndex(input);
|
|
898
|
+
return { ...result, span: annotateSpan(result.span, idx) };
|
|
899
|
+
}
|
|
900
|
+
return result;
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
|
|
648
905
|
// src/compiler/codegen.ts
|
|
649
906
|
function v(ctx, prefix = "_v") {
|
|
650
907
|
return `${prefix}${ctx.vars++}`;
|
|
@@ -652,9 +909,58 @@ function v(ctx, prefix = "_v") {
|
|
|
652
909
|
function ind(ctx) {
|
|
653
910
|
return " ".repeat(ctx.indent);
|
|
654
911
|
}
|
|
912
|
+
function emitLeafCapture(ctx, valExpr, startExpr, endExpr) {
|
|
913
|
+
if (!ctx.capturing) return [];
|
|
914
|
+
const i = ind(ctx);
|
|
915
|
+
if (ctx.capAsTrivia) {
|
|
916
|
+
return [`${i}if (_ctx._cstRawChildren) _ctx._cstRawChildren.push({ _tag: 'trivia', value: ${valExpr}, span: { start: ${startExpr}, end: ${endExpr} } })`];
|
|
917
|
+
}
|
|
918
|
+
const lf = v(ctx, "_lf");
|
|
919
|
+
return [
|
|
920
|
+
`${i}if (_ctx._cstLeaves) {`,
|
|
921
|
+
`${i} const ${lf} = { _tag: 'leaf', value: ${valExpr}, span: { start: ${startExpr}, end: ${endExpr} } }`,
|
|
922
|
+
`${i} _ctx._cstLeaves.push(${lf})`,
|
|
923
|
+
`${i} if (_ctx._cstRawChildren) _ctx._cstRawChildren.push(${lf})`,
|
|
924
|
+
`${i}}`
|
|
925
|
+
];
|
|
926
|
+
}
|
|
927
|
+
function ensureTriviaCaptureFn(ctx) {
|
|
928
|
+
const trivia2 = ctx.activeTrivia;
|
|
929
|
+
const existing = ctx.triviaCaptureNames.get(trivia2);
|
|
930
|
+
if (existing) return existing;
|
|
931
|
+
const fnName = `_tc${ctx.triviaCaptureNames.size}`;
|
|
932
|
+
ctx.triviaCaptureNames.set(trivia2, fnName);
|
|
933
|
+
const saved = { indent: ctx.indent, failLabel: ctx.failLabel, asTrivia: ctx.capAsTrivia, trivia: ctx.activeTrivia };
|
|
934
|
+
ctx.indent = 2;
|
|
935
|
+
ctx.failLabel = "_cap";
|
|
936
|
+
ctx.capAsTrivia = true;
|
|
937
|
+
delete ctx.activeTrivia;
|
|
938
|
+
const r = emit(trivia2, ctx, "_pos");
|
|
939
|
+
ctx.indent = saved.indent;
|
|
940
|
+
ctx.failLabel = saved.failLabel;
|
|
941
|
+
ctx.capAsTrivia = saved.asTrivia;
|
|
942
|
+
if (saved.trivia) ctx.activeTrivia = saved.trivia;
|
|
943
|
+
ctx.namedFnDecls.push([
|
|
944
|
+
`function ${fnName}(input, _pos, _ctx) {`,
|
|
945
|
+
` let _e = _pos`,
|
|
946
|
+
` _cap: {`,
|
|
947
|
+
...r.stmts,
|
|
948
|
+
` _e = ${r.endVar}`,
|
|
949
|
+
` }`,
|
|
950
|
+
` if (_ctx._triviaLog !== undefined && _e > _pos) _ctx._triviaLog.push(_pos, _e)`,
|
|
951
|
+
` return _e`,
|
|
952
|
+
`}`
|
|
953
|
+
].join("\n"));
|
|
954
|
+
return fnName;
|
|
955
|
+
}
|
|
655
956
|
function failStmt(ctx, expected, posExpr) {
|
|
957
|
+
if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
|
|
656
958
|
return `${ind(ctx)}return { ok: false, expected: [${expected}], span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
657
959
|
}
|
|
960
|
+
function failArr(ctx, expectedArr, posExpr) {
|
|
961
|
+
if (ctx.failLabel) return `${ind(ctx)}break ${ctx.failLabel}`;
|
|
962
|
+
return `${ind(ctx)}return { ok: false, expected: ${expectedArr}, span: { start: ${posExpr}, end: ${posExpr} } }`;
|
|
963
|
+
}
|
|
658
964
|
function firstSetCond(codeVar, fs) {
|
|
659
965
|
if (fs.kind === "any") return "true";
|
|
660
966
|
if (fs.kind === "empty") return "false";
|
|
@@ -670,6 +976,30 @@ function asIIFE(stmts, valueVar, endVar, startPos, indent) {
|
|
|
670
976
|
`${indent}})()`
|
|
671
977
|
].join("\n");
|
|
672
978
|
}
|
|
979
|
+
function emitFallible(inner, ctx, pos) {
|
|
980
|
+
const lbl = v(ctx, "_lbl");
|
|
981
|
+
const okV = `${lbl}ok`;
|
|
982
|
+
const valV = `${lbl}v`;
|
|
983
|
+
const endV = `${lbl}e`;
|
|
984
|
+
const savedLabel = ctx.failLabel;
|
|
985
|
+
const savedIndent = ctx.indent;
|
|
986
|
+
ctx.failLabel = lbl;
|
|
987
|
+
ctx.indent = 0;
|
|
988
|
+
const r = emit(inner, ctx, pos);
|
|
989
|
+
ctx.failLabel = savedLabel;
|
|
990
|
+
ctx.indent = savedIndent;
|
|
991
|
+
const ind0 = ind(ctx);
|
|
992
|
+
const stmts = [
|
|
993
|
+
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
994
|
+
`${ind0}${lbl}: {`,
|
|
995
|
+
...r.stmts,
|
|
996
|
+
`${ind0} ${valV} = ${r.valueVar}`,
|
|
997
|
+
`${ind0} ${endV} = ${r.endVar}`,
|
|
998
|
+
`${ind0} ${okV} = true`,
|
|
999
|
+
`${ind0}}`
|
|
1000
|
+
];
|
|
1001
|
+
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
1002
|
+
}
|
|
673
1003
|
function emitLit(def, ctx, pos) {
|
|
674
1004
|
const { value, caseInsensitive } = def;
|
|
675
1005
|
const len = value.length;
|
|
@@ -707,12 +1037,19 @@ function emitLit(def, ctx, pos) {
|
|
|
707
1037
|
`${ind(ctx)}const ${vv} = ${JSON.stringify(value)}`
|
|
708
1038
|
);
|
|
709
1039
|
}
|
|
710
|
-
|
|
1040
|
+
const endVar = len === 0 ? pos : `${pos} + ${len}`;
|
|
1041
|
+
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1042
|
+
return { stmts, valueVar: vv, endVar };
|
|
711
1043
|
}
|
|
712
1044
|
function emitRegex(def, ctx, pos) {
|
|
713
1045
|
const flags = "y" + def.flags.replace(/[gy]/g, "");
|
|
714
|
-
const
|
|
715
|
-
|
|
1046
|
+
const key = `${def.optimizedSource}/${flags}`;
|
|
1047
|
+
let rName = ctx.regexMap.get(key);
|
|
1048
|
+
if (rName === void 0) {
|
|
1049
|
+
rName = `_re${ctx.regexDecls.length}`;
|
|
1050
|
+
ctx.regexDecls.push(`const ${rName} = /${def.optimizedSource}/${flags}`);
|
|
1051
|
+
ctx.regexMap.set(key, rName);
|
|
1052
|
+
}
|
|
716
1053
|
const mv = v(ctx, "_m");
|
|
717
1054
|
const vv = v(ctx);
|
|
718
1055
|
const expectedStr = JSON.stringify(`/${def.source}/`);
|
|
@@ -722,7 +1059,9 @@ function emitRegex(def, ctx, pos) {
|
|
|
722
1059
|
`${ind(ctx)}if (${mv} === null) ${failStmt({ ...ctx, indent: 0 }, expectedStr, pos).trim()}`,
|
|
723
1060
|
`${ind(ctx)}const ${vv} = ${mv}[0]`
|
|
724
1061
|
];
|
|
725
|
-
|
|
1062
|
+
const endVar = `${pos} + ${vv}.length`;
|
|
1063
|
+
stmts.push(...emitLeafCapture(ctx, vv, pos, endVar));
|
|
1064
|
+
return { stmts, valueVar: vv, endVar };
|
|
726
1065
|
}
|
|
727
1066
|
function ensureTriviaFn(ctx) {
|
|
728
1067
|
const trivia2 = ctx.activeTrivia;
|
|
@@ -730,9 +1069,15 @@ function ensureTriviaFn(ctx) {
|
|
|
730
1069
|
const fnName = `_pf${ctx.namedParsers.size}`;
|
|
731
1070
|
ctx.namedParsers.set(trivia2, fnName);
|
|
732
1071
|
const savedIndent = ctx.indent;
|
|
1072
|
+
const savedFailLabel = ctx.failLabel;
|
|
1073
|
+
const savedTrivia = ctx.activeTrivia;
|
|
733
1074
|
ctx.indent = 1;
|
|
1075
|
+
ctx.failLabel = void 0;
|
|
1076
|
+
delete ctx.activeTrivia;
|
|
734
1077
|
const r = emit(trivia2, ctx, "_pos");
|
|
735
1078
|
ctx.indent = savedIndent;
|
|
1079
|
+
ctx.failLabel = savedFailLabel;
|
|
1080
|
+
if (savedTrivia) ctx.activeTrivia = savedTrivia;
|
|
736
1081
|
ctx.namedFnDecls.push([
|
|
737
1082
|
`function ${fnName}(input, _pos, _ctx) {`,
|
|
738
1083
|
...r.stmts,
|
|
@@ -752,12 +1097,17 @@ function emitSeq(def, ctx, pos) {
|
|
|
752
1097
|
const valueVars = [];
|
|
753
1098
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
754
1099
|
if (i > 0 && ctx.activeTrivia) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1100
|
+
if (ctx.capturing) {
|
|
1101
|
+
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1102
|
+
stmts.push(`${ind(ctx)}${curV} = ${capFn}(input, ${curV}, _ctx)`);
|
|
1103
|
+
} else {
|
|
1104
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1105
|
+
const tmp = v(ctx, "_trv");
|
|
1106
|
+
stmts.push(
|
|
1107
|
+
`${ind(ctx)}const ${tmp} = ${trivFn}(input, ${curV}, _ctx)`,
|
|
1108
|
+
`${ind(ctx)}if (${tmp}.ok) ${curV} = ${tmp}.span.end`
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
761
1111
|
}
|
|
762
1112
|
const r = emit(def.parsers[i], ctx, curV);
|
|
763
1113
|
stmts.push(...r.stmts, `${ind(ctx)}${curV} = ${r.endVar}`);
|
|
@@ -797,9 +1147,7 @@ function emitChoice(def, ctx, pos) {
|
|
|
797
1147
|
ctx.indent--;
|
|
798
1148
|
stmts.push(`${ind(ctx)}}`);
|
|
799
1149
|
}
|
|
800
|
-
stmts.push(
|
|
801
|
-
`${ind(ctx)}else return { ok: false, expected: ${allExpected}, span: { start: ${pos}, end: ${pos} } }`
|
|
802
|
-
);
|
|
1150
|
+
stmts.push(`${ind(ctx)}else ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
|
|
803
1151
|
return { stmts, valueVar: valV, endVar: endV };
|
|
804
1152
|
}
|
|
805
1153
|
return emitNonDisjoint(def, def.strategy, allExpected, ctx, pos);
|
|
@@ -807,17 +1155,21 @@ function emitChoice(def, ctx, pos) {
|
|
|
807
1155
|
function emitGreedyClassify(def, superIndex, allExpected, ctx, pos) {
|
|
808
1156
|
const superParser = def.parsers[superIndex];
|
|
809
1157
|
const regexDef = getCoreRegexDef(superParser);
|
|
810
|
-
const reIdx = ctx.regexDecls.length;
|
|
811
|
-
const reVar = `_re${reIdx}`;
|
|
812
1158
|
const cleanFlags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
813
|
-
|
|
1159
|
+
const reKey = `${regexDef.source}/${cleanFlags}`;
|
|
1160
|
+
let reVar = ctx.regexMap.get(reKey);
|
|
1161
|
+
if (reVar === void 0) {
|
|
1162
|
+
reVar = `_re${ctx.regexDecls.length}`;
|
|
1163
|
+
ctx.regexDecls.push(`const ${reVar} = /${regexDef.source}/${cleanFlags}`);
|
|
1164
|
+
ctx.regexMap.set(reKey, reVar);
|
|
1165
|
+
}
|
|
814
1166
|
const matchV = v(ctx, "_gm");
|
|
815
1167
|
const wordV = v(ctx, "_gw");
|
|
816
1168
|
const endV = v(ctx, "_ge");
|
|
817
1169
|
const stmts = [
|
|
818
1170
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
819
1171
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
820
|
-
`${ind(ctx)}if (${matchV} === null)
|
|
1172
|
+
`${ind(ctx)}if (${matchV} === null) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`,
|
|
821
1173
|
`${ind(ctx)}const ${wordV} = ${matchV}[0]`,
|
|
822
1174
|
`${ind(ctx)}const ${endV} = ${pos} + ${wordV}.length`
|
|
823
1175
|
];
|
|
@@ -857,7 +1209,7 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos) {
|
|
|
857
1209
|
ctx.indent--;
|
|
858
1210
|
stmts.push(`${ind(ctx)}}`);
|
|
859
1211
|
}
|
|
860
|
-
stmts.push(`${ind(ctx)}else
|
|
1212
|
+
stmts.push(`${ind(ctx)}else ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
|
|
861
1213
|
return { stmts, valueVar: valV, endVar: endV };
|
|
862
1214
|
}
|
|
863
1215
|
function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
@@ -868,40 +1220,60 @@ function emitFirstMatch(def, allExpected, ctx, pos) {
|
|
|
868
1220
|
const gate = def.gates[i];
|
|
869
1221
|
const autoNot = def.autoNot[i];
|
|
870
1222
|
const savedIndent = ctx.indent;
|
|
1223
|
+
const savedFailLabel = ctx.failLabel;
|
|
871
1224
|
ctx.indent = 0;
|
|
1225
|
+
ctx.failLabel = void 0;
|
|
872
1226
|
const r = emit(p, ctx, pos);
|
|
873
1227
|
ctx.indent = savedIndent;
|
|
1228
|
+
ctx.failLabel = savedFailLabel;
|
|
874
1229
|
const iife = asIIFE(r.stmts, r.valueVar, r.endVar, pos, ind(ctx));
|
|
875
1230
|
let gateCond = null;
|
|
876
1231
|
if (gate) {
|
|
877
1232
|
const gateIdx = ctx.mapFns.length;
|
|
878
1233
|
ctx.mapFns.push(gate);
|
|
879
|
-
gateCond = `_mf[${gateIdx}](_ctx.
|
|
1234
|
+
gateCond = `_mf[${gateIdx}](_ctx.state)`;
|
|
880
1235
|
}
|
|
881
1236
|
const skipCond = gateCond ? `!${resV}?.ok && ${gateCond}` : `!${resV}?.ok`;
|
|
1237
|
+
const markLeaves = ctx.capturing ? v(ctx, "_cml") : null;
|
|
1238
|
+
const markRaw = ctx.capturing ? v(ctx, "_cmr") : null;
|
|
1239
|
+
const rollback = markLeaves ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLeaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRaw}` : "";
|
|
1240
|
+
const markStmts = markLeaves ? [
|
|
1241
|
+
`${ind(ctx)} const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
1242
|
+
`${ind(ctx)} const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`
|
|
1243
|
+
] : [];
|
|
1244
|
+
const rollbackStmt = rollback ? `${ind(ctx)} if (!${resV}?.ok) { ${rollback} }` : "";
|
|
882
1245
|
if (autoNot && autoNot.length > 0) {
|
|
883
1246
|
const tmp = v(ctx, "_ct");
|
|
884
1247
|
const anCode = v(ctx, "_anc");
|
|
885
1248
|
const rejectCond = autoNot.map(
|
|
886
1249
|
(check) => check.kind === "firstSet" ? firstSetCond(anCode, check.set) : `input.startsWith(${JSON.stringify(check.value)}, ${tmp}.span.end)`
|
|
887
1250
|
).join(" || ");
|
|
1251
|
+
stmts.push(`${ind(ctx)}if (${skipCond}) {`);
|
|
1252
|
+
stmts.push(...markStmts);
|
|
888
1253
|
stmts.push(
|
|
889
|
-
`${ind(ctx)}
|
|
1254
|
+
`${ind(ctx)} const ${tmp} = (() => { try { return ${iife} } catch {} })()`,
|
|
1255
|
+
`${ind(ctx)} if (${tmp}?.ok) { const ${anCode} = ${tmp}.span.end < input.length ? input.charCodeAt(${tmp}.span.end) : -1; if (!(${rejectCond})) ${resV} = ${tmp} }`
|
|
890
1256
|
);
|
|
1257
|
+
if (rollbackStmt) stmts.push(rollbackStmt);
|
|
1258
|
+
stmts.push(`${ind(ctx)}}`);
|
|
891
1259
|
} else {
|
|
892
|
-
stmts.push(`${ind(ctx)}if (${skipCond}) {
|
|
1260
|
+
stmts.push(`${ind(ctx)}if (${skipCond}) {`);
|
|
1261
|
+
stmts.push(...markStmts);
|
|
1262
|
+
stmts.push(`${ind(ctx)} try { ${resV} = ${iife} } catch {}`);
|
|
1263
|
+
if (rollbackStmt) stmts.push(rollbackStmt);
|
|
1264
|
+
stmts.push(`${ind(ctx)}}`);
|
|
893
1265
|
}
|
|
894
1266
|
}
|
|
895
|
-
stmts.push(
|
|
896
|
-
`${ind(ctx)}if (!${resV}?.ok) return { ok: false, expected: ${allExpected}, span: { start: ${pos}, end: ${pos} } }`
|
|
897
|
-
);
|
|
1267
|
+
stmts.push(`${ind(ctx)}if (!${resV}?.ok) ${failArr({ ...ctx, indent: 0 }, allExpected, pos)}`);
|
|
898
1268
|
return { stmts, valueVar: `${resV}.value`, endVar: `${resV}.span.end` };
|
|
899
1269
|
}
|
|
900
1270
|
function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
901
|
-
if (
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1271
|
+
if (!ctx.capturing) {
|
|
1272
|
+
if (strategy.tag === "greedyClassify")
|
|
1273
|
+
return emitGreedyClassify(def, strategy.superIndex, allExpected, ctx, pos);
|
|
1274
|
+
if (strategy.tag === "literalsLongestFirst")
|
|
1275
|
+
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
1276
|
+
}
|
|
905
1277
|
return emitFirstMatch(def, allExpected, ctx, pos);
|
|
906
1278
|
}
|
|
907
1279
|
function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
@@ -910,6 +1282,7 @@ function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
|
910
1282
|
const innerR = emitTransformChain(def.parser, baseValue, endV, startPos, ctx);
|
|
911
1283
|
const fnIdx = ctx.mapFns.length;
|
|
912
1284
|
ctx.mapFns.push(def.fn);
|
|
1285
|
+
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
913
1286
|
const vv = v(ctx);
|
|
914
1287
|
return {
|
|
915
1288
|
stmts: [...innerR.stmts, `${ind(ctx)}const ${vv} = _mf[${fnIdx}](${innerR.valueVar}, { start: ${startPos}, end: ${endV} })`],
|
|
@@ -937,13 +1310,6 @@ function emitMany(def, ctx, pos) {
|
|
|
937
1310
|
`${ind(ctx)}const ${arrV} = []`,
|
|
938
1311
|
`${ind(ctx)}let ${curV} = ${pos}`
|
|
939
1312
|
];
|
|
940
|
-
const emitInnerIIFE = () => {
|
|
941
|
-
const savedIndent = ctx.indent;
|
|
942
|
-
ctx.indent = 0;
|
|
943
|
-
const r = emit(def.parser, ctx, curV);
|
|
944
|
-
ctx.indent = savedIndent;
|
|
945
|
-
return asIIFE(r.stmts, r.valueVar, r.endVar, curV, ind(ctx) + " ");
|
|
946
|
-
};
|
|
947
1313
|
if (def.min === 1) {
|
|
948
1314
|
const firstR = emit(def.parser, ctx, curV);
|
|
949
1315
|
stmts.push(...firstR.stmts);
|
|
@@ -954,11 +1320,35 @@ function emitMany(def, ctx, pos) {
|
|
|
954
1320
|
}
|
|
955
1321
|
stmts.push(`${ind(ctx)}while (${curV} < input.length) {`);
|
|
956
1322
|
ctx.indent++;
|
|
1323
|
+
let itemPos = curV;
|
|
1324
|
+
let rollback = "";
|
|
1325
|
+
if (ctx.activeTrivia) {
|
|
1326
|
+
if (ctx.capturing) {
|
|
1327
|
+
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1328
|
+
const markV = v(ctx, "_mk");
|
|
1329
|
+
const npV = v(ctx, "_np");
|
|
1330
|
+
stmts.push(
|
|
1331
|
+
`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
|
|
1332
|
+
`${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx)`
|
|
1333
|
+
);
|
|
1334
|
+
itemPos = npV;
|
|
1335
|
+
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
1336
|
+
} else {
|
|
1337
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1338
|
+
const npV = v(ctx, "_np");
|
|
1339
|
+
stmts.push(
|
|
1340
|
+
`${ind(ctx)}let ${npV} = ${curV}`,
|
|
1341
|
+
`${ind(ctx)}{ const _trv = ${trivFn}(input, ${npV}, _ctx); if (_trv.ok) ${npV} = _trv.span.end }`
|
|
1342
|
+
);
|
|
1343
|
+
itemPos = npV;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos);
|
|
957
1347
|
stmts.push(
|
|
958
|
-
|
|
959
|
-
`${ind(ctx)}if (
|
|
960
|
-
`${ind(ctx)}${arrV}.push(
|
|
961
|
-
`${ind(ctx)}${curV} =
|
|
1348
|
+
...iterStmts,
|
|
1349
|
+
`${ind(ctx)}if (!${iterOk} || ${iterEnd} === ${curV}) { ${rollback}break }`,
|
|
1350
|
+
`${ind(ctx)}${arrV}.push(${iterVal})`,
|
|
1351
|
+
`${ind(ctx)}${curV} = ${iterEnd}`
|
|
962
1352
|
);
|
|
963
1353
|
ctx.indent--;
|
|
964
1354
|
stmts.push(`${ind(ctx)}}`);
|
|
@@ -967,56 +1357,80 @@ function emitMany(def, ctx, pos) {
|
|
|
967
1357
|
function emitOptional(def, ctx, pos) {
|
|
968
1358
|
const valV = v(ctx, "_opt");
|
|
969
1359
|
const endV = v(ctx, "_opte");
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
const r = emit(def.parser, ctx, pos);
|
|
973
|
-
ctx.indent = savedIndent;
|
|
974
|
-
const iife = asIIFE(r.stmts, r.valueVar, r.endVar, pos, ind(ctx));
|
|
975
|
-
const resV = v(ctx, "_optr");
|
|
1360
|
+
const { stmts: lblStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
1361
|
+
const ind0 = ind(ctx);
|
|
976
1362
|
const stmts = [
|
|
977
|
-
|
|
978
|
-
`${
|
|
979
|
-
`${
|
|
1363
|
+
...lblStmts,
|
|
1364
|
+
`${ind0}const ${valV} = ${okVar} ? ${valVar} : null`,
|
|
1365
|
+
`${ind0}const ${endV} = ${okVar} ? ${endVar} : ${pos}`
|
|
980
1366
|
];
|
|
981
1367
|
return { stmts, valueVar: valV, endVar: endV };
|
|
982
1368
|
}
|
|
983
1369
|
function emitSepBy(_p, def, ctx, pos) {
|
|
984
1370
|
const arrV = v(ctx, "_arr");
|
|
985
1371
|
const curV = v(ctx, "_cur");
|
|
986
|
-
const
|
|
987
|
-
const saved = ctx.indent;
|
|
988
|
-
ctx.indent = 0;
|
|
989
|
-
const r = emit(inner, ctx, posExpr);
|
|
990
|
-
ctx.indent = saved;
|
|
991
|
-
return asIIFE(r.stmts, r.valueVar, r.endVar, posExpr, ind(ctx));
|
|
992
|
-
};
|
|
993
|
-
const firstR_saved = ctx.indent;
|
|
994
|
-
ctx.indent = 0;
|
|
995
|
-
const firstR = emit(def.parser, ctx, pos);
|
|
996
|
-
ctx.indent = firstR_saved;
|
|
997
|
-
const firstV = v(ctx, "_sb0");
|
|
998
|
-
const sepV = v(ctx, "_sbs");
|
|
999
|
-
const nextV = v(ctx, "_sbn");
|
|
1372
|
+
const { stmts: firstStmts, okVar: firstOk, valVar: firstVal, endVar: firstEnd } = emitFallible(def.parser, ctx, pos);
|
|
1000
1373
|
const stmts = [
|
|
1001
1374
|
`${ind(ctx)}const ${arrV} = []`,
|
|
1002
1375
|
`${ind(ctx)}let ${curV} = ${pos}`,
|
|
1003
|
-
|
|
1004
|
-
`${ind(ctx)}if (${
|
|
1376
|
+
...firstStmts,
|
|
1377
|
+
`${ind(ctx)}if (${firstOk}) {`
|
|
1005
1378
|
];
|
|
1006
1379
|
ctx.indent++;
|
|
1007
1380
|
stmts.push(
|
|
1008
|
-
`${ind(ctx)}${arrV}.push(${
|
|
1009
|
-
`${ind(ctx)}${curV} = ${
|
|
1381
|
+
`${ind(ctx)}${arrV}.push(${firstVal})`,
|
|
1382
|
+
`${ind(ctx)}${curV} = ${firstEnd}`,
|
|
1010
1383
|
`${ind(ctx)}while (${curV} < input.length) {`
|
|
1011
1384
|
);
|
|
1012
1385
|
ctx.indent++;
|
|
1386
|
+
let rollback = "";
|
|
1387
|
+
if (ctx.capturing) {
|
|
1388
|
+
const markV = v(ctx, "_mk");
|
|
1389
|
+
stmts.push(`${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`);
|
|
1390
|
+
rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; `;
|
|
1391
|
+
}
|
|
1392
|
+
let sepAtPos = curV;
|
|
1393
|
+
if (ctx.activeTrivia) {
|
|
1394
|
+
if (ctx.capturing) {
|
|
1395
|
+
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1396
|
+
const spV = v(ctx, "_sp");
|
|
1397
|
+
stmts.push(`${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx)`);
|
|
1398
|
+
sepAtPos = spV;
|
|
1399
|
+
} else {
|
|
1400
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1401
|
+
const spV = v(ctx, "_sp");
|
|
1402
|
+
stmts.push(
|
|
1403
|
+
`${ind(ctx)}let ${spV} = ${curV}`,
|
|
1404
|
+
`${ind(ctx)}{ const _trv = ${trivFn}(input, ${spV}, _ctx); if (_trv.ok) ${spV} = _trv.span.end }`
|
|
1405
|
+
);
|
|
1406
|
+
sepAtPos = spV;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos);
|
|
1410
|
+
stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollback}break }`);
|
|
1411
|
+
let nextAtPos = sepEnd;
|
|
1412
|
+
if (ctx.activeTrivia) {
|
|
1413
|
+
if (ctx.capturing) {
|
|
1414
|
+
const capFn = ensureTriviaCaptureFn(ctx);
|
|
1415
|
+
const npV = v(ctx, "_np");
|
|
1416
|
+
stmts.push(`${ind(ctx)}const ${npV} = ${capFn}(input, ${sepEnd}, _ctx)`);
|
|
1417
|
+
nextAtPos = npV;
|
|
1418
|
+
} else {
|
|
1419
|
+
const trivFn = ensureTriviaFn(ctx);
|
|
1420
|
+
const npV = v(ctx, "_np");
|
|
1421
|
+
stmts.push(
|
|
1422
|
+
`${ind(ctx)}let ${npV} = ${sepEnd}`,
|
|
1423
|
+
`${ind(ctx)}{ const _trv = ${trivFn}(input, ${npV}, _ctx); if (_trv.ok) ${npV} = _trv.span.end }`
|
|
1424
|
+
);
|
|
1425
|
+
nextAtPos = npV;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, nextAtPos);
|
|
1013
1429
|
stmts.push(
|
|
1014
|
-
|
|
1015
|
-
`${ind(ctx)}if (!${
|
|
1016
|
-
`${ind(ctx)}
|
|
1017
|
-
`${ind(ctx)}
|
|
1018
|
-
`${ind(ctx)}${arrV}.push(${nextV}.value)`,
|
|
1019
|
-
`${ind(ctx)}${curV} = ${nextV}.span.end`
|
|
1430
|
+
...nextStmts,
|
|
1431
|
+
`${ind(ctx)}if (!${nextOk}) { ${rollback}break }`,
|
|
1432
|
+
`${ind(ctx)}${arrV}.push(${nextVal})`,
|
|
1433
|
+
`${ind(ctx)}${curV} = ${nextEnd}`
|
|
1020
1434
|
);
|
|
1021
1435
|
ctx.indent--;
|
|
1022
1436
|
stmts.push(`${ind(ctx)}}`);
|
|
@@ -1025,13 +1439,6 @@ function emitSepBy(_p, def, ctx, pos) {
|
|
|
1025
1439
|
return { stmts, valueVar: arrV, endVar: curV };
|
|
1026
1440
|
}
|
|
1027
1441
|
function emitScanTo(def, ctx, pos) {
|
|
1028
|
-
const safeIIFE = (inner, posExpr) => {
|
|
1029
|
-
const saved = ctx.indent;
|
|
1030
|
-
ctx.indent = 0;
|
|
1031
|
-
const r = emit(inner, ctx, posExpr);
|
|
1032
|
-
ctx.indent = saved;
|
|
1033
|
-
return `(() => { try { return ${asIIFE(r.stmts, r.valueVar, r.endVar, posExpr, ind(ctx))} } catch { return null } })()`;
|
|
1034
|
-
};
|
|
1035
1442
|
const curV = v(ctx, "_stcur");
|
|
1036
1443
|
const foundV = v(ctx, "_stfnd");
|
|
1037
1444
|
const stmts = [
|
|
@@ -1040,18 +1447,19 @@ function emitScanTo(def, ctx, pos) {
|
|
|
1040
1447
|
`${ind(ctx)}while (${curV} < input.length) {`
|
|
1041
1448
|
];
|
|
1042
1449
|
ctx.indent++;
|
|
1043
|
-
const
|
|
1044
|
-
stmts.
|
|
1045
|
-
|
|
1046
|
-
`${ind(ctx)}if (${sentV}?.ok) { ${foundV} = true; break }`
|
|
1047
|
-
);
|
|
1450
|
+
const probeCtx = { ...ctx, capturing: false };
|
|
1451
|
+
const { stmts: sentStmts, okVar: sentOk } = emitFallible(def.sentinel, probeCtx, curV);
|
|
1452
|
+
stmts.push(...sentStmts, `${ind(ctx)}if (${sentOk}) { ${foundV} = true; break }`);
|
|
1048
1453
|
if (def.skip.length > 0) {
|
|
1049
1454
|
const advV = v(ctx, "_stadv");
|
|
1050
1455
|
stmts.push(`${ind(ctx)}let ${advV} = false`);
|
|
1051
1456
|
for (const skipper of def.skip) {
|
|
1052
|
-
const
|
|
1457
|
+
const { stmts: skStmts, okVar: skOk, endVar: skEnd } = emitFallible(skipper, probeCtx, curV);
|
|
1053
1458
|
stmts.push(
|
|
1054
|
-
`${ind(ctx)}if (!${advV}) {
|
|
1459
|
+
`${ind(ctx)}if (!${advV}) {`,
|
|
1460
|
+
...skStmts,
|
|
1461
|
+
`${ind(ctx)} if (${skOk} && ${skEnd} > ${curV}) { ${curV} = ${skEnd}; ${advV} = true }`,
|
|
1462
|
+
`${ind(ctx)}}`
|
|
1055
1463
|
);
|
|
1056
1464
|
}
|
|
1057
1465
|
stmts.push(`${ind(ctx)}if (!${advV}) ${curV}++`);
|
|
@@ -1063,14 +1471,54 @@ function emitScanTo(def, ctx, pos) {
|
|
|
1063
1471
|
if (!def.orEOF) {
|
|
1064
1472
|
const sentDef = def.sentinel._def;
|
|
1065
1473
|
const expectedStr = sentDef.tag === "literal" ? JSON.stringify([JSON.stringify(sentDef.value)]) : `["sentinel"]`;
|
|
1066
|
-
stmts.push(
|
|
1067
|
-
`${ind(ctx)}if (!${foundV}) return { ok: false, expected: ${expectedStr}, span: { start: ${pos}, end: ${curV} } }`
|
|
1068
|
-
);
|
|
1474
|
+
stmts.push(`${ind(ctx)}if (!${foundV}) ${failArr({ ...ctx, indent: 0 }, expectedStr, pos)}`);
|
|
1069
1475
|
}
|
|
1070
1476
|
const valV = v(ctx);
|
|
1071
1477
|
stmts.push(`${ind(ctx)}const ${valV} = input.slice(${pos}, ${curV})`);
|
|
1478
|
+
if (ctx.capturing) {
|
|
1479
|
+
const cap = emitLeafCapture(ctx, valV, pos, curV).map((s) => " " + s);
|
|
1480
|
+
stmts.push(`${ind(ctx)}if (${curV} > ${pos}) {`, ...cap, `${ind(ctx)}}`);
|
|
1481
|
+
}
|
|
1072
1482
|
return { stmts, valueVar: valV, endVar: curV };
|
|
1073
1483
|
}
|
|
1484
|
+
function emitNot(def, ctx, pos) {
|
|
1485
|
+
const { stmts, okVar } = emitFallible(def.parser, ctx, pos);
|
|
1486
|
+
return {
|
|
1487
|
+
stmts: [
|
|
1488
|
+
...stmts,
|
|
1489
|
+
`${ind(ctx)}if (${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"not"', pos).trim()}`
|
|
1490
|
+
],
|
|
1491
|
+
valueVar: "null",
|
|
1492
|
+
endVar: pos
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
function emitNode(def, ctx, pos) {
|
|
1496
|
+
const fnIdx = ctx.buildFns.length;
|
|
1497
|
+
ctx.buildFns.push(def.build);
|
|
1498
|
+
ctx.buildSrcs.push(def.buildSrc ?? null);
|
|
1499
|
+
const i = ind(ctx);
|
|
1500
|
+
const chV = v(ctx, "_ch");
|
|
1501
|
+
const rawV = v(ctx, "_raw");
|
|
1502
|
+
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st");
|
|
1503
|
+
const stmts = [
|
|
1504
|
+
`${i}const ${chV} = [], ${rawV} = []`,
|
|
1505
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia`,
|
|
1506
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true`
|
|
1507
|
+
];
|
|
1508
|
+
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
1509
|
+
stmts.push(...innerStmts);
|
|
1510
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}`);
|
|
1511
|
+
stmts.push(`${i}if (!${okVar}) ${failStmt({ ...ctx, indent: 0 }, '"node"', pos).trim()}`);
|
|
1512
|
+
const ndV = v(ctx, "_nd");
|
|
1513
|
+
stmts.push(
|
|
1514
|
+
`${i}const ${ndV} = _build[${fnIdx}](${chV}, ${rawV}, { start: ${pos}, end: ${endVar} })`,
|
|
1515
|
+
// Record into the caller's collectors (the node in children; the node, or a
|
|
1516
|
+
// spanned leaf if build collapsed to a non-node value, in rawChildren).
|
|
1517
|
+
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
1518
|
+
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && ${ndV}._tag === 'node') ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
1519
|
+
);
|
|
1520
|
+
return { stmts, valueVar: ndV, endVar };
|
|
1521
|
+
}
|
|
1074
1522
|
function emitRuntimeFallback(parser2, ctx, pos) {
|
|
1075
1523
|
const idx = ctx.runtimeParsers.length;
|
|
1076
1524
|
ctx.runtimeParsers.push(parser2);
|
|
@@ -1079,7 +1527,7 @@ function emitRuntimeFallback(parser2, ctx, pos) {
|
|
|
1079
1527
|
const ev = v(ctx, "_rte");
|
|
1080
1528
|
const stmts = [
|
|
1081
1529
|
`${ind(ctx)}const ${rv} = _rp[${idx}].parse(input, ${pos}, _ctx)`,
|
|
1082
|
-
`${ind(ctx)}if (!${rv}.ok)
|
|
1530
|
+
`${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"runtime"', pos).trim()}`,
|
|
1083
1531
|
`${ind(ctx)}const ${vv} = ${rv}.value`,
|
|
1084
1532
|
`${ind(ctx)}const ${ev} = ${rv}.span.end`
|
|
1085
1533
|
];
|
|
@@ -1097,9 +1545,12 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
1097
1545
|
return emitRuntimeFallback(p, ctx, pos);
|
|
1098
1546
|
}
|
|
1099
1547
|
const savedIndent = ctx.indent;
|
|
1548
|
+
const savedFailLabel = ctx.failLabel;
|
|
1100
1549
|
ctx.indent = 1;
|
|
1550
|
+
ctx.failLabel = void 0;
|
|
1101
1551
|
const r = emit(resolved, ctx, "_pos");
|
|
1102
1552
|
ctx.indent = savedIndent;
|
|
1553
|
+
ctx.failLabel = savedFailLabel;
|
|
1103
1554
|
ctx.namedFnDecls.push([
|
|
1104
1555
|
`function ${fnName2}(input, _pos, _ctx) {`,
|
|
1105
1556
|
...r.stmts,
|
|
@@ -1114,7 +1565,7 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
1114
1565
|
return {
|
|
1115
1566
|
stmts: [
|
|
1116
1567
|
`${ind(ctx)}const ${rv} = ${fnName}(input, ${pos}, _ctx)`,
|
|
1117
|
-
`${ind(ctx)}if (!${rv}.ok)
|
|
1568
|
+
`${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"parser"', pos).trim()}`,
|
|
1118
1569
|
`${ind(ctx)}const ${vv} = ${rv}.value`,
|
|
1119
1570
|
`${ind(ctx)}const ${ev} = ${rv}.span.end`
|
|
1120
1571
|
],
|
|
@@ -1122,6 +1573,33 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
1122
1573
|
endVar: ev
|
|
1123
1574
|
};
|
|
1124
1575
|
}
|
|
1576
|
+
function emitRecover(def, ctx, pos) {
|
|
1577
|
+
const { stmts: innerStmts, okVar, valVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
1578
|
+
const ind0 = ind(ctx);
|
|
1579
|
+
const scanV = v(ctx, "_sc");
|
|
1580
|
+
const errV = v(ctx, "_err");
|
|
1581
|
+
const savedIndent = ctx.indent;
|
|
1582
|
+
ctx.indent += 2;
|
|
1583
|
+
const { stmts: sentStmts, okVar: sentOk } = emitFallible(def.sentinel, ctx, scanV);
|
|
1584
|
+
ctx.indent = savedIndent;
|
|
1585
|
+
const stmts = [
|
|
1586
|
+
...innerStmts,
|
|
1587
|
+
`${ind0}if (!${okVar}) {`,
|
|
1588
|
+
`${ind0} let ${scanV} = ${pos}`,
|
|
1589
|
+
`${ind0} while (${scanV} < input.length) {`,
|
|
1590
|
+
...sentStmts,
|
|
1591
|
+
`${ind0} if (${sentOk}) break`,
|
|
1592
|
+
`${ind0} ${scanV}++`,
|
|
1593
|
+
`${ind0} }`,
|
|
1594
|
+
`${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: [] }`,
|
|
1595
|
+
`${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
|
|
1596
|
+
`${ind0} ${valVar} = ${errV}`,
|
|
1597
|
+
`${ind0} ${endVar} = ${scanV}`,
|
|
1598
|
+
`${ind0} ${okVar} = true`,
|
|
1599
|
+
`${ind0}}`
|
|
1600
|
+
];
|
|
1601
|
+
return { stmts, valueVar: valVar, endVar };
|
|
1602
|
+
}
|
|
1125
1603
|
function emit(p, ctx, pos) {
|
|
1126
1604
|
const def = p._def;
|
|
1127
1605
|
switch (def.tag) {
|
|
@@ -1144,6 +1622,7 @@ function emit(p, ctx, pos) {
|
|
|
1144
1622
|
const inner = emit(def.parser, ctx, pos);
|
|
1145
1623
|
const fnIdx = ctx.mapFns.length;
|
|
1146
1624
|
ctx.mapFns.push(def.fn);
|
|
1625
|
+
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
1147
1626
|
const mv = v(ctx, "_mapped");
|
|
1148
1627
|
return {
|
|
1149
1628
|
stmts: [
|
|
@@ -1184,15 +1663,21 @@ function emit(p, ctx, pos) {
|
|
|
1184
1663
|
else ctx.activeTrivia = savedTrivia;
|
|
1185
1664
|
return r;
|
|
1186
1665
|
}
|
|
1666
|
+
case "not":
|
|
1667
|
+
return emitNot(def, ctx, pos);
|
|
1668
|
+
case "node":
|
|
1669
|
+
return emitNode(def, ctx, pos);
|
|
1187
1670
|
case "scanTo":
|
|
1188
1671
|
return emitScanTo(def, ctx, pos);
|
|
1672
|
+
case "recover":
|
|
1673
|
+
return emitRecover(def, ctx, pos);
|
|
1189
1674
|
case "guard": {
|
|
1190
1675
|
const fnIdx = ctx.mapFns.length;
|
|
1191
1676
|
ctx.mapFns.push(def.predicate);
|
|
1192
1677
|
const vv = v(ctx);
|
|
1193
1678
|
return {
|
|
1194
1679
|
stmts: [
|
|
1195
|
-
`${ind(ctx)}if (!_mf[${fnIdx}](_ctx.
|
|
1680
|
+
`${ind(ctx)}if (!_mf[${fnIdx}](_ctx.state)) ${failStmt({ ...ctx, indent: 0 }, '"gate"', pos).trim()}`,
|
|
1196
1681
|
`${ind(ctx)}const ${vv} = null`
|
|
1197
1682
|
],
|
|
1198
1683
|
valueVar: vv,
|
|
@@ -1208,9 +1693,12 @@ function emit(p, ctx, pos) {
|
|
|
1208
1693
|
const fnName = `_wcf${ctx.namedParsers.size}`;
|
|
1209
1694
|
ctx.namedParsers.set(innerParser, fnName);
|
|
1210
1695
|
const savedIndent = ctx.indent;
|
|
1696
|
+
const savedFailLabel = ctx.failLabel;
|
|
1211
1697
|
ctx.indent = 1;
|
|
1698
|
+
ctx.failLabel = void 0;
|
|
1212
1699
|
const innerR = emit(innerParser, ctx, "_pos");
|
|
1213
1700
|
ctx.indent = savedIndent;
|
|
1701
|
+
ctx.failLabel = savedFailLabel;
|
|
1214
1702
|
ctx.namedFnDecls.push([
|
|
1215
1703
|
`function ${fnName}(input, _pos, _ctx) {`,
|
|
1216
1704
|
...innerR.stmts,
|
|
@@ -1224,8 +1712,8 @@ function emit(p, ctx, pos) {
|
|
|
1224
1712
|
const ev = v(ctx, "_wce");
|
|
1225
1713
|
return {
|
|
1226
1714
|
stmts: [
|
|
1227
|
-
`${ind(ctx)}const ${rv} = ${fn}(input, ${pos}, { ..._ctx,
|
|
1228
|
-
`${ind(ctx)}if (!${rv}.ok)
|
|
1715
|
+
`${ind(ctx)}const ${rv} = ${fn}(input, ${pos}, { ..._ctx, state: _mf[${evIdx}]() })`,
|
|
1716
|
+
`${ind(ctx)}if (!${rv}.ok) ${failStmt({ ...ctx, indent: 0 }, '"withCtx"', pos).trim()}`,
|
|
1229
1717
|
`${ind(ctx)}const ${vv} = ${rv}.value`,
|
|
1230
1718
|
`${ind(ctx)}const ${ev} = ${rv}.span.end`
|
|
1231
1719
|
],
|
|
@@ -1237,16 +1725,61 @@ function emit(p, ctx, pos) {
|
|
|
1237
1725
|
return emitRuntimeFallback(p, ctx, pos);
|
|
1238
1726
|
}
|
|
1239
1727
|
}
|
|
1240
|
-
function
|
|
1728
|
+
function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
1729
|
+
if (seen.has(p)) return false;
|
|
1730
|
+
seen.add(p);
|
|
1731
|
+
const d = p._def;
|
|
1732
|
+
switch (d.tag) {
|
|
1733
|
+
case "node":
|
|
1734
|
+
return true;
|
|
1735
|
+
case "lazy": {
|
|
1736
|
+
try {
|
|
1737
|
+
return hasNodeDef(d.thunk(), seen);
|
|
1738
|
+
} catch {
|
|
1739
|
+
return false;
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
case "grammar":
|
|
1743
|
+
case "trivia":
|
|
1744
|
+
case "optional":
|
|
1745
|
+
case "many":
|
|
1746
|
+
case "oneOrMore":
|
|
1747
|
+
case "not":
|
|
1748
|
+
case "transform":
|
|
1749
|
+
return hasNodeDef(d.parser, seen);
|
|
1750
|
+
case "skip":
|
|
1751
|
+
return hasNodeDef(d.main, seen) || hasNodeDef(d.skipped, seen);
|
|
1752
|
+
case "sequence":
|
|
1753
|
+
case "choice":
|
|
1754
|
+
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
1755
|
+
case "sepBy":
|
|
1756
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
1757
|
+
case "scanTo":
|
|
1758
|
+
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
|
|
1759
|
+
case "recover":
|
|
1760
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
1761
|
+
case "withCtx":
|
|
1762
|
+
return hasNodeDef(d.parser, seen);
|
|
1763
|
+
default:
|
|
1764
|
+
return false;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
function compile(parser2, mapFnSources) {
|
|
1241
1768
|
const ctx = {
|
|
1242
1769
|
vars: 0,
|
|
1243
1770
|
indent: 1,
|
|
1244
1771
|
regexDecls: [],
|
|
1772
|
+
regexMap: /* @__PURE__ */ new Map(),
|
|
1245
1773
|
mapFns: [],
|
|
1774
|
+
mapFnSrcs: [],
|
|
1775
|
+
buildFns: [],
|
|
1776
|
+
buildSrcs: [],
|
|
1246
1777
|
runtimeParsers: [],
|
|
1247
1778
|
needsCollator: false,
|
|
1248
1779
|
namedParsers: /* @__PURE__ */ new Map(),
|
|
1249
|
-
|
|
1780
|
+
triviaCaptureNames: /* @__PURE__ */ new Map(),
|
|
1781
|
+
namedFnDecls: [],
|
|
1782
|
+
capturing: hasNodeDef(parser2)
|
|
1250
1783
|
};
|
|
1251
1784
|
const r = emit(parser2, ctx, "_pos");
|
|
1252
1785
|
const collatorDecl = ctx.needsCollator ? `const _collator = new Intl.Collator(undefined, { sensitivity: 'accent' })
|
|
@@ -1255,13 +1788,13 @@ function compile(parser2) {
|
|
|
1255
1788
|
...ctx.regexDecls,
|
|
1256
1789
|
"",
|
|
1257
1790
|
...ctx.namedFnDecls,
|
|
1258
|
-
`${collatorDecl}function _parse(input, _pos, _rp, _mf, _ctx) {`,
|
|
1791
|
+
`${collatorDecl}function _parse(input, _pos, _rp, _mf, _build, _ctx) {`,
|
|
1259
1792
|
` let pos = _pos`,
|
|
1260
1793
|
...r.stmts,
|
|
1261
1794
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
1262
1795
|
`}`
|
|
1263
1796
|
].join("\n");
|
|
1264
|
-
const fn = new Function("input", "_pos", "_rp", "_mf", "_ctx", [
|
|
1797
|
+
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
1265
1798
|
...ctx.regexDecls,
|
|
1266
1799
|
collatorDecl,
|
|
1267
1800
|
...ctx.namedFnDecls,
|
|
@@ -1270,17 +1803,27 @@ function compile(parser2) {
|
|
|
1270
1803
|
`return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`
|
|
1271
1804
|
].join("\n"));
|
|
1272
1805
|
const defaultCtx = { trackLines: false };
|
|
1273
|
-
const
|
|
1274
|
-
const
|
|
1806
|
+
const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
|
|
1807
|
+
const effectiveSources = mapFnSources ?? derivedSrcs;
|
|
1808
|
+
const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
|
|
1809
|
+
const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
|
|
1810
|
+
const mfCovered = ctx.mapFns.length === 0 || effectiveSources !== void 0 && effectiveSources.length === ctx.mapFns.length;
|
|
1811
|
+
const canInline = ctx.runtimeParsers.length === 0 && mfCovered && buildCovered;
|
|
1812
|
+
const inlineExpression = canInline ? buildInlineExpression(ctx, r, collatorDecl, effectiveSources, buildSources) : null;
|
|
1275
1813
|
return {
|
|
1276
1814
|
source,
|
|
1277
1815
|
inlineExpression,
|
|
1278
1816
|
parse(input, pos = 0) {
|
|
1279
|
-
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, defaultCtx);
|
|
1817
|
+
return fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, defaultCtx);
|
|
1818
|
+
},
|
|
1819
|
+
parseWithErrors(input, pos = 0) {
|
|
1820
|
+
const errors = [];
|
|
1821
|
+
const result = fn(input, pos, ctx.runtimeParsers, ctx.mapFns, ctx.buildFns, { ...defaultCtx, _errors: errors });
|
|
1822
|
+
return { ...result, errors };
|
|
1280
1823
|
}
|
|
1281
1824
|
};
|
|
1282
1825
|
}
|
|
1283
|
-
function buildInlineExpression(ctx, r, collatorDecl) {
|
|
1826
|
+
function buildInlineExpression(ctx, r, collatorDecl, mapFnSources, buildSources) {
|
|
1284
1827
|
const bodyLines = [
|
|
1285
1828
|
` let pos = _pos`,
|
|
1286
1829
|
...r.stmts.map((s) => ` ${s}`),
|
|
@@ -1291,20 +1834,82 @@ function buildInlineExpression(ctx, r, collatorDecl) {
|
|
|
1291
1834
|
...bodyLines,
|
|
1292
1835
|
`}`
|
|
1293
1836
|
].join("\n");
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1837
|
+
const mfDecl = mapFnSources?.length ? ` const _mf = [${mapFnSources.join(", ")}]` : "";
|
|
1838
|
+
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
1839
|
+
const needsWrapper = ctx.regexDecls.length > 0 || !!collatorDecl || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl;
|
|
1840
|
+
if (!needsWrapper) return innerFn;
|
|
1298
1841
|
return [
|
|
1299
1842
|
`/* @__PURE__ */ (() => {`,
|
|
1300
1843
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
1301
1844
|
collatorDecl ? ` ${collatorDecl.trim()}` : "",
|
|
1845
|
+
mfDecl,
|
|
1846
|
+
buildDecl,
|
|
1302
1847
|
...ctx.namedFnDecls.flatMap((f) => f.split("\n").map((l) => ` ${l}`)),
|
|
1303
1848
|
` return ${innerFn}`,
|
|
1304
1849
|
`})()`
|
|
1305
1850
|
].filter(Boolean).join("\n");
|
|
1306
1851
|
}
|
|
1307
1852
|
|
|
1853
|
+
// src/combinators/scanTo.ts
|
|
1854
|
+
function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
1855
|
+
const meta = {
|
|
1856
|
+
firstSet: any(),
|
|
1857
|
+
canMatchNewline: true,
|
|
1858
|
+
isTrivia: false
|
|
1859
|
+
};
|
|
1860
|
+
return {
|
|
1861
|
+
_tag: "scanTo",
|
|
1862
|
+
_meta: meta,
|
|
1863
|
+
_def: { tag: "scanTo", sentinel, skip: skip2, orEOF },
|
|
1864
|
+
parse(input, pos, ctx) {
|
|
1865
|
+
let cur = pos;
|
|
1866
|
+
const probeCtx = { trackLines: ctx.trackLines, state: ctx.state };
|
|
1867
|
+
const emit2 = (end) => {
|
|
1868
|
+
if (end > pos && (ctx._cstLeaves || ctx._cstRawChildren)) {
|
|
1869
|
+
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
1870
|
+
if (ctx._cstLeaves) ctx._cstLeaves.push(leaf);
|
|
1871
|
+
if (ctx._cstRawChildren) ctx._cstRawChildren.push(leaf);
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
while (cur < input.length) {
|
|
1875
|
+
const s = sentinel.parse(input, cur, probeCtx);
|
|
1876
|
+
if (s.ok) {
|
|
1877
|
+
emit2(cur);
|
|
1878
|
+
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
1879
|
+
}
|
|
1880
|
+
let advanced = false;
|
|
1881
|
+
for (const skipper of skip2) {
|
|
1882
|
+
const r = skipper.parse(input, cur, probeCtx);
|
|
1883
|
+
if (r.ok && r.span.end > cur) {
|
|
1884
|
+
cur = r.span.end;
|
|
1885
|
+
advanced = true;
|
|
1886
|
+
break;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
if (!advanced) cur++;
|
|
1890
|
+
}
|
|
1891
|
+
if (orEOF) {
|
|
1892
|
+
emit2(cur);
|
|
1893
|
+
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
1894
|
+
}
|
|
1895
|
+
const sentDef = sentinel._def;
|
|
1896
|
+
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|
|
1897
|
+
return { ok: false, expected, span: { start: pos, end: cur } };
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
function balanced(open, close, options = {}) {
|
|
1902
|
+
const inner = scanTo(literal(close), options);
|
|
1903
|
+
const combi = transform(
|
|
1904
|
+
sequence(literal(open), inner, literal(close)),
|
|
1905
|
+
([o, content, c]) => o + content + c
|
|
1906
|
+
);
|
|
1907
|
+
if (combi._def.tag === "transform") {
|
|
1908
|
+
combi._def.fnSrc = "([o, content, c]) => o + content + c";
|
|
1909
|
+
}
|
|
1910
|
+
return combi;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1308
1913
|
// src/plugin/evaluator.ts
|
|
1309
1914
|
var SUPPORTED = {
|
|
1310
1915
|
literal: (...a) => literal(a[0], a[1]),
|
|
@@ -1314,19 +1919,144 @@ var SUPPORTED = {
|
|
|
1314
1919
|
many: (...a) => many(a[0]),
|
|
1315
1920
|
oneOrMore: (...a) => oneOrMore(a[0]),
|
|
1316
1921
|
optional: (...a) => optional(a[0]),
|
|
1317
|
-
sepBy: (...a) => sepBy(a[0], a[1])
|
|
1318
|
-
|
|
1922
|
+
sepBy: (...a) => sepBy(a[0], a[1]),
|
|
1923
|
+
trivia: (...a) => trivia(a[0])
|
|
1319
1924
|
};
|
|
1320
|
-
function
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1925
|
+
function isScopeEntry(v2) {
|
|
1926
|
+
return !!v2 && typeof v2 === "object" && "combi" in v2 && "mfSrcs" in v2;
|
|
1927
|
+
}
|
|
1928
|
+
function isCombinator(v2) {
|
|
1929
|
+
return !!v2 && typeof v2 === "object" && "_def" in v2;
|
|
1930
|
+
}
|
|
1931
|
+
function scopeGet(scope, name, mfs) {
|
|
1932
|
+
const entry = scope.get(name);
|
|
1933
|
+
if (!entry) return null;
|
|
1934
|
+
if (isScopeEntry(entry)) {
|
|
1935
|
+
if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
|
|
1936
|
+
return entry.combi;
|
|
1937
|
+
}
|
|
1938
|
+
if (isCombinator(entry)) return entry;
|
|
1939
|
+
return null;
|
|
1940
|
+
}
|
|
1941
|
+
function exprToCombi(node2, scope, code, mfs) {
|
|
1942
|
+
if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
|
|
1943
|
+
if (node2.type !== "CallExpression") return null;
|
|
1944
|
+
const callee = node2.callee;
|
|
1324
1945
|
if (callee.type !== "Identifier") return null;
|
|
1946
|
+
if (callee.name === "transform" && code !== void 0 && mfs !== void 0) {
|
|
1947
|
+
const [parserArg, fnArg] = node2.arguments;
|
|
1948
|
+
if (!parserArg || !fnArg || parserArg.type === "SpreadElement" || fnArg.type === "SpreadElement") return null;
|
|
1949
|
+
const inner = anyValue(parserArg, scope, code, mfs);
|
|
1950
|
+
if (!isCombinator(inner)) return null;
|
|
1951
|
+
const fnSrc = code.slice(fnArg.start, fnArg.end);
|
|
1952
|
+
mfs.push(fnSrc);
|
|
1953
|
+
try {
|
|
1954
|
+
const combi = transform(inner, (v2) => v2);
|
|
1955
|
+
if (combi._def.tag === "transform") combi._def.fnSrc = fnSrc;
|
|
1956
|
+
return combi;
|
|
1957
|
+
} catch {
|
|
1958
|
+
return null;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
if (callee.name === "node" && code !== void 0) {
|
|
1962
|
+
const [typeArg, parserArg, buildArg] = node2.arguments;
|
|
1963
|
+
if (!typeArg || !parserArg || !buildArg || typeArg.type === "SpreadElement" || parserArg.type === "SpreadElement" || buildArg.type === "SpreadElement") return null;
|
|
1964
|
+
const typeVal = anyValue(typeArg, scope, code);
|
|
1965
|
+
if (typeof typeVal !== "string") return null;
|
|
1966
|
+
const inner = anyValue(parserArg, scope, code, mfs);
|
|
1967
|
+
if (!isCombinator(inner)) return null;
|
|
1968
|
+
const buildSrc = code.slice(buildArg.start, buildArg.end);
|
|
1969
|
+
try {
|
|
1970
|
+
const combi = node(typeVal, inner, () => null);
|
|
1971
|
+
if (combi._def.tag === "node") combi._def.buildSrc = buildSrc;
|
|
1972
|
+
return combi;
|
|
1973
|
+
} catch {
|
|
1974
|
+
return null;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
if (callee.name === "rules") return null;
|
|
1978
|
+
if (callee.name === "parser") {
|
|
1979
|
+
const [optsArg, rootArg] = node2.arguments;
|
|
1980
|
+
if (!optsArg || !rootArg || optsArg.type === "SpreadElement" || rootArg.type === "SpreadElement") return null;
|
|
1981
|
+
const opts = anyValue(optsArg, scope, code, []);
|
|
1982
|
+
if (!opts || typeof opts !== "object") return null;
|
|
1983
|
+
const root = anyValue(rootArg, scope, code, mfs);
|
|
1984
|
+
if (!isCombinator(root)) return null;
|
|
1985
|
+
try {
|
|
1986
|
+
return parser(opts, root);
|
|
1987
|
+
} catch {
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
if (callee.name === "sepBy") {
|
|
1992
|
+
const [itemArg, sepArg] = node2.arguments;
|
|
1993
|
+
if (!itemArg || !sepArg || itemArg.type === "SpreadElement" || sepArg.type === "SpreadElement") return null;
|
|
1994
|
+
const itemMfs = [];
|
|
1995
|
+
const itemCombi = anyValue(itemArg, scope, code, itemMfs);
|
|
1996
|
+
if (!isCombinator(itemCombi)) return null;
|
|
1997
|
+
const sepMfs = [];
|
|
1998
|
+
const sepCombi = anyValue(sepArg, scope, code, sepMfs);
|
|
1999
|
+
if (!isCombinator(sepCombi)) return null;
|
|
2000
|
+
if (mfs) mfs.push(...itemMfs, ...sepMfs, ...itemMfs);
|
|
2001
|
+
try {
|
|
2002
|
+
return sepBy(itemCombi, sepCombi);
|
|
2003
|
+
} catch {
|
|
2004
|
+
return null;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
if (callee.name === "oneOrMore") {
|
|
2008
|
+
const [itemArg] = node2.arguments;
|
|
2009
|
+
if (!itemArg || itemArg.type === "SpreadElement") return null;
|
|
2010
|
+
const itemMfs = [];
|
|
2011
|
+
const itemCombi = anyValue(itemArg, scope, code, itemMfs);
|
|
2012
|
+
if (!isCombinator(itemCombi)) return null;
|
|
2013
|
+
if (mfs) mfs.push(...itemMfs, ...itemMfs);
|
|
2014
|
+
try {
|
|
2015
|
+
return oneOrMore(itemCombi);
|
|
2016
|
+
} catch {
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
if (callee.name === "not") {
|
|
2021
|
+
const [innerArg] = node2.arguments;
|
|
2022
|
+
if (!innerArg || innerArg.type === "SpreadElement") return null;
|
|
2023
|
+
const inner = anyValue(innerArg, scope, code, mfs);
|
|
2024
|
+
if (!isCombinator(inner)) return null;
|
|
2025
|
+
try {
|
|
2026
|
+
return not(inner);
|
|
2027
|
+
} catch {
|
|
2028
|
+
return null;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
if (callee.name === "balanced") {
|
|
2032
|
+
const [openArg, closeArg] = node2.arguments;
|
|
2033
|
+
if (!openArg || !closeArg || openArg.type === "SpreadElement" || closeArg.type === "SpreadElement") return null;
|
|
2034
|
+
const open = anyValue(openArg, scope, code, []);
|
|
2035
|
+
const close = anyValue(closeArg, scope, code, []);
|
|
2036
|
+
if (typeof open !== "string" || typeof close !== "string") return null;
|
|
2037
|
+
try {
|
|
2038
|
+
return balanced(open, close);
|
|
2039
|
+
} catch {
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
if (callee.name === "scanTo") {
|
|
2044
|
+
const [sentinelArg, optsArg] = node2.arguments;
|
|
2045
|
+
if (!sentinelArg || sentinelArg.type === "SpreadElement") return null;
|
|
2046
|
+
const sentinel = anyValue(sentinelArg, scope, code, []);
|
|
2047
|
+
if (!isCombinator(sentinel)) return null;
|
|
2048
|
+
const opts = optsArg && optsArg.type !== "SpreadElement" ? anyValue(optsArg, scope, code, []) : void 0;
|
|
2049
|
+
try {
|
|
2050
|
+
return scanTo(sentinel, opts);
|
|
2051
|
+
} catch {
|
|
2052
|
+
return null;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
1325
2055
|
const factory = SUPPORTED[callee.name];
|
|
1326
2056
|
if (!factory) return null;
|
|
1327
|
-
const args =
|
|
2057
|
+
const args = node2.arguments.map((arg) => {
|
|
1328
2058
|
if (arg.type === "SpreadElement") return null;
|
|
1329
|
-
return
|
|
2059
|
+
return anyValue(arg, scope, code, mfs);
|
|
1330
2060
|
});
|
|
1331
2061
|
if (args.some((a) => a === null)) return null;
|
|
1332
2062
|
try {
|
|
@@ -1335,37 +2065,142 @@ function evaluateExpr(node, scope) {
|
|
|
1335
2065
|
return null;
|
|
1336
2066
|
}
|
|
1337
2067
|
}
|
|
1338
|
-
function
|
|
1339
|
-
if (
|
|
1340
|
-
if ("regex" in
|
|
1341
|
-
return new RegExp(
|
|
2068
|
+
function anyValue(node2, scope, code, mfs) {
|
|
2069
|
+
if (node2.type === "Literal") {
|
|
2070
|
+
if ("regex" in node2 && node2.regex !== null && node2.regex !== void 0) {
|
|
2071
|
+
return new RegExp(node2.regex.pattern, node2.regex.flags);
|
|
1342
2072
|
}
|
|
1343
|
-
return
|
|
2073
|
+
return node2.value;
|
|
1344
2074
|
}
|
|
1345
|
-
if (
|
|
2075
|
+
if (node2.type === "ArrayExpression") {
|
|
2076
|
+
const arr = node2;
|
|
2077
|
+
const out = [];
|
|
2078
|
+
for (const el of arr.elements) {
|
|
2079
|
+
if (el === null) {
|
|
2080
|
+
out.push(null);
|
|
2081
|
+
continue;
|
|
2082
|
+
}
|
|
2083
|
+
if (el.type === "SpreadElement") return null;
|
|
2084
|
+
out.push(anyValue(el, scope, code, mfs));
|
|
2085
|
+
}
|
|
2086
|
+
return out;
|
|
2087
|
+
}
|
|
2088
|
+
if (node2.type === "ObjectExpression") {
|
|
1346
2089
|
const obj = {};
|
|
1347
|
-
for (const prop of
|
|
2090
|
+
for (const prop of node2.properties) {
|
|
1348
2091
|
if (prop.type !== "Property") return null;
|
|
1349
2092
|
if (prop.computed) return null;
|
|
1350
2093
|
const key = prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "Literal" ? String(prop.key.value) : null;
|
|
1351
2094
|
if (key === null) return null;
|
|
1352
|
-
obj[key] =
|
|
2095
|
+
obj[key] = anyValue(prop.value, scope, code, mfs);
|
|
1353
2096
|
}
|
|
1354
2097
|
return obj;
|
|
1355
2098
|
}
|
|
1356
|
-
if (
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
2099
|
+
if (node2.type === "Identifier") {
|
|
2100
|
+
if (node2.name === "undefined") return void 0;
|
|
2101
|
+
const entry = scope.get(node2.name) ?? null;
|
|
2102
|
+
if (isScopeEntry(entry)) {
|
|
2103
|
+
if (mfs && entry.mfSrcs.length > 0) mfs.push(...entry.mfSrcs);
|
|
2104
|
+
return entry.combi;
|
|
2105
|
+
}
|
|
2106
|
+
return entry;
|
|
1359
2107
|
}
|
|
1360
|
-
if (
|
|
2108
|
+
if (node2.type === "MemberExpression") {
|
|
2109
|
+
const mem = node2;
|
|
2110
|
+
const obj = anyValue(mem.object, scope, code, mfs);
|
|
2111
|
+
if (!obj || typeof obj !== "object") return null;
|
|
2112
|
+
if (node2.computed) {
|
|
2113
|
+
const key = anyValue(node2.property, scope, code, mfs);
|
|
2114
|
+
if (typeof key !== "string" && typeof key !== "number") return null;
|
|
2115
|
+
return obj[key] ?? null;
|
|
2116
|
+
}
|
|
2117
|
+
const propName = mem.property.name;
|
|
2118
|
+
if (!propName) return null;
|
|
2119
|
+
return obj[propName] ?? null;
|
|
2120
|
+
}
|
|
2121
|
+
if (node2.type === "CallExpression") return exprToCombi(node2, scope, code, mfs);
|
|
1361
2122
|
return null;
|
|
1362
2123
|
}
|
|
1363
|
-
function
|
|
1364
|
-
|
|
1365
|
-
|
|
2124
|
+
function evaluateExpr(node2, scope, code, mapFnSources) {
|
|
2125
|
+
return exprToCombi(node2, scope, code, mapFnSources);
|
|
2126
|
+
}
|
|
2127
|
+
function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
|
|
2128
|
+
if (factoryNode.type !== "ArrowFunctionExpression" && factoryNode.type !== "FunctionDeclaration" && factoryNode.type !== "FunctionExpression") return null;
|
|
2129
|
+
const factory = factoryNode;
|
|
2130
|
+
const params = factory.params;
|
|
2131
|
+
if (params.length !== 1) return null;
|
|
2132
|
+
const param = params[0];
|
|
2133
|
+
const proxyName = param.type === "Identifier" ? param.name ?? null : null;
|
|
2134
|
+
if (!proxyName) return null;
|
|
2135
|
+
const body = factory.body;
|
|
2136
|
+
if (!body) return null;
|
|
2137
|
+
const statements = [];
|
|
2138
|
+
let returnExpr = null;
|
|
2139
|
+
if (body.type === "BlockStatement") {
|
|
2140
|
+
const stmts = body.body;
|
|
2141
|
+
for (const stmt of stmts) {
|
|
2142
|
+
const s = stmt;
|
|
2143
|
+
if (s.type === "ReturnStatement") {
|
|
2144
|
+
returnExpr = s.argument ?? null;
|
|
2145
|
+
break;
|
|
2146
|
+
}
|
|
2147
|
+
if (s.type === "VariableDeclaration") {
|
|
2148
|
+
statements.push(s);
|
|
2149
|
+
} else {
|
|
2150
|
+
return null;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
} else {
|
|
2154
|
+
returnExpr = body;
|
|
2155
|
+
}
|
|
2156
|
+
if (!returnExpr) return null;
|
|
2157
|
+
const retObj = returnExpr.type === "ParenthesizedExpression" ? returnExpr.expression : returnExpr;
|
|
2158
|
+
if (retObj.type !== "ObjectExpression") return null;
|
|
2159
|
+
const ruleRefs = /* @__PURE__ */ new Map();
|
|
2160
|
+
for (const prop of retObj.properties) {
|
|
2161
|
+
if (prop.type !== "Property") return null;
|
|
2162
|
+
if (prop.computed) return null;
|
|
2163
|
+
const p = prop;
|
|
2164
|
+
const key = p.key.type === "Identifier" ? p.key.name : p.key.type === "Literal" ? String(p.key.value) : null;
|
|
2165
|
+
if (!key) return null;
|
|
2166
|
+
ruleRefs.set(key, ref());
|
|
2167
|
+
}
|
|
2168
|
+
const localScope = new Map(scope);
|
|
2169
|
+
localScope.set(proxyName, Object.fromEntries(ruleRefs));
|
|
2170
|
+
const bodyMfs = [];
|
|
2171
|
+
for (const stmt of statements) {
|
|
2172
|
+
for (const d of stmt.declarations) {
|
|
2173
|
+
const decl = d;
|
|
2174
|
+
if (!decl.init) return null;
|
|
2175
|
+
const id = decl.id;
|
|
2176
|
+
if (id.type !== "Identifier" && id.type !== "BindingIdentifier") return null;
|
|
2177
|
+
const name = id.name;
|
|
2178
|
+
const before = bodyMfs.length;
|
|
2179
|
+
const val = anyValue(decl.init, localScope, code, bodyMfs);
|
|
2180
|
+
if (val === null) return null;
|
|
2181
|
+
const thisDeclMfSrcs = bodyMfs.slice(before);
|
|
2182
|
+
if (isCombinator(val)) {
|
|
2183
|
+
localScope.set(name, { combi: val, mfSrcs: thisDeclMfSrcs });
|
|
2184
|
+
} else {
|
|
2185
|
+
localScope.set(name, val);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
for (const prop of retObj.properties) {
|
|
2190
|
+
const p = prop;
|
|
2191
|
+
const key = p.key.type === "Identifier" ? p.key.name : String(p.key.value);
|
|
2192
|
+
const val = anyValue(p.value, localScope, code, mapFnSources);
|
|
2193
|
+
if (!isCombinator(val)) return null;
|
|
2194
|
+
ruleRefs.get(key).define(val);
|
|
2195
|
+
}
|
|
2196
|
+
return ruleRefs;
|
|
2197
|
+
}
|
|
2198
|
+
function referencesAny(node2, names, scope) {
|
|
2199
|
+
if (node2.type === "Identifier") {
|
|
2200
|
+
return names.has(node2.name) || scope.has(node2.name);
|
|
1366
2201
|
}
|
|
1367
|
-
for (const key of Object.keys(
|
|
1368
|
-
const child =
|
|
2202
|
+
for (const key of Object.keys(node2)) {
|
|
2203
|
+
const child = node2[key];
|
|
1369
2204
|
if (!child || typeof child !== "object") continue;
|
|
1370
2205
|
if (Array.isArray(child)) {
|
|
1371
2206
|
if (child.some((c) => c && typeof c === "object" && "type" in c && referencesAny(c, names, scope))) return true;
|
|
@@ -1380,6 +2215,10 @@ function referencesAny(node, names, scope) {
|
|
|
1380
2215
|
var PARSEMAN_MODULE = "parseman";
|
|
1381
2216
|
var plugin_default = (0, import_unplugin.createUnplugin)((opts = {}) => ({
|
|
1382
2217
|
name: "parseman",
|
|
2218
|
+
// Run BEFORE the bundler's TS/JS transform — otherwise esbuild (Vite) strips
|
|
2219
|
+
// the `with { type: 'macro' }` import attribute before we ever see it, and the
|
|
2220
|
+
// macro silently never fires.
|
|
2221
|
+
enforce: "pre",
|
|
1383
2222
|
transformInclude(id) {
|
|
1384
2223
|
return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
|
|
1385
2224
|
},
|
|
@@ -1387,7 +2226,15 @@ var plugin_default = (0, import_unplugin.createUnplugin)((opts = {}) => ({
|
|
|
1387
2226
|
if (!code.includes("parseman")) return null;
|
|
1388
2227
|
if (!code.includes("macro")) return null;
|
|
1389
2228
|
const moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE, ...opts.moduleAliases ?? []]);
|
|
1390
|
-
|
|
2229
|
+
const result = transformMacro(code, id, moduleAliases);
|
|
2230
|
+
if (result?.warnings.length) {
|
|
2231
|
+
for (const w of result.warnings) {
|
|
2232
|
+
if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
|
|
2233
|
+
else console.warn(`[parseman] ${w}`);
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
if (!result) return null;
|
|
2237
|
+
return { code: result.code, map: result.map };
|
|
1391
2238
|
}
|
|
1392
2239
|
}));
|
|
1393
2240
|
function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE])) {
|
|
@@ -1420,35 +2267,136 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
1420
2267
|
if (macroImports.length === 0) return null;
|
|
1421
2268
|
const scope = /* @__PURE__ */ new Map();
|
|
1422
2269
|
const replacements = [];
|
|
2270
|
+
const warnings = [];
|
|
1423
2271
|
let anyUnresolved = false;
|
|
2272
|
+
const lineOf = (pos) => {
|
|
2273
|
+
let line = 1;
|
|
2274
|
+
for (let i = 0; i < pos && i < code.length; i++) if (code.charCodeAt(i) === 10) line++;
|
|
2275
|
+
return line;
|
|
2276
|
+
};
|
|
2277
|
+
const warn = (pos, msg) => {
|
|
2278
|
+
anyUnresolved = true;
|
|
2279
|
+
warnings.push(`${id}:${lineOf(pos)} \u2014 ${msg} (running via the interpreter; add the plugin or simplify the declaration to compile it)`);
|
|
2280
|
+
};
|
|
2281
|
+
const compileRulesFactory = (init, label) => {
|
|
2282
|
+
const args = init.arguments;
|
|
2283
|
+
const factoryArg = args[0];
|
|
2284
|
+
if (!factoryArg) {
|
|
2285
|
+
warn(init.start, `${label}: rules() needs a factory argument`);
|
|
2286
|
+
return null;
|
|
2287
|
+
}
|
|
2288
|
+
const ruleMap = evaluateParserFactory(factoryArg, scope, code, []);
|
|
2289
|
+
if (!ruleMap) {
|
|
2290
|
+
warn(init.start, `${label}: rules(...) factory isn't statically evaluable`);
|
|
2291
|
+
return null;
|
|
2292
|
+
}
|
|
2293
|
+
const entries = [];
|
|
2294
|
+
for (const [ruleKey, rule] of ruleMap) {
|
|
2295
|
+
const compiled = compile(rule);
|
|
2296
|
+
if (compiled.inlineExpression === null) {
|
|
2297
|
+
warn(init.start, `${label}: rule "${ruleKey}" couldn't be inlined`);
|
|
2298
|
+
return null;
|
|
2299
|
+
}
|
|
2300
|
+
entries.push([ruleKey, compiled.inlineExpression]);
|
|
2301
|
+
}
|
|
2302
|
+
return { entries, ruleMap };
|
|
2303
|
+
};
|
|
2304
|
+
const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
|
|
1424
2305
|
for (const stmt of body) {
|
|
1425
|
-
|
|
1426
|
-
|
|
2306
|
+
let vd = null;
|
|
2307
|
+
let stmtStart = stmt.start;
|
|
2308
|
+
let stmtEnd = stmt.end;
|
|
2309
|
+
let exportPrefix = "";
|
|
2310
|
+
if (stmt.type === "VariableDeclaration") {
|
|
2311
|
+
vd = stmt;
|
|
2312
|
+
} else if (stmt.type === "ExportNamedDeclaration") {
|
|
2313
|
+
const expStmt = stmt;
|
|
2314
|
+
if (expStmt.declaration?.type === "VariableDeclaration") {
|
|
2315
|
+
vd = expStmt.declaration;
|
|
2316
|
+
exportPrefix = "export ";
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
if (!vd) continue;
|
|
2320
|
+
for (const decl of vd.declarations) {
|
|
1427
2321
|
const d = decl;
|
|
1428
2322
|
if (!d.init) continue;
|
|
1429
|
-
if (d.id.type !== "Identifier") continue;
|
|
1430
|
-
const varName = d.id.name;
|
|
1431
2323
|
const init = d.init;
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
2324
|
+
const kind = vd.kind ?? "const";
|
|
2325
|
+
if (d.id.type === "Identifier") {
|
|
2326
|
+
const varName = d.id.name;
|
|
2327
|
+
if (!referencesAny(init, allNames, scope)) continue;
|
|
2328
|
+
if (isRulesCall(init)) {
|
|
2329
|
+
const compiledRules = compileRulesFactory(init, varName);
|
|
2330
|
+
if (!compiledRules) continue;
|
|
2331
|
+
replacements.push({
|
|
2332
|
+
start: init.start,
|
|
2333
|
+
end: init.end,
|
|
2334
|
+
replacement: `{ ${compiledRules.entries.map(([k, expr]) => `${k}: ${expr}`).join(", ")} }`
|
|
2335
|
+
});
|
|
2336
|
+
continue;
|
|
2337
|
+
}
|
|
2338
|
+
const mapFnSources = [];
|
|
2339
|
+
const parser2 = evaluateExpr(init, scope, code, mapFnSources);
|
|
2340
|
+
if (parser2 === null) {
|
|
2341
|
+
warn(init.start, `"${varName}" references a parseman macro import but isn't a statically-evaluable combinator`);
|
|
2342
|
+
continue;
|
|
2343
|
+
}
|
|
2344
|
+
const compiled = compile(parser2);
|
|
2345
|
+
if (compiled.inlineExpression === null) {
|
|
2346
|
+
warn(init.start, `"${varName}" couldn't be inlined (likely closes over a runtime value)`);
|
|
2347
|
+
continue;
|
|
2348
|
+
}
|
|
2349
|
+
replacements.push({
|
|
2350
|
+
start: init.start,
|
|
2351
|
+
end: init.end,
|
|
2352
|
+
replacement: compiled.inlineExpression
|
|
2353
|
+
});
|
|
2354
|
+
scope.set(varName, { combi: parser2, mfSrcs: mapFnSources });
|
|
2355
|
+
} else if (d.id.type === "ObjectPattern") {
|
|
2356
|
+
if (!referencesAny(init, allNames, scope)) continue;
|
|
2357
|
+
if (!isRulesCall(init)) {
|
|
2358
|
+
warn(init.start, `destructured macro binding must come from rules(...)`);
|
|
2359
|
+
continue;
|
|
2360
|
+
}
|
|
2361
|
+
const compiledRules = compileRulesFactory(init, "{ \u2026 }");
|
|
2362
|
+
if (!compiledRules) continue;
|
|
2363
|
+
const byKey = new Map(compiledRules.entries);
|
|
2364
|
+
const pattern = d.id;
|
|
2365
|
+
const lines = [];
|
|
2366
|
+
let allOk = true;
|
|
2367
|
+
for (const prop of pattern.properties) {
|
|
2368
|
+
const p = prop;
|
|
2369
|
+
if (p.type === "RestElement" || p.type === "BindingRestElement") {
|
|
2370
|
+
warn(init.start, `rest element in a rules() destructure isn't supported`);
|
|
2371
|
+
allOk = false;
|
|
2372
|
+
break;
|
|
2373
|
+
}
|
|
2374
|
+
const ruleKey = p.key.type === "Identifier" ? p.key.name : p.key.type === "StringLiteral" ? String(p.key.value) : null;
|
|
2375
|
+
const localName = p.value.type === "Identifier" || p.value.type === "BindingIdentifier" ? p.value.name : ruleKey;
|
|
2376
|
+
if (!ruleKey || !localName) {
|
|
2377
|
+
allOk = false;
|
|
2378
|
+
break;
|
|
2379
|
+
}
|
|
2380
|
+
const inlineExpr = byKey.get(ruleKey);
|
|
2381
|
+
if (inlineExpr === void 0) {
|
|
2382
|
+
warn(init.start, `destructured rule "${ruleKey}" isn't returned by the rules() factory`);
|
|
2383
|
+
allOk = false;
|
|
2384
|
+
break;
|
|
2385
|
+
}
|
|
2386
|
+
lines.push(`${exportPrefix}${kind} ${localName} = ${inlineExpr}`);
|
|
2387
|
+
const rule = compiledRules.ruleMap.get(ruleKey);
|
|
2388
|
+
if (rule) scope.set(localName, { combi: rule, mfSrcs: [] });
|
|
2389
|
+
}
|
|
2390
|
+
if (!allOk) continue;
|
|
2391
|
+
replacements.push({
|
|
2392
|
+
start: stmtStart,
|
|
2393
|
+
end: stmtEnd,
|
|
2394
|
+
replacement: lines.join("\n")
|
|
2395
|
+
});
|
|
1442
2396
|
}
|
|
1443
|
-
replacements.push({
|
|
1444
|
-
start: init.start,
|
|
1445
|
-
end: init.end,
|
|
1446
|
-
replacement: compiled.inlineExpression
|
|
1447
|
-
});
|
|
1448
|
-
scope.set(varName, parser2);
|
|
1449
2397
|
}
|
|
1450
2398
|
}
|
|
1451
|
-
if (replacements.length === 0) return null;
|
|
2399
|
+
if (replacements.length === 0 && warnings.length === 0) return null;
|
|
1452
2400
|
for (const imp of macroImports) {
|
|
1453
2401
|
imp.fullyResolved = !anyUnresolved;
|
|
1454
2402
|
}
|
|
@@ -1467,7 +2415,8 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
1467
2415
|
}
|
|
1468
2416
|
return {
|
|
1469
2417
|
code: ms.toString(),
|
|
1470
|
-
map: ms.generateMap({ hires: true })
|
|
2418
|
+
map: ms.generateMap({ hires: true }),
|
|
2419
|
+
warnings
|
|
1471
2420
|
};
|
|
1472
2421
|
}
|
|
1473
2422
|
//# sourceMappingURL=index.cjs.map
|