@spakhm/ts-parsec 0.1.8 → 0.3.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/base.d.ts +28 -27
- package/dist/base.d.ts.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +294 -7
- package/dist/lib.d.ts +30 -27
- package/dist/lib.d.ts.map +1 -0
- package/dist/stream.d.ts +11 -10
- package/dist/stream.d.ts.map +1 -0
- package/package.json +27 -1
- package/src/lib.ts +14 -5
- package/dist/ts-parsec.cjs.development.js +0 -376
- package/dist/ts-parsec.cjs.development.js.map +0 -1
- package/dist/ts-parsec.cjs.production.min.js +0 -2
- package/dist/ts-parsec.cjs.production.min.js.map +0 -1
- package/dist/ts-parsec.esm.js +0 -343
- package/dist/ts-parsec.esm.js.map +0 -1
package/dist/base.d.ts
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
import type { stream } from './stream';
|
|
2
|
-
export
|
|
3
|
-
type: 'ok';
|
|
4
|
-
res: T;
|
|
5
|
-
} | {
|
|
6
|
-
type: 'err';
|
|
7
|
-
err: E;
|
|
8
|
-
};
|
|
9
|
-
export
|
|
10
|
-
row: number;
|
|
11
|
-
col: number;
|
|
12
|
-
msg: string;
|
|
13
|
-
};
|
|
14
|
-
export declare const ok: <T>(res: T) => result<T, never>;
|
|
15
|
-
export declare const err: (row: number, col: number, msg: string) => result<never, parser_error>;
|
|
16
|
-
export
|
|
17
|
-
export
|
|
18
|
-
map: <U>(fn: ((value: T) => U)) => parser<U>;
|
|
19
|
-
};
|
|
20
|
-
export
|
|
21
|
-
export declare function toParser<T extends string>(p: T): parser<T>;
|
|
22
|
-
export declare function toParser<T>(p: parserlike<T>): parser<T>;
|
|
23
|
-
export declare const str: <T extends string>(match: T) => parser<T>;
|
|
24
|
-
export declare const lex: <T>(p: parserlike<T>) => parser<T>;
|
|
25
|
-
export declare const keepWs: <T>(p: parserlike<T>) => parser<T>;
|
|
26
|
-
export declare const ws: parser<{}>;
|
|
27
|
-
export declare const fwd: <T>(thunk: () => parserlike<T>) => parser<T>;
|
|
1
|
+
import type { stream } from './stream';
|
|
2
|
+
export type result<T, E> = {
|
|
3
|
+
type: 'ok';
|
|
4
|
+
res: T;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'err';
|
|
7
|
+
err: E;
|
|
8
|
+
};
|
|
9
|
+
export type parser_error = {
|
|
10
|
+
row: number;
|
|
11
|
+
col: number;
|
|
12
|
+
msg: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const ok: <T>(res: T) => result<T, never>;
|
|
15
|
+
export declare const err: (row: number, col: number, msg: string) => result<never, parser_error>;
|
|
16
|
+
export type parserFn<T> = (source: stream) => result<T, parser_error>;
|
|
17
|
+
export type parser<T> = parserFn<T> & {
|
|
18
|
+
map: <U>(fn: ((value: T) => U)) => parser<U>;
|
|
19
|
+
};
|
|
20
|
+
export type parserlike<T> = parserFn<T> | parser<T> | string;
|
|
21
|
+
export declare function toParser<T extends string>(p: T): parser<T>;
|
|
22
|
+
export declare function toParser<T>(p: parserlike<T>): parser<T>;
|
|
23
|
+
export declare const str: <T extends string>(match: T) => parser<T>;
|
|
24
|
+
export declare const lex: <T>(p: parserlike<T>) => parser<T>;
|
|
25
|
+
export declare const keepWs: <T>(p: parserlike<T>) => parser<T>;
|
|
26
|
+
export declare const ws: parser<{}>;
|
|
27
|
+
export declare const fwd: <T>(thunk: (() => parserlike<T>)) => parser<T>;
|
|
28
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAKvC,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;CAAE,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;CAAE,CAAC;AAEtE,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,KAAK,CAAC,KAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAA2B,CAAC;AAC1E,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAC3C,CAAC;AAK5C,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AACtE,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IACpC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;CAC9C,CAAC;AACF,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AAK7D,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AA6BzD,eAAO,MAAM,GAAG,GAAI,CAAC,SAAS,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,CAAC,CAQpD,CAAC;AAEN,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,cAWrC,CAAC;AAEH,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,cAOtC,CAAC;AAEL,eAAO,MAAM,EAAE,YAYb,CAAC;AAKH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,CAAC,CACL,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from './base';
|
|
2
|
-
export * from './lib';
|
|
3
|
-
export * from './stream';
|
|
1
|
+
export * from './base';
|
|
2
|
+
export * from './lib';
|
|
3
|
+
export * from './stream';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,295 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// src/base.ts
|
|
2
|
+
var ok = (res) => ({ type: "ok", res });
|
|
3
|
+
var err = (row, col, msg) => ({ type: "err", err: { row, col, msg } });
|
|
4
|
+
function toParser(pl) {
|
|
5
|
+
if (typeof pl == "string") {
|
|
6
|
+
return str(pl);
|
|
7
|
+
}
|
|
8
|
+
if ("map" in pl) {
|
|
9
|
+
return pl;
|
|
10
|
+
}
|
|
11
|
+
const fn_ = pl;
|
|
12
|
+
fn_.map = (fnTransform) => {
|
|
13
|
+
return toParser((source) => {
|
|
14
|
+
const res = fn_(source);
|
|
15
|
+
if (res.type == "ok") {
|
|
16
|
+
return ok(fnTransform(res.res));
|
|
17
|
+
} else {
|
|
18
|
+
return res;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
return fn_;
|
|
8
23
|
}
|
|
24
|
+
var str = (match) => lex(toParser((source) => {
|
|
25
|
+
for (let i = 0;i < match.length; i++) {
|
|
26
|
+
if (source.next() != match[i]) {
|
|
27
|
+
return err(0, 0, "");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return ok(match);
|
|
31
|
+
}));
|
|
32
|
+
var lex = (p) => toParser((source) => {
|
|
33
|
+
if (!source.drop_ws) {
|
|
34
|
+
return toParser(p)(source);
|
|
35
|
+
} else {
|
|
36
|
+
return keepWs((source2) => {
|
|
37
|
+
ws(source2);
|
|
38
|
+
return toParser(p)(source2);
|
|
39
|
+
})(source);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
var keepWs = (p) => toParser((source) => {
|
|
43
|
+
const prev_drop_ws = source.drop_ws;
|
|
44
|
+
source.drop_ws = false;
|
|
45
|
+
const res = toParser(p)(source);
|
|
46
|
+
source.drop_ws = prev_drop_ws;
|
|
47
|
+
return res;
|
|
48
|
+
});
|
|
49
|
+
var ws = toParser((source) => {
|
|
50
|
+
while (true) {
|
|
51
|
+
source.push();
|
|
52
|
+
const ch = source.next();
|
|
53
|
+
if (ch?.trim() === "") {
|
|
54
|
+
source.pop_continue();
|
|
55
|
+
} else {
|
|
56
|
+
source.pop_rollback();
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return ok({});
|
|
61
|
+
});
|
|
62
|
+
var fwd = (thunk) => toParser((source) => toParser(thunk())(source));
|
|
63
|
+
// src/lib.ts
|
|
64
|
+
var attempt = (parser) => toParser((source) => {
|
|
65
|
+
source.push();
|
|
66
|
+
const res = toParser(parser)(source);
|
|
67
|
+
if (res.type == "ok") {
|
|
68
|
+
source.pop_continue();
|
|
69
|
+
} else {
|
|
70
|
+
source.pop_rollback();
|
|
71
|
+
}
|
|
72
|
+
return res;
|
|
73
|
+
});
|
|
74
|
+
var range = (start, end) => toParser((source) => {
|
|
75
|
+
const next = source.next();
|
|
76
|
+
if (!next)
|
|
77
|
+
return err(0, 0, "");
|
|
78
|
+
if (next >= start[0] && next <= end[0])
|
|
79
|
+
return ok(next);
|
|
80
|
+
return err(0, 0, "");
|
|
81
|
+
});
|
|
82
|
+
var either = (...parsers) => toParser((source) => {
|
|
83
|
+
for (const parser of parsers) {
|
|
84
|
+
const res = attempt(parser)(source);
|
|
85
|
+
if (res.type == "ok") {
|
|
86
|
+
return res;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return err(0, 0, "");
|
|
90
|
+
});
|
|
91
|
+
var seq = (...parsers) => {
|
|
92
|
+
const p = toParser((source) => {
|
|
93
|
+
const res = [];
|
|
94
|
+
for (const parser of parsers) {
|
|
95
|
+
const res_ = toParser(parser)(source);
|
|
96
|
+
if (res_.type == "ok") {
|
|
97
|
+
res.push(res_.res);
|
|
98
|
+
} else {
|
|
99
|
+
return err(0, 0, "");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return ok(res);
|
|
103
|
+
});
|
|
104
|
+
p.map2 = (fn) => p.map((x) => fn(...x));
|
|
105
|
+
return p;
|
|
106
|
+
};
|
|
107
|
+
var many = (parser) => toParser((source) => {
|
|
108
|
+
const res = [];
|
|
109
|
+
while (true) {
|
|
110
|
+
const _res = attempt(parser)(source);
|
|
111
|
+
if (_res.type == "ok") {
|
|
112
|
+
res.push(_res.res);
|
|
113
|
+
} else {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return ok(res);
|
|
118
|
+
});
|
|
119
|
+
var some = (parser) => seq(parser, many(parser)).map2((ft, rt) => [ft, ...rt]);
|
|
120
|
+
var digit = range("0", "9");
|
|
121
|
+
var nat = lex(some(digit)).map((val) => BigInt(val.join("")));
|
|
122
|
+
var maybe = (p) => toParser((source) => {
|
|
123
|
+
const res = attempt(p)(source);
|
|
124
|
+
return res.type == "ok" ? res : ok(null);
|
|
125
|
+
});
|
|
126
|
+
var int = seq(maybe(either("-", "+")), nat).map2((sign, val) => {
|
|
127
|
+
if (sign === "-") {
|
|
128
|
+
return -val;
|
|
129
|
+
} else {
|
|
130
|
+
return val;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
var lower = range("a", "z");
|
|
134
|
+
var upper = range("A", "Z");
|
|
135
|
+
var alpha = either(lower, upper);
|
|
136
|
+
var alnum = either(alpha, digit);
|
|
137
|
+
var sepBy = (item, sep, trailingSep = "allow") => toParser((source) => {
|
|
138
|
+
const res = [];
|
|
139
|
+
const res_ = attempt(item)(source);
|
|
140
|
+
if (res_.type == "err") {
|
|
141
|
+
return ok(res);
|
|
142
|
+
} else {
|
|
143
|
+
res.push(res_.res);
|
|
144
|
+
}
|
|
145
|
+
while (true) {
|
|
146
|
+
const sepres_ = attempt(sep)(source);
|
|
147
|
+
if (sepres_.type == "err") {
|
|
148
|
+
return trailingSep === "require" ? err(0, 0, "") : ok(res);
|
|
149
|
+
}
|
|
150
|
+
const res_2 = attempt(item)(source);
|
|
151
|
+
if (res_2.type == "err") {
|
|
152
|
+
return trailingSep === "forbid" ? err(0, 0, "") : ok(res);
|
|
153
|
+
} else {
|
|
154
|
+
res.push(res_2.res);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
var sepBy1 = (item, sep, trailingSep = "allow") => toParser((source) => {
|
|
159
|
+
const res = sepBy(item, sep, trailingSep)(source);
|
|
160
|
+
if (res.type == "err")
|
|
161
|
+
return res;
|
|
162
|
+
return res.res.length >= 1 ? res : err(0, 0, "");
|
|
163
|
+
});
|
|
164
|
+
function binop(operator, operand, makeNode) {
|
|
165
|
+
return toParser((source) => {
|
|
166
|
+
const p = seq(operand, many(seq(operator, operand))).map2((left, rights) => {
|
|
167
|
+
const acc = rights.reduce((acc2, [op, right]) => makeNode(op, acc2, right), left);
|
|
168
|
+
return acc;
|
|
169
|
+
});
|
|
170
|
+
return p(source);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function binopr(operator, operand, makeNode) {
|
|
174
|
+
return toParser((source) => {
|
|
175
|
+
const p = seq(operand, many(seq(operator, operand))).map2((left, rights) => {
|
|
176
|
+
if (rights.length === 0)
|
|
177
|
+
return left;
|
|
178
|
+
let acc = rights[rights.length - 1][1];
|
|
179
|
+
for (let i = rights.length - 2;i >= 0; i--) {
|
|
180
|
+
const [op, right] = rights[i];
|
|
181
|
+
acc = makeNode(op, right, acc);
|
|
182
|
+
}
|
|
183
|
+
return makeNode(rights[0][0], left, acc);
|
|
184
|
+
});
|
|
185
|
+
return p(source);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
var noop = toParser((_) => ok(true));
|
|
189
|
+
var not = (p) => toParser((source) => {
|
|
190
|
+
const res = toParser(p)(source);
|
|
191
|
+
if (res.type == "ok") {
|
|
192
|
+
return err(0, 0, "");
|
|
193
|
+
} else {
|
|
194
|
+
return ok(null);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
var peek = (p) => toParser((source) => {
|
|
198
|
+
source.push();
|
|
199
|
+
const res = toParser(p)(source);
|
|
200
|
+
source.pop_rollback();
|
|
201
|
+
return res;
|
|
202
|
+
});
|
|
203
|
+
var anych = (opts) => toParser((source) => {
|
|
204
|
+
if (opts?.but) {
|
|
205
|
+
const res2 = peek(opts.but)(source);
|
|
206
|
+
if (res2.type == "ok") {
|
|
207
|
+
return err(0, 0, "");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const res = source.next();
|
|
211
|
+
return res ? ok(res) : err(0, 0, "");
|
|
212
|
+
});
|
|
213
|
+
var eof = not(anych());
|
|
214
|
+
// src/stream.ts
|
|
215
|
+
class string_stream {
|
|
216
|
+
source;
|
|
217
|
+
drop_ws;
|
|
218
|
+
row = 1;
|
|
219
|
+
col = 1;
|
|
220
|
+
idx = 0;
|
|
221
|
+
stack = [];
|
|
222
|
+
constructor(source, drop_ws = true) {
|
|
223
|
+
this.source = source;
|
|
224
|
+
this.drop_ws = drop_ws;
|
|
225
|
+
}
|
|
226
|
+
next() {
|
|
227
|
+
if (this.idx == this.source.length) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const ch = this.source[this.idx++];
|
|
231
|
+
this.col++;
|
|
232
|
+
if (ch == "\n") {
|
|
233
|
+
this.row++;
|
|
234
|
+
this.col = 1;
|
|
235
|
+
}
|
|
236
|
+
if (this.drop_ws && ch.trim() === "") {
|
|
237
|
+
return this.next();
|
|
238
|
+
} else {
|
|
239
|
+
return ch;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
push() {
|
|
243
|
+
this.stack.push({
|
|
244
|
+
row: this.row,
|
|
245
|
+
col: this.col,
|
|
246
|
+
idx: this.idx
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
pop_continue() {
|
|
250
|
+
this.stack.pop();
|
|
251
|
+
}
|
|
252
|
+
pop_rollback() {
|
|
253
|
+
const x = this.stack.pop();
|
|
254
|
+
this.row = x.row;
|
|
255
|
+
this.col = x.col;
|
|
256
|
+
this.idx = x.idx;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
var fromString = (source) => {
|
|
260
|
+
return new string_stream(source);
|
|
261
|
+
};
|
|
262
|
+
export {
|
|
263
|
+
ws,
|
|
264
|
+
upper,
|
|
265
|
+
toParser,
|
|
266
|
+
str,
|
|
267
|
+
some,
|
|
268
|
+
seq,
|
|
269
|
+
sepBy1,
|
|
270
|
+
sepBy,
|
|
271
|
+
range,
|
|
272
|
+
peek,
|
|
273
|
+
ok,
|
|
274
|
+
not,
|
|
275
|
+
noop,
|
|
276
|
+
nat,
|
|
277
|
+
maybe,
|
|
278
|
+
many,
|
|
279
|
+
lower,
|
|
280
|
+
lex,
|
|
281
|
+
keepWs,
|
|
282
|
+
int,
|
|
283
|
+
fwd,
|
|
284
|
+
fromString,
|
|
285
|
+
err,
|
|
286
|
+
eof,
|
|
287
|
+
either,
|
|
288
|
+
digit,
|
|
289
|
+
binopr,
|
|
290
|
+
binop,
|
|
291
|
+
attempt,
|
|
292
|
+
anych,
|
|
293
|
+
alpha,
|
|
294
|
+
alnum
|
|
295
|
+
};
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import type { parser, parserlike } from './base';
|
|
2
|
-
export declare const attempt: <T>(parser: parserlike<T>) => parser<T>;
|
|
3
|
-
export declare const range: (start: string, end: string) => parser<string>;
|
|
4
|
-
export declare const either: <Ts extends any[]>(...parsers: { [K in keyof Ts]: parserlike<Ts[K]>; }) => parser<Ts[number]>;
|
|
5
|
-
export
|
|
6
|
-
map2: <U>(fn: ((...values: T) => U)) => parser<U>;
|
|
7
|
-
};
|
|
8
|
-
export declare const seq: <Ts extends any[]>(...parsers: { [K in keyof Ts]: parserlike<Ts[K]>; }) => seq_parser<Ts>;
|
|
9
|
-
export declare const many: <T>(parser: parserlike<T>) => parser<T[]>;
|
|
10
|
-
export declare const some: <T>(parser: parserlike<T>) => parser<T[]>;
|
|
11
|
-
export declare const digit: parser<string>;
|
|
12
|
-
export declare const nat: parser<
|
|
13
|
-
export declare const maybe: <T>(p: parserlike<T>) => parser<T | null>;
|
|
14
|
-
export declare const int: parser<
|
|
15
|
-
export declare const lower: parser<string>;
|
|
16
|
-
export declare const upper: parser<string>;
|
|
17
|
-
export declare const alpha: parser<string>;
|
|
18
|
-
export declare const alnum: parser<string>;
|
|
19
|
-
export declare const sepBy: <T, U>(item: parserlike<T>, sep: parserlike<U>,
|
|
20
|
-
export declare
|
|
21
|
-
export declare function
|
|
22
|
-
export declare
|
|
23
|
-
export declare const
|
|
24
|
-
export declare const
|
|
25
|
-
export declare const
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
import type { parser, parserlike } from './base';
|
|
2
|
+
export declare const attempt: <T>(parser: parserlike<T>) => parser<T>;
|
|
3
|
+
export declare const range: (start: string, end: string) => parser<string>;
|
|
4
|
+
export declare const either: <Ts extends any[]>(...parsers: { [K in keyof Ts]: parserlike<Ts[K]>; }) => parser<Ts[number]>;
|
|
5
|
+
export type seq_parser<T extends any[]> = parser<T> & {
|
|
6
|
+
map2: <U>(fn: ((...values: T) => U)) => parser<U>;
|
|
7
|
+
};
|
|
8
|
+
export declare const seq: <Ts extends any[]>(...parsers: { [K in keyof Ts]: parserlike<Ts[K]>; }) => seq_parser<Ts>;
|
|
9
|
+
export declare const many: <T>(parser: parserlike<T>) => parser<T[]>;
|
|
10
|
+
export declare const some: <T>(parser: parserlike<T>) => parser<T[]>;
|
|
11
|
+
export declare const digit: parser<string>;
|
|
12
|
+
export declare const nat: parser<bigint>;
|
|
13
|
+
export declare const maybe: <T>(p: parserlike<T>) => parser<T | null>;
|
|
14
|
+
export declare const int: parser<bigint>;
|
|
15
|
+
export declare const lower: parser<string>;
|
|
16
|
+
export declare const upper: parser<string>;
|
|
17
|
+
export declare const alpha: parser<string>;
|
|
18
|
+
export declare const alnum: parser<string>;
|
|
19
|
+
export declare const sepBy: <T, U>(item: parserlike<T>, sep: parserlike<U>, trailingSep?: "allow" | "forbid" | "require") => parser<T[]>;
|
|
20
|
+
export declare const sepBy1: <T, U>(item: parserlike<T>, sep: parserlike<U>, trailingSep?: "allow" | "forbid" | "require") => parser<T[]>;
|
|
21
|
+
export declare function binop<O, D, N>(operator: parserlike<O>, operand: parserlike<D>, makeNode: (op: O, left: D | N, right: D) => N): parser<N | D>;
|
|
22
|
+
export declare function binopr<O, D, N>(operator: parserlike<O>, operand: parserlike<D>, makeNode: (op: O, left: D, right: D | N) => N): parser<N | D>;
|
|
23
|
+
export declare const noop: parser<boolean>;
|
|
24
|
+
export declare const not: <T>(p: parserlike<T>) => parser<null>;
|
|
25
|
+
export declare const peek: <T>(p: parserlike<T>) => parser<T>;
|
|
26
|
+
export declare const anych: (opts?: {
|
|
27
|
+
but: parserlike<unknown>;
|
|
28
|
+
}) => parser<string>;
|
|
29
|
+
export declare const eof: parser<null>;
|
|
30
|
+
//# sourceMappingURL=lib.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"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"}
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export
|
|
2
|
-
row: number;
|
|
3
|
-
col: number;
|
|
4
|
-
drop_ws: boolean;
|
|
5
|
-
next: () => string | null;
|
|
6
|
-
push: () => void;
|
|
7
|
-
pop_continue: () => void;
|
|
8
|
-
pop_rollback: () => void;
|
|
9
|
-
};
|
|
10
|
-
export declare const fromString: (source: string) => stream;
|
|
1
|
+
export type stream = {
|
|
2
|
+
row: number;
|
|
3
|
+
col: number;
|
|
4
|
+
drop_ws: boolean;
|
|
5
|
+
next: () => string | null;
|
|
6
|
+
push: () => void;
|
|
7
|
+
pop_continue: () => void;
|
|
8
|
+
pop_rollback: () => void;
|
|
9
|
+
};
|
|
10
|
+
export declare const fromString: (source: string) => stream;
|
|
11
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAmDF,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,KAAG,MAE3C,CAAA"}
|
package/package.json
CHANGED
|
@@ -1 +1,27 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "@spakhm/ts-parsec",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"author": "Slava Akhmechet",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": ["dist", "src"],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target node && bun run build:types",
|
|
13
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
14
|
+
"test": "bun test",
|
|
15
|
+
"prepublishOnly": "bun run build"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/bun": "^1.1.14",
|
|
19
|
+
"typescript": "^5.7.2"
|
|
20
|
+
},
|
|
21
|
+
"prettier": {
|
|
22
|
+
"printWidth": 80,
|
|
23
|
+
"semi": true,
|
|
24
|
+
"singleQuote": true,
|
|
25
|
+
"trailingComma": "es5"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/lib.ts
CHANGED
|
@@ -76,7 +76,7 @@ export const some = <T>(parser: parserlike<T>): parser<T[]> =>
|
|
|
76
76
|
export const digit = range('0', '9');
|
|
77
77
|
|
|
78
78
|
export const nat = lex(some(digit)).map((val) =>
|
|
79
|
-
|
|
79
|
+
BigInt(val.join("")));
|
|
80
80
|
|
|
81
81
|
export const maybe = <T>(p: parserlike<T>) =>
|
|
82
82
|
toParser((source: stream) => {
|
|
@@ -97,7 +97,7 @@ export const upper = range('A', 'Z');
|
|
|
97
97
|
export const alpha = either(lower, upper);
|
|
98
98
|
export const alnum = either(alpha, digit);
|
|
99
99
|
|
|
100
|
-
export const sepBy = <T, U>(item: parserlike<T>, sep: parserlike<U>,
|
|
100
|
+
export const sepBy = <T, U>(item: parserlike<T>, sep: parserlike<U>, trailingSep: 'allow' | 'forbid' | 'require' = 'allow'): parser<T[]> =>
|
|
101
101
|
toParser((source: stream) => {
|
|
102
102
|
const res: T[] = [];
|
|
103
103
|
|
|
@@ -111,18 +111,25 @@ export const sepBy = <T, U>(item: parserlike<T>, sep: parserlike<U>, allowTraili
|
|
|
111
111
|
while (true) {
|
|
112
112
|
const sepres_ = attempt(sep)(source);
|
|
113
113
|
if (sepres_.type == 'err') {
|
|
114
|
-
return ok(res);
|
|
114
|
+
return trailingSep === 'require' ? err(0, 0, '') : ok(res);
|
|
115
115
|
}
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
const res_ = attempt(item)(source);
|
|
118
118
|
if (res_.type == 'err') {
|
|
119
|
-
return
|
|
119
|
+
return trailingSep === 'forbid' ? err(0, 0, '') : ok(res);
|
|
120
120
|
} else {
|
|
121
121
|
res.push(res_.res);
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
+
export const sepBy1 = <T, U>(item: parserlike<T>, sep: parserlike<U>, trailingSep: 'allow' | 'forbid' | 'require' = 'allow'): parser<T[]> =>
|
|
127
|
+
toParser((source: stream) => {
|
|
128
|
+
const res = sepBy(item, sep, trailingSep)(source);
|
|
129
|
+
if (res.type == 'err') return res;
|
|
130
|
+
return res.res.length >= 1 ? res : err(0, 0, '');
|
|
131
|
+
});
|
|
132
|
+
|
|
126
133
|
export function binop<O, D, N>(
|
|
127
134
|
operator: parserlike<O>,
|
|
128
135
|
operand: parserlike<D>,
|
|
@@ -189,3 +196,5 @@ export const anych = (opts?: { but: parserlike<unknown> }) => toParser((source:
|
|
|
189
196
|
const res = source.next()
|
|
190
197
|
return res ? ok(res) : err(0, 0, "");
|
|
191
198
|
});
|
|
199
|
+
|
|
200
|
+
export const eof = not(anych());
|