tarsec 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/combinators.d.ts +15 -0
- package/dist/combinators.js +189 -0
- package/dist/index.js +19 -0
- package/dist/parsers.d.ts +17 -0
- package/dist/parsers.js +104 -0
- package/dist/trace.d.ts +3 -0
- package/dist/trace.js +32 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.js +2 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +38 -0
- package/package.json +3 -1
- package/.github/workflows/node.js.yml +0 -31
- package/TODOS.md +0 -5
- package/index.ts +0 -105
- package/lib/combinators.ts +0 -224
- package/lib/parsers.test.ts +0 -300
- package/lib/parsers.ts +0 -108
- package/lib/trace.ts +0 -40
- package/lib/types.ts +0 -24
- package/lib/utils.ts +0 -33
- package/makefile +0 -5
- package/tests/combinators/many.test.ts +0 -18
- package/tests/combinators/many1.test.ts +0 -20
- package/tests/combinators/or.test.ts +0 -25
- package/tests/combinators/seq.test.ts +0 -38
- package/tests/integration/hello_capture.test.ts +0 -21
- package/tests/integration/hello_world.test.ts +0 -14
- package/tests/parsers/char.test.ts +0 -30
- package/tests/parsers/noneOf.test.ts +0 -19
- package/tests/parsers/oneOf.test.ts +0 -19
- package/tests/parsers/str.test.ts +0 -35
- package/tsconfig.json +0 -105
- package/vitest.config.ts +0 -23
- package/vitest.globals.ts +0 -20
- /package/{lib/index.ts → dist/index.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Parser } from "./types";
|
|
2
|
+
export declare function many<T>(parser: Parser<T>): Parser<T[]>;
|
|
3
|
+
export declare function many1<T>(parser: Parser<T>): Parser<T[]>;
|
|
4
|
+
export declare function manyWithJoin(parser: Parser<string>): Parser<string>;
|
|
5
|
+
export declare function many1WithJoin(parser: Parser<string>): Parser<string>;
|
|
6
|
+
export declare function or<T>(parsers: Parser<T>[], name?: string): Parser<T>;
|
|
7
|
+
export declare function optional<T>(parser: Parser<T>): Parser<T | null>;
|
|
8
|
+
export declare function not(parser: Parser<any>): Parser<null>;
|
|
9
|
+
export declare function between<O, C, P>(open: Parser<O>, close: Parser<C>, parser: Parser<P>): Parser<P>;
|
|
10
|
+
export declare function sepBy<S, P>(separator: Parser<S>, parser: Parser<P>): Parser<P[]>;
|
|
11
|
+
export declare function seq<M, C extends string>(parsers: Parser<M>[], name?: string): Parser<M[], C>;
|
|
12
|
+
export declare function capture<M, C extends string>(parser: Parser<M>, name: string): Parser<M, C>;
|
|
13
|
+
export declare function captureCaptures<M, C extends string>(parser: Parser<M>, name: string): Parser<M, C>;
|
|
14
|
+
export declare function shapeCaptures<M, C extends string>(parser: Parser<M>, func: (captures: Record<string, any>) => Record<string, any>, name: string): Parser<M, C>;
|
|
15
|
+
export declare function transform<T, X>(parser: Parser<T>, transformerFunc: (x: T) => X): Parser<X>;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transform = exports.shapeCaptures = exports.captureCaptures = exports.capture = exports.seq = exports.sepBy = exports.between = exports.not = exports.optional = exports.or = exports.many1WithJoin = exports.manyWithJoin = exports.many1 = exports.many = void 0;
|
|
4
|
+
const trace_1 = require("./trace");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
function many(parser) {
|
|
7
|
+
return (0, trace_1.trace)("many", (input) => {
|
|
8
|
+
let match = [];
|
|
9
|
+
let rest = input;
|
|
10
|
+
while (true) {
|
|
11
|
+
let result = parser(rest);
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
return { success: true, match, rest };
|
|
14
|
+
}
|
|
15
|
+
match.push(result.match);
|
|
16
|
+
rest = result.rest;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
exports.many = many;
|
|
21
|
+
function many1(parser) {
|
|
22
|
+
return (0, trace_1.trace)(`many1`, (input) => {
|
|
23
|
+
let result = many(parser)(input);
|
|
24
|
+
// this logic doesn't work with optional and not
|
|
25
|
+
if (result.rest !== input) {
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
rest: input,
|
|
31
|
+
message: "expected at least one match",
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
exports.many1 = many1;
|
|
36
|
+
function manyWithJoin(parser) {
|
|
37
|
+
return transform(many(parser), (x) => x.join(""));
|
|
38
|
+
}
|
|
39
|
+
exports.manyWithJoin = manyWithJoin;
|
|
40
|
+
function many1WithJoin(parser) {
|
|
41
|
+
return transform(many1(parser), (x) => x.join(""));
|
|
42
|
+
}
|
|
43
|
+
exports.many1WithJoin = many1WithJoin;
|
|
44
|
+
function or(parsers, name = "") {
|
|
45
|
+
return (0, trace_1.trace)(`or(${name})`, (input) => {
|
|
46
|
+
for (let parser of parsers) {
|
|
47
|
+
let result = parser(input);
|
|
48
|
+
if (result.success) {
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
rest: input,
|
|
55
|
+
message: "all parsers failed",
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
exports.or = or;
|
|
60
|
+
function optional(parser) {
|
|
61
|
+
return (0, trace_1.trace)("optional", (input) => {
|
|
62
|
+
let result = parser(input);
|
|
63
|
+
if (result.success) {
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
return { success: true, match: null, rest: input };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
exports.optional = optional;
|
|
70
|
+
function not(parser) {
|
|
71
|
+
return (0, trace_1.trace)("not", (input) => {
|
|
72
|
+
let result = parser(input);
|
|
73
|
+
if (result.success) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
rest: input,
|
|
77
|
+
message: "unexpected match",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { success: true, match: null, rest: input };
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
exports.not = not;
|
|
84
|
+
function between(open, close, parser) {
|
|
85
|
+
return (input) => {
|
|
86
|
+
const result1 = open(input);
|
|
87
|
+
if (!result1.success) {
|
|
88
|
+
return result1;
|
|
89
|
+
}
|
|
90
|
+
const parserResult = parser(result1.rest);
|
|
91
|
+
if (!parserResult.success) {
|
|
92
|
+
return parserResult;
|
|
93
|
+
}
|
|
94
|
+
const result2 = close(parserResult.rest);
|
|
95
|
+
if (!result2.success) {
|
|
96
|
+
return result2;
|
|
97
|
+
}
|
|
98
|
+
return { success: true, match: parserResult.match, rest: result2.rest };
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
exports.between = between;
|
|
102
|
+
function sepBy(separator, parser) {
|
|
103
|
+
return (input) => {
|
|
104
|
+
let match = [];
|
|
105
|
+
let rest = input;
|
|
106
|
+
while (true) {
|
|
107
|
+
const result = parser(rest);
|
|
108
|
+
if (!result.success) {
|
|
109
|
+
return { success: true, match, rest };
|
|
110
|
+
}
|
|
111
|
+
match.push(result.match);
|
|
112
|
+
rest = result.rest;
|
|
113
|
+
const sepResult = separator(rest);
|
|
114
|
+
if (!sepResult.success) {
|
|
115
|
+
return { success: true, match, rest };
|
|
116
|
+
}
|
|
117
|
+
rest = sepResult.rest;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
exports.sepBy = sepBy;
|
|
122
|
+
function seq(parsers, name = "") {
|
|
123
|
+
return (0, trace_1.trace)(`seq(${name})`, (input) => {
|
|
124
|
+
let match = [];
|
|
125
|
+
let rest = input;
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
let captures = {};
|
|
128
|
+
for (let parser of parsers) {
|
|
129
|
+
let result = parser(rest);
|
|
130
|
+
if (!result.success) {
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
match.push(result.match);
|
|
134
|
+
rest = result.rest;
|
|
135
|
+
if (result.captures) {
|
|
136
|
+
captures = (0, utils_1.mergeCaptures)(captures, result.captures);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return { success: true, match, rest, captures };
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
exports.seq = seq;
|
|
143
|
+
function capture(parser, name) {
|
|
144
|
+
return (0, trace_1.trace)(`captures(${(0, utils_1.escape)(name)})`, (input) => {
|
|
145
|
+
let result = parser(input);
|
|
146
|
+
if (result.success) {
|
|
147
|
+
const captures = {
|
|
148
|
+
[name]: result.match,
|
|
149
|
+
};
|
|
150
|
+
return Object.assign(Object.assign({}, result), { captures: (0, utils_1.mergeCaptures)(result.captures || {}, captures) });
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
exports.capture = capture;
|
|
156
|
+
function captureCaptures(parser, name) {
|
|
157
|
+
return (0, trace_1.trace)(`captures(${(0, utils_1.escape)(name)})`, (input) => {
|
|
158
|
+
let result = parser(input);
|
|
159
|
+
if (result.success) {
|
|
160
|
+
const captures = {
|
|
161
|
+
[name]: result.captures,
|
|
162
|
+
};
|
|
163
|
+
return Object.assign(Object.assign({}, result), { captures: (0, utils_1.mergeCaptures)(result.captures || {}, captures) });
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
exports.captureCaptures = captureCaptures;
|
|
169
|
+
function shapeCaptures(parser, func, name) {
|
|
170
|
+
return (0, trace_1.trace)(`captures(${(0, utils_1.escape)(name)})`, (input) => {
|
|
171
|
+
let result = parser(input);
|
|
172
|
+
if (result.success) {
|
|
173
|
+
const captures = result.captures || {};
|
|
174
|
+
return Object.assign(Object.assign({}, result), { captures: func(captures) });
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
exports.shapeCaptures = shapeCaptures;
|
|
180
|
+
function transform(parser, transformerFunc) {
|
|
181
|
+
return (0, trace_1.trace)(`transform(${transformerFunc})`, (input) => {
|
|
182
|
+
let result = parser(input);
|
|
183
|
+
if (result.success) {
|
|
184
|
+
return Object.assign(Object.assign({}, result), { match: transformerFunc(result.match) });
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
exports.transform = transform;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./parsers"), exports);
|
|
18
|
+
__exportStar(require("./combinators"), exports);
|
|
19
|
+
__exportStar(require("./trace"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Parser } from "./types";
|
|
2
|
+
export declare function char(c: string): Parser<string>;
|
|
3
|
+
export declare function str(s: string): Parser<string>;
|
|
4
|
+
export declare function oneOf(chars: string): Parser<string>;
|
|
5
|
+
export declare function noneOf(chars: string): Parser<string>;
|
|
6
|
+
export declare function anyChar(input: string): Parser<string>;
|
|
7
|
+
export declare const space: Parser<string>;
|
|
8
|
+
export declare const spaces: Parser<string>;
|
|
9
|
+
export declare const digit: Parser<string>;
|
|
10
|
+
export declare const letter: Parser<string>;
|
|
11
|
+
export declare const alphanum: Parser<string>;
|
|
12
|
+
export declare const word: Parser<string>;
|
|
13
|
+
export declare const num: Parser<string>;
|
|
14
|
+
export declare const quote: Parser<string>;
|
|
15
|
+
export declare const tab: Parser<string>;
|
|
16
|
+
export declare const newline: Parser<string>;
|
|
17
|
+
export declare const quotedString: Parser<string, string>;
|
package/dist/parsers.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.quotedString = exports.newline = exports.tab = exports.quote = exports.num = exports.word = exports.alphanum = exports.letter = exports.digit = exports.spaces = exports.space = exports.anyChar = exports.noneOf = exports.oneOf = exports.str = exports.char = void 0;
|
|
4
|
+
const combinators_1 = require("./combinators");
|
|
5
|
+
const trace_1 = require("./trace");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
function char(c) {
|
|
8
|
+
return (0, trace_1.trace)(`char(${(0, utils_1.escape)(c)})`, (input) => {
|
|
9
|
+
if (input.length === 0) {
|
|
10
|
+
return {
|
|
11
|
+
success: false,
|
|
12
|
+
rest: input,
|
|
13
|
+
message: "unexpected end of input",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (input[0] === c) {
|
|
17
|
+
return { success: true, match: c, rest: input.slice(1) };
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
rest: input,
|
|
22
|
+
message: `expected ${c}, got ${input[0]}`,
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.char = char;
|
|
27
|
+
function str(s) {
|
|
28
|
+
return (0, trace_1.trace)(`str(${(0, utils_1.escape)(s)})`, (input) => {
|
|
29
|
+
if (input.substring(0, s.length) === s) {
|
|
30
|
+
return { success: true, match: s, rest: input.slice(s.length) };
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
rest: input,
|
|
35
|
+
message: `expected ${s}, got ${input.substring(0, s.length)}`,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
exports.str = str;
|
|
40
|
+
function oneOf(chars) {
|
|
41
|
+
return (0, trace_1.trace)(`oneOf(${(0, utils_1.escape)(chars)})`, (input) => {
|
|
42
|
+
if (input.length === 0) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
rest: input,
|
|
46
|
+
message: "unexpected end of input",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const c = input[0];
|
|
50
|
+
if (chars.includes(c)) {
|
|
51
|
+
return char(c)(input);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
rest: input,
|
|
56
|
+
message: `expected one of ${(0, utils_1.escape)(chars)}, got ${c}`,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
exports.oneOf = oneOf;
|
|
61
|
+
function noneOf(chars) {
|
|
62
|
+
return (0, trace_1.trace)(`noneOf(${(0, utils_1.escape)(chars)})`, (input) => {
|
|
63
|
+
if (input.length === 0) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
rest: input,
|
|
67
|
+
message: "unexpected end of input",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (chars.includes(input[0])) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
rest: input,
|
|
74
|
+
message: `expected none of ${chars}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return char(input[0])(input);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
exports.noneOf = noneOf;
|
|
81
|
+
function anyChar(input) {
|
|
82
|
+
return (0, trace_1.trace)("anyChar", (input) => {
|
|
83
|
+
if (input.length === 0) {
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
rest: input,
|
|
87
|
+
message: "unexpected end of input",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return { success: true, match: input[0], rest: input.slice(1) };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
exports.anyChar = anyChar;
|
|
94
|
+
exports.space = oneOf(" \t\n\r");
|
|
95
|
+
exports.spaces = (0, combinators_1.many1WithJoin)(exports.space);
|
|
96
|
+
exports.digit = oneOf("0123456789");
|
|
97
|
+
exports.letter = oneOf("abcdefghijklmnopqrstuvwxyz");
|
|
98
|
+
exports.alphanum = oneOf("abcdefghijklmnopqrstuvwxyz0123456789");
|
|
99
|
+
exports.word = (0, combinators_1.many1WithJoin)(exports.letter);
|
|
100
|
+
exports.num = (0, combinators_1.many1WithJoin)(exports.digit);
|
|
101
|
+
exports.quote = oneOf(`'"`);
|
|
102
|
+
exports.tab = char("\t");
|
|
103
|
+
exports.newline = char("\n");
|
|
104
|
+
exports.quotedString = (0, combinators_1.transform)((0, combinators_1.seq)([exports.quote, exports.word, exports.quote], "quotedString"), (x) => x.join(""));
|
package/dist/trace.d.ts
ADDED
package/dist/trace.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trace = exports.resultToString = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const STEP = 2;
|
|
6
|
+
function resultToString(name, result) {
|
|
7
|
+
if (result.success) {
|
|
8
|
+
return `✅ ${name} -- match: ${(0, utils_1.escape)(result.match)}, rest: ${(0, utils_1.escape)(result.rest)}`;
|
|
9
|
+
}
|
|
10
|
+
return `❌ ${name} -- message: ${(0, utils_1.escape)(result.message)}, rest: ${(0, utils_1.escape)(result.rest)}`;
|
|
11
|
+
}
|
|
12
|
+
exports.resultToString = resultToString;
|
|
13
|
+
let level = 0;
|
|
14
|
+
function trace(name, parser) {
|
|
15
|
+
return (input) => {
|
|
16
|
+
if (process.env.DEBUG) {
|
|
17
|
+
console.log(" ".repeat(level) + `🔍 ${name} -- input: ${(0, utils_1.escape)(input)}`);
|
|
18
|
+
}
|
|
19
|
+
level += STEP;
|
|
20
|
+
const result = parser(input);
|
|
21
|
+
level -= STEP;
|
|
22
|
+
if (process.env.DEBUG) {
|
|
23
|
+
console.log(" ".repeat(level) + resultToString(name, result));
|
|
24
|
+
if (result.success && result.captures) {
|
|
25
|
+
console.log(" ".repeat(level) +
|
|
26
|
+
`⭐ ${name} -- captures: ${JSON.stringify(result.captures)}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
exports.trace = trace;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Object = Record<string, string>;
|
|
2
|
+
export type ParserSuccess<M, C extends string> = {
|
|
3
|
+
success: true;
|
|
4
|
+
match: M;
|
|
5
|
+
captures?: Record<C, any>;
|
|
6
|
+
rest: string;
|
|
7
|
+
};
|
|
8
|
+
export type ParserFailure = {
|
|
9
|
+
success: false;
|
|
10
|
+
rest: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
export type ParserOptions = {
|
|
14
|
+
capture: string;
|
|
15
|
+
};
|
|
16
|
+
export type ParserResult<M, C extends string> = ParserSuccess<M, C> | ParserFailure;
|
|
17
|
+
export type Parser<M, C extends string = string> = (input: string) => ParserResult<M, C>;
|
package/dist/types.js
ADDED
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeCaptures = exports.merge = exports.escape = void 0;
|
|
4
|
+
function escape(str) {
|
|
5
|
+
return JSON.stringify(str);
|
|
6
|
+
}
|
|
7
|
+
exports.escape = escape;
|
|
8
|
+
function merge(a, b) {
|
|
9
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
10
|
+
return [...a, ...b];
|
|
11
|
+
}
|
|
12
|
+
else if (Array.isArray(a)) {
|
|
13
|
+
return [...a, b];
|
|
14
|
+
}
|
|
15
|
+
else if (Array.isArray(b)) {
|
|
16
|
+
return [a, ...b];
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return [a, b];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.merge = merge;
|
|
23
|
+
function mergeCaptures(a, b) {
|
|
24
|
+
const result = {};
|
|
25
|
+
Object.keys(a).forEach((key) => {
|
|
26
|
+
result[key] = a[key];
|
|
27
|
+
});
|
|
28
|
+
Object.keys(b).forEach((key) => {
|
|
29
|
+
if (result[key]) {
|
|
30
|
+
result[key] = merge(result[key], b[key]);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
result[key] = b[key];
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
exports.mergeCaptures = mergeCaptures;
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tarsec",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A parser combinator library for TypeScript, inspired by Parsec.",
|
|
5
|
+
"homepage": "https://github.com/egonSchiele/tarsec",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"test": "vitest",
|
|
7
8
|
"build": "tsc",
|
|
8
9
|
"start": "cd dist && node index.js"
|
|
9
10
|
},
|
|
11
|
+
"files": ["./dist"],
|
|
10
12
|
"keywords": [],
|
|
11
13
|
"author": "",
|
|
12
14
|
"license": "ISC",
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
|
3
|
-
|
|
4
|
-
name: Node.js CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ "main" ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ "main" ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version: [16.x, 18.x]
|
|
20
|
-
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
21
|
-
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v3
|
|
24
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
-
uses: actions/setup-node@v3
|
|
26
|
-
with:
|
|
27
|
-
node-version: ${{ matrix.node-version }}
|
|
28
|
-
cache: 'npm'
|
|
29
|
-
- run: npm install
|
|
30
|
-
- run: npm run build --if-present
|
|
31
|
-
- run: npm test
|
package/TODOS.md
DELETED
package/index.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
seq,
|
|
3
|
-
capture,
|
|
4
|
-
many1WithJoin,
|
|
5
|
-
many,
|
|
6
|
-
optional,
|
|
7
|
-
or,
|
|
8
|
-
manyWithJoin,
|
|
9
|
-
transform,
|
|
10
|
-
many1,
|
|
11
|
-
captureCaptures,
|
|
12
|
-
shapeCaptures,
|
|
13
|
-
} from "./lib/combinators.js";
|
|
14
|
-
import {
|
|
15
|
-
noneOf,
|
|
16
|
-
space,
|
|
17
|
-
str,
|
|
18
|
-
char,
|
|
19
|
-
quote,
|
|
20
|
-
word,
|
|
21
|
-
quotedString,
|
|
22
|
-
} from "./lib/parsers.js";
|
|
23
|
-
/*
|
|
24
|
-
const helloParser = seq<any, "name">([
|
|
25
|
-
str("hello"),
|
|
26
|
-
space,
|
|
27
|
-
capture<string, "name">(many1WithJoin(noneOf("!")), "name"),
|
|
28
|
-
char("!"),
|
|
29
|
-
]);
|
|
30
|
-
|
|
31
|
-
const questionParser = seq<any, "question">([
|
|
32
|
-
capture<string, "question">(many1WithJoin(noneOf("?")), "question"),
|
|
33
|
-
char("?"),
|
|
34
|
-
]);
|
|
35
|
-
|
|
36
|
-
const parser = seq<any, "name" | "question">([
|
|
37
|
-
helloParser,
|
|
38
|
-
space,
|
|
39
|
-
questionParser,
|
|
40
|
-
]);
|
|
41
|
-
|
|
42
|
-
const result = parser("hello adit! how are you?");
|
|
43
|
-
console.log(result); */
|
|
44
|
-
|
|
45
|
-
/*
|
|
46
|
-
if (result.success) {
|
|
47
|
-
console.log(result.captures?.name);
|
|
48
|
-
} */
|
|
49
|
-
|
|
50
|
-
const input = `terraform {
|
|
51
|
-
required_providers {
|
|
52
|
-
aws = {
|
|
53
|
-
source = "hashicorp"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}`;
|
|
57
|
-
|
|
58
|
-
const line = seq<any, string>(
|
|
59
|
-
[
|
|
60
|
-
many(space),
|
|
61
|
-
capture(word, "key"),
|
|
62
|
-
many(space),
|
|
63
|
-
char("="),
|
|
64
|
-
many(space),
|
|
65
|
-
capture(quotedString, "value"),
|
|
66
|
-
],
|
|
67
|
-
"line"
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
let block: any = char("{");
|
|
71
|
-
block = shapeCaptures(
|
|
72
|
-
seq<any, string>(
|
|
73
|
-
[
|
|
74
|
-
manyWithJoin(space),
|
|
75
|
-
capture(
|
|
76
|
-
or(
|
|
77
|
-
[str("terraform"), str("required_providers"), str("aws")],
|
|
78
|
-
"blockName"
|
|
79
|
-
),
|
|
80
|
-
"blockName"
|
|
81
|
-
),
|
|
82
|
-
space,
|
|
83
|
-
optional(str("= ")),
|
|
84
|
-
char("{"),
|
|
85
|
-
manyWithJoin(space),
|
|
86
|
-
// this works
|
|
87
|
-
or([line, (x) => block(x)], "line or block"),
|
|
88
|
-
// but this doesnt
|
|
89
|
-
// many(or([line, (x) => block(x)], "line or block")),
|
|
90
|
-
// nor this
|
|
91
|
-
// many1(or([line, (x) => block(x)], "line or block")),
|
|
92
|
-
manyWithJoin(space),
|
|
93
|
-
char("}"),
|
|
94
|
-
],
|
|
95
|
-
"block"
|
|
96
|
-
),
|
|
97
|
-
({ blockName }) => ({ blockName }),
|
|
98
|
-
"block"
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const result2 = block(input);
|
|
102
|
-
console.log(result2);
|
|
103
|
-
if (result2.success) {
|
|
104
|
-
console.log(JSON.stringify(result2.captures, null, 2));
|
|
105
|
-
}
|