@bablr/helpers 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/builders.js +380 -192
- package/lib/decorators.js +0 -11
- package/lib/grammar.js +186 -43
- package/lib/productions.js +41 -57
- package/lib/shorthand.js +1 -1
- package/lib/source.js +17 -10
- package/lib/trivia.js +180 -319
- package/package.json +12 -15
- package/lib/productions.macro.js +0 -89
package/lib/builders.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
// import { i } from '@bablr/boot/shorthand.macro';
|
|
2
1
|
import { interpolateFragment, buildFilledGapFunction } from '@bablr/agast-helpers/template';
|
|
3
|
-
import {
|
|
4
|
-
buildNullNode,
|
|
5
|
-
getRootArray,
|
|
6
|
-
treeFromStreamSync as treeFromStream,
|
|
7
|
-
} from '@bablr/agast-helpers/tree';
|
|
2
|
+
import { get, isEmpty, treeFromStreamSync as treeFromStream } from '@bablr/agast-helpers/tree';
|
|
8
3
|
import { buildLiteralTag as agastBuildLiteralTag } from '@bablr/agast-helpers/builders';
|
|
9
4
|
import * as t from '@bablr/agast-helpers/shorthand';
|
|
10
|
-
import * as
|
|
5
|
+
import * as Tags from '@bablr/agast-helpers/tags';
|
|
11
6
|
import * as l from '@bablr/agast-vm-helpers/languages';
|
|
12
7
|
import { concat } from '@bablr/agast-vm-helpers/iterable';
|
|
8
|
+
import { buildNullNode } from '@bablr/agast-helpers/path';
|
|
13
9
|
|
|
14
10
|
const { freeze } = Object;
|
|
15
11
|
const { isArray } = Array;
|
|
@@ -18,7 +14,7 @@ const when = (condition, value) => (condition ? value : { *[Symbol.iterator]() {
|
|
|
18
14
|
|
|
19
15
|
const isString = (val) => typeof val === 'string';
|
|
20
16
|
|
|
21
|
-
export const buildReferenceTag = (name,
|
|
17
|
+
export const buildReferenceTag = (name, flags = t.referenceFlags) => {
|
|
22
18
|
let expressions = [];
|
|
23
19
|
const gap = buildFilledGapFunction(expressions);
|
|
24
20
|
|
|
@@ -27,14 +23,102 @@ export const buildReferenceTag = (name, isArray = false, flags = t.referenceFlag
|
|
|
27
23
|
t.nodeOpen(t.nodeFlags, 'ReferenceTag'),
|
|
28
24
|
t.ref`name`,
|
|
29
25
|
gap(name ? buildIdentifier(name) : buildNullNode()),
|
|
30
|
-
t.ref`openIndexToken`,
|
|
31
|
-
gap(isArray ? buildToken('Punctuator', '[') : buildNullNode()),
|
|
32
|
-
t.ref`closeIndexToken`,
|
|
33
|
-
gap(isArray ? buildToken('Punctuator', ']') : buildNullNode()),
|
|
34
26
|
t.ref`flags`,
|
|
35
27
|
gap(flags ? buildReferenceFlags(flags) : buildNullNode()),
|
|
36
28
|
t.ref`sigilToken`,
|
|
37
|
-
gap(buildToken(
|
|
29
|
+
gap(buildToken(null, ':')),
|
|
30
|
+
t.nodeClose(),
|
|
31
|
+
],
|
|
32
|
+
{ expressions },
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const buildBindingMatcher = (segments) => {
|
|
37
|
+
let expressions = [];
|
|
38
|
+
const gap = buildFilledGapFunction(expressions);
|
|
39
|
+
|
|
40
|
+
return treeFromStream(
|
|
41
|
+
concat(
|
|
42
|
+
[t.nodeOpen(t.nodeFlags, 'BindingMatcher')],
|
|
43
|
+
segments.flatMap((segment) => [t.ref`segments[]`, gap(buildBindingSegment(segment))]),
|
|
44
|
+
[t.nodeClose()],
|
|
45
|
+
),
|
|
46
|
+
{ expressions },
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const buildBindingMatchers = (matchers) => {
|
|
51
|
+
let expressions = [];
|
|
52
|
+
const gap = buildFilledGapFunction(expressions);
|
|
53
|
+
|
|
54
|
+
return treeFromStream(
|
|
55
|
+
concat(
|
|
56
|
+
[t.fragOpen()],
|
|
57
|
+
matchers.flatMap((matcher) => [
|
|
58
|
+
t.ref`bindingMatchers[]`,
|
|
59
|
+
gap(buildBindingMatcher(matcher.segments)),
|
|
60
|
+
]),
|
|
61
|
+
[t.nodeClose()],
|
|
62
|
+
),
|
|
63
|
+
{ expressions },
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const buildBoundNodeMatcher = (bindingMatchers, valueMatcher) => {
|
|
68
|
+
if (valueMatcher.value.name.description === 'BoundNodeMatcher') throw new Error();
|
|
69
|
+
const expressions = [];
|
|
70
|
+
const gap = buildFilledGapFunction(expressions);
|
|
71
|
+
|
|
72
|
+
return treeFromStream(
|
|
73
|
+
(function* () {
|
|
74
|
+
yield t.nodeOpen(t.nodeFlags, 'BoundNodeMatcher');
|
|
75
|
+
if (bindingMatchers.length) {
|
|
76
|
+
yield* interpolateFragment(
|
|
77
|
+
buildBindingMatchers(bindingMatchers),
|
|
78
|
+
t.ref`bindingMatchers`,
|
|
79
|
+
expressions,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
yield t.ref`nodeMatcher`;
|
|
83
|
+
yield gap(valueMatcher);
|
|
84
|
+
yield t.nodeClose();
|
|
85
|
+
})(),
|
|
86
|
+
{ expressions },
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const buildPropertyMatcher = (refMatcher, valueMatcher) => {
|
|
91
|
+
const expressions = [];
|
|
92
|
+
const gap = buildFilledGapFunction(expressions);
|
|
93
|
+
|
|
94
|
+
return treeFromStream(
|
|
95
|
+
(function* () {
|
|
96
|
+
yield t.nodeOpen(t.nodeFlags, 'PropertyMatcher');
|
|
97
|
+
yield t.ref`refMatcher`;
|
|
98
|
+
yield gap(refMatcher || buildNullNode());
|
|
99
|
+
yield t.ref`valueMatcher`;
|
|
100
|
+
yield gap(valueMatcher || buildNullNode());
|
|
101
|
+
yield t.nodeClose();
|
|
102
|
+
})(),
|
|
103
|
+
{ expressions },
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const buildBindingSegment = (segment) => {
|
|
108
|
+
let expressions = [];
|
|
109
|
+
const gap = buildFilledGapFunction(expressions);
|
|
110
|
+
|
|
111
|
+
let { type, name } = segment;
|
|
112
|
+
|
|
113
|
+
return treeFromStream(
|
|
114
|
+
[
|
|
115
|
+
t.nodeOpen(t.nodeFlags, 'BindingSegment'),
|
|
116
|
+
t.ref`openToken`,
|
|
117
|
+
gap(buildToken(null, ':')),
|
|
118
|
+
t.ref`path`,
|
|
119
|
+
gap(type ? buildToken(null, type) : buildIdentifier(name)),
|
|
120
|
+
t.ref`closeToken`,
|
|
121
|
+
gap(buildToken(null, ':')),
|
|
38
122
|
t.nodeClose(),
|
|
39
123
|
],
|
|
40
124
|
{ expressions },
|
|
@@ -47,9 +131,9 @@ export const buildGapTag = () => {
|
|
|
47
131
|
|
|
48
132
|
return treeFromStream(
|
|
49
133
|
[
|
|
50
|
-
t.nodeOpen(t.nodeFlags, '
|
|
134
|
+
t.nodeOpen(t.nodeFlags, 'GapTag'),
|
|
51
135
|
t.ref`sigilToken`,
|
|
52
|
-
gap(buildToken(
|
|
136
|
+
gap(buildToken(null, '<//>')),
|
|
53
137
|
t.nodeClose(),
|
|
54
138
|
],
|
|
55
139
|
{ expressions },
|
|
@@ -64,7 +148,7 @@ export const buildShiftTag = () => {
|
|
|
64
148
|
[
|
|
65
149
|
t.nodeOpen(t.nodeFlags, 'ShiftTag'),
|
|
66
150
|
t.ref`sigilToken`,
|
|
67
|
-
gap(buildToken(
|
|
151
|
+
gap(buildToken(null, '^^^')),
|
|
68
152
|
t.nodeClose(),
|
|
69
153
|
],
|
|
70
154
|
{ expressions },
|
|
@@ -72,17 +156,21 @@ export const buildShiftTag = () => {
|
|
|
72
156
|
};
|
|
73
157
|
|
|
74
158
|
export const buildReferenceFlags = (flags = t.referenceFlags) => {
|
|
75
|
-
const { expression
|
|
159
|
+
const { array, expression, intrinsic, hasGap } = flags;
|
|
76
160
|
let expressions = [];
|
|
77
161
|
const gap = buildFilledGapFunction(expressions);
|
|
78
162
|
|
|
79
163
|
return treeFromStream(
|
|
80
164
|
[
|
|
81
165
|
t.nodeOpen(t.nodeFlags, 'ReferenceFlags'),
|
|
166
|
+
t.ref`arrayToken`,
|
|
167
|
+
gap(array ? buildToken(null, '[]') : buildNullNode()),
|
|
82
168
|
t.ref`expressionToken`,
|
|
83
|
-
gap(expression ? buildToken(
|
|
169
|
+
gap(expression ? buildToken(null, '+') : buildNullNode()),
|
|
170
|
+
t.ref`intrinsicToken`,
|
|
171
|
+
gap(intrinsic ? buildToken(null, '*') : buildNullNode()),
|
|
84
172
|
t.ref`hasGapToken`,
|
|
85
|
-
gap(hasGap ? buildToken(
|
|
173
|
+
gap(hasGap ? buildToken(null, '$') : buildNullNode()),
|
|
86
174
|
t.nodeClose(),
|
|
87
175
|
],
|
|
88
176
|
{ expressions },
|
|
@@ -90,86 +178,113 @@ export const buildReferenceFlags = (flags = t.referenceFlags) => {
|
|
|
90
178
|
};
|
|
91
179
|
|
|
92
180
|
export const buildNodeFlags = (flags = t.nodeFlags) => {
|
|
93
|
-
const { token = null, hasGap = null
|
|
181
|
+
const { token = null, hasGap = null } = flags;
|
|
94
182
|
let expressions = [];
|
|
95
183
|
const gap = buildFilledGapFunction(expressions);
|
|
96
184
|
|
|
185
|
+
let flags_ = { token, hasGap };
|
|
186
|
+
let attributes = flags_;
|
|
187
|
+
|
|
97
188
|
return treeFromStream(
|
|
98
189
|
[
|
|
99
|
-
t.nodeOpen(t.nodeFlags, 'NodeFlags'),
|
|
190
|
+
t.nodeOpen(t.nodeFlags, 'NodeFlags', null, attributes),
|
|
100
191
|
t.ref`tokenToken`,
|
|
101
|
-
gap(token ? buildToken(
|
|
192
|
+
gap(token ? buildToken(null, '*') : buildNullNode()),
|
|
102
193
|
t.ref`hasGapToken`,
|
|
103
|
-
gap(hasGap ? buildToken(
|
|
104
|
-
t.ref`fragmentToken`,
|
|
105
|
-
gap(fragment ? buildToken('Punctuator', '_') : buildNullNode()),
|
|
106
|
-
t.ref`coverFragmentToken`,
|
|
107
|
-
gap(cover ? buildToken('Punctuator', '_') : buildNullNode()),
|
|
194
|
+
gap(hasGap ? buildToken(null, '$') : buildNullNode()),
|
|
108
195
|
t.nodeClose(),
|
|
109
196
|
],
|
|
110
197
|
{ expressions },
|
|
111
198
|
);
|
|
112
199
|
};
|
|
113
200
|
|
|
114
|
-
export const buildSpamMatcher = (
|
|
115
|
-
return
|
|
201
|
+
export const buildSpamMatcher = (name = null, value = null, attributes = null) => {
|
|
202
|
+
return buildTreeNodeMatcherOpen(buildNodeFlags(t.nodeFlags), null, name, value, attributes);
|
|
116
203
|
};
|
|
117
204
|
|
|
118
|
-
export const
|
|
205
|
+
export const buildTreeNodeMatcherOpen = (flags, type, name, literalValue, attributes = null) => {
|
|
119
206
|
const expressions = [];
|
|
120
207
|
const gap = buildFilledGapFunction(expressions);
|
|
121
208
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!type) throw new Error();
|
|
209
|
+
if (!type && !name) throw new Error();
|
|
125
210
|
|
|
126
211
|
return treeFromStream(
|
|
127
212
|
(function* () {
|
|
128
|
-
yield t.nodeOpen(t.nodeFlags, '
|
|
213
|
+
yield t.nodeOpen(t.nodeFlags, 'TreeNodeMatcherOpen');
|
|
129
214
|
yield t.ref`openToken`;
|
|
130
|
-
yield gap(buildToken(
|
|
215
|
+
yield gap(buildToken(null, '<'));
|
|
131
216
|
yield t.ref`flags`;
|
|
132
217
|
yield gap(flags);
|
|
133
218
|
yield t.ref`type`;
|
|
134
|
-
yield gap(typeof type === 'string' ?
|
|
135
|
-
|
|
136
|
-
yield
|
|
219
|
+
yield gap(typeof type === 'string' ? buildToken(null, type) : type);
|
|
220
|
+
yield t.ref`name`;
|
|
221
|
+
yield gap(typeof name === 'string' ? buildIdentifier(name) : name);
|
|
137
222
|
|
|
138
|
-
yield t.ref
|
|
139
|
-
yield gap(intrinsicValue ? buildString(intrinsicValue) : buildNullNode());
|
|
223
|
+
yield* when(literalValue, [t.ref`#`, ...Tags.traverse(buildSpace().value.tags)]);
|
|
140
224
|
|
|
141
|
-
|
|
225
|
+
yield t.ref`literalValue`;
|
|
226
|
+
yield gap(literalValue ? buildString(literalValue) : buildNullNode());
|
|
142
227
|
|
|
143
|
-
if (
|
|
228
|
+
if (!isEmpty(attributes)) {
|
|
144
229
|
yield t.ref`#`;
|
|
145
|
-
yield* buildSpace().
|
|
230
|
+
yield* buildSpace().value.tags;
|
|
146
231
|
yield* interpolateFragment(attributes, t.ref`attributes[]`, expressions);
|
|
147
232
|
}
|
|
148
233
|
|
|
149
|
-
yield t.ref`
|
|
150
|
-
yield gap(buildToken(
|
|
234
|
+
yield t.ref`selfClosingToken`;
|
|
235
|
+
yield gap(buildToken(null, '/'));
|
|
151
236
|
yield t.ref`closeToken`;
|
|
152
|
-
yield gap(buildToken(
|
|
237
|
+
yield gap(buildToken(null, '>'));
|
|
153
238
|
yield t.nodeClose();
|
|
154
239
|
})(),
|
|
155
240
|
{ expressions },
|
|
156
241
|
);
|
|
157
242
|
};
|
|
158
243
|
|
|
159
|
-
export const
|
|
244
|
+
export const buildTreeNodeMatcher = (open, children) => {
|
|
160
245
|
const expressions = [];
|
|
161
246
|
const gap = buildFilledGapFunction(expressions);
|
|
162
247
|
|
|
248
|
+
let children_ = children;
|
|
249
|
+
|
|
250
|
+
if (children_) {
|
|
251
|
+
throw new Error('not implemented');
|
|
252
|
+
// if (isArray(children_)) {
|
|
253
|
+
// children_ = buildTreeNodeMatcherChildren(children_);
|
|
254
|
+
// }
|
|
255
|
+
}
|
|
256
|
+
|
|
163
257
|
return treeFromStream(
|
|
164
|
-
|
|
258
|
+
(function* () {
|
|
259
|
+
yield t.nodeOpen(t.nodeFlags, 'TreeNodeMatcher');
|
|
260
|
+
yield t.ref`open`;
|
|
261
|
+
yield gap(open);
|
|
262
|
+
if (!isEmpty(children_)) {
|
|
263
|
+
yield* interpolateFragment(children_, t.ref`children[]`, expressions);
|
|
264
|
+
}
|
|
265
|
+
yield t.nodeClose();
|
|
266
|
+
})(),
|
|
165
267
|
{ expressions },
|
|
166
268
|
);
|
|
167
269
|
};
|
|
168
270
|
|
|
169
|
-
export const buildReferenceMatcher = (type, name,
|
|
271
|
+
export const buildReferenceMatcher = (type = '.', name, flags) => {
|
|
170
272
|
const expressions = [];
|
|
171
273
|
const gap = buildFilledGapFunction(expressions);
|
|
172
274
|
|
|
275
|
+
if (isString(flags)) {
|
|
276
|
+
let array = flags.includes('[');
|
|
277
|
+
let intrinsic = flags.includes('*');
|
|
278
|
+
let hasGap = flags.includes('$');
|
|
279
|
+
let expression = flags.includes('+');
|
|
280
|
+
|
|
281
|
+
return buildReferenceMatcher(
|
|
282
|
+
type,
|
|
283
|
+
name,
|
|
284
|
+
buildReferenceFlags({ array, intrinsic, hasGap, expression }),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
173
288
|
return treeFromStream(
|
|
174
289
|
(function* () {
|
|
175
290
|
yield t.nodeOpen(t.nodeFlags, 'ReferenceMatcher');
|
|
@@ -177,56 +292,31 @@ export const buildReferenceMatcher = (type, name, isArray, flags) => {
|
|
|
177
292
|
yield gap(type && buildKeyword(type));
|
|
178
293
|
yield t.ref`name`;
|
|
179
294
|
yield gap(name && buildIdentifier(name));
|
|
180
|
-
yield* (function* () {
|
|
181
|
-
if (isArray) {
|
|
182
|
-
yield t.ref`openIndexToken`;
|
|
183
|
-
yield gap(buildToken('Punctuator', '['));
|
|
184
|
-
yield t.ref`closeIndexToken`;
|
|
185
|
-
yield gap(buildToken('Punctuator', ']'));
|
|
186
|
-
}
|
|
187
|
-
})();
|
|
188
295
|
yield t.ref`flags`;
|
|
189
296
|
yield gap(flags);
|
|
190
297
|
yield t.ref`sigilToken`;
|
|
191
|
-
yield gap(buildToken(
|
|
298
|
+
yield gap(buildToken(null, ':'));
|
|
192
299
|
yield t.ref`#`;
|
|
193
|
-
yield*
|
|
300
|
+
yield* Tags.traverse(buildSpace().value.tags);
|
|
194
301
|
yield t.nodeClose();
|
|
195
302
|
})(),
|
|
196
303
|
{ expressions },
|
|
197
304
|
);
|
|
198
305
|
};
|
|
199
306
|
|
|
200
|
-
export const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return treeFromStream(
|
|
207
|
-
(function* () {
|
|
208
|
-
yield t.nodeOpen(t.nodeFlags, 'FragmentMatcher');
|
|
209
|
-
yield t.ref`openToken`;
|
|
210
|
-
yield gap(buildToken('Punctuator', '<'));
|
|
211
|
-
yield t.ref`flags`;
|
|
212
|
-
yield gap(flags);
|
|
213
|
-
yield t.ref`closeToken`;
|
|
214
|
-
yield gap(buildToken('Punctuator', '/>'));
|
|
215
|
-
yield t.nodeClose();
|
|
216
|
-
})(),
|
|
217
|
-
{ expressions },
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export const buildToken = (type, value, attributes = {}) => {
|
|
222
|
-
return treeFromStream([t.nodeOpen(t.tokenFlags, type, attributes), t.lit(value), t.nodeClose()]);
|
|
307
|
+
export const buildToken = (name, value, attributes = {}) => {
|
|
308
|
+
return treeFromStream([
|
|
309
|
+
t.nodeOpen(t.tokenFlags, name, null, attributes),
|
|
310
|
+
t.lit(value),
|
|
311
|
+
t.nodeClose(),
|
|
312
|
+
]);
|
|
223
313
|
};
|
|
224
314
|
|
|
225
315
|
export const buildPunctuator = (value, attributes = {}) => {
|
|
226
|
-
return buildToken(
|
|
316
|
+
return buildToken(null, value, attributes);
|
|
227
317
|
};
|
|
228
318
|
|
|
229
|
-
export const buildOpenNodeTag = (flags,
|
|
319
|
+
export const buildOpenNodeTag = (flags, name = null, attributes) => {
|
|
230
320
|
const expressions = [];
|
|
231
321
|
const gap = buildFilledGapFunction(expressions);
|
|
232
322
|
|
|
@@ -236,10 +326,9 @@ export const buildOpenNodeTag = (flags, type = null, attributes) => {
|
|
|
236
326
|
yield gap(buildPunctuator('<'));
|
|
237
327
|
yield t.ref`flags`;
|
|
238
328
|
yield gap(buildNodeFlags(flags));
|
|
239
|
-
yield t.ref`
|
|
240
|
-
yield gap(
|
|
241
|
-
|
|
242
|
-
yield* when(rootArr.length, [t.ref`#`, gap(buildSpace())]);
|
|
329
|
+
yield t.ref`name`;
|
|
330
|
+
yield gap(name ? buildIdentifier(name) : buildNullNode());
|
|
331
|
+
yield* when(!isEmpty(attributes), [t.ref`#`, gap(buildSpace())]);
|
|
243
332
|
yield* interpolateFragment(attributes, t.ref`attributes[]`, expressions);
|
|
244
333
|
yield t.ref`closeToken`;
|
|
245
334
|
yield gap(buildPunctuator('>'));
|
|
@@ -256,20 +345,20 @@ export const buildDoctypeTag = (attributes) => {
|
|
|
256
345
|
(function* () {
|
|
257
346
|
yield t.nodeOpen(t.nodeFlags, 'DoctypeTag');
|
|
258
347
|
yield t.ref`openToken`;
|
|
259
|
-
yield gap(buildPunctuator('
|
|
348
|
+
yield gap(buildPunctuator('<!'));
|
|
260
349
|
yield t.ref`version`;
|
|
261
350
|
yield gap(buildToken('PositiveInteger', '0'));
|
|
262
351
|
yield t.ref`versionSeparator`;
|
|
263
|
-
yield gap(buildPunctuator('
|
|
352
|
+
yield gap(buildPunctuator(':'));
|
|
264
353
|
yield t.ref`doctype`;
|
|
265
354
|
yield gap(buildKeyword('cstml'));
|
|
266
355
|
yield t.nodeClose();
|
|
267
356
|
|
|
268
|
-
yield* when(
|
|
357
|
+
yield* when(!isEmpty(attributes), [t.ref`#`, ...buildSpace().value.tags]);
|
|
269
358
|
yield* interpolateFragment(attributes, t.ref`attributes[]`, expressions);
|
|
270
359
|
|
|
271
360
|
yield t.ref`closeToken`;
|
|
272
|
-
yield gap(buildToken(
|
|
361
|
+
yield gap(buildToken(null, '>'));
|
|
273
362
|
})(),
|
|
274
363
|
{ expressions },
|
|
275
364
|
);
|
|
@@ -287,19 +376,15 @@ export const buildIdentifierPath = (path) => {
|
|
|
287
376
|
return treeFromStream(
|
|
288
377
|
(function* () {
|
|
289
378
|
yield t.nodeOpen(t.nodeFlags, 'IdentifierPath');
|
|
290
|
-
yield t.ref`segments[]`;
|
|
291
|
-
yield t.arr();
|
|
292
|
-
yield t.ref`separatorTokens[]`;
|
|
293
|
-
yield t.arr();
|
|
294
379
|
|
|
295
380
|
yield* path_
|
|
296
|
-
.flatMap((
|
|
381
|
+
.flatMap((segment) => [
|
|
297
382
|
t.ref`segments[]`,
|
|
298
|
-
gap(buildIdentifier(name)),
|
|
299
|
-
t.ref
|
|
300
|
-
gap(buildToken(
|
|
383
|
+
gap(segment.type ? buildPunctuator(segment.type) : buildIdentifier(segment.name)),
|
|
384
|
+
t.ref`#separatorTokens`,
|
|
385
|
+
gap(buildToken(null, '.')),
|
|
301
386
|
])
|
|
302
|
-
.slice(0, -
|
|
387
|
+
.slice(0, -2);
|
|
303
388
|
|
|
304
389
|
yield t.nodeClose();
|
|
305
390
|
})(),
|
|
@@ -321,9 +406,9 @@ export const buildCloseNodeTag = () => {
|
|
|
321
406
|
[
|
|
322
407
|
t.nodeOpen(t.nodeFlags, 'CloseNodeTag'),
|
|
323
408
|
t.ref`openToken`,
|
|
324
|
-
gap(buildToken(
|
|
409
|
+
gap(buildToken(null, '</')),
|
|
325
410
|
t.ref`closeToken`,
|
|
326
|
-
gap(buildToken(
|
|
411
|
+
gap(buildToken(null, '>')),
|
|
327
412
|
t.nodeClose(),
|
|
328
413
|
],
|
|
329
414
|
{ expressions },
|
|
@@ -340,7 +425,8 @@ export const buildLiteralTag = (value) => {
|
|
|
340
425
|
};
|
|
341
426
|
|
|
342
427
|
export const buildTerminalProps = (matcher) => {
|
|
343
|
-
const
|
|
428
|
+
const value = get('value', matcher);
|
|
429
|
+
const attributes = get('attributes', matcher);
|
|
344
430
|
|
|
345
431
|
return buildObject({ value, attributes });
|
|
346
432
|
};
|
|
@@ -350,20 +436,68 @@ export const buildSpace = () => {
|
|
|
350
436
|
};
|
|
351
437
|
|
|
352
438
|
export const buildIdentifier = (name) => {
|
|
353
|
-
|
|
354
|
-
|
|
439
|
+
let unquoted = /^[a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*$/uy.test(name);
|
|
355
440
|
const expressions = [];
|
|
356
441
|
const gap = buildFilledGapFunction(expressions);
|
|
357
442
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
443
|
+
if (unquoted) {
|
|
444
|
+
return treeFromStream(
|
|
445
|
+
[
|
|
446
|
+
t.nodeOpen(t.nodeFlags, 'Identifier'),
|
|
447
|
+
t.ref`content`,
|
|
448
|
+
gap(buildIdentifierContent(name)),
|
|
449
|
+
t.nodeClose(),
|
|
450
|
+
],
|
|
451
|
+
{ expressions },
|
|
452
|
+
);
|
|
453
|
+
} else {
|
|
454
|
+
return treeFromStream(
|
|
455
|
+
(function* () {
|
|
456
|
+
yield t.nodeOpen(t.nodeFlags, 'Identifier');
|
|
457
|
+
|
|
458
|
+
yield t.ref`openToken`;
|
|
459
|
+
yield gap(buildToken(null, '`'));
|
|
460
|
+
yield t.ref`content`;
|
|
461
|
+
yield t.nodeOpen(t.tokenFlags, 'IdentifierContent');
|
|
462
|
+
|
|
463
|
+
let lit = '';
|
|
464
|
+
|
|
465
|
+
let pieces = name.split(/[\\`]/g);
|
|
466
|
+
|
|
467
|
+
for (const piece of pieces) {
|
|
468
|
+
if (/[\\`]/y.test(piece)) {
|
|
469
|
+
let chr = piece;
|
|
470
|
+
if (lit) {
|
|
471
|
+
yield agastBuildLiteralTag(lit);
|
|
472
|
+
lit = '';
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
let value = buildKeyword(chr);
|
|
476
|
+
|
|
477
|
+
yield t.ref`@`;
|
|
478
|
+
yield t.nodeOpen(t.nodeFlags, 'EscapeSequence', null, { cooked: chr });
|
|
479
|
+
yield t.ref`escape`;
|
|
480
|
+
yield gap(buildToken(null, '\\'));
|
|
481
|
+
yield t.ref`value`;
|
|
482
|
+
yield gap(value);
|
|
483
|
+
yield t.nodeClose();
|
|
484
|
+
} else {
|
|
485
|
+
lit += piece;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (lit) yield agastBuildLiteralTag(lit);
|
|
490
|
+
lit = '';
|
|
491
|
+
|
|
492
|
+
yield t.nodeClose();
|
|
493
|
+
|
|
494
|
+
yield t.ref`closeToken`;
|
|
495
|
+
yield gap(buildToken(null, '`'));
|
|
496
|
+
yield t.nodeClose();
|
|
497
|
+
})(),
|
|
498
|
+
{ expressions },
|
|
499
|
+
);
|
|
500
|
+
}
|
|
367
501
|
};
|
|
368
502
|
|
|
369
503
|
export const buildIdentifierContent = (value) => {
|
|
@@ -371,7 +505,7 @@ export const buildIdentifierContent = (value) => {
|
|
|
371
505
|
};
|
|
372
506
|
|
|
373
507
|
export const buildKeyword = (name) => {
|
|
374
|
-
return buildToken(
|
|
508
|
+
return buildToken(null, name);
|
|
375
509
|
};
|
|
376
510
|
|
|
377
511
|
export const buildCall = (verb, args) => {
|
|
@@ -401,7 +535,7 @@ export const buildProperty = (key, value) => {
|
|
|
401
535
|
yield t.ref`key`;
|
|
402
536
|
yield gap(key);
|
|
403
537
|
yield t.ref`mapOperator`;
|
|
404
|
-
yield gap(buildToken(
|
|
538
|
+
yield gap(buildToken(null, ':'));
|
|
405
539
|
yield t.ref`#`;
|
|
406
540
|
yield gap(buildSpace());
|
|
407
541
|
yield t.ref`value`;
|
|
@@ -431,7 +565,7 @@ export const buildInteger = (value, base = 10) => {
|
|
|
431
565
|
|
|
432
566
|
return treeFromStream(
|
|
433
567
|
concat(
|
|
434
|
-
[t.nodeOpen(t.nodeFlags, 'Integer')
|
|
568
|
+
[t.nodeOpen(t.nodeFlags, 'Integer')],
|
|
435
569
|
digits.flatMap((digit) => [t.ref`digits[]`, gap(buildDigit(digit))]),
|
|
436
570
|
[t.nodeClose()],
|
|
437
571
|
),
|
|
@@ -457,9 +591,9 @@ export const buildInfinity = (value) => {
|
|
|
457
591
|
[
|
|
458
592
|
t.nodeOpen(t.nodeFlags, 'Infinity'),
|
|
459
593
|
t.ref`sign`,
|
|
460
|
-
gap(buildToken(
|
|
594
|
+
gap(buildToken(null, sign)),
|
|
461
595
|
t.ref`value`,
|
|
462
|
-
gap(buildToken(
|
|
596
|
+
gap(buildToken(null, 'Infinity')),
|
|
463
597
|
t.nodeClose(),
|
|
464
598
|
],
|
|
465
599
|
{ expressions },
|
|
@@ -486,11 +620,11 @@ export const buildString = (value) => {
|
|
|
486
620
|
[
|
|
487
621
|
t.nodeOpen(t.nodeFlags, 'String'),
|
|
488
622
|
t.ref`openToken`,
|
|
489
|
-
gap(buildToken(
|
|
623
|
+
gap(buildToken(null, '"')),
|
|
490
624
|
t.ref`content`,
|
|
491
625
|
gap(buildToken('StringContent', value)),
|
|
492
626
|
t.ref`closeToken`,
|
|
493
|
-
gap(buildToken(
|
|
627
|
+
gap(buildToken(null, '"')),
|
|
494
628
|
t.nodeClose(),
|
|
495
629
|
],
|
|
496
630
|
{ expressions },
|
|
@@ -504,7 +638,7 @@ export const buildString = (value) => {
|
|
|
504
638
|
(function* () {
|
|
505
639
|
yield t.nodeOpen(t.nodeFlags, 'String');
|
|
506
640
|
yield t.ref`openToken`;
|
|
507
|
-
const tok = buildToken(
|
|
641
|
+
const tok = buildToken(null, "'");
|
|
508
642
|
yield gap(tok);
|
|
509
643
|
yield t.ref`content`;
|
|
510
644
|
yield t.nodeOpen(t.tokenFlags, 'StringContent');
|
|
@@ -539,8 +673,6 @@ export const buildString = (value) => {
|
|
|
539
673
|
t.nodeOpen(t.nodeFlags, 'EscapeCode'),
|
|
540
674
|
t.ref`sigilToken`,
|
|
541
675
|
gap(buildKeyword(escapables[chr])),
|
|
542
|
-
t.ref`digits[]`,
|
|
543
|
-
t.arr(),
|
|
544
676
|
t.nodeClose(),
|
|
545
677
|
],
|
|
546
678
|
{ expressions },
|
|
@@ -555,8 +687,6 @@ export const buildString = (value) => {
|
|
|
555
687
|
t.nodeOpen(t.nodeFlags, 'EscapeCode'),
|
|
556
688
|
t.ref`sigilToken`,
|
|
557
689
|
gap(buildKeyword('u')),
|
|
558
|
-
t.ref`digits[]`,
|
|
559
|
-
t.arr(),
|
|
560
690
|
[...hexDigits].flatMap((digit) => [t.ref`digits[]`, gap(buildDigit(digit))]),
|
|
561
691
|
t.nodeClose(),
|
|
562
692
|
],
|
|
@@ -567,9 +697,9 @@ export const buildString = (value) => {
|
|
|
567
697
|
}
|
|
568
698
|
|
|
569
699
|
yield t.ref`@`;
|
|
570
|
-
yield t.nodeOpen(t.nodeFlags, 'EscapeSequence', { cooked: chr });
|
|
700
|
+
yield t.nodeOpen(t.nodeFlags, 'EscapeSequence', null, { cooked: chr });
|
|
571
701
|
yield t.ref`escape`;
|
|
572
|
-
yield gap(buildToken(
|
|
702
|
+
yield gap(buildToken(null, '\\'));
|
|
573
703
|
yield t.ref`value`;
|
|
574
704
|
yield gap(value);
|
|
575
705
|
yield t.nodeClose();
|
|
@@ -596,7 +726,7 @@ export const buildString = (value) => {
|
|
|
596
726
|
|
|
597
727
|
yield t.nodeClose();
|
|
598
728
|
yield t.ref`closeToken`;
|
|
599
|
-
yield gap(buildToken(
|
|
729
|
+
yield gap(buildToken(null, "'"));
|
|
600
730
|
yield t.nodeClose();
|
|
601
731
|
})(),
|
|
602
732
|
{ expressions },
|
|
@@ -611,7 +741,7 @@ export const buildBoolean = (value) => {
|
|
|
611
741
|
[
|
|
612
742
|
t.nodeOpen(t.nodeFlags, 'Boolean'),
|
|
613
743
|
t.ref`sigilToken`,
|
|
614
|
-
gap(buildToken(
|
|
744
|
+
gap(buildToken(null, value ? 'true' : 'false')),
|
|
615
745
|
t.nodeClose(),
|
|
616
746
|
],
|
|
617
747
|
{ expressions },
|
|
@@ -626,7 +756,22 @@ export const buildNull = () => {
|
|
|
626
756
|
[
|
|
627
757
|
t.nodeOpen(t.nodeFlags, 'Null'),
|
|
628
758
|
t.ref`sigilToken`,
|
|
629
|
-
gap(buildToken(
|
|
759
|
+
gap(buildToken(null, 'null')),
|
|
760
|
+
t.nodeClose(),
|
|
761
|
+
],
|
|
762
|
+
{ expressions },
|
|
763
|
+
);
|
|
764
|
+
};
|
|
765
|
+
|
|
766
|
+
export const buildUndefined = () => {
|
|
767
|
+
const expressions = [];
|
|
768
|
+
const gap = buildFilledGapFunction(expressions);
|
|
769
|
+
|
|
770
|
+
return treeFromStream(
|
|
771
|
+
[
|
|
772
|
+
t.nodeOpen(t.nodeFlags, 'Undefined'),
|
|
773
|
+
t.ref`sigilToken`,
|
|
774
|
+
gap(buildToken(null, 'undefined')),
|
|
630
775
|
t.nodeClose(),
|
|
631
776
|
],
|
|
632
777
|
{ expressions },
|
|
@@ -641,7 +786,7 @@ export const buildNullTag = () => {
|
|
|
641
786
|
[
|
|
642
787
|
t.nodeOpen(t.nodeFlags, 'NullTag'),
|
|
643
788
|
t.ref`sigilToken`,
|
|
644
|
-
gap(buildToken(
|
|
789
|
+
gap(buildToken(null, 'null')),
|
|
645
790
|
t.nodeClose(),
|
|
646
791
|
],
|
|
647
792
|
{ expressions },
|
|
@@ -656,10 +801,14 @@ export const buildArray = (elements) => {
|
|
|
656
801
|
(function* () {
|
|
657
802
|
yield t.nodeOpen(t.nodeFlags, 'Array');
|
|
658
803
|
yield t.ref`openToken`;
|
|
659
|
-
yield gap(buildToken(
|
|
660
|
-
yield* interpolateFragment(
|
|
804
|
+
yield gap(buildToken(null, '['));
|
|
805
|
+
yield* interpolateFragment(
|
|
806
|
+
isArray(elements) ? buildArrayElements(elements) : elements,
|
|
807
|
+
t.ref`elements[]`,
|
|
808
|
+
expressions,
|
|
809
|
+
);
|
|
661
810
|
yield t.ref`closeToken`;
|
|
662
|
-
yield gap(buildToken(
|
|
811
|
+
yield gap(buildToken(null, ']'));
|
|
663
812
|
yield t.nodeClose();
|
|
664
813
|
})(),
|
|
665
814
|
{ expressions },
|
|
@@ -670,28 +819,24 @@ export const buildArrayElements = (values) => {
|
|
|
670
819
|
const expressions = [];
|
|
671
820
|
return treeFromStream(
|
|
672
821
|
(function* () {
|
|
673
|
-
yield t.
|
|
674
|
-
yield
|
|
675
|
-
yield* buildSpaceSeparatedList(values, t.ref`.[]`, expressions);
|
|
822
|
+
yield t.fragOpen();
|
|
823
|
+
yield* buildSeparatedList(',', values, t.ref`elements[]`, expressions);
|
|
676
824
|
yield t.nodeClose();
|
|
677
825
|
})(),
|
|
678
826
|
{ expressions },
|
|
679
827
|
);
|
|
680
828
|
};
|
|
681
829
|
|
|
682
|
-
export function*
|
|
830
|
+
export function* buildSeparatedList(separator, values, ref, expressions) {
|
|
683
831
|
const gap = buildFilledGapFunction(expressions);
|
|
684
832
|
|
|
685
|
-
if (!ref.value.
|
|
686
|
-
|
|
687
|
-
yield freeze({ ...ref });
|
|
688
|
-
yield t.arr();
|
|
833
|
+
if (!ref.value.flags.array) throw new Error();
|
|
689
834
|
|
|
690
835
|
let first = true;
|
|
691
836
|
for (const value of values) {
|
|
692
837
|
if (!first) {
|
|
693
|
-
yield t.buildReferenceTag('#');
|
|
694
|
-
yield gap(
|
|
838
|
+
yield t.buildReferenceTag('#', 'separatorTokens');
|
|
839
|
+
yield gap(buildToken(null, separator));
|
|
695
840
|
}
|
|
696
841
|
yield freeze({ ...ref });
|
|
697
842
|
yield gap(value || buildNullNode());
|
|
@@ -704,8 +849,8 @@ export const buildObjectProperties = (properties) => {
|
|
|
704
849
|
|
|
705
850
|
return treeFromStream(
|
|
706
851
|
concat(
|
|
707
|
-
[t.doctype({
|
|
708
|
-
|
|
852
|
+
[t.doctype({ 'bablr-lang': l.Instruction }), t.fragOpen(t.nodeFlags)],
|
|
853
|
+
buildSeparatedList(',', properties, t.ref`properties[]`, expressions),
|
|
709
854
|
[t.nodeClose()],
|
|
710
855
|
),
|
|
711
856
|
{ expressions },
|
|
@@ -720,12 +865,16 @@ export const buildObject = (properties) => {
|
|
|
720
865
|
(function* () {
|
|
721
866
|
yield t.nodeOpen(t.nodeFlags, 'Object');
|
|
722
867
|
yield t.ref`openToken`;
|
|
723
|
-
yield gap(buildToken(
|
|
868
|
+
yield gap(buildToken(null, '{'));
|
|
724
869
|
|
|
725
|
-
yield* interpolateFragment(
|
|
870
|
+
yield* interpolateFragment(
|
|
871
|
+
isArray(properties) ? buildObjectProperties(properties) : properties,
|
|
872
|
+
t.ref`properties[]`,
|
|
873
|
+
expressions,
|
|
874
|
+
);
|
|
726
875
|
|
|
727
876
|
yield t.ref`closeToken`;
|
|
728
|
-
yield gap(buildToken(
|
|
877
|
+
yield gap(buildToken(null, '}'));
|
|
729
878
|
yield t.nodeClose();
|
|
730
879
|
})(),
|
|
731
880
|
{ expressions },
|
|
@@ -740,14 +889,14 @@ export const buildPattern = (alternatives, flags) => {
|
|
|
740
889
|
(function* () {
|
|
741
890
|
yield t.nodeOpen(t.nodeFlags, 'Pattern');
|
|
742
891
|
yield t.ref`openToken`;
|
|
743
|
-
yield gap(buildToken(
|
|
892
|
+
yield gap(buildToken(null, '/'));
|
|
744
893
|
|
|
745
894
|
yield* interpolateFragment(alternatives, t.ref`alternatives[]`, expressions);
|
|
746
895
|
|
|
747
896
|
yield t.ref`closeToken`;
|
|
748
|
-
yield gap(buildToken(
|
|
897
|
+
yield gap(buildToken(null, '/'));
|
|
749
898
|
yield t.ref`flags`;
|
|
750
|
-
yield gap(flags ||
|
|
899
|
+
yield gap(flags || buildRegexFlags());
|
|
751
900
|
yield t.nodeClose();
|
|
752
901
|
})(),
|
|
753
902
|
{ expressions },
|
|
@@ -762,12 +911,12 @@ export const buildRegexGroup = (alternatives, flags) => {
|
|
|
762
911
|
(function* () {
|
|
763
912
|
yield t.nodeOpen(t.nodeFlags, 'Group');
|
|
764
913
|
yield t.ref`openToken`;
|
|
765
|
-
yield gap(buildToken(
|
|
914
|
+
yield gap(buildToken(null, '(?:'));
|
|
766
915
|
|
|
767
916
|
yield* interpolateFragment(alternatives, t.ref`alternatives[]`, expressions);
|
|
768
917
|
|
|
769
918
|
yield t.ref`closeToken`;
|
|
770
|
-
yield gap(buildToken(
|
|
919
|
+
yield gap(buildToken(null, ')'));
|
|
771
920
|
yield t.ref`flags`;
|
|
772
921
|
yield gap(flags || buildReferenceFlags());
|
|
773
922
|
yield t.nodeClose();
|
|
@@ -794,9 +943,9 @@ export const buildRegexFlags = (flags = '') => {
|
|
|
794
943
|
yield t.nodeOpen(t.nodeFlags, 'Flags');
|
|
795
944
|
|
|
796
945
|
for (const { 0: name, 1: chr } of Object.entries(flagCharacters)) {
|
|
797
|
-
yield t.buildReferenceTag(name + 'Token');
|
|
946
|
+
yield t.buildReferenceTag(null, name + 'Token');
|
|
798
947
|
|
|
799
|
-
yield gap(flags.includes(chr) ? buildToken(
|
|
948
|
+
yield gap(flags.includes(chr) ? buildToken(null, chr) : buildNullNode());
|
|
800
949
|
}
|
|
801
950
|
yield t.nodeClose();
|
|
802
951
|
})(),
|
|
@@ -823,18 +972,13 @@ export const buildAlternatives = (alternatives = []) => {
|
|
|
823
972
|
|
|
824
973
|
return treeFromStream(
|
|
825
974
|
(function* () {
|
|
826
|
-
yield t.
|
|
827
|
-
yield t.nodeOpen(t.nodeFlags);
|
|
828
|
-
yield t.ref`.[]`;
|
|
829
|
-
yield t.arr();
|
|
830
|
-
yield t.ref`separatorTokens[]`;
|
|
831
|
-
yield t.arr();
|
|
975
|
+
yield t.fragOpen();
|
|
832
976
|
|
|
833
977
|
yield* alternatives
|
|
834
978
|
.flatMap((alt) => [
|
|
835
|
-
t.ref
|
|
979
|
+
t.ref`alternatives[]`,
|
|
836
980
|
gap(alt),
|
|
837
|
-
t.ref
|
|
981
|
+
t.ref`#separatorTokens`,
|
|
838
982
|
gap(buildPunctuator('|')),
|
|
839
983
|
])
|
|
840
984
|
.slice(0, -2);
|
|
@@ -853,9 +997,9 @@ export const buildRegexGap = () => {
|
|
|
853
997
|
[
|
|
854
998
|
t.nodeOpen(t.nodeFlags, 'Gap'),
|
|
855
999
|
t.ref`escapeToken`,
|
|
856
|
-
gap(buildToken(
|
|
1000
|
+
gap(buildToken(null, '\\')),
|
|
857
1001
|
t.ref`value`,
|
|
858
|
-
gap(buildToken(
|
|
1002
|
+
gap(buildToken(null, 'g')),
|
|
859
1003
|
t.nodeClose(),
|
|
860
1004
|
],
|
|
861
1005
|
{ expressions },
|
|
@@ -868,14 +1012,77 @@ export const buildElements = (elements) => {
|
|
|
868
1012
|
|
|
869
1013
|
return treeFromStream(
|
|
870
1014
|
concat(
|
|
871
|
-
[t.doctype({
|
|
872
|
-
elements.flatMap((el) => [t.ref
|
|
1015
|
+
[t.doctype({ 'bablr-lang': l.Instruction }), t.fragOpen()],
|
|
1016
|
+
elements.flatMap((el) => [t.ref`elements[]+`, gap(el)]),
|
|
873
1017
|
[t.nodeClose()],
|
|
874
1018
|
),
|
|
875
1019
|
{ expressions },
|
|
876
1020
|
);
|
|
877
1021
|
};
|
|
878
1022
|
|
|
1023
|
+
export const buildCharacterClass = (elements, negate = false) => {
|
|
1024
|
+
const expressions = [];
|
|
1025
|
+
const gap = buildFilledGapFunction(expressions);
|
|
1026
|
+
|
|
1027
|
+
return treeFromStream(
|
|
1028
|
+
(function* () {
|
|
1029
|
+
yield t.nodeOpen(t.nodeFlags, 'CharacterClass', null, { negate });
|
|
1030
|
+
yield t.ref`openToken`;
|
|
1031
|
+
yield gap(buildToken(null, '['));
|
|
1032
|
+
|
|
1033
|
+
yield* interpolateFragment(elements, t.ref`elements[]`, expressions);
|
|
1034
|
+
yield t.ref`closeToken`;
|
|
1035
|
+
yield gap(buildToken(null, ']'));
|
|
1036
|
+
yield t.nodeClose();
|
|
1037
|
+
})(),
|
|
1038
|
+
{ expressions },
|
|
1039
|
+
);
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
export const buildJSExpressionDeep = (expr) => {
|
|
1043
|
+
if (expr === null) {
|
|
1044
|
+
return buildNull();
|
|
1045
|
+
} else if (expr === undefined) {
|
|
1046
|
+
return buildUndefined();
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
switch (typeof expr) {
|
|
1050
|
+
case 'boolean':
|
|
1051
|
+
return buildBoolean(expr);
|
|
1052
|
+
|
|
1053
|
+
case 'string':
|
|
1054
|
+
return buildString(expr);
|
|
1055
|
+
|
|
1056
|
+
case 'number':
|
|
1057
|
+
return buildInteger(expr);
|
|
1058
|
+
|
|
1059
|
+
case 'object': {
|
|
1060
|
+
switch (Object.getPrototypeOf(expr)) {
|
|
1061
|
+
case Array.prototype:
|
|
1062
|
+
return buildArray(buildArrayElements(expr.map((e) => buildJSExpressionDeep(e))));
|
|
1063
|
+
|
|
1064
|
+
case Object.prototype:
|
|
1065
|
+
return buildObject(
|
|
1066
|
+
buildObjectProperties(
|
|
1067
|
+
Object.entries(expr).map((e) =>
|
|
1068
|
+
buildProperty(
|
|
1069
|
+
/^[a-zA-Z_]+$/.test(e[0]) ? buildIdentifier(e[0]) : buildString(e[0]),
|
|
1070
|
+
buildJSExpressionDeep(e[1]),
|
|
1071
|
+
),
|
|
1072
|
+
),
|
|
1073
|
+
),
|
|
1074
|
+
);
|
|
1075
|
+
|
|
1076
|
+
default:
|
|
1077
|
+
throw new Error();
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
default:
|
|
1082
|
+
throw new Error();
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
|
|
879
1086
|
export const buildTaggedString = (tag, content) => {
|
|
880
1087
|
const expressions = [];
|
|
881
1088
|
const gap = buildFilledGapFunction(expressions);
|
|
@@ -884,13 +1091,13 @@ export const buildTaggedString = (tag, content) => {
|
|
|
884
1091
|
[
|
|
885
1092
|
t.buildOpenNodeTag(t.nodeFlags, 'SpamexString'),
|
|
886
1093
|
t.buildReferenceTag('sigilToken'),
|
|
887
|
-
gap(buildToken(
|
|
1094
|
+
gap(buildToken(null, tag)),
|
|
888
1095
|
t.buildReferenceTag('openToken'),
|
|
889
|
-
gap(buildToken(
|
|
1096
|
+
gap(buildToken(null, "'")),
|
|
890
1097
|
t.buildReferenceTag('content'),
|
|
891
1098
|
gap(content),
|
|
892
1099
|
t.buildReferenceTag('closeToken'),
|
|
893
|
-
gap(buildToken(
|
|
1100
|
+
gap(buildToken(null, "'")),
|
|
894
1101
|
t.buildCloseNodeTag(),
|
|
895
1102
|
],
|
|
896
1103
|
{ expressions },
|
|
@@ -905,25 +1112,6 @@ export const buildRegexString = (content) => {
|
|
|
905
1112
|
return buildTaggedString('re', content);
|
|
906
1113
|
};
|
|
907
1114
|
|
|
908
|
-
export const buildPropertyMatcher = (refMatcher, bindingMatcher, nodeMatcher) => {
|
|
909
|
-
const expressions = [];
|
|
910
|
-
const gap = buildFilledGapFunction(expressions);
|
|
911
|
-
|
|
912
|
-
return treeFromStream(
|
|
913
|
-
[
|
|
914
|
-
t.nodeOpen(t.nodeFlags, 'PropertyMatcher'),
|
|
915
|
-
t.ref`refMatcher`,
|
|
916
|
-
gap(refMatcher || buildNullNode()),
|
|
917
|
-
t.ref`bindingMatcher`,
|
|
918
|
-
gap(bindingMatcher || buildNullNode()),
|
|
919
|
-
t.ref`nodeMatcher`,
|
|
920
|
-
gap(nodeMatcher),
|
|
921
|
-
t.nodeClose(),
|
|
922
|
-
],
|
|
923
|
-
{ expressions },
|
|
924
|
-
);
|
|
925
|
-
};
|
|
926
|
-
|
|
927
1115
|
export const buildGapNodeMatcher = () => {
|
|
928
1116
|
return buildToken('GapNodeMatcher', '<//>');
|
|
929
1117
|
};
|