@thi.ng/parse 1.0.4 → 2.0.3
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/CHANGELOG.md +85 -137
- package/README.md +15 -6
- package/api.d.ts +1 -1
- package/combinators/alt.d.ts +1 -1
- package/combinators/alt.js +1 -1
- package/combinators/boundary.d.ts +1 -1
- package/combinators/boundary.js +2 -2
- package/combinators/check.d.ts +1 -1
- package/combinators/check.js +2 -2
- package/combinators/dynamic.d.ts +1 -1
- package/combinators/expect.d.ts +1 -1
- package/combinators/expect.js +1 -1
- package/combinators/lookahead.d.ts +1 -1
- package/combinators/lookahead.js +1 -1
- package/combinators/maybe.d.ts +1 -1
- package/combinators/maybe.js +1 -1
- package/combinators/not.d.ts +1 -1
- package/combinators/not.js +1 -1
- package/combinators/repeat.d.ts +1 -1
- package/combinators/repeat.js +1 -1
- package/combinators/seq.d.ts +1 -1
- package/combinators/seq.js +1 -1
- package/combinators/wrap.d.ts +1 -1
- package/combinators/wrap.js +3 -3
- package/combinators/xform.d.ts +1 -1
- package/context.d.ts +1 -1
- package/context.js +8 -7
- package/error.d.ts +1 -1
- package/error.js +1 -1
- package/grammar.d.ts +1 -1
- package/grammar.js +65 -48
- package/index.d.ts +49 -49
- package/index.js +49 -49
- package/package.json +183 -31
- package/presets/alpha.d.ts +4 -4
- package/presets/alpha.js +3 -3
- package/presets/bits.d.ts +2 -2
- package/presets/bits.js +4 -4
- package/presets/digits.d.ts +2 -2
- package/presets/digits.js +2 -2
- package/presets/escape.d.ts +2 -2
- package/presets/escape.js +9 -9
- package/presets/hex.d.ts +3 -3
- package/presets/hex.js +5 -5
- package/presets/numbers.d.ts +5 -5
- package/presets/numbers.js +12 -12
- package/presets/string.d.ts +1 -1
- package/presets/string.js +7 -7
- package/presets/whitespace.d.ts +8 -8
- package/presets/whitespace.js +3 -3
- package/prims/always.d.ts +2 -2
- package/prims/always.js +1 -1
- package/prims/anchor.d.ts +1 -1
- package/prims/anchor.js +1 -1
- package/prims/fail.d.ts +1 -1
- package/prims/fail.js +1 -1
- package/prims/lit.d.ts +2 -2
- package/prims/lit.js +1 -1
- package/prims/none-of.d.ts +1 -1
- package/prims/none-of.js +3 -2
- package/prims/one-of.d.ts +1 -1
- package/prims/one-of.js +3 -2
- package/prims/pass.d.ts +1 -1
- package/prims/pass.js +1 -1
- package/prims/range.d.ts +1 -1
- package/prims/range.js +1 -1
- package/prims/satisfy.d.ts +1 -1
- package/prims/skip.d.ts +1 -1
- package/prims/skip.js +1 -1
- package/prims/string.d.ts +1 -1
- package/prims/string.js +2 -2
- package/readers/array-reader.d.ts +1 -1
- package/readers/string-reader.d.ts +1 -1
- package/utils.js +1 -0
- package/xform/collect.d.ts +1 -1
- package/xform/collect.js +1 -1
- package/xform/comp.d.ts +1 -1
- package/xform/count.d.ts +1 -1
- package/xform/count.js +1 -1
- package/xform/discard.d.ts +1 -1
- package/xform/discard.js +1 -1
- package/xform/hoist.d.ts +1 -1
- package/xform/hoist.js +1 -1
- package/xform/join.d.ts +1 -1
- package/xform/join.js +1 -1
- package/xform/nest.d.ts +1 -1
- package/xform/nest.js +4 -4
- package/xform/number.d.ts +1 -1
- package/xform/number.js +1 -1
- package/xform/print.d.ts +1 -1
- package/xform/print.js +2 -2
- package/xform/replace.d.ts +1 -1
- package/xform/replace.js +1 -1
- package/xform/trim.d.ts +1 -1
- package/xform/trim.js +1 -1
- package/xform/with-id.d.ts +1 -1
- package/xform/with-id.js +1 -1
- package/lib/index.js +0 -967
- package/lib/index.js.map +0 -1
- package/lib/index.umd.js +0 -1
- package/lib/index.umd.js.map +0 -1
package/lib/index.js
DELETED
|
@@ -1,967 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var checks = require('@thi.ng/checks');
|
|
6
|
-
var errors = require('@thi.ng/errors');
|
|
7
|
-
var defmulti = require('@thi.ng/defmulti');
|
|
8
|
-
var strings = require('@thi.ng/strings');
|
|
9
|
-
|
|
10
|
-
const ParseError = errors.defError(() => `ParseError`);
|
|
11
|
-
const parseError = (ctx, msg) => {
|
|
12
|
-
const info = ctx.reader.format(ctx.scope.state);
|
|
13
|
-
throw new ParseError(msg + (info ? ` @ ${info}` : ""));
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
class ArrayReader {
|
|
17
|
-
constructor(_src) {
|
|
18
|
-
this._src = _src;
|
|
19
|
-
}
|
|
20
|
-
read(state) {
|
|
21
|
-
return this._src[state.p];
|
|
22
|
-
}
|
|
23
|
-
next(state) {
|
|
24
|
-
if (state.done)
|
|
25
|
-
return;
|
|
26
|
-
state.last = this._src[state.p];
|
|
27
|
-
state.done = ++state.p >= this._src.length;
|
|
28
|
-
}
|
|
29
|
-
isDone(state) {
|
|
30
|
-
return (state.done = state.p >= this._src.length);
|
|
31
|
-
}
|
|
32
|
-
format(state) {
|
|
33
|
-
return `offset ${state.p}`;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const defArrayReader = (input) => new ArrayReader(input);
|
|
37
|
-
|
|
38
|
-
class StringReader {
|
|
39
|
-
constructor(_src) {
|
|
40
|
-
this._src = _src;
|
|
41
|
-
}
|
|
42
|
-
read(state) {
|
|
43
|
-
return this._src[state.p];
|
|
44
|
-
}
|
|
45
|
-
next(state) {
|
|
46
|
-
if (state.done)
|
|
47
|
-
return;
|
|
48
|
-
state.last = this._src[state.p];
|
|
49
|
-
if (state.last === "\n") {
|
|
50
|
-
state.l++;
|
|
51
|
-
state.c = 1;
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
state.c++;
|
|
55
|
-
}
|
|
56
|
-
state.done = ++state.p >= this._src.length;
|
|
57
|
-
}
|
|
58
|
-
isDone(state) {
|
|
59
|
-
return (state.done = state.p >= this._src.length);
|
|
60
|
-
}
|
|
61
|
-
format(state) {
|
|
62
|
-
return `offset ${state.p} (${state.l}:${state.c})`;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const defStringReader = (input) => new StringReader(input);
|
|
66
|
-
|
|
67
|
-
const cache = [];
|
|
68
|
-
const indent = (x) => (cache[x] = " ".repeat(x));
|
|
69
|
-
|
|
70
|
-
class ParseContext {
|
|
71
|
-
constructor(reader, opts) {
|
|
72
|
-
this.reader = reader;
|
|
73
|
-
this.opts = Object.assign({ maxDepth: 32, debug: false, retain: false }, opts);
|
|
74
|
-
this._maxDepth = this.opts.maxDepth;
|
|
75
|
-
this._debug = this.opts.debug;
|
|
76
|
-
this._retain = this.opts.retain;
|
|
77
|
-
this.reset();
|
|
78
|
-
}
|
|
79
|
-
reset() {
|
|
80
|
-
this._curr = {
|
|
81
|
-
id: "root",
|
|
82
|
-
state: { p: 0, l: 1, c: 1 },
|
|
83
|
-
children: null,
|
|
84
|
-
result: null,
|
|
85
|
-
};
|
|
86
|
-
this._scopes = [this._curr];
|
|
87
|
-
this.reader.isDone(this._curr.state);
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
start(id) {
|
|
91
|
-
if (this._scopes.length >= this._maxDepth) {
|
|
92
|
-
parseError(this, `recursion limit reached ${this._maxDepth}`);
|
|
93
|
-
}
|
|
94
|
-
const scopes = this._scopes;
|
|
95
|
-
const scope = {
|
|
96
|
-
id,
|
|
97
|
-
state: Object.assign({}, scopes[scopes.length - 1].state),
|
|
98
|
-
children: null,
|
|
99
|
-
result: null,
|
|
100
|
-
};
|
|
101
|
-
scopes.push(scope);
|
|
102
|
-
this._debug &&
|
|
103
|
-
console.log(`${indent(scopes.length)}start: ${id} (${scope.state.p})`);
|
|
104
|
-
return (this._curr = scope);
|
|
105
|
-
}
|
|
106
|
-
discard() {
|
|
107
|
-
const scopes = this._scopes;
|
|
108
|
-
const child = scopes.pop();
|
|
109
|
-
this._curr = scopes[scopes.length - 1];
|
|
110
|
-
this._debug &&
|
|
111
|
-
console.log(`${indent(scopes.length + 1)}discard: ${child.id}`);
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
end() {
|
|
115
|
-
const scopes = this._scopes;
|
|
116
|
-
const child = scopes.pop();
|
|
117
|
-
const parent = scopes[scopes.length - 1];
|
|
118
|
-
const cstate = child.state;
|
|
119
|
-
let pstate;
|
|
120
|
-
this._debug &&
|
|
121
|
-
console.log(`${indent(scopes.length + 1)}end: ${child.id} (${cstate.p})`);
|
|
122
|
-
child.state = this._retain
|
|
123
|
-
? ((pstate = parent.state),
|
|
124
|
-
{ p: pstate.p, l: pstate.l, c: pstate.c })
|
|
125
|
-
: null;
|
|
126
|
-
parent.state = cstate;
|
|
127
|
-
const children = parent.children;
|
|
128
|
-
children ? children.push(child) : (parent.children = [child]);
|
|
129
|
-
this._curr = parent;
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
addChild(id, result = null, newState = false) {
|
|
133
|
-
const curr = this._curr;
|
|
134
|
-
const cstate = curr.state;
|
|
135
|
-
const child = {
|
|
136
|
-
id,
|
|
137
|
-
state: this._retain
|
|
138
|
-
? { p: cstate.p, l: cstate.l, c: cstate.c }
|
|
139
|
-
: null,
|
|
140
|
-
children: null,
|
|
141
|
-
result,
|
|
142
|
-
};
|
|
143
|
-
this._debug &&
|
|
144
|
-
console.log(`${indent(this._scopes.length + 1)}addChild: ${id} (${cstate.p})`);
|
|
145
|
-
const children = curr.children;
|
|
146
|
-
children ? children.push(child) : (curr.children = [child]);
|
|
147
|
-
if (newState !== false) {
|
|
148
|
-
newState === true
|
|
149
|
-
? this.reader.next(cstate)
|
|
150
|
-
: (this._curr.state = newState);
|
|
151
|
-
}
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
get scope() {
|
|
155
|
-
return this._curr;
|
|
156
|
-
}
|
|
157
|
-
get state() {
|
|
158
|
-
return this._curr.state;
|
|
159
|
-
}
|
|
160
|
-
set state(state) {
|
|
161
|
-
this._curr.state = state;
|
|
162
|
-
}
|
|
163
|
-
get done() {
|
|
164
|
-
return this._curr.state.done;
|
|
165
|
-
}
|
|
166
|
-
get root() {
|
|
167
|
-
return this._scopes[0];
|
|
168
|
-
}
|
|
169
|
-
get result() {
|
|
170
|
-
const children = this.root.children;
|
|
171
|
-
return children ? children[0].result : undefined;
|
|
172
|
-
}
|
|
173
|
-
get children() {
|
|
174
|
-
const children = this.root.children;
|
|
175
|
-
return children ? children[0].children : undefined;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function defContext(input, opts) {
|
|
179
|
-
return new ParseContext(checks.isString(input)
|
|
180
|
-
? defStringReader(input)
|
|
181
|
-
: checks.isArrayLike(input)
|
|
182
|
-
? defArrayReader(input)
|
|
183
|
-
: input, opts);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const xform = (parser, xf, user) => (ctx) => {
|
|
187
|
-
if (parser(ctx)) {
|
|
188
|
-
const children = ctx.scope.children;
|
|
189
|
-
const scope = children[children.length - 1];
|
|
190
|
-
if (xf(scope, ctx, user)) {
|
|
191
|
-
if (scope.children && !scope.children.length) {
|
|
192
|
-
scope.children = null;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
children.pop();
|
|
197
|
-
}
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const xfDiscard = () => null;
|
|
204
|
-
const discard = (parser) => xform(parser, xfDiscard);
|
|
205
|
-
|
|
206
|
-
const alt = (parsers) => (ctx) => {
|
|
207
|
-
if (ctx.done)
|
|
208
|
-
return false;
|
|
209
|
-
for (let i = 0, n = parsers.length; i < n; i++) {
|
|
210
|
-
if (parsers[i](ctx)) {
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return false;
|
|
215
|
-
};
|
|
216
|
-
const altD = (parsers) => discard(alt(parsers));
|
|
217
|
-
|
|
218
|
-
const dynamic = () => {
|
|
219
|
-
let impl;
|
|
220
|
-
const wrapper = (ctx) => (impl ? impl(ctx) : false);
|
|
221
|
-
wrapper.set = (p) => (impl = p);
|
|
222
|
-
return wrapper;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const lookahead = (parser, ahead, capture = false, id = "lookahead") => (ctx) => {
|
|
226
|
-
if (ctx.done)
|
|
227
|
-
return false;
|
|
228
|
-
ctx.start(id);
|
|
229
|
-
let pass = false;
|
|
230
|
-
while (true) {
|
|
231
|
-
const state = capture ? null : Object.assign({}, ctx.state);
|
|
232
|
-
if (ahead(ctx)) {
|
|
233
|
-
!capture && (ctx.state = state);
|
|
234
|
-
return pass ? ctx.end() : ctx.discard();
|
|
235
|
-
}
|
|
236
|
-
if (!parser(ctx))
|
|
237
|
-
return ctx.discard();
|
|
238
|
-
pass = true;
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const pass = (result, id = "pass") => (ctx) => ctx.addChild(id, checks.isFunction(result) ? result() : result);
|
|
243
|
-
const passD = () => true;
|
|
244
|
-
|
|
245
|
-
const maybe = (parser, result, id = "maybe") => (ctx) => parser(ctx) || pass(result, id)(ctx);
|
|
246
|
-
|
|
247
|
-
const satisfy = (pred, id = "satisfy") => ((ctx) => {
|
|
248
|
-
if (ctx.done)
|
|
249
|
-
return false;
|
|
250
|
-
const r = ctx.reader.read(ctx.state);
|
|
251
|
-
return pred(r) ? ctx.addChild(id, r, true) : false;
|
|
252
|
-
});
|
|
253
|
-
const satisfyD = (pred) => ((ctx) => {
|
|
254
|
-
if (ctx.done)
|
|
255
|
-
return false;
|
|
256
|
-
const state = ctx.state;
|
|
257
|
-
const reader = ctx.reader;
|
|
258
|
-
return pred(reader.read(state)) ? (reader.next(state), true) : false;
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
const always = (id = "always") => satisfy(() => true, id);
|
|
262
|
-
const alwaysD = () => satisfyD(() => true);
|
|
263
|
-
|
|
264
|
-
const not = (parser, fail = always()) => (ctx) => {
|
|
265
|
-
if (ctx.done)
|
|
266
|
-
return false;
|
|
267
|
-
ctx.start("");
|
|
268
|
-
const res = parser(ctx);
|
|
269
|
-
ctx.discard();
|
|
270
|
-
return res ? false : fail(ctx);
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
const repeat = (parser, min, max, id = "repeat") => (ctx) => {
|
|
274
|
-
if (ctx.done) {
|
|
275
|
-
return min < 1 ? ctx.addChild(id) : false;
|
|
276
|
-
}
|
|
277
|
-
ctx.start(id);
|
|
278
|
-
for (let i = 0; i < max; i++) {
|
|
279
|
-
if (!parser(ctx)) {
|
|
280
|
-
if (i < min) {
|
|
281
|
-
return ctx.discard();
|
|
282
|
-
}
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return ctx.end();
|
|
287
|
-
};
|
|
288
|
-
const zeroOrMore = (parser, id = "repeat0", max = Infinity) => repeat(parser, 0, max, id);
|
|
289
|
-
const oneOrMore = (parser, id = "repeat1", max = Infinity) => repeat(parser, 1, max, id);
|
|
290
|
-
const repeatD = (parser, min, max) => discard(repeat(parser, min, max));
|
|
291
|
-
const zeroOrMoreD = (parser, max = Infinity) => repeatD(parser, 0, max);
|
|
292
|
-
const oneOrMoreD = (parser, max = Infinity) => repeatD(parser, 1, max);
|
|
293
|
-
|
|
294
|
-
const seq = (parsers, id = "seq") => (ctx) => {
|
|
295
|
-
if (ctx.done)
|
|
296
|
-
return false;
|
|
297
|
-
ctx.start(id);
|
|
298
|
-
for (let i = 0, n = parsers.length; i < n; i++) {
|
|
299
|
-
if (!parsers[i](ctx)) {
|
|
300
|
-
return ctx.discard();
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return ctx.end();
|
|
304
|
-
};
|
|
305
|
-
const seqD = (parsers) => discard(seq(parsers));
|
|
306
|
-
|
|
307
|
-
const oneOfP = (opts) => checks.isSet(opts)
|
|
308
|
-
? (x) => opts.has(x)
|
|
309
|
-
: checks.isPlainObject(opts)
|
|
310
|
-
? (x) => opts[x]
|
|
311
|
-
: (x) => opts.indexOf(x) >= 0;
|
|
312
|
-
function oneOf(opts, id = "oneOf") {
|
|
313
|
-
return satisfy(oneOfP(opts), id);
|
|
314
|
-
}
|
|
315
|
-
function oneOfD(opts) {
|
|
316
|
-
return satisfyD(oneOfP(opts));
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const rangeP = (min, max) => (x) => x >= min && x <= max;
|
|
320
|
-
const utf16RangeP = (min, max) => (x) => {
|
|
321
|
-
const c = x.charCodeAt(0);
|
|
322
|
-
return c >= min && c <= max;
|
|
323
|
-
};
|
|
324
|
-
function range(min, max, id = "lit") {
|
|
325
|
-
return satisfy(rangeP(min, max), id);
|
|
326
|
-
}
|
|
327
|
-
function rangeD(min, max) {
|
|
328
|
-
return satisfyD(rangeP(min, max));
|
|
329
|
-
}
|
|
330
|
-
const utf16Range = (min, max, id = "utfLit") => satisfy(utf16RangeP(min, max), id);
|
|
331
|
-
const utf16RangeD = (min, max) => satisfyD(utf16RangeP(min, max));
|
|
332
|
-
|
|
333
|
-
const LOWER_CASE = range("a", "z");
|
|
334
|
-
const UPPER_CASE = range("A", "Z");
|
|
335
|
-
const ALPHA = oneOf(strings.ALPHA);
|
|
336
|
-
const ALPHA_NUM = oneOf(strings.ALPHA_NUM);
|
|
337
|
-
|
|
338
|
-
const xfJoin = (scope) => {
|
|
339
|
-
if (!scope || !scope.children)
|
|
340
|
-
return null;
|
|
341
|
-
const res = [];
|
|
342
|
-
for (let c of scope.children) {
|
|
343
|
-
xfJoin(c);
|
|
344
|
-
if (c.result)
|
|
345
|
-
res.push(c.result);
|
|
346
|
-
}
|
|
347
|
-
scope.result = res.join("");
|
|
348
|
-
scope.children = null;
|
|
349
|
-
return scope;
|
|
350
|
-
};
|
|
351
|
-
const join = (parser) => xform(parser, xfJoin);
|
|
352
|
-
|
|
353
|
-
const xfInt = (radix = 10) => (scope) => {
|
|
354
|
-
scope.result = parseInt(xfJoin(scope).result, radix);
|
|
355
|
-
return scope;
|
|
356
|
-
};
|
|
357
|
-
const xfFloat = (scope) => {
|
|
358
|
-
scope.result = parseFloat(xfJoin(scope).result);
|
|
359
|
-
return scope;
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
const BIT = oneOf("01");
|
|
363
|
-
const BINARY_UINT = xform(repeat(BIT, 1, 32, "uint"), xfInt(2));
|
|
364
|
-
|
|
365
|
-
const DIGIT = range("0", "9", "digit");
|
|
366
|
-
const DIGITS = oneOrMore(DIGIT);
|
|
367
|
-
|
|
368
|
-
const litP = (c) => (x) => x === c;
|
|
369
|
-
const lit = (c, id = "lit") => satisfy(litP(c), id);
|
|
370
|
-
const litD = (c) => satisfyD(litP(c));
|
|
371
|
-
|
|
372
|
-
const string = (str, id = "string") => (ctx) => {
|
|
373
|
-
if (ctx.done)
|
|
374
|
-
return false;
|
|
375
|
-
const scope = ctx.start(id);
|
|
376
|
-
const state = scope.state;
|
|
377
|
-
const reader = ctx.reader;
|
|
378
|
-
for (let i = 0, n = str.length; i < n; i++) {
|
|
379
|
-
if (state.done)
|
|
380
|
-
return false;
|
|
381
|
-
const r = reader.read(state);
|
|
382
|
-
if (r !== str[i]) {
|
|
383
|
-
return ctx.discard();
|
|
384
|
-
}
|
|
385
|
-
reader.next(state);
|
|
386
|
-
}
|
|
387
|
-
scope.result = str;
|
|
388
|
-
return ctx.end();
|
|
389
|
-
};
|
|
390
|
-
const stringD = (str) => (ctx) => {
|
|
391
|
-
if (ctx.done)
|
|
392
|
-
return false;
|
|
393
|
-
const state = Object.assign({}, ctx.state);
|
|
394
|
-
const reader = ctx.reader;
|
|
395
|
-
for (let i = 0, n = str.length; i < n; i++) {
|
|
396
|
-
if (state.done)
|
|
397
|
-
return false;
|
|
398
|
-
const r = reader.read(state);
|
|
399
|
-
if (r !== str[i]) {
|
|
400
|
-
return false;
|
|
401
|
-
}
|
|
402
|
-
reader.next(state);
|
|
403
|
-
}
|
|
404
|
-
ctx.state = state;
|
|
405
|
-
return true;
|
|
406
|
-
};
|
|
407
|
-
const stringOf = (pred, id = "string", reduce = (x) => x.join("")) => (ctx) => {
|
|
408
|
-
const state = Object.assign({}, ctx.state);
|
|
409
|
-
const reader = ctx.reader;
|
|
410
|
-
let acc = [];
|
|
411
|
-
while (!state.done) {
|
|
412
|
-
const r = reader.read(state);
|
|
413
|
-
if (!pred(r))
|
|
414
|
-
break;
|
|
415
|
-
acc.push(r);
|
|
416
|
-
reader.next(state);
|
|
417
|
-
}
|
|
418
|
-
return ctx.addChild(id, reduce(acc), state);
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
const HEX_DIGIT = oneOf(strings.HEX);
|
|
422
|
-
const HEX_DIGITS = oneOrMore(HEX_DIGIT);
|
|
423
|
-
const HEX_UINT = xform(repeat(HEX_DIGIT, 1, 8, "uint"), xfInt(16));
|
|
424
|
-
|
|
425
|
-
const ESC = xform(seq([litD("\\"), always()], "esc"), ($) => {
|
|
426
|
-
const id = $.children[0].result;
|
|
427
|
-
const resolved = strings.ESCAPES[id];
|
|
428
|
-
$.result = resolved !== undefined ? resolved : `\\${id}`;
|
|
429
|
-
$.children = null;
|
|
430
|
-
return $;
|
|
431
|
-
});
|
|
432
|
-
const UNICODE = xform(seq([stringD("\\u"), repeat(HEX_DIGIT, 4, 4)], "unicode"), ($, ctx) => (($.result = String.fromCharCode(xfInt(16)($, ctx).result)), $));
|
|
433
|
-
|
|
434
|
-
const comp = (...xs) => {
|
|
435
|
-
const [a, b, c, d] = xs;
|
|
436
|
-
switch (xs.length) {
|
|
437
|
-
case 0:
|
|
438
|
-
return (x) => x;
|
|
439
|
-
case 1:
|
|
440
|
-
return a;
|
|
441
|
-
case 2:
|
|
442
|
-
return (scope, ctx, user) => b(a(scope, ctx, user), ctx, user);
|
|
443
|
-
case 3:
|
|
444
|
-
return (scope, ctx, user) => c(b(a(scope, ctx, user), ctx, user), ctx, user);
|
|
445
|
-
case 4:
|
|
446
|
-
return (scope, ctx, user) => d(c(b(a(scope, ctx, user), ctx, user), ctx, user), ctx, user);
|
|
447
|
-
default:
|
|
448
|
-
return (scope, ctx, user) => xs.reduce((scope, x) => x(scope, ctx, user), scope);
|
|
449
|
-
}
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
const xfID = (id) => (scope) => ((scope.id = id), scope);
|
|
453
|
-
const withID = (id, parser) => xform(parser, xfID(id));
|
|
454
|
-
|
|
455
|
-
const SIGN = maybe(oneOf("-+"));
|
|
456
|
-
const INT = xform(seq([SIGN, DIGITS], "int"), xfInt());
|
|
457
|
-
const UINT = xform(DIGITS, comp(xfID("uint"), xfInt()));
|
|
458
|
-
const EXP = maybe(seq([maybe(oneOf("eE")), SIGN, DIGITS]));
|
|
459
|
-
const DOT = lit(".");
|
|
460
|
-
const FRACT0 = maybe(seq([DOT, zeroOrMore(DIGIT)]));
|
|
461
|
-
const FRACT1 = seq([DOT, DIGITS]);
|
|
462
|
-
const _REAL = seq([SIGN, alt([FRACT1, seq([DIGITS, FRACT0])]), EXP], "real");
|
|
463
|
-
const REAL = join(_REAL);
|
|
464
|
-
const FLOAT = xform(_REAL, xfFloat);
|
|
465
|
-
|
|
466
|
-
const noneOfP = (opts) => checks.isSet(opts)
|
|
467
|
-
? (x) => !opts.has(x)
|
|
468
|
-
: checks.isPlainObject(opts)
|
|
469
|
-
? (x) => !opts[x]
|
|
470
|
-
: (x) => opts.indexOf(x) < 0;
|
|
471
|
-
function noneOf(opts, id = "noneOf") {
|
|
472
|
-
return satisfy(noneOfP(opts), id);
|
|
473
|
-
}
|
|
474
|
-
function noneOfD(opts) {
|
|
475
|
-
return satisfyD(noneOfP(opts));
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const quote = litD('"');
|
|
479
|
-
const STRING = join(seq([quote, zeroOrMore(alt([UNICODE, ESC, noneOf('"')])), quote], "string"));
|
|
480
|
-
|
|
481
|
-
const WS = oneOfD(strings.WS);
|
|
482
|
-
const SPACE = oneOfD(" \t");
|
|
483
|
-
const NL = oneOf("\n\r");
|
|
484
|
-
const DNL = oneOfD("\n\r");
|
|
485
|
-
const WS0 = zeroOrMoreD(WS);
|
|
486
|
-
const WS1 = oneOrMoreD(WS);
|
|
487
|
-
const SPACES0 = zeroOrMoreD(SPACE);
|
|
488
|
-
const SPACES = oneOrMoreD(SPACE);
|
|
489
|
-
|
|
490
|
-
const anchor = (fn) => (ctx) => {
|
|
491
|
-
const state = ctx.state;
|
|
492
|
-
return fn(state.last, state.done ? null : ctx.reader.read(state));
|
|
493
|
-
};
|
|
494
|
-
const inputStart = (ctx) => ctx.state.last == null;
|
|
495
|
-
const inputEnd = (ctx) => ctx.state.done || ctx.reader.read(ctx.state) === undefined;
|
|
496
|
-
const lineStart = (ctx) => {
|
|
497
|
-
const l = ctx.state.last;
|
|
498
|
-
return l == null || l === "\n" || l === "\r";
|
|
499
|
-
};
|
|
500
|
-
const lineEnd = (ctx) => {
|
|
501
|
-
const state = ctx.state;
|
|
502
|
-
let c;
|
|
503
|
-
return state.done || (c = ctx.reader.read(state)) === "\n" || c === "\r";
|
|
504
|
-
};
|
|
505
|
-
const wordBoundaryP = (prev, next) => {
|
|
506
|
-
return prev
|
|
507
|
-
? next
|
|
508
|
-
? strings.ALPHA_NUM[prev] && !strings.ALPHA_NUM[next]
|
|
509
|
-
: strings.ALPHA_NUM[prev]
|
|
510
|
-
: next
|
|
511
|
-
? strings.ALPHA_NUM[next]
|
|
512
|
-
: false;
|
|
513
|
-
};
|
|
514
|
-
const wordBoundary = anchor(wordBoundaryP);
|
|
515
|
-
|
|
516
|
-
const xfCollect = (scope) => {
|
|
517
|
-
scope.result = scope.children.map((c) => c.result);
|
|
518
|
-
scope.children = null;
|
|
519
|
-
return scope;
|
|
520
|
-
};
|
|
521
|
-
const collect = (parser) => xform(parser, xfCollect);
|
|
522
|
-
|
|
523
|
-
const xfCount = (scope) => {
|
|
524
|
-
scope.result = scope.children ? scope.children.length : 0;
|
|
525
|
-
scope.children = null;
|
|
526
|
-
return scope;
|
|
527
|
-
};
|
|
528
|
-
const count = (parser) => xform(parser, xfCount);
|
|
529
|
-
|
|
530
|
-
const xfHoist = (scope) => {
|
|
531
|
-
Object.assign(scope, scope.children[0]);
|
|
532
|
-
return scope;
|
|
533
|
-
};
|
|
534
|
-
const xfHoistResult = (scope) => {
|
|
535
|
-
scope.result = scope.children[0].result;
|
|
536
|
-
scope.children = null;
|
|
537
|
-
return scope;
|
|
538
|
-
};
|
|
539
|
-
const hoist = (parser) => xform(parser, xfHoist);
|
|
540
|
-
const hoistResult = (parser) => xform(parser, xfHoistResult);
|
|
541
|
-
|
|
542
|
-
const xfNest = (parser) => (scope, ctx) => {
|
|
543
|
-
if (!scope)
|
|
544
|
-
return;
|
|
545
|
-
const src = scope.result || xfJoin(Object.assign({}, scope)).result;
|
|
546
|
-
const inner = defContext(src, ctx.opts);
|
|
547
|
-
const state = scope.state;
|
|
548
|
-
if (state) {
|
|
549
|
-
const istate = inner.scope.state;
|
|
550
|
-
istate.l = state.l;
|
|
551
|
-
istate.c = state.c;
|
|
552
|
-
}
|
|
553
|
-
if (parser(inner)) {
|
|
554
|
-
scope.result = null;
|
|
555
|
-
scope.children = inner.children;
|
|
556
|
-
}
|
|
557
|
-
return scope;
|
|
558
|
-
};
|
|
559
|
-
const nest = (outer, inner) => xform(outer, xfNest(inner));
|
|
560
|
-
|
|
561
|
-
const xfPrint = (fn = console.log) => {
|
|
562
|
-
const $print = (scope, _, level = 0) => {
|
|
563
|
-
if (!scope)
|
|
564
|
-
return;
|
|
565
|
-
const prefix = indent(level);
|
|
566
|
-
const state = scope.state;
|
|
567
|
-
const info = state ? ` (${state.l}:${state.c})` : "";
|
|
568
|
-
fn(`${prefix}${scope.id}${info}: ${JSON.stringify(scope.result)}`);
|
|
569
|
-
if (scope.children) {
|
|
570
|
-
for (let c of scope.children) {
|
|
571
|
-
$print(c, _, level + 1);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
return scope;
|
|
575
|
-
};
|
|
576
|
-
return $print;
|
|
577
|
-
};
|
|
578
|
-
const print = (parser, fn) => xform(parser, xfPrint(fn));
|
|
579
|
-
|
|
580
|
-
const xfReplace = (result) => (scope) => {
|
|
581
|
-
scope.result = result;
|
|
582
|
-
scope.children = null;
|
|
583
|
-
return scope;
|
|
584
|
-
};
|
|
585
|
-
const replace = (parser, result) => xform(parser, xfReplace(result));
|
|
586
|
-
|
|
587
|
-
const xfTrim = (scope) => {
|
|
588
|
-
scope.result = scope.result.trim();
|
|
589
|
-
return scope;
|
|
590
|
-
};
|
|
591
|
-
const trim = (parser) => xform(parser, xfTrim);
|
|
592
|
-
|
|
593
|
-
const apos = litD("'");
|
|
594
|
-
const dash = litD("-");
|
|
595
|
-
const REPEAT = maybe(alt([
|
|
596
|
-
oneOf("?*+", "repeat"),
|
|
597
|
-
collect(seq([litD("{"), UINT, maybe(lit(",")), maybe(UINT), litD("}")], "repeatN")),
|
|
598
|
-
]));
|
|
599
|
-
const DISCARD = maybe(lit("!"), undefined, "discard");
|
|
600
|
-
const CHAR_OR_ESC = alt([UNICODE, ESC, always()]);
|
|
601
|
-
const CHAR_RANGE = seq([CHAR_OR_ESC, dash, CHAR_OR_ESC], "charRange");
|
|
602
|
-
const CHAR_SEL = seq([
|
|
603
|
-
litD("["),
|
|
604
|
-
maybe(lit("^", "invert")),
|
|
605
|
-
oneOrMore(alt([CHAR_RANGE, UNICODE, noneOf("]", "char")]), "choice"),
|
|
606
|
-
litD("]"),
|
|
607
|
-
], "charSel");
|
|
608
|
-
const ANY = lit(".", "any");
|
|
609
|
-
const LIT = hoistResult(seq([apos, CHAR_OR_ESC, apos], "char"));
|
|
610
|
-
const SYM = join(oneOrMore(alt([ALPHA_NUM, oneOf(".-_$")]), "sym"));
|
|
611
|
-
const RULE_REF = seq([litD("<"), SYM, litD(">")], "ref");
|
|
612
|
-
const TERM_BODY = alt([RULE_REF, ANY, LIT, STRING, CHAR_SEL]);
|
|
613
|
-
const LOOK_AHEAD = maybe(seq([
|
|
614
|
-
stringD("(?"),
|
|
615
|
-
oneOf("-+"),
|
|
616
|
-
seq([TERM_BODY, REPEAT, DISCARD], "lhterm"),
|
|
617
|
-
litD(")"),
|
|
618
|
-
], "lhspec"), undefined, "lhnone");
|
|
619
|
-
const TERM = seq([TERM_BODY, REPEAT, DISCARD, LOOK_AHEAD], "term");
|
|
620
|
-
const ALT = seq([
|
|
621
|
-
litD("("),
|
|
622
|
-
WS0,
|
|
623
|
-
TERM,
|
|
624
|
-
zeroOrMore(seq([WS0, litD("|"), WS0, TERM])),
|
|
625
|
-
WS0,
|
|
626
|
-
litD(")"),
|
|
627
|
-
REPEAT,
|
|
628
|
-
DISCARD,
|
|
629
|
-
LOOK_AHEAD,
|
|
630
|
-
], "alt");
|
|
631
|
-
const RULE_XF = hoist(seq([stringD("=>"), WS1, alt([SYM, RULE_REF, STRING]), WS1], "xform"));
|
|
632
|
-
const RULE = seq([
|
|
633
|
-
WS0,
|
|
634
|
-
SYM,
|
|
635
|
-
WS0,
|
|
636
|
-
litD(":"),
|
|
637
|
-
oneOrMore(alt([TERM, ALT, WS1]), "body"),
|
|
638
|
-
maybe(RULE_XF),
|
|
639
|
-
litD(";"),
|
|
640
|
-
WS0,
|
|
641
|
-
], "rule");
|
|
642
|
-
const COMMENT = seqD([WS0, litD("#"), lookahead(always(), DNL)]);
|
|
643
|
-
const GRAMMAR = zeroOrMore(alt([RULE, COMMENT]), "rules");
|
|
644
|
-
const first = ($) => $.children[0];
|
|
645
|
-
const nth = ($, n) => $.children[n];
|
|
646
|
-
const compile = defmulti.defmulti((scope) => scope.id, {
|
|
647
|
-
unicode: ["char"],
|
|
648
|
-
});
|
|
649
|
-
compile.addAll({
|
|
650
|
-
root: ($, lang, opts, flags) => {
|
|
651
|
-
const rules = first($).children;
|
|
652
|
-
rules.reduce((acc, r) => ((acc[first(r).result] = dynamic()), acc), lang.rules);
|
|
653
|
-
for (let r of rules) {
|
|
654
|
-
const id = first(r).result;
|
|
655
|
-
lang.rules[id].set(compile(r, lang, opts, flags));
|
|
656
|
-
}
|
|
657
|
-
return lang;
|
|
658
|
-
},
|
|
659
|
-
rule: ($, lang, opts, flags) => {
|
|
660
|
-
const [id, body, xf] = $.children;
|
|
661
|
-
opts.debug && console.log(`rule: ${id.result}`, xf);
|
|
662
|
-
const acc = [];
|
|
663
|
-
for (let b of body.children) {
|
|
664
|
-
const c = compile(b, lang, opts, flags);
|
|
665
|
-
c && acc.push(c);
|
|
666
|
-
}
|
|
667
|
-
let parser = acc.length > 1 ? seq(acc, id.result) : withID(id.result, acc[0]);
|
|
668
|
-
if (xf.id === "sym") {
|
|
669
|
-
const $xf = lang.env[xf.result];
|
|
670
|
-
if (!$xf)
|
|
671
|
-
errors.illegalArgs(`missing xform: ${xf.result}`);
|
|
672
|
-
parser = xform(parser, $xf);
|
|
673
|
-
}
|
|
674
|
-
else if (xf.id === "ref") {
|
|
675
|
-
const $id = first(xf).result;
|
|
676
|
-
if ($id === id)
|
|
677
|
-
errors.illegalArgs(`self-referential: ${$id}`);
|
|
678
|
-
const $xf = lang.rules[$id];
|
|
679
|
-
if (!$xf)
|
|
680
|
-
errors.illegalArgs(`missing xform rule: ${$id}`);
|
|
681
|
-
parser = nest(parser, $xf);
|
|
682
|
-
}
|
|
683
|
-
else if (xf.id === "string") {
|
|
684
|
-
parser = xform(parser, xfReplace(xf.result));
|
|
685
|
-
}
|
|
686
|
-
return parser;
|
|
687
|
-
},
|
|
688
|
-
ref: ($, lang, opts, flags) => {
|
|
689
|
-
const id = first($).result;
|
|
690
|
-
opts.debug && console.log(`ref: ${id}`, flags);
|
|
691
|
-
const ref = lang.rules[id];
|
|
692
|
-
return ref
|
|
693
|
-
? flags.discard
|
|
694
|
-
? discard(ref)
|
|
695
|
-
: ref
|
|
696
|
-
: errors.illegalArgs(`invalid rule ref: ${id}`);
|
|
697
|
-
},
|
|
698
|
-
term: ($, lang, opts, flags) => {
|
|
699
|
-
const [term, repeat, discard, lookahead] = $.children;
|
|
700
|
-
opts.debug && console.log(`term: ${term.id}`, flags);
|
|
701
|
-
return compileRDL((discard) => compile(term, lang, opts, Object.assign(Object.assign({}, flags), { discard })), repeat, discard, lookahead, lang, opts);
|
|
702
|
-
},
|
|
703
|
-
lhterm: ($, lang, opts, flags) => {
|
|
704
|
-
const [term, repeat, discard] = $.children;
|
|
705
|
-
opts.debug && console.log(`lhterm: ${term.id}`);
|
|
706
|
-
return compileRD((discard) => compile(term, lang, opts, Object.assign(Object.assign({}, flags), { discard })), repeat, discard, opts);
|
|
707
|
-
},
|
|
708
|
-
alt: ($, lang, opts, flags) => {
|
|
709
|
-
opts.debug && console.log(`alt: ${$.id}`, flags);
|
|
710
|
-
const [term0, { children: terms }, repeat, disc, lookahead,] = $.children;
|
|
711
|
-
const acc = [compile(term0, lang, opts, flags)];
|
|
712
|
-
if (terms) {
|
|
713
|
-
for (let c of terms) {
|
|
714
|
-
acc.push(compile(first(c), lang, opts, flags));
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
return compileRDL((optimize) => optimize || flags.discard
|
|
718
|
-
? acc.length > 1
|
|
719
|
-
? altD(acc)
|
|
720
|
-
: discard(acc[0])
|
|
721
|
-
: acc.length > 1
|
|
722
|
-
? alt(acc)
|
|
723
|
-
: acc[0], repeat, disc, lookahead, lang, opts);
|
|
724
|
-
},
|
|
725
|
-
any: (_, __, opts, flags) => {
|
|
726
|
-
opts.debug && console.log(`any`, flags);
|
|
727
|
-
return flags.discard ? alwaysD() : always("any");
|
|
728
|
-
},
|
|
729
|
-
char: ($, _, opts, flags) => {
|
|
730
|
-
const x = $.result;
|
|
731
|
-
opts.debug && console.log(`lit: '${x}'`, flags);
|
|
732
|
-
return (flags.discard ? litD : lit)(x);
|
|
733
|
-
},
|
|
734
|
-
string: ($, _, opts, flags) => {
|
|
735
|
-
const x = $.result;
|
|
736
|
-
opts.debug && console.log(`string: "${x}"`, flags);
|
|
737
|
-
return (flags.discard ? stringD : string)(x);
|
|
738
|
-
},
|
|
739
|
-
charRange: ($, _, opts, flags) => {
|
|
740
|
-
const [a, b] = $.children;
|
|
741
|
-
opts.debug && console.log(`range: ${a.result} - ${b.result}`, flags);
|
|
742
|
-
return (flags.discard ? rangeD : range)(a.result, b.result);
|
|
743
|
-
},
|
|
744
|
-
charSel: ($, lang, opts, flags) => {
|
|
745
|
-
opts.debug && console.log("charSel", flags);
|
|
746
|
-
const choices = nth($, 1).children.map((c) => compile(c, lang, opts, flags));
|
|
747
|
-
const invert = first($).result;
|
|
748
|
-
const parser = choices.length > 1 ? alt(choices) : choices[0];
|
|
749
|
-
opts.debug && console.log(`invert: ${invert}`);
|
|
750
|
-
return invert
|
|
751
|
-
? not(parser, flags.discard ? alwaysD() : always())
|
|
752
|
-
: parser;
|
|
753
|
-
},
|
|
754
|
-
});
|
|
755
|
-
compile.add(defmulti.DEFAULT, ($) => errors.unsupported(`unknown op: ${$.id}`));
|
|
756
|
-
const compileRepeat = (parser, rspec, opts) => {
|
|
757
|
-
opts.debug && console.log(`repeat: ${rspec.id}`);
|
|
758
|
-
if (rspec.id === "repeat") {
|
|
759
|
-
switch (rspec.result) {
|
|
760
|
-
case "?":
|
|
761
|
-
return maybe(parser);
|
|
762
|
-
case "*":
|
|
763
|
-
return zeroOrMore(parser);
|
|
764
|
-
case "+":
|
|
765
|
-
return oneOrMore(parser);
|
|
766
|
-
default:
|
|
767
|
-
return parser;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
else if (rspec.id === "repeatN") {
|
|
771
|
-
const [n, sep, m] = rspec.result;
|
|
772
|
-
return repeat(parser, n, sep ? m || Infinity : m || n);
|
|
773
|
-
}
|
|
774
|
-
return parser;
|
|
775
|
-
};
|
|
776
|
-
const compileDiscard = (parser, dspec, opts) => {
|
|
777
|
-
opts.debug && console.log(`discard:`, dspec.result);
|
|
778
|
-
return dspec.result === "!" ? discard(parser) : parser;
|
|
779
|
-
};
|
|
780
|
-
const compileLookahead = (parser, spec, lang, opts) => {
|
|
781
|
-
opts.debug && console.log(`lookahead:`, spec.id);
|
|
782
|
-
return spec.id === "lhspec"
|
|
783
|
-
? lookahead(parser, compile(nth(spec, 1), lang, opts, {}), first(spec).result === "+")
|
|
784
|
-
: parser;
|
|
785
|
-
};
|
|
786
|
-
const compileRD = (parser, rspec, dspec, opts) => dspec.result != null && rspec.result == null
|
|
787
|
-
? parser(true)
|
|
788
|
-
: compileDiscard(compileRepeat(parser(false), rspec, opts), dspec, opts);
|
|
789
|
-
const compileRDL = (parser, rspec, dspec, lhspec, lang, opts) => compileLookahead(compileRD(parser, rspec, dspec, opts), lhspec, lang, opts);
|
|
790
|
-
const defGrammar = (rules, env, opts) => {
|
|
791
|
-
opts = Object.assign({ debug: false, optimize: true }, opts);
|
|
792
|
-
env = Object.assign({ binary: xfInt(2), collect: xfCollect, count: xfCount, discard: xfDiscard, float: xfFloat, hex: xfInt(16), hoist: xfHoist, hoistR: xfHoistResult, int: xfInt(10), join: xfJoin, print: xfPrint(), trim: xfTrim }, env);
|
|
793
|
-
const ctx = defContext(rules);
|
|
794
|
-
const result = (opts.debug ? print(GRAMMAR) : GRAMMAR)(ctx);
|
|
795
|
-
if (result) {
|
|
796
|
-
return compile(ctx.root, {
|
|
797
|
-
env,
|
|
798
|
-
grammar: ctx,
|
|
799
|
-
rules: {
|
|
800
|
-
ALPHA_NUM,
|
|
801
|
-
ALPHA,
|
|
802
|
-
BIT,
|
|
803
|
-
DIGIT,
|
|
804
|
-
DNL,
|
|
805
|
-
END: inputEnd,
|
|
806
|
-
ESC,
|
|
807
|
-
FLOAT,
|
|
808
|
-
HEX_DIGIT,
|
|
809
|
-
INT,
|
|
810
|
-
LEND: lineEnd,
|
|
811
|
-
LSTART: lineStart,
|
|
812
|
-
NL,
|
|
813
|
-
START: inputStart,
|
|
814
|
-
STRING,
|
|
815
|
-
UNICODE,
|
|
816
|
-
WB: wordBoundary,
|
|
817
|
-
WS,
|
|
818
|
-
WS0,
|
|
819
|
-
WS1,
|
|
820
|
-
},
|
|
821
|
-
}, opts, {});
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
const startsWith = (parser) => seq([inputStart, parser]);
|
|
826
|
-
const endsWith = (parser) => seq([parser, inputEnd]);
|
|
827
|
-
const entireLine = (parser) => seq([lineStart, parser, lineEnd]);
|
|
828
|
-
const entirely = (parser) => seq([inputStart, parser, inputEnd]);
|
|
829
|
-
|
|
830
|
-
const check = (parser, pred, msg = "check failed") => xform(parser, (scope, ctx) => {
|
|
831
|
-
if (!pred(scope))
|
|
832
|
-
parseError(ctx, msg);
|
|
833
|
-
return scope;
|
|
834
|
-
});
|
|
835
|
-
|
|
836
|
-
const expect = (parser, err) => (ctx) => parser(ctx) || parseError(ctx, err);
|
|
837
|
-
|
|
838
|
-
const wrap = (parser, pre, post = pre) => hoist(seq([litD(pre), parser, litD(post)]));
|
|
839
|
-
|
|
840
|
-
const fail = (msg) => (ctx) => parseError(ctx, msg);
|
|
841
|
-
|
|
842
|
-
const skipWhile = (pred) => (ctx) => {
|
|
843
|
-
const state = Object.assign({}, ctx.state);
|
|
844
|
-
const reader = ctx.reader;
|
|
845
|
-
while (!state.done) {
|
|
846
|
-
if (!pred(reader.read(state)))
|
|
847
|
-
break;
|
|
848
|
-
reader.next(state);
|
|
849
|
-
}
|
|
850
|
-
ctx.state = state;
|
|
851
|
-
return true;
|
|
852
|
-
};
|
|
853
|
-
|
|
854
|
-
exports.ALPHA = ALPHA;
|
|
855
|
-
exports.ALPHA_NUM = ALPHA_NUM;
|
|
856
|
-
exports.BINARY_UINT = BINARY_UINT;
|
|
857
|
-
exports.BIT = BIT;
|
|
858
|
-
exports.DIGIT = DIGIT;
|
|
859
|
-
exports.DIGITS = DIGITS;
|
|
860
|
-
exports.DNL = DNL;
|
|
861
|
-
exports.ESC = ESC;
|
|
862
|
-
exports.FLOAT = FLOAT;
|
|
863
|
-
exports.GRAMMAR = GRAMMAR;
|
|
864
|
-
exports.HEX_DIGIT = HEX_DIGIT;
|
|
865
|
-
exports.HEX_DIGITS = HEX_DIGITS;
|
|
866
|
-
exports.HEX_UINT = HEX_UINT;
|
|
867
|
-
exports.INT = INT;
|
|
868
|
-
exports.LOWER_CASE = LOWER_CASE;
|
|
869
|
-
exports.NL = NL;
|
|
870
|
-
exports.ParseContext = ParseContext;
|
|
871
|
-
exports.REAL = REAL;
|
|
872
|
-
exports.SIGN = SIGN;
|
|
873
|
-
exports.SPACE = SPACE;
|
|
874
|
-
exports.SPACES = SPACES;
|
|
875
|
-
exports.SPACES0 = SPACES0;
|
|
876
|
-
exports.STRING = STRING;
|
|
877
|
-
exports.UINT = UINT;
|
|
878
|
-
exports.UNICODE = UNICODE;
|
|
879
|
-
exports.UPPER_CASE = UPPER_CASE;
|
|
880
|
-
exports.WS = WS;
|
|
881
|
-
exports.WS0 = WS0;
|
|
882
|
-
exports.WS1 = WS1;
|
|
883
|
-
exports.alt = alt;
|
|
884
|
-
exports.altD = altD;
|
|
885
|
-
exports.always = always;
|
|
886
|
-
exports.alwaysD = alwaysD;
|
|
887
|
-
exports.anchor = anchor;
|
|
888
|
-
exports.check = check;
|
|
889
|
-
exports.collect = collect;
|
|
890
|
-
exports.comp = comp;
|
|
891
|
-
exports.count = count;
|
|
892
|
-
exports.defArrayReader = defArrayReader;
|
|
893
|
-
exports.defContext = defContext;
|
|
894
|
-
exports.defGrammar = defGrammar;
|
|
895
|
-
exports.defStringReader = defStringReader;
|
|
896
|
-
exports.discard = discard;
|
|
897
|
-
exports.dynamic = dynamic;
|
|
898
|
-
exports.endsWith = endsWith;
|
|
899
|
-
exports.entireLine = entireLine;
|
|
900
|
-
exports.entirely = entirely;
|
|
901
|
-
exports.expect = expect;
|
|
902
|
-
exports.fail = fail;
|
|
903
|
-
exports.hoist = hoist;
|
|
904
|
-
exports.hoistResult = hoistResult;
|
|
905
|
-
exports.inputEnd = inputEnd;
|
|
906
|
-
exports.inputStart = inputStart;
|
|
907
|
-
exports.join = join;
|
|
908
|
-
exports.lineEnd = lineEnd;
|
|
909
|
-
exports.lineStart = lineStart;
|
|
910
|
-
exports.lit = lit;
|
|
911
|
-
exports.litD = litD;
|
|
912
|
-
exports.litP = litP;
|
|
913
|
-
exports.lookahead = lookahead;
|
|
914
|
-
exports.maybe = maybe;
|
|
915
|
-
exports.nest = nest;
|
|
916
|
-
exports.noneOf = noneOf;
|
|
917
|
-
exports.noneOfD = noneOfD;
|
|
918
|
-
exports.noneOfP = noneOfP;
|
|
919
|
-
exports.not = not;
|
|
920
|
-
exports.oneOf = oneOf;
|
|
921
|
-
exports.oneOfD = oneOfD;
|
|
922
|
-
exports.oneOfP = oneOfP;
|
|
923
|
-
exports.oneOrMore = oneOrMore;
|
|
924
|
-
exports.oneOrMoreD = oneOrMoreD;
|
|
925
|
-
exports.parseError = parseError;
|
|
926
|
-
exports.pass = pass;
|
|
927
|
-
exports.passD = passD;
|
|
928
|
-
exports.print = print;
|
|
929
|
-
exports.range = range;
|
|
930
|
-
exports.rangeD = rangeD;
|
|
931
|
-
exports.rangeP = rangeP;
|
|
932
|
-
exports.repeat = repeat;
|
|
933
|
-
exports.repeatD = repeatD;
|
|
934
|
-
exports.replace = replace;
|
|
935
|
-
exports.satisfy = satisfy;
|
|
936
|
-
exports.satisfyD = satisfyD;
|
|
937
|
-
exports.seq = seq;
|
|
938
|
-
exports.seqD = seqD;
|
|
939
|
-
exports.skipWhile = skipWhile;
|
|
940
|
-
exports.startsWith = startsWith;
|
|
941
|
-
exports.string = string;
|
|
942
|
-
exports.stringD = stringD;
|
|
943
|
-
exports.stringOf = stringOf;
|
|
944
|
-
exports.trim = trim;
|
|
945
|
-
exports.utf16Range = utf16Range;
|
|
946
|
-
exports.utf16RangeD = utf16RangeD;
|
|
947
|
-
exports.utf16RangeP = utf16RangeP;
|
|
948
|
-
exports.withID = withID;
|
|
949
|
-
exports.wordBoundary = wordBoundary;
|
|
950
|
-
exports.wordBoundaryP = wordBoundaryP;
|
|
951
|
-
exports.wrap = wrap;
|
|
952
|
-
exports.xfCollect = xfCollect;
|
|
953
|
-
exports.xfCount = xfCount;
|
|
954
|
-
exports.xfDiscard = xfDiscard;
|
|
955
|
-
exports.xfFloat = xfFloat;
|
|
956
|
-
exports.xfHoist = xfHoist;
|
|
957
|
-
exports.xfHoistResult = xfHoistResult;
|
|
958
|
-
exports.xfID = xfID;
|
|
959
|
-
exports.xfInt = xfInt;
|
|
960
|
-
exports.xfJoin = xfJoin;
|
|
961
|
-
exports.xfNest = xfNest;
|
|
962
|
-
exports.xfPrint = xfPrint;
|
|
963
|
-
exports.xfReplace = xfReplace;
|
|
964
|
-
exports.xfTrim = xfTrim;
|
|
965
|
-
exports.xform = xform;
|
|
966
|
-
exports.zeroOrMore = zeroOrMore;
|
|
967
|
-
exports.zeroOrMoreD = zeroOrMoreD;
|