parseman 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/combinators/expect.d.ts +2 -2
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/token.d.ts +10 -0
- package/dist/combinators/token.d.ts.map +1 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/index.cjs +189 -15
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +189 -15
- package/dist/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +191 -13
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.js +191 -13
- package/dist/plugin/index.js.map +3 -3
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ See **[The three modes](https://matthew-dean.github.io/parseman/guide/modes)** f
|
|
|
71
71
|
|
|
72
72
|
## What's in the box
|
|
73
73
|
|
|
74
|
-
- **[Combinators](https://matthew-dean.github.io/parseman/guide/combinators)** — `literal`, `regex`, `sequence`, `choice`, `many`, `sepBy`, `not`, and more.
|
|
74
|
+
- **[Combinators](https://matthew-dean.github.io/parseman/guide/combinators)** — `literal`, `regex`, `sequence`, `choice`, `many`, `sepBy`, `token`, `not`, and more.
|
|
75
75
|
- **[Whitespace & trivia](https://matthew-dean.github.io/parseman/guide/trivia)** — grammar-defined filler skipping, with per-chunk kind capture.
|
|
76
76
|
- **[Recursive rules](https://matthew-dean.github.io/parseman/guide/recursive-rules)** — `rules()` for mutually recursive grammars; fully macro-compilable.
|
|
77
77
|
- **[CST / AST nodes](https://matthew-dean.github.io/parseman/guide/ast)** — `node()` captures terminals and trivia for you, with a `collapse` option for transparent wrapper rules.
|
|
@@ -14,7 +14,7 @@ export type { ParseError };
|
|
|
14
14
|
* the interpreter and the compiled output (the compiled path does not rebuild the
|
|
15
15
|
* runtime `expected` array, so it reads this precomputed set instead).
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function deriveExpected(c: Combinator<unknown>): string[];
|
|
18
18
|
/**
|
|
19
19
|
* Required-token combinator. Tries `combinator`; on success returns it verbatim.
|
|
20
20
|
* On failure it does NOT fail — it records a {@link ParseError} (the statically
|
|
@@ -26,7 +26,7 @@ export declare function staticExpected(c: Combinator<unknown>): string[];
|
|
|
26
26
|
* block) so a missing one is reported with position + expectation rather than
|
|
27
27
|
* aborting the whole parse or being silently swallowed by a catch-all.
|
|
28
28
|
*
|
|
29
|
-
* sequence(literal('{'), declList, expect(literal('}')
|
|
29
|
+
* sequence(literal('{'), declList, expect(literal('}')))
|
|
30
30
|
*
|
|
31
31
|
* Errors are only collected when the parse runs with `{ recover: true }`; without
|
|
32
32
|
* it, expect() still recovers in place but records nothing (zero overhead beyond
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/combinators/expect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAyC,UAAU,EAAE,MAAM,aAAa,CAAA;AAEhG,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/combinators/expect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAyC,UAAU,EAAE,MAAM,aAAa,CAAA;AAEhG,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,CA4B/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,CAmB/F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"first-set.d.ts","sourceRoot":"","sources":["../../src/combinators/first-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAE7E,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAKxD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAS5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE/C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAE1D;AAED,wBAAgB,GAAG,IAAI,QAAQ,CAE9B;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAEhC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"first-set.d.ts","sourceRoot":"","sources":["../../src/combinators/first-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAE7E,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAKxD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAS5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE/C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAE1D;AAED,wBAAgB,GAAG,IAAI,QAAQ,CAE9B;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAEhC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAoCxG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,CAOlF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,QAAQ,CAqCvG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Combinator } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Treat a parser as one source token.
|
|
4
|
+
*
|
|
5
|
+
* The wrapped parser runs with trivia cleared, so its parts must be contiguous.
|
|
6
|
+
* On success the token returns the matched source text and captures one CST leaf
|
|
7
|
+
* for the full span, suppressing any internal terminal leaves.
|
|
8
|
+
*/
|
|
9
|
+
export declare function token(root: Combinator<unknown>): Combinator<string>;
|
|
10
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/combinators/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,aAAa,CAAA;AAGpF;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAqDnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAA;AAyBzH;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,uTAC0R,CAAA;AActT,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAI7C;AA6bD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,MAAM,CAQlE;AAcD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAA0B;
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAA;AAyBzH;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,uTAC0R,CAAA;AActT,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAI7C;AA6bD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,MAAM,CAQlE;AAcD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAA0B;AAmxDjF,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;IAClD,kGAAkG;IAClG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;IAChF;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG;QAAE,MAAM,EAAE,UAAU,EAAE,CAAA;KAAE,CAAA;IACvF,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC,CAAA;AAsOD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CA+BvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CA4GhG;AAgDD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4FhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;OAIG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAChC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3B,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,KAAK,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;IACrD,QAAQ,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;CACzD,CAAA;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EACjE,EAAE,EAAE,MAAM,GACT,cAAc,GAAG,IAAI,CAyKvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ir-serialize.d.ts","sourceRoot":"","sources":["../../src/compiler/ir-serialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"ir-serialize.d.ts","sourceRoot":"","sources":["../../src/compiler/ir-serialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAiBxD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;AA2C/B,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,GAC9C,MAAM,GAAG,IAAI,CAUf;AAED;;oFAEoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAgC/D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-usage.d.ts","sourceRoot":"","sources":["../../src/compiler/value-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"value-usage.d.ts","sourceRoot":"","sources":["../../src/compiler/value-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAwGhE"}
|
package/dist/index.cjs
CHANGED
|
@@ -85,7 +85,7 @@ __export(index_exports, {
|
|
|
85
85
|
sequence: () => sequence,
|
|
86
86
|
shiftAbsolute: () => shiftAbsolute,
|
|
87
87
|
skip: () => skip,
|
|
88
|
-
|
|
88
|
+
token: () => token,
|
|
89
89
|
transform: () => transform,
|
|
90
90
|
trivia: () => trivia,
|
|
91
91
|
triviaEntries: () => triviaEntries,
|
|
@@ -155,6 +155,7 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
155
155
|
case "transform":
|
|
156
156
|
case "label":
|
|
157
157
|
case "trivia":
|
|
158
|
+
case "token":
|
|
158
159
|
case "expect":
|
|
159
160
|
case "withCtx":
|
|
160
161
|
case "node":
|
|
@@ -217,6 +218,7 @@ function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
217
218
|
case "transform":
|
|
218
219
|
case "label":
|
|
219
220
|
case "trivia":
|
|
221
|
+
case "token":
|
|
220
222
|
case "node":
|
|
221
223
|
case "grammar":
|
|
222
224
|
case "expect":
|
|
@@ -1343,6 +1345,7 @@ function markUnusedValues(root) {
|
|
|
1343
1345
|
return;
|
|
1344
1346
|
case "label":
|
|
1345
1347
|
case "trivia":
|
|
1348
|
+
case "token":
|
|
1346
1349
|
case "withCtx":
|
|
1347
1350
|
case "expect":
|
|
1348
1351
|
visit(def.parser, consumed);
|
|
@@ -1643,8 +1646,60 @@ function parse(combinator, input, opts = {}) {
|
|
|
1643
1646
|
return withErrors;
|
|
1644
1647
|
}
|
|
1645
1648
|
|
|
1649
|
+
// src/combinators/token.ts
|
|
1650
|
+
function token(root) {
|
|
1651
|
+
const meta = {
|
|
1652
|
+
firstSet: root._meta.firstSet,
|
|
1653
|
+
canMatchNewline: root._meta.canMatchNewline,
|
|
1654
|
+
isTrivia: false
|
|
1655
|
+
};
|
|
1656
|
+
return {
|
|
1657
|
+
_tag: "token",
|
|
1658
|
+
_meta: meta,
|
|
1659
|
+
_def: { tag: "token", parser: root },
|
|
1660
|
+
parse(input, pos, ctx) {
|
|
1661
|
+
const savedTrivia = ctx.trivia;
|
|
1662
|
+
const savedKinds = ctx.triviaKindLabels;
|
|
1663
|
+
const savedBuf = ctx._cstBuf;
|
|
1664
|
+
const savedChildren = ctx._cstChildren;
|
|
1665
|
+
const savedLeaves = ctx._cstLeaves;
|
|
1666
|
+
const savedRaw = ctx._cstRawChildren;
|
|
1667
|
+
const savedTriviaLog = ctx._cstTriviaLog;
|
|
1668
|
+
const savedOuterTriviaLog = ctx._triviaLog;
|
|
1669
|
+
const wasCapturing = cstCaptureActive(ctx);
|
|
1670
|
+
ctx.trivia = void 0;
|
|
1671
|
+
ctx.triviaKindLabels = void 0;
|
|
1672
|
+
ctx._cstBuf = void 0;
|
|
1673
|
+
ctx._cstChildren = void 0;
|
|
1674
|
+
ctx._cstLeaves = void 0;
|
|
1675
|
+
ctx._cstRawChildren = void 0;
|
|
1676
|
+
ctx._cstTriviaLog = void 0;
|
|
1677
|
+
delete ctx._triviaLog;
|
|
1678
|
+
let result;
|
|
1679
|
+
try {
|
|
1680
|
+
result = root.parse(input, pos, ctx);
|
|
1681
|
+
} finally {
|
|
1682
|
+
ctx.trivia = savedTrivia;
|
|
1683
|
+
ctx.triviaKindLabels = savedKinds;
|
|
1684
|
+
ctx._cstBuf = savedBuf;
|
|
1685
|
+
ctx._cstChildren = savedChildren;
|
|
1686
|
+
ctx._cstLeaves = savedLeaves;
|
|
1687
|
+
ctx._cstRawChildren = savedRaw;
|
|
1688
|
+
ctx._cstTriviaLog = savedTriviaLog;
|
|
1689
|
+
if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
|
|
1690
|
+
else ctx._triviaLog = savedOuterTriviaLog;
|
|
1691
|
+
}
|
|
1692
|
+
if (!result.ok) return result;
|
|
1693
|
+
const span = result.span;
|
|
1694
|
+
const value = input.slice(pos, span.end);
|
|
1695
|
+
if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
1696
|
+
return { ok: true, value, span };
|
|
1697
|
+
}
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1646
1701
|
// src/combinators/expect.ts
|
|
1647
|
-
function
|
|
1702
|
+
function deriveExpected(c) {
|
|
1648
1703
|
const def = c._def;
|
|
1649
1704
|
switch (def.tag) {
|
|
1650
1705
|
case "literal":
|
|
@@ -1656,22 +1711,23 @@ function staticExpected(c) {
|
|
|
1656
1711
|
case "label":
|
|
1657
1712
|
return [def.label];
|
|
1658
1713
|
case "choice":
|
|
1659
|
-
return def.parsers.flatMap(
|
|
1714
|
+
return def.parsers.flatMap(deriveExpected);
|
|
1660
1715
|
case "sequence":
|
|
1661
|
-
return def.parsers.length > 0 ?
|
|
1716
|
+
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
1662
1717
|
case "node":
|
|
1663
1718
|
case "grammar":
|
|
1664
1719
|
case "trivia":
|
|
1720
|
+
case "token":
|
|
1665
1721
|
case "optional":
|
|
1666
1722
|
case "many":
|
|
1667
1723
|
case "oneOrMore":
|
|
1668
1724
|
case "transform":
|
|
1669
1725
|
case "not":
|
|
1670
|
-
return
|
|
1726
|
+
return deriveExpected(def.parser);
|
|
1671
1727
|
case "lazy": {
|
|
1672
1728
|
const name = c._ruleName;
|
|
1673
1729
|
try {
|
|
1674
|
-
return
|
|
1730
|
+
return deriveExpected(def.thunk());
|
|
1675
1731
|
} catch {
|
|
1676
1732
|
return name ? [name] : [];
|
|
1677
1733
|
}
|
|
@@ -1681,7 +1737,7 @@ function staticExpected(c) {
|
|
|
1681
1737
|
}
|
|
1682
1738
|
}
|
|
1683
1739
|
function expect(combinator, label2) {
|
|
1684
|
-
const expected = label2 !== void 0 ? [label2] :
|
|
1740
|
+
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
1685
1741
|
const meta = {
|
|
1686
1742
|
firstSet: combinator._meta.firstSet,
|
|
1687
1743
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
@@ -3333,6 +3389,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3333
3389
|
case "guard":
|
|
3334
3390
|
case "not":
|
|
3335
3391
|
case "trivia":
|
|
3392
|
+
case "token":
|
|
3336
3393
|
case "scanTo":
|
|
3337
3394
|
case "unknown":
|
|
3338
3395
|
return false;
|
|
@@ -3394,6 +3451,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3394
3451
|
case "regex":
|
|
3395
3452
|
case "keywords":
|
|
3396
3453
|
case "node":
|
|
3454
|
+
case "token":
|
|
3397
3455
|
return true;
|
|
3398
3456
|
case "not":
|
|
3399
3457
|
case "guard":
|
|
@@ -3672,9 +3730,9 @@ function emitSeq(def, ctx, pos) {
|
|
|
3672
3730
|
stmts.push(`${ind(ctx)}const ${arrV} = [${valueVars.join(", ")}]`);
|
|
3673
3731
|
return { stmts, valueVar: arrV, endVar };
|
|
3674
3732
|
}
|
|
3675
|
-
function
|
|
3733
|
+
function deriveExpectedArr(parsers) {
|
|
3676
3734
|
return JSON.stringify(parsers.flatMap((p) => {
|
|
3677
|
-
const e =
|
|
3735
|
+
const e = deriveExpected(p);
|
|
3678
3736
|
return e.length > 0 ? e : [p._tag];
|
|
3679
3737
|
}));
|
|
3680
3738
|
}
|
|
@@ -3695,7 +3753,7 @@ function failsAtStart(p) {
|
|
|
3695
3753
|
}
|
|
3696
3754
|
}
|
|
3697
3755
|
function armStaticExpected(ctx, p) {
|
|
3698
|
-
return hoistExpected(ctx,
|
|
3756
|
+
return hoistExpected(ctx, deriveExpectedArr([p]));
|
|
3699
3757
|
}
|
|
3700
3758
|
function canMatchEmptyAtStart(p) {
|
|
3701
3759
|
const d = p._def;
|
|
@@ -3733,7 +3791,7 @@ function emitDisjointArm(p, ctx, pos, valV, endV) {
|
|
|
3733
3791
|
];
|
|
3734
3792
|
}
|
|
3735
3793
|
function emitChoice(def, ctx, pos) {
|
|
3736
|
-
const allExpected =
|
|
3794
|
+
const allExpected = deriveExpectedArr(def.parsers);
|
|
3737
3795
|
if (def.disjoint) {
|
|
3738
3796
|
const codeV = v(ctx, "_code");
|
|
3739
3797
|
const valV = v(ctx, "_chv");
|
|
@@ -3794,7 +3852,7 @@ function emitGreedyClassify(def, superIndex, ctx, pos) {
|
|
|
3794
3852
|
const wordV = v(ctx, "_gw");
|
|
3795
3853
|
const endV = v(ctx, "_ge");
|
|
3796
3854
|
const valV = v(ctx, "_gcv");
|
|
3797
|
-
const regexExpected = JSON.stringify(
|
|
3855
|
+
const regexExpected = JSON.stringify(deriveExpected(superParser));
|
|
3798
3856
|
const stmts = [
|
|
3799
3857
|
`${ind(ctx)}${reVar}.lastIndex = ${pos}`,
|
|
3800
3858
|
`${ind(ctx)}const ${matchV} = ${reVar}.exec(input)`,
|
|
@@ -4186,6 +4244,116 @@ function emitNot(def, ctx, pos) {
|
|
|
4186
4244
|
endVar: pos
|
|
4187
4245
|
};
|
|
4188
4246
|
}
|
|
4247
|
+
function escapeTokenLiteral(value) {
|
|
4248
|
+
return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
|
4249
|
+
}
|
|
4250
|
+
function regexMatchesEmpty(source, flags) {
|
|
4251
|
+
try {
|
|
4252
|
+
return new RegExp(`^(?:${source})$`, flags).test("");
|
|
4253
|
+
} catch {
|
|
4254
|
+
return true;
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
function tokenTerminalSource(p) {
|
|
4258
|
+
const def = p._def;
|
|
4259
|
+
switch (def.tag) {
|
|
4260
|
+
case "literal":
|
|
4261
|
+
if (def.value.length === 0) return null;
|
|
4262
|
+
return {
|
|
4263
|
+
source: escapeTokenLiteral(def.value),
|
|
4264
|
+
caseInsensitive: def.caseInsensitive,
|
|
4265
|
+
rawCaseSensitive: def.caseInsensitive ? "" : def.value
|
|
4266
|
+
};
|
|
4267
|
+
case "regex": {
|
|
4268
|
+
if (def.flags.replace(/i/g, "") !== "") return null;
|
|
4269
|
+
if (regexMatchesEmpty(def.source, def.flags)) return null;
|
|
4270
|
+
return {
|
|
4271
|
+
source: `(?:${def.source})`,
|
|
4272
|
+
caseInsensitive: def.flags.includes("i"),
|
|
4273
|
+
rawCaseSensitive: def.flags.includes("i") ? "" : def.source
|
|
4274
|
+
};
|
|
4275
|
+
}
|
|
4276
|
+
default:
|
|
4277
|
+
return null;
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
function tokenSequenceSource(p) {
|
|
4281
|
+
const def = p._def;
|
|
4282
|
+
const parts = def.tag === "sequence" ? def.parsers.map(tokenTerminalSource) : [tokenTerminalSource(p)];
|
|
4283
|
+
if (parts.some((part) => part === null)) return null;
|
|
4284
|
+
const typed = parts;
|
|
4285
|
+
const flags = typed.some((part) => part.caseInsensitive) ? "i" : "";
|
|
4286
|
+
if (flags.includes("i") && typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))) return null;
|
|
4287
|
+
return {
|
|
4288
|
+
source: typed.map((part) => part.source).join(""),
|
|
4289
|
+
flags,
|
|
4290
|
+
hasCaseSensitiveLetters: typed.some((part) => /[A-Za-z]/.test(part.rawCaseSensitive))
|
|
4291
|
+
};
|
|
4292
|
+
}
|
|
4293
|
+
function combineTokenRegexSources(parts) {
|
|
4294
|
+
const flags = parts.some((part) => part.flags.includes("i")) ? "i" : "";
|
|
4295
|
+
if (flags.includes("i") && parts.some((part) => part.flags === "" && part.hasCaseSensitiveLetters)) return null;
|
|
4296
|
+
return { source: parts.map((part) => part.source).join(""), flags };
|
|
4297
|
+
}
|
|
4298
|
+
function tokenNullableRegex(def) {
|
|
4299
|
+
const inner = def.parser._def;
|
|
4300
|
+
if (inner.tag === "many") {
|
|
4301
|
+
const seq = tokenSequenceSource(inner.parser);
|
|
4302
|
+
if (!seq) return null;
|
|
4303
|
+
return { tag: "regex", source: `(?:${seq.source})*`, flags: seq.flags };
|
|
4304
|
+
}
|
|
4305
|
+
if (inner.tag === "optional") {
|
|
4306
|
+
const seq = tokenSequenceSource(inner.parser);
|
|
4307
|
+
if (!seq) return null;
|
|
4308
|
+
return { tag: "regex", source: `(?:${seq.source})?`, flags: seq.flags };
|
|
4309
|
+
}
|
|
4310
|
+
if (inner.tag === "sepBy") {
|
|
4311
|
+
const item = tokenSequenceSource(inner.parser);
|
|
4312
|
+
const sep = tokenSequenceSource(inner.separator);
|
|
4313
|
+
if (!item || !sep) return null;
|
|
4314
|
+
const combined = combineTokenRegexSources([item, sep]);
|
|
4315
|
+
if (!combined) return null;
|
|
4316
|
+
return { tag: "regex", source: `(?:${item.source}(?:${sep.source}${item.source})*)?`, flags: combined.flags };
|
|
4317
|
+
}
|
|
4318
|
+
return null;
|
|
4319
|
+
}
|
|
4320
|
+
function emitToken(def, ctx, pos) {
|
|
4321
|
+
const lowered = tokenNullableRegex(def);
|
|
4322
|
+
if (lowered) return emitRegex(lowered, ctx, pos);
|
|
4323
|
+
const savedTrivia = ctx.activeTrivia;
|
|
4324
|
+
const savedKindLabels = ctx.triviaKindLabels;
|
|
4325
|
+
ctx.activeTrivia = void 0;
|
|
4326
|
+
ctx.triviaKindLabels = void 0;
|
|
4327
|
+
const inner = emitFallible(def.parser, ctx, pos);
|
|
4328
|
+
ctx.activeTrivia = savedTrivia;
|
|
4329
|
+
ctx.triviaKindLabels = savedKindLabels;
|
|
4330
|
+
const i = ind(ctx);
|
|
4331
|
+
const sc = v(ctx, "_tokCh");
|
|
4332
|
+
const sl = v(ctx, "_tokLv");
|
|
4333
|
+
const sr = v(ctx, "_tokRaw");
|
|
4334
|
+
const sv = v(ctx, "_tokTr");
|
|
4335
|
+
const sk = v(ctx, "_tokKinds");
|
|
4336
|
+
const stl = v(ctx, "_tokTl");
|
|
4337
|
+
const sol = v(ctx, "_tokLog");
|
|
4338
|
+
const sb = v(ctx, "_tokBuf");
|
|
4339
|
+
const valV = v(ctx, "_tok");
|
|
4340
|
+
return {
|
|
4341
|
+
stmts: [
|
|
4342
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${sv} = _ctx.trivia, ${sk} = _ctx.triviaKindLabels, ${stl} = _ctx._cstTriviaLog, ${sol} = _ctx._triviaLog, ${sb} = _ctx._cstBuf`,
|
|
4343
|
+
`${i}_ctx.trivia = undefined; _ctx.triviaKindLabels = undefined; _ctx._cstChildren = undefined; _ctx._cstLeaves = undefined; _ctx._cstRawChildren = undefined; _ctx._cstTriviaLog = undefined; _ctx._triviaLog = undefined; _ctx._cstBuf = undefined`,
|
|
4344
|
+
`${i}try {`,
|
|
4345
|
+
...reindentStmts(inner.stmts, ctx.indent + 1).map((stmt) => stmt.replace(/^(\s*)(?:const|let)\s+/, "$1var ")),
|
|
4346
|
+
`${i}} finally {`,
|
|
4347
|
+
`${i} _ctx.trivia = ${sv}; _ctx.triviaKindLabels = ${sk}; _ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx._cstTriviaLog = ${stl}; _ctx._triviaLog = ${sol}; _ctx._cstBuf = ${sb}`,
|
|
4348
|
+
`${i}}`,
|
|
4349
|
+
...emitIfFail(ctx, `!${inner.okVar}`, propagateFailBody(ctx)),
|
|
4350
|
+
`${i}const ${valV} = input.slice(${pos}, ${inner.endVar})`,
|
|
4351
|
+
...emitLeafCapture(ctx, valV, pos, inner.endVar)
|
|
4352
|
+
],
|
|
4353
|
+
valueVar: valV,
|
|
4354
|
+
endVar: inner.endVar
|
|
4355
|
+
};
|
|
4356
|
+
}
|
|
4189
4357
|
function emitNode(def, ctx, pos) {
|
|
4190
4358
|
const structural = def.build === void 0;
|
|
4191
4359
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
@@ -4305,7 +4473,7 @@ function emitRecover(def, ctx, pos) {
|
|
|
4305
4473
|
`${ind0} if (${sentOk}) break`,
|
|
4306
4474
|
`${ind0} ${scanV}++`,
|
|
4307
4475
|
`${ind0} }`,
|
|
4308
|
-
`${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(
|
|
4476
|
+
`${ind0} const ${errV} = { _tag: 'parseError', span: { start: ${pos}, end: ${scanV} }, expected: ${JSON.stringify(deriveExpected(def.parser))} }`,
|
|
4309
4477
|
`${ind0} if (_ctx._errors) _ctx._errors.push(${errV})`,
|
|
4310
4478
|
`${ind0} ${valVar} = ${errV}`,
|
|
4311
4479
|
`${ind0} ${endVar} = ${scanV}`,
|
|
@@ -4435,6 +4603,8 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4435
4603
|
return emitLazy(p, def, ctx, pos);
|
|
4436
4604
|
case "trivia":
|
|
4437
4605
|
return emit(def.parser, ctx, pos);
|
|
4606
|
+
case "token":
|
|
4607
|
+
return emitToken(def, ctx, pos);
|
|
4438
4608
|
case "label":
|
|
4439
4609
|
return emit(def.parser, ctx, pos);
|
|
4440
4610
|
case "grammar": {
|
|
@@ -4536,6 +4706,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4536
4706
|
}
|
|
4537
4707
|
case "grammar":
|
|
4538
4708
|
case "trivia":
|
|
4709
|
+
case "token":
|
|
4539
4710
|
case "label":
|
|
4540
4711
|
case "optional":
|
|
4541
4712
|
case "many":
|
|
@@ -4571,6 +4742,7 @@ function childrenOf(def) {
|
|
|
4571
4742
|
case "optional":
|
|
4572
4743
|
case "transform":
|
|
4573
4744
|
case "trivia":
|
|
4745
|
+
case "token":
|
|
4574
4746
|
case "label":
|
|
4575
4747
|
case "grammar":
|
|
4576
4748
|
case "not":
|
|
@@ -5081,7 +5253,7 @@ function balanced(open, close, options = {}) {
|
|
|
5081
5253
|
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
5082
5254
|
const inner = many(choice(self, ...skips, content));
|
|
5083
5255
|
const combi = transform(
|
|
5084
|
-
sequence(literal(open), inner, expect(literal(close)
|
|
5256
|
+
sequence(literal(open), inner, expect(literal(close))),
|
|
5085
5257
|
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
5086
5258
|
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
5087
5259
|
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
@@ -5143,6 +5315,7 @@ function evalRuleMapIR(ir) {
|
|
|
5143
5315
|
"node",
|
|
5144
5316
|
"parser",
|
|
5145
5317
|
"scanTo",
|
|
5318
|
+
"token",
|
|
5146
5319
|
"transform",
|
|
5147
5320
|
"skip",
|
|
5148
5321
|
"trivia",
|
|
@@ -5168,6 +5341,7 @@ function evalRuleMapIR(ir) {
|
|
|
5168
5341
|
node,
|
|
5169
5342
|
parser,
|
|
5170
5343
|
scanTo,
|
|
5344
|
+
token,
|
|
5171
5345
|
transform,
|
|
5172
5346
|
skip,
|
|
5173
5347
|
trivia,
|
|
@@ -5328,7 +5502,7 @@ function recover(combinator, sentinel) {
|
|
|
5328
5502
|
canMatchNewline: true,
|
|
5329
5503
|
isTrivia: false
|
|
5330
5504
|
};
|
|
5331
|
-
const expected =
|
|
5505
|
+
const expected = deriveExpected(combinator);
|
|
5332
5506
|
return {
|
|
5333
5507
|
_tag: "recover",
|
|
5334
5508
|
_meta: meta,
|