parseman 0.50.6 → 0.51.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/dist/analysis/choice-cost.d.ts.map +1 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +214 -67
- package/dist/analysis/diagnostics.js.map +2 -2
- package/dist/analysis/duplication.d.ts.map +1 -1
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/cli/index.js +220 -68
- package/dist/cli/index.js.map +2 -2
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts +2 -26
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts +23 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +40 -29
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/index.js +241 -74
- package/dist/index.js.map +2 -2
- package/dist/plugin/index.js +228 -71
- package/dist/plugin/index.js.map +2 -2
- package/dist/spec/index.js +164 -48
- package/dist/spec/index.js.map +2 -2
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +220 -68
- package/dist/table/index.js.map +2 -2
- package/dist/table/program.d.ts +2 -0
- package/dist/table/program.d.ts.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/choice-cost.ts +6 -1
- package/src/analysis/commitment.ts +10 -2
- package/src/analysis/duplication.ts +7 -2
- package/src/analysis/gating.ts +6 -1
- package/src/analysis/rebuild.ts +1 -1
- package/src/combinators/dispatch.ts +4 -1
- package/src/combinators/first-set.ts +58 -36
- package/src/combinators/scanTo.ts +163 -9
- package/src/compiler/fields.ts +8 -2
- package/src/compiler/grammar-coverage-ids.ts +6 -1
- package/src/compiler/ir-serialize.ts +7 -2
- package/src/compiler/token-alphabet.ts +1 -1
- package/src/coverage.ts +7 -1
- package/src/cst/reflection.ts +6 -1
- package/src/table/assemble.ts +11 -1
- package/src/table/emit.ts +4 -0
- package/src/table/encode.ts +16 -8
- package/src/table/exec.ts +7 -1
- package/src/table/program.ts +2 -0
- package/src/types.ts +1 -1
- package/src/version.ts +1 -1
package/dist/spec/index.js
CHANGED
|
@@ -31,7 +31,7 @@ function intersects(a, b) {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
function fromChar(code) {
|
|
34
|
-
return
|
|
34
|
+
return fromRange(code, code);
|
|
35
35
|
}
|
|
36
36
|
function startsFirstSet(combinator, input, pos) {
|
|
37
37
|
const fs = combinator._meta.firstSet;
|
|
@@ -124,11 +124,10 @@ function matchesEmptyBody(p, seen, resolve) {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
function isZeroWidthAssertion(p) {
|
|
127
|
-
|
|
128
|
-
return tag === "not" || tag === "adjacency";
|
|
127
|
+
return p._tag === "not" || p._tag === "adjacency";
|
|
129
128
|
}
|
|
130
129
|
function isPositiveLookahead(p) {
|
|
131
|
-
return p.
|
|
130
|
+
return p._tag === "peek";
|
|
132
131
|
}
|
|
133
132
|
function narrowBy(acc, constraint) {
|
|
134
133
|
if (constraint.kind === "any") return acc;
|
|
@@ -144,34 +143,42 @@ function narrowBy(acc, constraint) {
|
|
|
144
143
|
return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges };
|
|
145
144
|
}
|
|
146
145
|
function applyAssertion(fs, assertion) {
|
|
147
|
-
|
|
148
|
-
if (fs.kind === "empty") return assertion;
|
|
149
|
-
return narrowBy(fs, assertion) ?? fs;
|
|
146
|
+
return assertion === null ? fs : fs.kind === "empty" ? assertion : narrowBy(fs, assertion);
|
|
150
147
|
}
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
148
|
+
function sequenceSet(parsers, fs, empties, trivia2) {
|
|
149
|
+
const afterBoundary = (i) => {
|
|
150
|
+
const rest = at(i);
|
|
151
|
+
return trivia2 ? union(rest, fs(trivia2)) : rest;
|
|
152
|
+
};
|
|
153
|
+
const at = (i) => {
|
|
154
|
+
const p = parsers[i];
|
|
155
155
|
if (isPositiveLookahead(p)) {
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
const constraint = fs(p);
|
|
157
|
+
return i + 1 === parsers.length ? constraint : applyAssertion(afterBoundary(i + 1), constraint);
|
|
158
158
|
}
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
if (isZeroWidthAssertion(p)) {
|
|
160
|
+
return i + 1 === parsers.length ? empty() : afterBoundary(i + 1);
|
|
161
|
+
}
|
|
162
|
+
const first = fs(p);
|
|
163
|
+
if (!empties(p) || i + 1 === parsers.length) return first;
|
|
164
|
+
return union(first, afterBoundary(i + 1));
|
|
165
|
+
};
|
|
166
|
+
return at(0);
|
|
163
167
|
}
|
|
164
|
-
function
|
|
168
|
+
function sequenceFirstSet(parsers) {
|
|
169
|
+
return sequenceSet(parsers, (p) => p._meta.firstSet, matchesEmpty);
|
|
170
|
+
}
|
|
171
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve, activeTrivia) {
|
|
165
172
|
if (seen.has(p)) return any();
|
|
166
173
|
seen.add(p);
|
|
167
174
|
try {
|
|
168
|
-
return firstSetBody(p, seen, resolve);
|
|
175
|
+
return firstSetBody(p, seen, resolve, activeTrivia);
|
|
169
176
|
} finally {
|
|
170
177
|
seen.delete(p);
|
|
171
178
|
}
|
|
172
179
|
}
|
|
173
|
-
function firstSetBody(p, seen, resolve) {
|
|
174
|
-
const fs = (c) => firstSetOf(c, seen, resolve);
|
|
180
|
+
function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
181
|
+
const fs = (c) => firstSetOf(c, seen, resolve, activeTrivia);
|
|
175
182
|
const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
|
|
176
183
|
const d = p._def;
|
|
177
184
|
switch (d.tag) {
|
|
@@ -197,17 +204,7 @@ function firstSetBody(p, seen, resolve) {
|
|
|
197
204
|
return out;
|
|
198
205
|
}
|
|
199
206
|
case "sequence": {
|
|
200
|
-
|
|
201
|
-
let assertion = null;
|
|
202
|
-
for (const term of d.parsers) {
|
|
203
|
-
if (isPositiveLookahead(term)) {
|
|
204
|
-
assertion = narrowBy(assertion, fs(term));
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
if (!isZeroWidthAssertion(term)) out = union(out, fs(term));
|
|
208
|
-
if (!empties(term)) return applyAssertion(out, assertion);
|
|
209
|
-
}
|
|
210
|
-
return applyAssertion(out, assertion);
|
|
207
|
+
return sequenceSet(d.parsers, fs, empties, activeTrivia);
|
|
211
208
|
}
|
|
212
209
|
case "peek": {
|
|
213
210
|
const inner = d.parser;
|
|
@@ -222,12 +219,16 @@ function firstSetBody(p, seen, resolve) {
|
|
|
222
219
|
case "token":
|
|
223
220
|
case "leaf":
|
|
224
221
|
case "node":
|
|
225
|
-
case "grammar":
|
|
226
|
-
case "expect":
|
|
227
|
-
return fs(d.parser);
|
|
228
222
|
case "sepBy":
|
|
223
|
+
case "expect":
|
|
229
224
|
return fs(d.parser);
|
|
230
|
-
|
|
225
|
+
case "grammar":
|
|
226
|
+
return firstSetOf(
|
|
227
|
+
d.parser,
|
|
228
|
+
seen,
|
|
229
|
+
resolve,
|
|
230
|
+
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
231
|
+
);
|
|
231
232
|
default:
|
|
232
233
|
return p._meta.firstSet;
|
|
233
234
|
}
|
|
@@ -1705,7 +1706,12 @@ function childrenOf(def) {
|
|
|
1705
1706
|
case "sepBy":
|
|
1706
1707
|
return [def.parser, def.separator];
|
|
1707
1708
|
case "scanTo":
|
|
1708
|
-
return [
|
|
1709
|
+
return [
|
|
1710
|
+
def.sentinel,
|
|
1711
|
+
...def.skip,
|
|
1712
|
+
...def.recoverAt === void 0 ? [] : [def.recoverAt],
|
|
1713
|
+
...def.stopAt === void 0 ? [] : [def.stopAt]
|
|
1714
|
+
];
|
|
1709
1715
|
case "routed":
|
|
1710
1716
|
return def.fallback ? [def.fallback] : [];
|
|
1711
1717
|
case "literal":
|
|
@@ -3750,7 +3756,7 @@ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
|
|
|
3750
3756
|
case "grammar":
|
|
3751
3757
|
return parserUsesRouted(def.parser, seen) || (def.triviaParser ? parserUsesRouted(def.triviaParser, seen) : false);
|
|
3752
3758
|
case "scanTo":
|
|
3753
|
-
return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen));
|
|
3759
|
+
return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen)) || def.recoverAt !== void 0 && parserUsesRouted(def.recoverAt, seen) || def.stopAt !== void 0 && parserUsesRouted(def.stopAt, seen);
|
|
3754
3760
|
case "recover":
|
|
3755
3761
|
return parserUsesRouted(def.parser, seen) || parserUsesRouted(def.sentinel, seen);
|
|
3756
3762
|
case "lazy":
|
|
@@ -4657,7 +4663,7 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4657
4663
|
case "grammar":
|
|
4658
4664
|
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
4659
4665
|
case "scanTo":
|
|
4660
|
-
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
4666
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen)) || d.recoverAt !== void 0 && parserHasOwnFields(d.recoverAt, seen) || d.stopAt !== void 0 && parserHasOwnFields(d.stopAt, seen);
|
|
4661
4667
|
case "recover":
|
|
4662
4668
|
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
4663
4669
|
case "routed":
|
|
@@ -5034,7 +5040,7 @@ function resolveScanSkip(explicitSkip, raw, ctx) {
|
|
|
5034
5040
|
out.push(...explicitSkip);
|
|
5035
5041
|
return out;
|
|
5036
5042
|
}
|
|
5037
|
-
function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
|
|
5043
|
+
function scanTo(sentinel, { skip, raw = false, orEOF = false, recoverAt, stopAt } = {}) {
|
|
5038
5044
|
const meta = {
|
|
5039
5045
|
firstSet: any(),
|
|
5040
5046
|
canMatchNewline: true,
|
|
@@ -5044,7 +5050,15 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
|
|
|
5044
5050
|
return {
|
|
5045
5051
|
_tag: "scanTo",
|
|
5046
5052
|
_meta: meta,
|
|
5047
|
-
_def: {
|
|
5053
|
+
_def: {
|
|
5054
|
+
tag: "scanTo",
|
|
5055
|
+
sentinel,
|
|
5056
|
+
skip: explicitSkip,
|
|
5057
|
+
raw,
|
|
5058
|
+
orEOF,
|
|
5059
|
+
...recoverAt === void 0 ? {} : { recoverAt },
|
|
5060
|
+
...stopAt === void 0 ? {} : { stopAt }
|
|
5061
|
+
},
|
|
5048
5062
|
parse(input, pos, ctx) {
|
|
5049
5063
|
let cur = pos;
|
|
5050
5064
|
const skip2 = resolveScanSkip(explicitSkip, raw, ctx);
|
|
@@ -5056,28 +5070,130 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false } = {}) {
|
|
|
5056
5070
|
pushCstLeaf(ctx, leaf2);
|
|
5057
5071
|
}
|
|
5058
5072
|
};
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5073
|
+
if (recoverAt === void 0 && stopAt === void 0) {
|
|
5074
|
+
while (cur < input.length) {
|
|
5075
|
+
const s = sentinel.parse(input, cur, probeCtx);
|
|
5076
|
+
if (s.ok) {
|
|
5077
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
|
|
5078
|
+
emit(cur);
|
|
5079
|
+
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5080
|
+
}
|
|
5081
|
+
let advanced = false;
|
|
5082
|
+
for (const skipper of skip2) {
|
|
5083
|
+
const r = skipper.parse(input, cur, probeCtx);
|
|
5084
|
+
if (r.ok && r.span.end > cur) {
|
|
5085
|
+
cur = r.span.end;
|
|
5086
|
+
advanced = true;
|
|
5087
|
+
break;
|
|
5088
|
+
}
|
|
5089
|
+
}
|
|
5090
|
+
if (!advanced) cur++;
|
|
5091
|
+
}
|
|
5092
|
+
if (orEOF) {
|
|
5062
5093
|
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
|
|
5063
5094
|
emit(cur);
|
|
5064
5095
|
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5065
5096
|
}
|
|
5097
|
+
const sentDef2 = sentinel._def;
|
|
5098
|
+
const expected2 = sentDef2.tag === "literal" ? [JSON.stringify(sentDef2.value)] : ["sentinel"];
|
|
5099
|
+
return { ok: false, expected: expected2, span: { start: pos, end: cur } };
|
|
5100
|
+
}
|
|
5101
|
+
let recovery = -1;
|
|
5102
|
+
let firstSentinel = -1;
|
|
5103
|
+
let sentinelCount = 0;
|
|
5104
|
+
let recoveryErrorCount = -1;
|
|
5105
|
+
let sentinelErrorCount = -1;
|
|
5106
|
+
const succeed = (end) => {
|
|
5107
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
5108
|
+
emit(end);
|
|
5109
|
+
return { ok: true, value: input.slice(pos, end), span: { start: pos, end } };
|
|
5110
|
+
};
|
|
5111
|
+
const recoveredEnd = () => {
|
|
5112
|
+
const acceptSentinel = firstSentinel >= 0 && (sentinelCount & 1) === 1;
|
|
5113
|
+
const errors = ctx._errors;
|
|
5114
|
+
if (errors !== void 0) {
|
|
5115
|
+
const keep = acceptSentinel ? sentinelErrorCount : recoveryErrorCount;
|
|
5116
|
+
if (keep >= 0 && errors.length > keep) errors.length = keep;
|
|
5117
|
+
}
|
|
5118
|
+
return acceptSentinel ? firstSentinel : recovery;
|
|
5119
|
+
};
|
|
5120
|
+
while (cur < input.length) {
|
|
5121
|
+
const sentinelProbeErrorCount = ctx._errors?.length ?? -1;
|
|
5122
|
+
const s = sentinel.parse(input, cur, probeCtx);
|
|
5123
|
+
const sentinelProbeErrors = ctx._errors;
|
|
5124
|
+
if (sentinelProbeErrors !== void 0 && sentinelProbeErrorCount >= 0 && sentinelProbeErrors.length > sentinelProbeErrorCount) {
|
|
5125
|
+
sentinelProbeErrors.length = sentinelProbeErrorCount;
|
|
5126
|
+
}
|
|
5127
|
+
if (s.ok) {
|
|
5128
|
+
if (recovery < 0) return succeed(cur);
|
|
5129
|
+
if (s.span.end <= cur) {
|
|
5130
|
+
throw new TypeError("scanTo recovery requires a sentinel that consumes input");
|
|
5131
|
+
}
|
|
5132
|
+
if (firstSentinel < 0) {
|
|
5133
|
+
firstSentinel = cur;
|
|
5134
|
+
sentinelErrorCount = sentinelProbeErrorCount;
|
|
5135
|
+
}
|
|
5136
|
+
sentinelCount++;
|
|
5137
|
+
cur = s.span.end;
|
|
5138
|
+
continue;
|
|
5139
|
+
}
|
|
5140
|
+
if (stopAt !== void 0) {
|
|
5141
|
+
const errorCount = ctx._errors?.length ?? -1;
|
|
5142
|
+
const stop = stopAt.parse(input, cur, probeCtx);
|
|
5143
|
+
const errors = ctx._errors;
|
|
5144
|
+
if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
|
|
5145
|
+
errors.length = errorCount;
|
|
5146
|
+
}
|
|
5147
|
+
if (stop.ok) {
|
|
5148
|
+
if (recovery < 0) {
|
|
5149
|
+
recovery = cur;
|
|
5150
|
+
recoveryErrorCount = errorCount;
|
|
5151
|
+
}
|
|
5152
|
+
return succeed(recoveredEnd());
|
|
5153
|
+
}
|
|
5154
|
+
}
|
|
5066
5155
|
let advanced = false;
|
|
5067
5156
|
for (const skipper of skip2) {
|
|
5157
|
+
const errorCount = ctx._errors?.length ?? -1;
|
|
5068
5158
|
const r = skipper.parse(input, cur, probeCtx);
|
|
5069
5159
|
if (r.ok && r.span.end > cur) {
|
|
5070
5160
|
cur = r.span.end;
|
|
5071
5161
|
advanced = true;
|
|
5072
5162
|
break;
|
|
5073
5163
|
}
|
|
5164
|
+
const errors = ctx._errors;
|
|
5165
|
+
if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
|
|
5166
|
+
errors.length = errorCount;
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
if (advanced) continue;
|
|
5170
|
+
if (recoverAt !== void 0) {
|
|
5171
|
+
const errorCount = ctx._errors?.length ?? -1;
|
|
5172
|
+
const recover = recoverAt.parse(input, cur, probeCtx);
|
|
5173
|
+
const errors = ctx._errors;
|
|
5174
|
+
if (errors !== void 0 && errorCount >= 0 && errors.length > errorCount) {
|
|
5175
|
+
errors.length = errorCount;
|
|
5176
|
+
}
|
|
5177
|
+
if (recover.ok) {
|
|
5178
|
+
if (recover.span.end <= cur) {
|
|
5179
|
+
throw new TypeError("scanTo recoverAt must consume input");
|
|
5180
|
+
}
|
|
5181
|
+
if (recovery < 0) {
|
|
5182
|
+
recovery = cur;
|
|
5183
|
+
recoveryErrorCount = errorCount;
|
|
5184
|
+
}
|
|
5185
|
+
if (firstSentinel >= 0 && (sentinelCount & 1) === 1) {
|
|
5186
|
+
return succeed(recoveredEnd());
|
|
5187
|
+
}
|
|
5188
|
+
cur = recover.span.end;
|
|
5189
|
+
continue;
|
|
5190
|
+
}
|
|
5074
5191
|
}
|
|
5075
|
-
|
|
5192
|
+
cur++;
|
|
5076
5193
|
}
|
|
5194
|
+
if (recovery >= 0) return succeed(recoveredEnd());
|
|
5077
5195
|
if (orEOF) {
|
|
5078
|
-
|
|
5079
|
-
emit(cur);
|
|
5080
|
-
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5196
|
+
return succeed(cur);
|
|
5081
5197
|
}
|
|
5082
5198
|
const sentDef = sentinel._def;
|
|
5083
5199
|
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|