effect-grammar 0.0.1 → 0.1.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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -62
  3. package/dist/combinators.d.ts +64 -27
  4. package/dist/combinators.d.ts.map +1 -1
  5. package/dist/combinators.js +73 -91
  6. package/dist/combinators.js.map +1 -1
  7. package/dist/core.d.ts +85 -0
  8. package/dist/core.d.ts.map +1 -0
  9. package/dist/core.js +34 -0
  10. package/dist/core.js.map +1 -0
  11. package/dist/errors.d.ts +19 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +27 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/grammar.d.ts +7 -190
  16. package/dist/grammar.d.ts.map +1 -1
  17. package/dist/grammar.js +7 -494
  18. package/dist/grammar.js.map +1 -1
  19. package/dist/index.d.ts +7 -6
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +6 -6
  22. package/dist/index.js.map +1 -1
  23. package/dist/parse.d.ts +5 -0
  24. package/dist/parse.d.ts.map +1 -0
  25. package/dist/parse.js +157 -0
  26. package/dist/parse.js.map +1 -0
  27. package/dist/print.d.ts +5 -0
  28. package/dist/print.d.ts.map +1 -0
  29. package/dist/print.js +121 -0
  30. package/dist/print.js.map +1 -0
  31. package/dist/render.d.ts +5 -0
  32. package/dist/render.d.ts.map +1 -0
  33. package/dist/render.js +64 -0
  34. package/dist/render.js.map +1 -0
  35. package/dist/schema.d.ts +6 -0
  36. package/dist/schema.d.ts.map +1 -0
  37. package/dist/schema.js +9 -0
  38. package/dist/schema.js.map +1 -0
  39. package/package.json +22 -21
  40. package/dist/error.d.ts +0 -28
  41. package/dist/error.d.ts.map +0 -1
  42. package/dist/error.js +0 -52
  43. package/dist/error.js.map +0 -1
  44. package/dist/parser.d.ts +0 -6
  45. package/dist/parser.d.ts.map +0 -1
  46. package/dist/parser.js +0 -6
  47. package/dist/parser.js.map +0 -1
  48. package/dist/run.d.ts +0 -6
  49. package/dist/run.d.ts.map +0 -1
  50. package/dist/run.js +0 -11
  51. package/dist/run.js.map +0 -1
  52. package/dist/state.d.ts +0 -51
  53. package/dist/state.d.ts.map +0 -1
  54. package/dist/state.js +0 -114
  55. package/dist/state.js.map +0 -1
  56. package/dist/stream.d.ts +0 -18
  57. package/dist/stream.d.ts.map +0 -1
  58. package/dist/stream.js +0 -38
  59. package/dist/stream.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sai Ashirwad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,42 +1,92 @@
1
1
  # effect-grammar
2
2
 
3
- Effect Schema, but for text formats. One definition yields a parser, a printer,
4
- a rendered grammar, and a `Schema<A, string>`.
3
+ Invertible grammar combinators and parser-printers for Effect.
4
+
5
+ Schema models your structured data. `effect-grammar` models the text formats inside your strings: connection strings, duration strings (`1h30m`), cron expressions, search queries, or DSLs.
6
+
7
+ You write the grammar definition once. You get four outputs:
8
+
9
+ - **A Parser**: Reads text and outputs structured data with line and column error messages.
10
+ - **A Printer**: Converts structured data back to canonical text.
11
+ - **A `Schema.Codec<A, string>`**: Integrates directly with Effect Schema (`decode` parses, `encode` prints, and Schema refinements compose).
12
+ - **A Text Renderer**: Formats the grammar as readable text for documentation and schema descriptions.
13
+
14
+ ## Why effect-grammar?
15
+
16
+ - **`Schema.transformOrFail`**: Requires you to write and maintain both `decode` and `encode` functions manually.
17
+ - **`Schema.TemplateLiteralParser`**: Supports only flat `${a}-${b}` string patterns.
18
+ - **`effect-grammar`**: Automatically derives the parser and printer for formats with optional parts, repetition, alternation, and recursion.
19
+
20
+ This is for format strings, not documents. The parser backtracks with no memoization and no left recursion. Printing is canonical, not pretty.
5
21
 
6
22
  ## Install
7
23
 
8
24
  ```bash
9
- pnpm add effect-grammar effect
25
+ pnpm add effect-grammar
10
26
  ```
11
27
 
12
- Depends on Effect v4.
13
-
14
- ## Grammar
28
+ Depends on Effect v4. The package pins `effect` to `4.0.0-beta.102` for now.
15
29
 
16
- Define an HTTPS endpoint once, then parse it, print it, or derive a validated
17
- Schema.
30
+ ## A grammar
18
31
 
19
32
  ```ts
20
33
  import { Schema } from "effect"
21
- import { Grammar } from "effect-grammar"
22
-
23
- const endpoint = Grammar.map(
24
- Grammar.struct({
25
- scheme: Grammar.literal("https://"),
26
- host: Grammar.label("host", Grammar.regex(/[^:/?#]+/, "host")),
27
- portPart: Grammar.optional(
28
- Grammar.struct({ sep: Grammar.literal(":"), port: Grammar.integer }),
29
- ),
30
- }),
31
- {
32
- to: ({ host, portPart }) => ({ host, port: portPart?.port ?? 443 }),
33
- from: ({ host, port }) => ({
34
- scheme: "https://" as const,
35
- host,
36
- portPart: { sep: ":" as const, port },
37
- }),
38
- },
34
+ import * as Grammar from "effect-grammar"
35
+
36
+ const endpoint = Grammar.gen(function* () {
37
+ yield* Grammar.literal("https://")
38
+ const host = yield* Grammar.field("host", Grammar.regex(/[^:/?#]+/, "host"))
39
+ const port = yield* Grammar.field(
40
+ "port",
41
+ Grammar.optional(Grammar.prefix(":", Grammar.integer)),
42
+ )
43
+ return { host, port: port ?? 443 }
44
+ })
45
+
46
+ Grammar.parse(endpoint, "https://effect.website:8080")
47
+ // Result.succeed({ host: "effect.website", port: 8080 })
48
+ Grammar.parse(endpoint, "https://effect.website:abc")
49
+ // Result.fail(ParseError: line 1, column 24: expected integer, found "a")
50
+ Grammar.print(endpoint, { host: "effect.website", port: 443 })
51
+ // Result.succeed("https://effect.website:443")
52
+ Grammar.render(endpoint)
53
+ // "https://" host:<host> port:(":" <integer>)?
54
+ ```
55
+
56
+ A silent grammar (`literal`, `symbol`, `whitespace`, anything under `skip`)
57
+ carries no value and can be `yield*`-ed bare. A value grammar goes through
58
+ `field(name, g)`.
59
+
60
+ `print` replays the generator. It reads each field from `value[name]` and
61
+ passes that back as the `yield*` result. An `if` on a parsed value takes the
62
+ same path both ways. The generator's return must hold every field under its
63
+ name, and the types enforce it. Return nothing and you get the object of fields.
64
+
65
+ `render` cannot read a generator. It runs the generator once with no values and
66
+ shows the parts it yields. The rendering is exact when the generator is
67
+ straight-line, as above. If the generator branches on a parsed value, render
68
+ still runs with no values. `if (kind === "a") yield* ...` shows only the path
69
+ `undefined` takes, with no warning. Put the branch in `choice` instead, which
70
+ renders every option.
71
+
72
+ `seq` is the same field object without generator control flow. It renders every
73
+ part:
74
+
75
+ ```ts
76
+ const member = Grammar.seq(
77
+ Grammar.field("key", jsonString),
78
+ Grammar.symbol(":"),
79
+ Grammar.field("value", jsonValue),
39
80
  )
81
+ // Grammar<{ key: string; value: Json }>
82
+ ```
83
+
84
+ ## The Schema
85
+
86
+ `toSchema` takes the grammar and the Schema it should decode to. Parsing happens
87
+ first, then the target's refinements. Encoding prints.
88
+
89
+ ```ts
40
90
  const Endpoint = Grammar.toSchema(
41
91
  endpoint,
42
92
  Schema.Struct({
@@ -45,52 +95,64 @@ const Endpoint = Grammar.toSchema(
45
95
  }),
46
96
  { identifier: "Endpoint" },
47
97
  )
48
- Schema.decodeUnknownSync(Endpoint)("https://effect.website:443") // { host: "effect.website", port: 443 }
49
- Schema.encodeSync(Endpoint)({ host: "effect.website", port: 443 }) // "https://effect.website:443"
98
+
99
+ Schema.decodeUnknownSync(Endpoint)("https://effect.website:443")
100
+ // { host: "effect.website", port: 443 }
101
+ Schema.encodeSync(Endpoint)({ host: "effect.website", port: 443 })
102
+ // "https://effect.website:443"
50
103
  ```
51
104
 
52
- ## Parse-only with `Effect.gen`
105
+ ## Values and alternatives
53
106
 
54
- Write plain Effect programs over the input. Custom errors are yielded failures.
107
+ `transform` maps a value both ways. `decodeTo` takes a Schema that types
108
+ `decode` and `encode` and checks the value on parse and on print. A `choice`
109
+ of Schema-typed branches picks the matching Schema when printing.
55
110
 
56
111
  ```ts
57
- import { Effect, Schema } from "effect"
58
- import { char, digit, endOfInput, many, parse } from "effect-grammar/parser"
59
-
60
- class OutOfRange extends Schema.TaggedErrorClass<OutOfRange>()("OutOfRange", {
61
- n: Schema.Finite,
62
- }) {}
63
-
64
- const byte = Effect.gen(function* () {
65
- const digits = yield* many(digit, { atLeast: 1 })
66
- const n = Number(digits.join(""))
67
- if (n > 255) return yield* new OutOfRange({ n })
68
- return n
69
- })
112
+ const Num = Schema.Struct({ kind: Schema.Literal("num"), value: Schema.Finite })
113
+ const num = Grammar.integer.pipe(
114
+ Grammar.decodeTo(Num)({
115
+ decode: (value) => ({ kind: "num", value }),
116
+ encode: (n) => n.value,
117
+ }),
118
+ )
119
+ ```
70
120
 
71
- const ip = Effect.gen(function* () {
72
- const a = yield* byte
73
- yield* char(".")
74
- const b = yield* byte
75
- yield* char(".")
76
- const c = yield* byte
77
- yield* char(".")
78
- const d = yield* byte
79
- yield* endOfInput
80
- return [a, b, c, d] as const
81
- })
121
+ `as` turns a silent grammar into a constant. `flag` turns presence into a
122
+ boolean:
82
123
 
83
- Effect.runSync(parse("192.168.1.1", ip))
84
- // { _tag: "Success", value: [192, 168, 1, 1] }
124
+ ```ts
125
+ const jsonNull = Grammar.symbol("null").pipe(Grammar.as(null))
126
+ const negate = Grammar.flag("-")
85
127
  ```
86
128
 
87
- ## Releasing
129
+ Recursion uses `suspend`:
88
130
 
89
- Add a changeset for a user-facing change:
131
+ ```ts
132
+ const jsonValue: Grammar.Grammar<Json> = Grammar.suspend(
133
+ () =>
134
+ Grammar.choice(
135
+ jsonNull,
136
+ jsonBool,
137
+ jsonNumber,
138
+ jsonString,
139
+ jsonArray,
140
+ jsonObject,
141
+ ),
142
+ "value",
143
+ )
144
+ ```
90
145
 
91
- ```bash
92
- pnpm changeset
146
+ See `examples/` for JSON, Scheme, a Postgres DSN, netstrings, and GitHub's
147
+ search syntax.
148
+
149
+ ## Errors
150
+
151
+ `choice` backtracks. Errors report the furthest position the parser reached and
152
+ everything that could have matched there:
153
+
154
+ ```
155
+ line 1, column 7: expected one of "null", "true", "false", number, string, "[", "{", found end of input
93
156
  ```
94
157
 
95
- After the change lands on `main`, the release workflow opens a version pull
96
- request. Merging that pull request publishes the package to npm.
158
+ `label(name)` names a grammar for these messages.
@@ -1,28 +1,65 @@
1
- import { Effect } from "effect";
2
- import { ParseError } from "./error.ts";
3
- export declare const satisfy: (pred: (c: string) => boolean, expected: string) => Effect.Effect<string, ParseError | import("./error.ts").UpstreamError, import("./state.ts").ParseState>;
4
- export declare const char: (c: string) => Effect.Effect<string, ParseError | import("./error.ts").UpstreamError, import("./state.ts").ParseState>;
5
- export declare const digit: Effect.Effect<string, ParseError | import("./error.ts").UpstreamError, import("./state.ts").ParseState>;
6
- export declare const regex: (re: RegExp, expected: string) => Effect.Effect<string, ParseError | import("./error.ts").UpstreamError, import("./state.ts").ParseState>;
7
- export declare const endOfInput: Effect.Effect<undefined, ParseError | import("./error.ts").UpstreamError, import("./state.ts").ParseState>;
8
- /**
9
- * Ordered choice. Commits to `p` once it has consumed input — if `p` fails
10
- * after consuming, `q` is not tried. Wrap `p` in {@link attempt} to opt back
11
- * into backtracking.
12
- */
13
- export declare const or_: <A, E, R, B, E2, R2>(p: Effect.Effect<A, E, R>, q: Effect.Effect<B, E2, R2>) => Effect.Effect<A | B, E | E2, R | R2 | import("./state.ts").ParseState>;
14
- /**
15
- * Rewind on failure: run `p`, and if it fails, restore the input position so
16
- * an enclosing {@link or_} will try its next option. Errors keep their
17
- * original position for messages.
18
- */
19
- export declare const attempt: <A, E, R>(p: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R | import("./state.ts").ParseState>;
20
- /**
21
- * Run `p` zero or more times (`atLeast` sets a minimum). If `p` fails after
22
- * consuming input, `many` fails too — wrap `p` in {@link attempt} to keep
23
- * collecting instead.
24
- */
25
- export declare const many: <A, E, R>(p: Effect.Effect<A, E, R>, opts?: {
26
- atLeast?: number;
27
- }) => Effect.Effect<A[], E, R | import("./state.ts").ParseState>;
1
+ import { Schema } from "effect";
2
+ import { type Field, type Fields, type Grammar, type Silent, type Type } from "./core.ts";
3
+ export { field } from "./core.ts";
4
+ export declare const literal: (value: string) => Silent;
5
+ export declare const empty: Silent;
6
+ /** The regex is made sticky so the parser can match at a position without slicing. */
7
+ export declare const regex: (re: RegExp, name: string) => Grammar<string>;
8
+ export declare function seq(...parts: ReadonlyArray<Silent>): Silent;
9
+ export declare function seq<const Parts extends ReadonlyArray<Silent | Field<string, any>>>(...parts: Parts): Grammar<Fields<Parts[number]>>;
10
+ export declare const gen: <Y extends Silent | Field<string, any>, R extends Fields<Y> | void = void>(run: () => Generator<Y, R, any>) => Grammar<[R] extends [void] ? Fields<Y> : R>;
11
+ export declare function wrap(open: Silent | string, inner: Silent, close: Silent | string): Silent;
12
+ export declare function wrap<A>(open: Silent | string, inner: Grammar<A>, close: Silent | string): Grammar<A>;
13
+ export declare function prefix(open: Silent | string, inner: Silent): Silent;
14
+ export declare function prefix<A>(open: Silent | string, inner: Grammar<A>): Grammar<A>;
15
+ export declare function suffix(inner: Silent, close: Silent | string): Silent;
16
+ export declare function suffix<A>(inner: Grammar<A>, close: Silent | string): Grammar<A>;
17
+ export declare const choice: <const Gs extends readonly [Grammar<any>, ...Array<Grammar<any>>]>(...options: Gs) => Grammar<Type<Gs[number]>>;
18
+ export declare function optional(inner: Silent): Silent;
19
+ export declare function optional<A>(inner: Grammar<A>): Grammar<A | undefined>;
20
+ export interface RepeatOptions {
21
+ readonly min?: number;
22
+ readonly max?: number;
23
+ }
24
+ export declare const many: {
25
+ <A>(inner: Grammar<A>, opts?: RepeatOptions): Grammar<ReadonlyArray<A>>;
26
+ (opts?: RepeatOptions): <A>(inner: Grammar<A>) => Grammar<ReadonlyArray<A>>;
27
+ };
28
+ export declare const sepBy: {
29
+ <A>(inner: Grammar<A>, sep: Silent | string, opts?: RepeatOptions): Grammar<ReadonlyArray<A>>;
30
+ (sep: Silent | string, opts?: RepeatOptions): <A>(inner: Grammar<A>) => Grammar<ReadonlyArray<A>>;
31
+ };
32
+ export interface TransformOptions<A, B> {
33
+ readonly decode: (a: A) => B;
34
+ readonly encode: (b: B) => A;
35
+ readonly is?: (value: B) => boolean;
36
+ readonly name?: string;
37
+ }
38
+ export declare const transform: {
39
+ <A, B>(f: TransformOptions<A, B>): (inner: Grammar<A>) => Grammar<B>;
40
+ <A, B>(inner: Grammar<A>, f: TransformOptions<A, B>): Grammar<B>;
41
+ };
42
+ export interface DecodeToOptions<A, T> extends Omit<TransformOptions<A, T>, "is"> {
43
+ readonly is?: ((value: T) => boolean) | undefined;
44
+ }
45
+ export declare const decodeTo: <T>(schema: Schema.Codec<T, unknown, unknown, unknown>) => <A>(f: DecodeToOptions<A, T>) => (inner: Grammar<A>) => Grammar<T>;
46
+ export declare const as: {
47
+ <const V>(value: V): (inner: Silent) => Grammar<V>;
48
+ <const V>(inner: Silent, value: V): Grammar<V>;
49
+ };
50
+ export declare const flag: (s: Silent | string) => Grammar<boolean>;
51
+ export declare const skip: {
52
+ <A>(printAs: A): (inner: Grammar<A>) => Silent;
53
+ <A>(inner: Grammar<A>, printAs: A): Silent;
54
+ };
55
+ export declare const label: {
56
+ (name: string): <A>(inner: Grammar<A>) => Grammar<A>;
57
+ <A>(inner: Grammar<A>, name: string): Grammar<A>;
58
+ };
59
+ export declare const suspend: <A>(thunk: () => Grammar<A>, name?: string) => Grammar<A>;
60
+ export declare const whitespace: Silent;
61
+ export declare function lexeme(inner: Silent): Silent;
62
+ export declare function lexeme<A>(inner: Grammar<A>): Grammar<A>;
63
+ export declare const symbol: (s: string) => Silent;
64
+ export declare const integer: Grammar<number>;
28
65
  //# sourceMappingURL=combinators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"combinators.d.ts","sourceRoot":"","sources":["../src/combinators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAA;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGvC,eAAO,MAAM,OAAO,SAAU,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,YAAY,MAAM,4GAMlE,CAAA;AAEJ,eAAO,MAAM,IAAI,MAAO,MAAM,4GAA+C,CAAA;AAE7E,eAAO,MAAM,KAAK,yGAAgD,CAAA;AAElE,eAAO,MAAM,KAAK,OAAQ,MAAM,YAAY,MAAM,4GAUjD,CAAA;AAED,eAAO,MAAM,UAAU,4GAGrB,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,2EAc1F,CAAA;AAEJ;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,6DAOtD,CAAA;AAEJ;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,+DAmBhF,CAAA"}
1
+ {"version":3,"file":"combinators.d.ts","sourceRoot":"","sources":["../src/combinators.ts"],"names":[],"mappings":"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"}
@@ -1,95 +1,77 @@
1
- import { Effect, Option, Schema } from "effect";
2
- import { ParseError } from "./error.js";
3
- import { failHere, getPos, matchRegex, peek, seek } from "./state.js";
4
- export const satisfy = (pred, expected) => Effect.gen(function* () {
5
- const c = yield* peek;
6
- if (c === undefined || !pred(c))
7
- return yield* failHere(expected);
8
- yield* seek((yield* getPos) + 1);
9
- return c;
10
- });
11
- export const char = (c) => satisfy((x) => x === c, JSON.stringify(c));
12
- export const digit = satisfy((c) => c >= "0" && c <= "9", "digit");
13
- export const regex = (re, expected) => {
14
- // Drop g/y so sticky/global lastIndex cannot break sequential matches.
15
- const normalized = new RegExp(re.source, re.flags.replace(/[gy]/g, ""));
16
- return Effect.gen(function* () {
17
- const pos = yield* getPos;
18
- const m = yield* matchRegex(normalized);
19
- if (Option.isNone(m))
20
- return yield* failHere(expected);
21
- yield* seek(pos + m.value.length);
22
- return m.value;
1
+ import { Equal, Function as F, Schema } from "effect";
2
+ import { isField, isGrammar, isSilent, make, silent, } from "./core.js";
3
+ import { preview } from "./errors.js";
4
+ export { field } from "./core.js";
5
+ export const literal = (value) => silent({ _tag: "Literal", value });
6
+ export const empty = literal("");
7
+ /** The regex is made sticky so the parser can match at a position without slicing. */
8
+ export const regex = (re, name) => {
9
+ const flags = re.flags.replace(/[gy]/g, "");
10
+ return make({
11
+ _tag: "Regex",
12
+ re: new RegExp(re.source, `${flags}y`),
13
+ whole: new RegExp(`^(?:${re.source})$`, flags),
14
+ name,
23
15
  });
24
16
  };
25
- export const endOfInput = Effect.gen(function* () {
26
- const c = yield* peek;
27
- if (c !== undefined)
28
- return yield* failHere("end of input");
29
- });
30
- /**
31
- * Ordered choice. Commits to `p` once it has consumed input — if `p` fails
32
- * after consuming, `q` is not tried. Wrap `p` in {@link attempt} to opt back
33
- * into backtracking.
34
- */
35
- export const or_ = (p, q) => Effect.gen(function* () {
36
- const mark = yield* getPos;
37
- const r1 = yield* Effect.result(p);
38
- if (r1._tag === "Success")
39
- return r1.success;
40
- const e1 = r1.failure;
41
- if (!Schema.is(ParseError)(e1))
42
- return yield* Effect.fail(e1);
43
- if ((yield* getPos) > mark)
44
- return yield* e1;
45
- yield* seek(mark);
46
- const r2 = yield* Effect.result(q);
47
- if (r2._tag === "Success")
48
- return r2.success;
49
- const e2 = r2.failure;
50
- if (!Schema.is(ParseError)(e2))
51
- return yield* Effect.fail(e2);
52
- return yield* e2.pos >= e1.pos ? e2 : e1;
53
- });
54
- /**
55
- * Rewind on failure: run `p`, and if it fails, restore the input position so
56
- * an enclosing {@link or_} will try its next option. Errors keep their
57
- * original position for messages.
58
- */
59
- export const attempt = (p) => Effect.gen(function* () {
60
- const mark = yield* getPos;
61
- const r = yield* Effect.result(p);
62
- if (r._tag === "Success")
63
- return r.success;
64
- if (Schema.is(ParseError)(r.failure))
65
- yield* seek(mark);
66
- return yield* Effect.fail(r.failure);
67
- });
68
- /**
69
- * Run `p` zero or more times (`atLeast` sets a minimum). If `p` fails after
70
- * consuming input, `many` fails too — wrap `p` in {@link attempt} to keep
71
- * collecting instead.
72
- */
73
- export const many = (p, opts) => Effect.gen(function* () {
74
- const out = [];
75
- const atLeast = opts?.atLeast ?? 0;
76
- for (let i = 0; i < atLeast; i++)
77
- out.push(yield* p);
78
- while (true) {
79
- const mark = yield* getPos;
80
- const r = yield* Effect.result(p);
81
- if (r._tag === "Failure") {
82
- if (!Schema.is(ParseError)(r.failure))
83
- return yield* Effect.fail(r.failure);
84
- if ((yield* getPos) > mark)
85
- return yield* r.failure;
86
- yield* seek(mark);
87
- return out;
88
- }
89
- if ((yield* getPos) === mark) {
90
- return yield* Effect.die(new Error("many: parser succeeded without consuming input"));
91
- }
92
- out.push(r.success);
17
+ const _toSilent = (s) => (isGrammar(s) ? s : literal(s));
18
+ const _silentIf = (cond, node) => (cond ? silent(node) : make(node));
19
+ export function seq(...parts) {
20
+ return _silentIf(!parts.some(isField), { _tag: "Seq", parts });
21
+ }
22
+ export const gen = (run) => make({ _tag: "Gen", run });
23
+ export function wrap(open, inner, close) {
24
+ return _silentIf(isSilent(inner), {
25
+ _tag: "Wrap",
26
+ open: _toSilent(open),
27
+ inner,
28
+ close: _toSilent(close),
29
+ });
30
+ }
31
+ export function prefix(open, inner) {
32
+ return wrap(open, inner, empty);
33
+ }
34
+ export function suffix(inner, close) {
35
+ return wrap(empty, inner, close);
36
+ }
37
+ export const choice = (...options) => make({ _tag: "Choice", options });
38
+ export function optional(inner) {
39
+ return _silentIf(isSilent(inner), { _tag: "Optional", inner });
40
+ }
41
+ const bounds = (name, opts) => {
42
+ const min = opts?.min ?? 0;
43
+ const max = opts?.max ?? Number.POSITIVE_INFINITY;
44
+ if (!Number.isSafeInteger(min) || min < 0) {
45
+ throw new RangeError(`${name}: min must be a non-negative safe integer`);
46
+ }
47
+ if (max !== Number.POSITIVE_INFINITY && !(Number.isSafeInteger(max) && max >= min)) {
48
+ throw new RangeError(`${name}: max must be a safe integer >= min`);
93
49
  }
94
- });
50
+ return { min, max };
51
+ };
52
+ const _dataFirst = (args) => isGrammar(args[0]);
53
+ export const many = F.dual(_dataFirst, (inner, opts) => make({ _tag: "Many", inner, sep: empty, ...bounds("many", opts) }));
54
+ export const sepBy = F.dual(_dataFirst, (inner, sep, opts) => make({ _tag: "Many", inner, sep: _toSilent(sep), ...bounds("sepBy", opts) }));
55
+ export const transform = F.dual(2, (inner, f) => make({ _tag: "Transform", inner, ...f }));
56
+ export const decodeTo = (schema) => (f) => (inner) => {
57
+ let is;
58
+ return transform(inner, { ...f, is: f.is ?? ((value) => (is ??= Schema.is(schema))(value)) });
59
+ };
60
+ export const as = F.dual(2, (inner, value) => transform(inner, {
61
+ decode: () => value,
62
+ encode: () => undefined,
63
+ is: (u) => Equal.equals(u, value),
64
+ name: preview(value),
65
+ }));
66
+ export const flag = (s) => choice(as(_toSilent(s), true), as(empty, false));
67
+ export const skip = F.dual(2, (inner, printAs) => silent({ _tag: "Skip", inner, printAs, show: true }));
68
+ export const label = F.dual(2, (inner, name) => make({ _tag: "Label", inner, name }));
69
+ export const suspend = (thunk, name) => make({ _tag: "Suspend", thunk, name });
70
+ const hiddenWhitespace = (printAs) => silent({ _tag: "Skip", inner: regex(/\s*/, "whitespace"), printAs, show: false });
71
+ export const whitespace = hiddenWhitespace("");
72
+ export function lexeme(inner) {
73
+ return suffix(inner, hiddenWhitespace(" "));
74
+ }
75
+ export const symbol = (s) => lexeme(literal(s));
76
+ export const integer = regex(/-?\d+/, "integer").pipe(transform({ decode: Number, encode: String, is: Number.isSafeInteger, name: "integer" }));
95
77
  //# sourceMappingURL=combinators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"combinators.js","sourceRoot":"","sources":["../src/combinators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combinators.js","sourceRoot":"","sources":["../src/combinators.ts"],"names":[],"mappings":"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"}