parser-combinators 1.2.5 → 1.2.6
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/parsers/any.js +1 -0
- package/dist/parsers/anyString.js +11 -16
- package/dist/parsers/index.d.ts +4 -0
- package/dist/parsers/index.js +4 -0
- package/dist/parsers/many.d.ts +0 -12
- package/dist/parsers/many.js +1 -139
- package/dist/parsers/oneOrMany.d.ts +5 -0
- package/dist/parsers/oneOrMany.js +66 -0
- package/dist/parsers/oneOrManyRed.d.ts +5 -0
- package/dist/parsers/oneOrManyRed.js +44 -0
- package/dist/parsers/readymade.d.ts +7 -0
- package/dist/parsers/readymade.js +46 -0
- package/dist/parsers/regex.js +1 -1
- package/dist/parsers/utilities.js +2 -1
- package/dist/parsers/zeroOrMany.d.ts +5 -0
- package/dist/parsers/zeroOrMany.js +64 -0
- package/dist/types.d.ts +1 -0
- package/dist-esm/parsers/any.js +1 -0
- package/dist-esm/parsers/anyString.js +11 -16
- package/dist-esm/parsers/index.d.ts +4 -0
- package/dist-esm/parsers/index.js +4 -0
- package/dist-esm/parsers/many.d.ts +0 -12
- package/dist-esm/parsers/many.js +1 -136
- package/dist-esm/parsers/oneOrMany.d.ts +5 -0
- package/dist-esm/parsers/oneOrMany.js +63 -0
- package/dist-esm/parsers/oneOrManyRed.d.ts +5 -0
- package/dist-esm/parsers/oneOrManyRed.js +41 -0
- package/dist-esm/parsers/readymade.d.ts +7 -0
- package/dist-esm/parsers/readymade.js +43 -0
- package/dist-esm/parsers/regex.js +1 -1
- package/dist-esm/parsers/utilities.js +2 -1
- package/dist-esm/parsers/zeroOrMany.d.ts +5 -0
- package/dist-esm/parsers/zeroOrMany.js +61 -0
- package/dist-esm/types.d.ts +1 -0
- package/package.json +61 -61
package/dist/parsers/any.js
CHANGED
|
@@ -23,6 +23,7 @@ function any(...parsers) {
|
|
|
23
23
|
const res = parser(ctx);
|
|
24
24
|
if ((0, types_1.isFailure)(res)) {
|
|
25
25
|
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
26
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
26
27
|
if (surelyIndex >= 0) {
|
|
27
28
|
return (0, types_1.failure)(res.ctx, res.expected, ['any', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
28
29
|
}
|
|
@@ -26,14 +26,7 @@ function createSearchTree(matches) {
|
|
|
26
26
|
}
|
|
27
27
|
function addMatchToTree(node, match, idIndex, charIndex = 0) {
|
|
28
28
|
if (charIndex >= match[0].length) {
|
|
29
|
-
|
|
30
|
-
if (node.matchIndex > idIndex) {
|
|
31
|
-
node.matchIndex = idIndex;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
node.matchIndex = idIndex;
|
|
36
|
-
}
|
|
29
|
+
node.matchIndex ??= idIndex;
|
|
37
30
|
}
|
|
38
31
|
else {
|
|
39
32
|
const char = match[0][charIndex];
|
|
@@ -51,15 +44,17 @@ function addMatchToTree(node, match, idIndex, charIndex = 0) {
|
|
|
51
44
|
}
|
|
52
45
|
}
|
|
53
46
|
else {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
node.set(char, node.get(char) ?? newNode);
|
|
48
|
+
if (lowercase !== uppercase) {
|
|
49
|
+
const lower = node.get(lowercase);
|
|
50
|
+
const upper = node.get(uppercase);
|
|
51
|
+
if (lower != null && lower === upper) {
|
|
52
|
+
const copy = new Map(lower.entries());
|
|
53
|
+
copy.matchIndex = lower.matchIndex;
|
|
54
|
+
node.set(uppercase, copy);
|
|
55
|
+
}
|
|
61
56
|
}
|
|
62
|
-
addMatchToTree(
|
|
57
|
+
addMatchToTree(node.get(char), match, idIndex, charIndex + 1);
|
|
63
58
|
}
|
|
64
59
|
}
|
|
65
60
|
}
|
package/dist/parsers/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export * from './any';
|
|
|
2
2
|
export * from './between';
|
|
3
3
|
export * from './exhaust';
|
|
4
4
|
export * from './many';
|
|
5
|
+
export * from './zeroOrMany';
|
|
6
|
+
export * from './oneOrMany';
|
|
7
|
+
export * from './oneOrManyRed';
|
|
5
8
|
export * from './map';
|
|
6
9
|
export * from './opt';
|
|
7
10
|
export * from './regex';
|
|
@@ -10,3 +13,4 @@ export { str, stri } from './str';
|
|
|
10
13
|
export * from './recovery';
|
|
11
14
|
export * from './utilities';
|
|
12
15
|
export * from './values';
|
|
16
|
+
export * from './readymade';
|
package/dist/parsers/index.js
CHANGED
|
@@ -19,6 +19,9 @@ __exportStar(require("./any"), exports);
|
|
|
19
19
|
__exportStar(require("./between"), exports);
|
|
20
20
|
__exportStar(require("./exhaust"), exports);
|
|
21
21
|
__exportStar(require("./many"), exports);
|
|
22
|
+
__exportStar(require("./zeroOrMany"), exports);
|
|
23
|
+
__exportStar(require("./oneOrMany"), exports);
|
|
24
|
+
__exportStar(require("./oneOrManyRed"), exports);
|
|
22
25
|
__exportStar(require("./map"), exports);
|
|
23
26
|
__exportStar(require("./opt"), exports);
|
|
24
27
|
__exportStar(require("./regex"), exports);
|
|
@@ -29,3 +32,4 @@ Object.defineProperty(exports, "stri", { enumerable: true, get: function () { re
|
|
|
29
32
|
__exportStar(require("./recovery"), exports);
|
|
30
33
|
__exportStar(require("./utilities"), exports);
|
|
31
34
|
__exportStar(require("./values"), exports);
|
|
35
|
+
__exportStar(require("./readymade"), exports);
|
package/dist/parsers/many.d.ts
CHANGED
|
@@ -3,15 +3,3 @@ import { Parser } from "../types";
|
|
|
3
3
|
* @returns A parser returning an array of many parses.
|
|
4
4
|
*/
|
|
5
5
|
export declare function many<T>(parser: Parser<T>): Parser<T[]>;
|
|
6
|
-
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
7
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
8
|
-
*/
|
|
9
|
-
export declare function zeroOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
10
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
11
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
12
|
-
*/
|
|
13
|
-
export declare function oneOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
14
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
15
|
-
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
16
|
-
*/
|
|
17
|
-
export declare function oneOrManyRed<T, V, U = T>(item: Parser<T>, separator: Parser<V>, reducer: (left: U | T, right: T, sep: V) => U): Parser<U | T>;
|
package/dist/parsers/many.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.many = many;
|
|
4
|
-
exports.zeroOrMany = zeroOrMany;
|
|
5
|
-
exports.oneOrMany = oneOrMany;
|
|
6
|
-
exports.oneOrManyRed = oneOrManyRed;
|
|
7
4
|
const types_1 = require("../types");
|
|
8
5
|
/** Parses zero or more occurences of the given parser.
|
|
9
6
|
* @returns A parser returning an array of many parses.
|
|
@@ -15,6 +12,7 @@ function many(parser) {
|
|
|
15
12
|
const res = parser(ctx);
|
|
16
13
|
if ((0, types_1.isFailure)(res)) {
|
|
17
14
|
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
15
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
18
16
|
if (surelyIndex >= 0) {
|
|
19
17
|
return (0, types_1.failure)(res.ctx, res.expected, ['many', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
20
18
|
}
|
|
@@ -25,139 +23,3 @@ function many(parser) {
|
|
|
25
23
|
}
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
|
-
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
29
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
30
|
-
*/
|
|
31
|
-
function zeroOrMany(item, separator = undefined) {
|
|
32
|
-
if (separator) {
|
|
33
|
-
return (ctx) => {
|
|
34
|
-
const results = [];
|
|
35
|
-
const res = item(ctx);
|
|
36
|
-
if ((0, types_1.isFailure)(res)) {
|
|
37
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
38
|
-
if (surelyIndex >= 0) {
|
|
39
|
-
return (0, types_1.failure)(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
40
|
-
}
|
|
41
|
-
return (0, types_1.success)(ctx, results);
|
|
42
|
-
}
|
|
43
|
-
ctx = res.ctx;
|
|
44
|
-
results.push(res.value);
|
|
45
|
-
while (true) {
|
|
46
|
-
const resSep = separator(ctx);
|
|
47
|
-
if ((0, types_1.isFailure)(resSep)) {
|
|
48
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
49
|
-
if (surelyIndex >= 0) {
|
|
50
|
-
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['zeroOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
51
|
-
}
|
|
52
|
-
return (0, types_1.success)(ctx, results);
|
|
53
|
-
}
|
|
54
|
-
const res = item(resSep.ctx);
|
|
55
|
-
if ((0, types_1.isFailure)(res)) {
|
|
56
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
57
|
-
if (surelyIndex >= 0) {
|
|
58
|
-
return (0, types_1.failure)(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
59
|
-
}
|
|
60
|
-
return (0, types_1.success)(ctx, results);
|
|
61
|
-
}
|
|
62
|
-
ctx = res.ctx;
|
|
63
|
-
results.push(res.value);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
else
|
|
68
|
-
return many(item);
|
|
69
|
-
}
|
|
70
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
71
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
72
|
-
*/
|
|
73
|
-
function oneOrMany(item, separator = undefined) {
|
|
74
|
-
if (separator) {
|
|
75
|
-
return (ctx) => {
|
|
76
|
-
const results = [];
|
|
77
|
-
const res = item(ctx);
|
|
78
|
-
if ((0, types_1.isFailure)(res))
|
|
79
|
-
return res;
|
|
80
|
-
ctx = res.ctx;
|
|
81
|
-
results.push(res.value);
|
|
82
|
-
while (true) {
|
|
83
|
-
const resSep = separator(ctx);
|
|
84
|
-
if ((0, types_1.isFailure)(resSep)) {
|
|
85
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
86
|
-
if (surelyIndex >= 0) {
|
|
87
|
-
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['oneOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
88
|
-
}
|
|
89
|
-
return (0, types_1.success)(ctx, results);
|
|
90
|
-
}
|
|
91
|
-
const res = item(resSep.ctx);
|
|
92
|
-
if ((0, types_1.isFailure)(res)) {
|
|
93
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
94
|
-
if (surelyIndex >= 0) {
|
|
95
|
-
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
96
|
-
}
|
|
97
|
-
return (0, types_1.success)(ctx, results);
|
|
98
|
-
}
|
|
99
|
-
ctx = res.ctx;
|
|
100
|
-
results.push(res.value);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
return (ctx) => {
|
|
106
|
-
const results = [];
|
|
107
|
-
const res = item(ctx);
|
|
108
|
-
if ((0, types_1.isFailure)(res))
|
|
109
|
-
return res;
|
|
110
|
-
ctx = res.ctx;
|
|
111
|
-
results.push(res.value);
|
|
112
|
-
while (true) {
|
|
113
|
-
const res = item(ctx);
|
|
114
|
-
if ((0, types_1.isFailure)(res)) {
|
|
115
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
116
|
-
if (surelyIndex >= 0) {
|
|
117
|
-
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
118
|
-
}
|
|
119
|
-
return (0, types_1.success)(ctx, results);
|
|
120
|
-
}
|
|
121
|
-
ctx = res.ctx;
|
|
122
|
-
results.push(res.value);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
128
|
-
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
129
|
-
*/
|
|
130
|
-
function oneOrManyRed(item, separator, reducer) {
|
|
131
|
-
return (ctx) => {
|
|
132
|
-
const res = item(ctx);
|
|
133
|
-
if ((0, types_1.isFailure)(res))
|
|
134
|
-
return res;
|
|
135
|
-
ctx = res.ctx;
|
|
136
|
-
let result = res.value;
|
|
137
|
-
while (true) {
|
|
138
|
-
const resSep = separator(ctx);
|
|
139
|
-
if ((0, types_1.isFailure)(resSep)) {
|
|
140
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
141
|
-
if (surelyIndex >= 0) {
|
|
142
|
-
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['oneOrManyRed', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
143
|
-
}
|
|
144
|
-
return (0, types_1.success)(ctx, result);
|
|
145
|
-
}
|
|
146
|
-
const res = item(resSep.ctx);
|
|
147
|
-
if ((0, types_1.isFailure)(res)) {
|
|
148
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
149
|
-
if (surelyIndex >= 0) {
|
|
150
|
-
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrManyRed', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
151
|
-
}
|
|
152
|
-
return (0, types_1.success)(ctx, result);
|
|
153
|
-
}
|
|
154
|
-
ctx = res.ctx;
|
|
155
|
-
try {
|
|
156
|
-
result = reducer(result, res.value, resSep.value);
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
return (0, types_1.failure)(res.ctx, 'Error while reducing', ['oneOrManyRed']);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export declare function oneOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.oneOrMany = oneOrMany;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
6
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
7
|
+
*/
|
|
8
|
+
function oneOrMany(item, separator = undefined) {
|
|
9
|
+
if (separator) {
|
|
10
|
+
return (ctx) => {
|
|
11
|
+
const results = [];
|
|
12
|
+
const res = item(ctx);
|
|
13
|
+
if ((0, types_1.isFailure)(res)) {
|
|
14
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history]);
|
|
15
|
+
}
|
|
16
|
+
ctx = res.ctx;
|
|
17
|
+
results.push(res.value);
|
|
18
|
+
while (true) {
|
|
19
|
+
const resSep = separator(ctx);
|
|
20
|
+
if ((0, types_1.isFailure)(resSep)) {
|
|
21
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
22
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
23
|
+
if (surelyIndex >= 0) {
|
|
24
|
+
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['oneOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
25
|
+
}
|
|
26
|
+
return (0, types_1.success)(ctx, results);
|
|
27
|
+
}
|
|
28
|
+
const res = item(resSep.ctx);
|
|
29
|
+
if ((0, types_1.isFailure)(res)) {
|
|
30
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
31
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
32
|
+
if (surelyIndex >= 0) {
|
|
33
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
34
|
+
}
|
|
35
|
+
return (0, types_1.success)(ctx, results);
|
|
36
|
+
}
|
|
37
|
+
ctx = res.ctx;
|
|
38
|
+
results.push(res.value);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return (ctx) => {
|
|
44
|
+
const results = [];
|
|
45
|
+
const res = item(ctx);
|
|
46
|
+
if ((0, types_1.isFailure)(res)) {
|
|
47
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history]);
|
|
48
|
+
}
|
|
49
|
+
ctx = res.ctx;
|
|
50
|
+
results.push(res.value);
|
|
51
|
+
while (true) {
|
|
52
|
+
const res = item(ctx);
|
|
53
|
+
if ((0, types_1.isFailure)(res)) {
|
|
54
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
55
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
56
|
+
if (surelyIndex >= 0) {
|
|
57
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
58
|
+
}
|
|
59
|
+
return (0, types_1.success)(ctx, results);
|
|
60
|
+
}
|
|
61
|
+
ctx = res.ctx;
|
|
62
|
+
results.push(res.value);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
4
|
+
*/
|
|
5
|
+
export declare function oneOrManyRed<T, V, U = T>(item: Parser<T>, separator: Parser<V>, reducer: (left: U | T, right: T, sep: V) => U): Parser<U | T>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.oneOrManyRed = oneOrManyRed;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
6
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
7
|
+
*/
|
|
8
|
+
function oneOrManyRed(item, separator, reducer) {
|
|
9
|
+
return (ctx) => {
|
|
10
|
+
const res = item(ctx);
|
|
11
|
+
if ((0, types_1.isFailure)(res)) {
|
|
12
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrManyRed', ...res.history]);
|
|
13
|
+
}
|
|
14
|
+
ctx = res.ctx;
|
|
15
|
+
let result = res.value;
|
|
16
|
+
while (true) {
|
|
17
|
+
const resSep = separator(ctx);
|
|
18
|
+
if ((0, types_1.isFailure)(resSep)) {
|
|
19
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
20
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
21
|
+
if (surelyIndex >= 0) {
|
|
22
|
+
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['oneOrManyRed', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
23
|
+
}
|
|
24
|
+
return (0, types_1.success)(ctx, result);
|
|
25
|
+
}
|
|
26
|
+
const res = item(resSep.ctx);
|
|
27
|
+
if ((0, types_1.isFailure)(res)) {
|
|
28
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
29
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
30
|
+
if (surelyIndex >= 0) {
|
|
31
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['oneOrManyRed', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
32
|
+
}
|
|
33
|
+
return (0, types_1.success)(ctx, result);
|
|
34
|
+
}
|
|
35
|
+
ctx = res.ctx;
|
|
36
|
+
try {
|
|
37
|
+
result = reducer(result, res.value, resSep.value);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return (0, types_1.failure)(res.ctx, 'Error while reducing', ['oneOrManyRed']);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.json = void 0;
|
|
4
|
+
const any_1 = require("./any");
|
|
5
|
+
const between_1 = require("./between");
|
|
6
|
+
const zeroOrMany_1 = require("./zeroOrMany");
|
|
7
|
+
const map_1 = require("./map");
|
|
8
|
+
const regex_1 = require("./regex");
|
|
9
|
+
const seq_1 = require("./seq");
|
|
10
|
+
const str_1 = require("./str");
|
|
11
|
+
const utilities_1 = require("./utilities");
|
|
12
|
+
const WhiteSpace = (0, regex_1.regex)(/\s*/m, 'whitespace');
|
|
13
|
+
const True = (0, map_1.map)((0, str_1.str)("true"), () => true);
|
|
14
|
+
const False = (0, map_1.map)((0, str_1.str)("false"), () => false);
|
|
15
|
+
const Null = (0, map_1.map)((0, str_1.str)("null"), () => null);
|
|
16
|
+
const LCurly = (0, str_1.str)("{");
|
|
17
|
+
const RCurly = (0, utilities_1.surely)((0, str_1.str)("}"));
|
|
18
|
+
const LSquare = (0, str_1.str)("[");
|
|
19
|
+
const RSquare = (0, utilities_1.surely)((0, str_1.str)("]"));
|
|
20
|
+
const Quote = (0, str_1.str)('"');
|
|
21
|
+
const Comma = (0, str_1.str)(",");
|
|
22
|
+
const Colon = (0, utilities_1.surely)((0, str_1.str)(":"));
|
|
23
|
+
const replacements = {
|
|
24
|
+
'\\\\': '\\',
|
|
25
|
+
'\\0': '\0',
|
|
26
|
+
'\\b': '\b',
|
|
27
|
+
'\\f': '\f',
|
|
28
|
+
'\\n': '\n',
|
|
29
|
+
'\\r': '\r',
|
|
30
|
+
'\\t': '\t',
|
|
31
|
+
'\\v': '\v',
|
|
32
|
+
'\\"': '"'
|
|
33
|
+
};
|
|
34
|
+
const StringLiteral = (0, between_1.between)(Quote, (0, map_1.map)((0, regex_1.regex)(/(?:[^\\"]|\\(?:[0bfnrtv"\\]|u[0-9a-fA-F]{4}))*/, 'string literal'), str => str.replace(/\\(?:[0bfnrtv"\\]|u[0-9a-fA-F]{4})/g, function (replace) {
|
|
35
|
+
const tabled = replacements[replace];
|
|
36
|
+
if (tabled != null) {
|
|
37
|
+
return tabled;
|
|
38
|
+
}
|
|
39
|
+
return String.fromCharCode(parseInt(replace.slice(2), 16));
|
|
40
|
+
})), Quote);
|
|
41
|
+
const NumberLiteral = (0, map_1.map)((0, regex_1.regex)(/-?(?:0|(?:[1-9]\d*))(?:\.\d+)?(?:[eE][+-]?\d+)?/, 'number literal'), parseFloat);
|
|
42
|
+
const JArray = (0, utilities_1.lazy)(() => (0, map_1.map)((0, seq_1.seq)(LSquare, (0, utilities_1.surely)((0, seq_1.seq)(WhiteSpace, (0, zeroOrMany_1.zeroOrMany)(Value, (0, seq_1.seq)(WhiteSpace, Comma, WhiteSpace)), WhiteSpace, RSquare))), (data) => data[1][1]));
|
|
43
|
+
const JObject = (0, utilities_1.lazy)(() => (0, map_1.map)((0, seq_1.seq)(LCurly, (0, utilities_1.surely)((0, seq_1.seq)(WhiteSpace, (0, zeroOrMany_1.zeroOrMany)(ObjectEntry, (0, seq_1.seq)(WhiteSpace, Comma, WhiteSpace)), WhiteSpace, RCurly))), data => Object.fromEntries(data[1][1])));
|
|
44
|
+
const Value = (0, any_1.any)(StringLiteral, NumberLiteral, JObject, JArray, True, False, Null);
|
|
45
|
+
const ObjectEntry = (0, map_1.map)((0, seq_1.seq)(StringLiteral, (0, utilities_1.surely)((0, seq_1.seq)(WhiteSpace, Colon, WhiteSpace, Value))), ([key, rest]) => [key, rest[3]]);
|
|
46
|
+
exports.json = (0, between_1.between)(WhiteSpace, Value, WhiteSpace);
|
package/dist/parsers/regex.js
CHANGED
|
@@ -10,7 +10,7 @@ function regex(match, expected) {
|
|
|
10
10
|
return (ctx) => {
|
|
11
11
|
regexp.lastIndex = ctx.index;
|
|
12
12
|
const regexMatch = regexp.exec(ctx.text);
|
|
13
|
-
if (regexMatch !== null
|
|
13
|
+
if (regexMatch !== null) {
|
|
14
14
|
return (0, types_1.success)({ ...ctx, index: ctx.index + regexMatch[0].length }, regexMatch[0]);
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
@@ -15,7 +15,8 @@ function ref(parser, check, expected) {
|
|
|
15
15
|
return (ctx) => {
|
|
16
16
|
const res = parser(ctx);
|
|
17
17
|
if (!(0, types_1.isFailure)(res) && !check(res.value)) {
|
|
18
|
-
|
|
18
|
+
const phrase = expected ?? 'check';
|
|
19
|
+
return (0, types_1.failure)(res.ctx, phrase, [`ref: ${phrase}`]);
|
|
19
20
|
}
|
|
20
21
|
return res;
|
|
21
22
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export declare function zeroOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.zeroOrMany = zeroOrMany;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
6
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
7
|
+
*/
|
|
8
|
+
function zeroOrMany(item, separator = undefined) {
|
|
9
|
+
if (separator) {
|
|
10
|
+
return (ctx) => {
|
|
11
|
+
const results = [];
|
|
12
|
+
const res = item(ctx);
|
|
13
|
+
if ((0, types_1.isFailure)(res)) {
|
|
14
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
15
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
16
|
+
if (surelyIndex >= 0) {
|
|
17
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
18
|
+
}
|
|
19
|
+
return (0, types_1.success)(ctx, results);
|
|
20
|
+
}
|
|
21
|
+
ctx = res.ctx;
|
|
22
|
+
results.push(res.value);
|
|
23
|
+
while (true) {
|
|
24
|
+
const resSep = separator(ctx);
|
|
25
|
+
if ((0, types_1.isFailure)(resSep)) {
|
|
26
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
27
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
28
|
+
if (surelyIndex >= 0) {
|
|
29
|
+
return (0, types_1.failure)(resSep.ctx, resSep.expected, ['zeroOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
30
|
+
}
|
|
31
|
+
return (0, types_1.success)(ctx, results);
|
|
32
|
+
}
|
|
33
|
+
const res = item(resSep.ctx);
|
|
34
|
+
if ((0, types_1.isFailure)(res)) {
|
|
35
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
36
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
37
|
+
if (surelyIndex >= 0) {
|
|
38
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
39
|
+
}
|
|
40
|
+
return (0, types_1.success)(ctx, results);
|
|
41
|
+
}
|
|
42
|
+
ctx = res.ctx;
|
|
43
|
+
results.push(res.value);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
return (ctx) => {
|
|
49
|
+
const results = [];
|
|
50
|
+
while (true) {
|
|
51
|
+
const res = item(ctx);
|
|
52
|
+
if ((0, types_1.isFailure)(res)) {
|
|
53
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
54
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
55
|
+
if (surelyIndex >= 0) {
|
|
56
|
+
return (0, types_1.failure)(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
57
|
+
}
|
|
58
|
+
return (0, types_1.success)(ctx, results);
|
|
59
|
+
}
|
|
60
|
+
ctx = res.ctx;
|
|
61
|
+
results.push(res.value);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
package/dist/types.d.ts
CHANGED
package/dist-esm/parsers/any.js
CHANGED
|
@@ -20,6 +20,7 @@ export function any(...parsers) {
|
|
|
20
20
|
const res = parser(ctx);
|
|
21
21
|
if (isFailure(res)) {
|
|
22
22
|
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
23
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
23
24
|
if (surelyIndex >= 0) {
|
|
24
25
|
return failure(res.ctx, res.expected, ['any', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
25
26
|
}
|
|
@@ -23,14 +23,7 @@ function createSearchTree(matches) {
|
|
|
23
23
|
}
|
|
24
24
|
function addMatchToTree(node, match, idIndex, charIndex = 0) {
|
|
25
25
|
if (charIndex >= match[0].length) {
|
|
26
|
-
|
|
27
|
-
if (node.matchIndex > idIndex) {
|
|
28
|
-
node.matchIndex = idIndex;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
node.matchIndex = idIndex;
|
|
33
|
-
}
|
|
26
|
+
node.matchIndex ??= idIndex;
|
|
34
27
|
}
|
|
35
28
|
else {
|
|
36
29
|
const char = match[0][charIndex];
|
|
@@ -48,15 +41,17 @@ function addMatchToTree(node, match, idIndex, charIndex = 0) {
|
|
|
48
41
|
}
|
|
49
42
|
}
|
|
50
43
|
else {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
node.set(char, node.get(char) ?? newNode);
|
|
45
|
+
if (lowercase !== uppercase) {
|
|
46
|
+
const lower = node.get(lowercase);
|
|
47
|
+
const upper = node.get(uppercase);
|
|
48
|
+
if (lower != null && lower === upper) {
|
|
49
|
+
const copy = new Map(lower.entries());
|
|
50
|
+
copy.matchIndex = lower.matchIndex;
|
|
51
|
+
node.set(uppercase, copy);
|
|
52
|
+
}
|
|
58
53
|
}
|
|
59
|
-
addMatchToTree(
|
|
54
|
+
addMatchToTree(node.get(char), match, idIndex, charIndex + 1);
|
|
60
55
|
}
|
|
61
56
|
}
|
|
62
57
|
}
|
|
@@ -2,6 +2,9 @@ export * from './any';
|
|
|
2
2
|
export * from './between';
|
|
3
3
|
export * from './exhaust';
|
|
4
4
|
export * from './many';
|
|
5
|
+
export * from './zeroOrMany';
|
|
6
|
+
export * from './oneOrMany';
|
|
7
|
+
export * from './oneOrManyRed';
|
|
5
8
|
export * from './map';
|
|
6
9
|
export * from './opt';
|
|
7
10
|
export * from './regex';
|
|
@@ -10,3 +13,4 @@ export { str, stri } from './str';
|
|
|
10
13
|
export * from './recovery';
|
|
11
14
|
export * from './utilities';
|
|
12
15
|
export * from './values';
|
|
16
|
+
export * from './readymade';
|
|
@@ -2,6 +2,9 @@ export * from './any';
|
|
|
2
2
|
export * from './between';
|
|
3
3
|
export * from './exhaust';
|
|
4
4
|
export * from './many';
|
|
5
|
+
export * from './zeroOrMany';
|
|
6
|
+
export * from './oneOrMany';
|
|
7
|
+
export * from './oneOrManyRed';
|
|
5
8
|
export * from './map';
|
|
6
9
|
export * from './opt';
|
|
7
10
|
export * from './regex';
|
|
@@ -10,3 +13,4 @@ export { str, stri } from './str';
|
|
|
10
13
|
export * from './recovery';
|
|
11
14
|
export * from './utilities';
|
|
12
15
|
export * from './values';
|
|
16
|
+
export * from './readymade';
|
|
@@ -3,15 +3,3 @@ import { Parser } from "../types";
|
|
|
3
3
|
* @returns A parser returning an array of many parses.
|
|
4
4
|
*/
|
|
5
5
|
export declare function many<T>(parser: Parser<T>): Parser<T[]>;
|
|
6
|
-
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
7
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
8
|
-
*/
|
|
9
|
-
export declare function zeroOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
10
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
11
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
12
|
-
*/
|
|
13
|
-
export declare function oneOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
14
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
15
|
-
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
16
|
-
*/
|
|
17
|
-
export declare function oneOrManyRed<T, V, U = T>(item: Parser<T>, separator: Parser<V>, reducer: (left: U | T, right: T, sep: V) => U): Parser<U | T>;
|
package/dist-esm/parsers/many.js
CHANGED
|
@@ -9,6 +9,7 @@ export function many(parser) {
|
|
|
9
9
|
const res = parser(ctx);
|
|
10
10
|
if (isFailure(res)) {
|
|
11
11
|
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
12
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
12
13
|
if (surelyIndex >= 0) {
|
|
13
14
|
return failure(res.ctx, res.expected, ['many', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
14
15
|
}
|
|
@@ -19,139 +20,3 @@ export function many(parser) {
|
|
|
19
20
|
}
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
|
-
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
23
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
24
|
-
*/
|
|
25
|
-
export function zeroOrMany(item, separator = undefined) {
|
|
26
|
-
if (separator) {
|
|
27
|
-
return (ctx) => {
|
|
28
|
-
const results = [];
|
|
29
|
-
const res = item(ctx);
|
|
30
|
-
if (isFailure(res)) {
|
|
31
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
32
|
-
if (surelyIndex >= 0) {
|
|
33
|
-
return failure(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
34
|
-
}
|
|
35
|
-
return success(ctx, results);
|
|
36
|
-
}
|
|
37
|
-
ctx = res.ctx;
|
|
38
|
-
results.push(res.value);
|
|
39
|
-
while (true) {
|
|
40
|
-
const resSep = separator(ctx);
|
|
41
|
-
if (isFailure(resSep)) {
|
|
42
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
43
|
-
if (surelyIndex >= 0) {
|
|
44
|
-
return failure(resSep.ctx, resSep.expected, ['zeroOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
45
|
-
}
|
|
46
|
-
return success(ctx, results);
|
|
47
|
-
}
|
|
48
|
-
const res = item(resSep.ctx);
|
|
49
|
-
if (isFailure(res)) {
|
|
50
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
51
|
-
if (surelyIndex >= 0) {
|
|
52
|
-
return failure(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
53
|
-
}
|
|
54
|
-
return success(ctx, results);
|
|
55
|
-
}
|
|
56
|
-
ctx = res.ctx;
|
|
57
|
-
results.push(res.value);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
else
|
|
62
|
-
return many(item);
|
|
63
|
-
}
|
|
64
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
65
|
-
* @returns A parser returning an array of many parses, omitting the separator.
|
|
66
|
-
*/
|
|
67
|
-
export function oneOrMany(item, separator = undefined) {
|
|
68
|
-
if (separator) {
|
|
69
|
-
return (ctx) => {
|
|
70
|
-
const results = [];
|
|
71
|
-
const res = item(ctx);
|
|
72
|
-
if (isFailure(res))
|
|
73
|
-
return res;
|
|
74
|
-
ctx = res.ctx;
|
|
75
|
-
results.push(res.value);
|
|
76
|
-
while (true) {
|
|
77
|
-
const resSep = separator(ctx);
|
|
78
|
-
if (isFailure(resSep)) {
|
|
79
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
80
|
-
if (surelyIndex >= 0) {
|
|
81
|
-
return failure(resSep.ctx, resSep.expected, ['oneOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
82
|
-
}
|
|
83
|
-
return success(ctx, results);
|
|
84
|
-
}
|
|
85
|
-
const res = item(resSep.ctx);
|
|
86
|
-
if (isFailure(res)) {
|
|
87
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
88
|
-
if (surelyIndex >= 0) {
|
|
89
|
-
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
90
|
-
}
|
|
91
|
-
return success(ctx, results);
|
|
92
|
-
}
|
|
93
|
-
ctx = res.ctx;
|
|
94
|
-
results.push(res.value);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
return (ctx) => {
|
|
100
|
-
const results = [];
|
|
101
|
-
const res = item(ctx);
|
|
102
|
-
if (isFailure(res))
|
|
103
|
-
return res;
|
|
104
|
-
ctx = res.ctx;
|
|
105
|
-
results.push(res.value);
|
|
106
|
-
while (true) {
|
|
107
|
-
const res = item(ctx);
|
|
108
|
-
if (isFailure(res)) {
|
|
109
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
110
|
-
if (surelyIndex >= 0) {
|
|
111
|
-
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
112
|
-
}
|
|
113
|
-
return success(ctx, results);
|
|
114
|
-
}
|
|
115
|
-
ctx = res.ctx;
|
|
116
|
-
results.push(res.value);
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
122
|
-
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
123
|
-
*/
|
|
124
|
-
export function oneOrManyRed(item, separator, reducer) {
|
|
125
|
-
return (ctx) => {
|
|
126
|
-
const res = item(ctx);
|
|
127
|
-
if (isFailure(res))
|
|
128
|
-
return res;
|
|
129
|
-
ctx = res.ctx;
|
|
130
|
-
let result = res.value;
|
|
131
|
-
while (true) {
|
|
132
|
-
const resSep = separator(ctx);
|
|
133
|
-
if (isFailure(resSep)) {
|
|
134
|
-
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
135
|
-
if (surelyIndex >= 0) {
|
|
136
|
-
return failure(resSep.ctx, resSep.expected, ['oneOrManyRed', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
137
|
-
}
|
|
138
|
-
return success(ctx, result);
|
|
139
|
-
}
|
|
140
|
-
const res = item(resSep.ctx);
|
|
141
|
-
if (isFailure(res)) {
|
|
142
|
-
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
143
|
-
if (surelyIndex >= 0) {
|
|
144
|
-
return failure(res.ctx, res.expected, ['oneOrManyRed', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
145
|
-
}
|
|
146
|
-
return success(ctx, result);
|
|
147
|
-
}
|
|
148
|
-
ctx = res.ctx;
|
|
149
|
-
try {
|
|
150
|
-
result = reducer(result, res.value, resSep.value);
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
return failure(res.ctx, 'Error while reducing', ['oneOrManyRed']);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export declare function oneOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { failure, isFailure, success } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export function oneOrMany(item, separator = undefined) {
|
|
6
|
+
if (separator) {
|
|
7
|
+
return (ctx) => {
|
|
8
|
+
const results = [];
|
|
9
|
+
const res = item(ctx);
|
|
10
|
+
if (isFailure(res)) {
|
|
11
|
+
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history]);
|
|
12
|
+
}
|
|
13
|
+
ctx = res.ctx;
|
|
14
|
+
results.push(res.value);
|
|
15
|
+
while (true) {
|
|
16
|
+
const resSep = separator(ctx);
|
|
17
|
+
if (isFailure(resSep)) {
|
|
18
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
19
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
20
|
+
if (surelyIndex >= 0) {
|
|
21
|
+
return failure(resSep.ctx, resSep.expected, ['oneOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
22
|
+
}
|
|
23
|
+
return success(ctx, results);
|
|
24
|
+
}
|
|
25
|
+
const res = item(resSep.ctx);
|
|
26
|
+
if (isFailure(res)) {
|
|
27
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
28
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
29
|
+
if (surelyIndex >= 0) {
|
|
30
|
+
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
31
|
+
}
|
|
32
|
+
return success(ctx, results);
|
|
33
|
+
}
|
|
34
|
+
ctx = res.ctx;
|
|
35
|
+
results.push(res.value);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return (ctx) => {
|
|
41
|
+
const results = [];
|
|
42
|
+
const res = item(ctx);
|
|
43
|
+
if (isFailure(res)) {
|
|
44
|
+
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history]);
|
|
45
|
+
}
|
|
46
|
+
ctx = res.ctx;
|
|
47
|
+
results.push(res.value);
|
|
48
|
+
while (true) {
|
|
49
|
+
const res = item(ctx);
|
|
50
|
+
if (isFailure(res)) {
|
|
51
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
52
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
53
|
+
if (surelyIndex >= 0) {
|
|
54
|
+
return failure(res.ctx, res.expected, ['oneOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
55
|
+
}
|
|
56
|
+
return success(ctx, results);
|
|
57
|
+
}
|
|
58
|
+
ctx = res.ctx;
|
|
59
|
+
results.push(res.value);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
4
|
+
*/
|
|
5
|
+
export declare function oneOrManyRed<T, V, U = T>(item: Parser<T>, separator: Parser<V>, reducer: (left: U | T, right: T, sep: V) => U): Parser<U | T>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { failure, isFailure, success } from "../types";
|
|
2
|
+
/** Parses one or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning the result of many parses, reduced using the `reducer` function passed in.
|
|
4
|
+
*/
|
|
5
|
+
export function oneOrManyRed(item, separator, reducer) {
|
|
6
|
+
return (ctx) => {
|
|
7
|
+
const res = item(ctx);
|
|
8
|
+
if (isFailure(res)) {
|
|
9
|
+
return failure(res.ctx, res.expected, ['oneOrManyRed', ...res.history]);
|
|
10
|
+
}
|
|
11
|
+
ctx = res.ctx;
|
|
12
|
+
let result = res.value;
|
|
13
|
+
while (true) {
|
|
14
|
+
const resSep = separator(ctx);
|
|
15
|
+
if (isFailure(resSep)) {
|
|
16
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
17
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
18
|
+
if (surelyIndex >= 0) {
|
|
19
|
+
return failure(resSep.ctx, resSep.expected, ['oneOrManyRed', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
20
|
+
}
|
|
21
|
+
return success(ctx, result);
|
|
22
|
+
}
|
|
23
|
+
const res = item(resSep.ctx);
|
|
24
|
+
if (isFailure(res)) {
|
|
25
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
26
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
27
|
+
if (surelyIndex >= 0) {
|
|
28
|
+
return failure(res.ctx, res.expected, ['oneOrManyRed', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
29
|
+
}
|
|
30
|
+
return success(ctx, result);
|
|
31
|
+
}
|
|
32
|
+
ctx = res.ctx;
|
|
33
|
+
try {
|
|
34
|
+
result = reducer(result, res.value, resSep.value);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return failure(res.ctx, 'Error while reducing', ['oneOrManyRed']);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { any } from "./any";
|
|
2
|
+
import { between } from "./between";
|
|
3
|
+
import { zeroOrMany } from "./zeroOrMany";
|
|
4
|
+
import { map } from "./map";
|
|
5
|
+
import { regex } from "./regex";
|
|
6
|
+
import { seq } from "./seq";
|
|
7
|
+
import { str } from "./str";
|
|
8
|
+
import { lazy, surely } from "./utilities";
|
|
9
|
+
const WhiteSpace = regex(/\s*/m, 'whitespace');
|
|
10
|
+
const True = map(str("true"), () => true);
|
|
11
|
+
const False = map(str("false"), () => false);
|
|
12
|
+
const Null = map(str("null"), () => null);
|
|
13
|
+
const LCurly = str("{");
|
|
14
|
+
const RCurly = surely(str("}"));
|
|
15
|
+
const LSquare = str("[");
|
|
16
|
+
const RSquare = surely(str("]"));
|
|
17
|
+
const Quote = str('"');
|
|
18
|
+
const Comma = str(",");
|
|
19
|
+
const Colon = surely(str(":"));
|
|
20
|
+
const replacements = {
|
|
21
|
+
'\\\\': '\\',
|
|
22
|
+
'\\0': '\0',
|
|
23
|
+
'\\b': '\b',
|
|
24
|
+
'\\f': '\f',
|
|
25
|
+
'\\n': '\n',
|
|
26
|
+
'\\r': '\r',
|
|
27
|
+
'\\t': '\t',
|
|
28
|
+
'\\v': '\v',
|
|
29
|
+
'\\"': '"'
|
|
30
|
+
};
|
|
31
|
+
const StringLiteral = between(Quote, map(regex(/(?:[^\\"]|\\(?:[0bfnrtv"\\]|u[0-9a-fA-F]{4}))*/, 'string literal'), str => str.replace(/\\(?:[0bfnrtv"\\]|u[0-9a-fA-F]{4})/g, function (replace) {
|
|
32
|
+
const tabled = replacements[replace];
|
|
33
|
+
if (tabled != null) {
|
|
34
|
+
return tabled;
|
|
35
|
+
}
|
|
36
|
+
return String.fromCharCode(parseInt(replace.slice(2), 16));
|
|
37
|
+
})), Quote);
|
|
38
|
+
const NumberLiteral = map(regex(/-?(?:0|(?:[1-9]\d*))(?:\.\d+)?(?:[eE][+-]?\d+)?/, 'number literal'), parseFloat);
|
|
39
|
+
const JArray = lazy(() => map(seq(LSquare, surely(seq(WhiteSpace, zeroOrMany(Value, seq(WhiteSpace, Comma, WhiteSpace)), WhiteSpace, RSquare))), (data) => data[1][1]));
|
|
40
|
+
const JObject = lazy(() => map(seq(LCurly, surely(seq(WhiteSpace, zeroOrMany(ObjectEntry, seq(WhiteSpace, Comma, WhiteSpace)), WhiteSpace, RCurly))), data => Object.fromEntries(data[1][1])));
|
|
41
|
+
const Value = any(StringLiteral, NumberLiteral, JObject, JArray, True, False, Null);
|
|
42
|
+
const ObjectEntry = map(seq(StringLiteral, surely(seq(WhiteSpace, Colon, WhiteSpace, Value))), ([key, rest]) => [key, rest[3]]);
|
|
43
|
+
export const json = between(WhiteSpace, Value, WhiteSpace);
|
|
@@ -7,7 +7,7 @@ export function regex(match, expected) {
|
|
|
7
7
|
return (ctx) => {
|
|
8
8
|
regexp.lastIndex = ctx.index;
|
|
9
9
|
const regexMatch = regexp.exec(ctx.text);
|
|
10
|
-
if (regexMatch !== null
|
|
10
|
+
if (regexMatch !== null) {
|
|
11
11
|
return success({ ...ctx, index: ctx.index + regexMatch[0].length }, regexMatch[0]);
|
|
12
12
|
}
|
|
13
13
|
else {
|
|
@@ -6,7 +6,8 @@ export function ref(parser, check, expected) {
|
|
|
6
6
|
return (ctx) => {
|
|
7
7
|
const res = parser(ctx);
|
|
8
8
|
if (!isFailure(res) && !check(res.value)) {
|
|
9
|
-
|
|
9
|
+
const phrase = expected ?? 'check';
|
|
10
|
+
return failure(res.ctx, phrase, [`ref: ${phrase}`]);
|
|
10
11
|
}
|
|
11
12
|
return res;
|
|
12
13
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Parser } from "../types";
|
|
2
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export declare function zeroOrMany<T, V>(item: Parser<T>, separator?: Parser<V> | undefined): Parser<T[]>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { failure, isFailure, success } from "../types";
|
|
2
|
+
/** Parses zero or more occurences of the given parser, separated with the separator parser.
|
|
3
|
+
* @returns A parser returning an array of many parses, omitting the separator.
|
|
4
|
+
*/
|
|
5
|
+
export function zeroOrMany(item, separator = undefined) {
|
|
6
|
+
if (separator) {
|
|
7
|
+
return (ctx) => {
|
|
8
|
+
const results = [];
|
|
9
|
+
const res = item(ctx);
|
|
10
|
+
if (isFailure(res)) {
|
|
11
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
12
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
13
|
+
if (surelyIndex >= 0) {
|
|
14
|
+
return failure(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
15
|
+
}
|
|
16
|
+
return success(ctx, results);
|
|
17
|
+
}
|
|
18
|
+
ctx = res.ctx;
|
|
19
|
+
results.push(res.value);
|
|
20
|
+
while (true) {
|
|
21
|
+
const resSep = separator(ctx);
|
|
22
|
+
if (isFailure(resSep)) {
|
|
23
|
+
const surelyIndex = resSep.history.findIndex(h => h === 'surely');
|
|
24
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
25
|
+
if (surelyIndex >= 0) {
|
|
26
|
+
return failure(resSep.ctx, resSep.expected, ['zeroOrMany', ...resSep.history.slice(0, surelyIndex), ...resSep.history.slice(surelyIndex + 1)]);
|
|
27
|
+
}
|
|
28
|
+
return success(ctx, results);
|
|
29
|
+
}
|
|
30
|
+
const res = item(resSep.ctx);
|
|
31
|
+
if (isFailure(res)) {
|
|
32
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
33
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
34
|
+
if (surelyIndex >= 0) {
|
|
35
|
+
return failure(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
36
|
+
}
|
|
37
|
+
return success(ctx, results);
|
|
38
|
+
}
|
|
39
|
+
ctx = res.ctx;
|
|
40
|
+
results.push(res.value);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
return (ctx) => {
|
|
46
|
+
const results = [];
|
|
47
|
+
while (true) {
|
|
48
|
+
const res = item(ctx);
|
|
49
|
+
if (isFailure(res)) {
|
|
50
|
+
const surelyIndex = res.history.findIndex(h => h === 'surely');
|
|
51
|
+
// Stryker disable next-line EqualityOperator: The > mutant results in an equivalent mutant
|
|
52
|
+
if (surelyIndex >= 0) {
|
|
53
|
+
return failure(res.ctx, res.expected, ['zeroOrMany', ...res.history.slice(0, surelyIndex), ...res.history.slice(surelyIndex + 1)]);
|
|
54
|
+
}
|
|
55
|
+
return success(ctx, results);
|
|
56
|
+
}
|
|
57
|
+
ctx = res.ctx;
|
|
58
|
+
results.push(res.value);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
package/dist-esm/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "parser-combinators",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"license": "ISC",
|
|
5
|
-
"maintainers": [
|
|
6
|
-
"Micha_i"
|
|
7
|
-
],
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/michalusio/Parser.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/michalusio/Parser/issues"
|
|
14
|
-
},
|
|
15
|
-
"homepage": "https://github.com/michalusio/Parser#readme",
|
|
16
|
-
"description": "A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.",
|
|
17
|
-
"scripts": {
|
|
18
|
-
"start": "tsc && node .",
|
|
19
|
-
"lint": "eslint src --ext .ts",
|
|
20
|
-
"build": "tsc",
|
|
21
|
-
"build-esm": "tsc --project tsconfig.esm.json",
|
|
22
|
-
"bundle": "npm run lint && npm run build && npm run build-esm",
|
|
23
|
-
"test:mutate": "stryker run",
|
|
24
|
-
"test:unit": "mocha",
|
|
25
|
-
"test": "nyc -e '.ts' --r html -r lcov -r text npm run test:unit"
|
|
26
|
-
},
|
|
27
|
-
"author": "Micha_i <isalski.michal@gmail.com> (https://github.com/michalusio)",
|
|
28
|
-
"main": "./dist/index.js",
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"type": "commonjs",
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=18"
|
|
33
|
-
},
|
|
34
|
-
"devDependencies": {
|
|
35
|
-
"@stryker-mutator/core": "^9.
|
|
36
|
-
"@stryker-mutator/mocha-runner": "^9.
|
|
37
|
-
"@stryker-mutator/typescript-checker": "^9.
|
|
38
|
-
"@types/mocha": "10.0.10",
|
|
39
|
-
"@types/node": "25.0
|
|
40
|
-
"cross-env": "10.1.0",
|
|
41
|
-
"esbuild": "0.27.2",
|
|
42
|
-
"eslint": "9.39.2",
|
|
43
|
-
"mocha": "11.7.5",
|
|
44
|
-
"nyc": "17.1.0",
|
|
45
|
-
"ts-node": "10.9.2",
|
|
46
|
-
"typescript": "5.9.3",
|
|
47
|
-
"typescript-eslint": "8.
|
|
48
|
-
},
|
|
49
|
-
"keywords": [
|
|
50
|
-
"parser",
|
|
51
|
-
"combinator",
|
|
52
|
-
"parser-combinator",
|
|
53
|
-
"parsing",
|
|
54
|
-
"combining",
|
|
55
|
-
"functional"
|
|
56
|
-
],
|
|
57
|
-
"prettier": {
|
|
58
|
-
"tabWidth": 4,
|
|
59
|
-
"useTabs": false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "parser-combinators",
|
|
3
|
+
"version": "1.2.6",
|
|
4
|
+
"license": "ISC",
|
|
5
|
+
"maintainers": [
|
|
6
|
+
"Micha_i"
|
|
7
|
+
],
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/michalusio/Parser.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/michalusio/Parser/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/michalusio/Parser#readme",
|
|
16
|
+
"description": "A library of parser combinators, with which you can create your own parsers. The library will be continuously improved in time.",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"start": "tsc && node .",
|
|
19
|
+
"lint": "eslint src --ext .ts",
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"build-esm": "tsc --project tsconfig.esm.json",
|
|
22
|
+
"bundle": "npm run lint && npm run build && npm run build-esm",
|
|
23
|
+
"test:mutate": "stryker run",
|
|
24
|
+
"test:unit": "mocha",
|
|
25
|
+
"test": "nyc -e '.ts' --r html -r lcov -r text npm run test:unit"
|
|
26
|
+
},
|
|
27
|
+
"author": "Micha_i <isalski.michal@gmail.com> (https://github.com/michalusio)",
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"type": "commonjs",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@stryker-mutator/core": "^9.5.0",
|
|
36
|
+
"@stryker-mutator/mocha-runner": "^9.5.0",
|
|
37
|
+
"@stryker-mutator/typescript-checker": "^9.5.0",
|
|
38
|
+
"@types/mocha": "10.0.10",
|
|
39
|
+
"@types/node": "25.1.0",
|
|
40
|
+
"cross-env": "10.1.0",
|
|
41
|
+
"esbuild": "0.27.2",
|
|
42
|
+
"eslint": "9.39.2",
|
|
43
|
+
"mocha": "11.7.5",
|
|
44
|
+
"nyc": "17.1.0",
|
|
45
|
+
"ts-node": "10.9.2",
|
|
46
|
+
"typescript": "5.9.3",
|
|
47
|
+
"typescript-eslint": "8.54.0"
|
|
48
|
+
},
|
|
49
|
+
"keywords": [
|
|
50
|
+
"parser",
|
|
51
|
+
"combinator",
|
|
52
|
+
"parser-combinator",
|
|
53
|
+
"parsing",
|
|
54
|
+
"combining",
|
|
55
|
+
"functional"
|
|
56
|
+
],
|
|
57
|
+
"prettier": {
|
|
58
|
+
"tabWidth": 4,
|
|
59
|
+
"useTabs": false
|
|
60
|
+
}
|
|
61
|
+
}
|