@bablr/helpers 0.23.0 → 0.24.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 +138 -32
- package/lib/productions.js +10 -10
- package/lib/productions.macro.js +9 -14
- package/lib/trivia.js +32 -36
- package/package.json +7 -7
package/lib/builders.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// import { i } from '@bablr/boot/shorthand.macro';
|
|
2
1
|
import { interpolateFragment, buildFilledGapFunction } from '@bablr/agast-helpers/template';
|
|
3
2
|
import {
|
|
4
3
|
buildNullNode,
|
|
4
|
+
get,
|
|
5
5
|
getRootArray,
|
|
6
6
|
treeFromStreamSync as treeFromStream,
|
|
7
7
|
} from '@bablr/agast-helpers/tree';
|
|
8
8
|
import { buildLiteralTag as agastBuildLiteralTag } from '@bablr/agast-helpers/builders';
|
|
9
9
|
import * as t from '@bablr/agast-helpers/shorthand';
|
|
10
|
-
import * as
|
|
10
|
+
import * as Tags from '@bablr/agast-helpers/tags';
|
|
11
11
|
import * as l from '@bablr/agast-vm-helpers/languages';
|
|
12
12
|
import { concat } from '@bablr/agast-vm-helpers/iterable';
|
|
13
13
|
|
|
@@ -103,8 +103,8 @@ export const buildNodeFlags = (flags = t.nodeFlags) => {
|
|
|
103
103
|
gap(hasGap ? buildToken('Punctuator', '$') : buildNullNode()),
|
|
104
104
|
t.ref`fragmentToken`,
|
|
105
105
|
gap(fragment ? buildToken('Punctuator', '_') : buildNullNode()),
|
|
106
|
-
t.ref`
|
|
107
|
-
gap(cover ? buildToken('Punctuator', '_') : buildNullNode()),
|
|
106
|
+
t.ref`multiFragmentToken`,
|
|
107
|
+
gap(!cover ? buildToken('Punctuator', '_') : buildNullNode()),
|
|
108
108
|
t.nodeClose(),
|
|
109
109
|
],
|
|
110
110
|
{ expressions },
|
|
@@ -115,12 +115,10 @@ export const buildSpamMatcher = (type = null, value = null, attributes = null) =
|
|
|
115
115
|
return buildOpenNodeMatcher(buildNodeFlags(t.nodeFlags), null, type, value, attributes);
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
export const buildOpenNodeMatcher = (flags, type,
|
|
118
|
+
export const buildOpenNodeMatcher = (flags, type, literalValue, attributes = null) => {
|
|
119
119
|
const expressions = [];
|
|
120
120
|
const gap = buildFilledGapFunction(expressions);
|
|
121
121
|
|
|
122
|
-
let language_;
|
|
123
|
-
|
|
124
122
|
if (!type) throw new Error();
|
|
125
123
|
|
|
126
124
|
return treeFromStream(
|
|
@@ -133,20 +131,20 @@ export const buildOpenNodeMatcher = (flags, type, intrinsicValue, attributes = n
|
|
|
133
131
|
yield t.ref`type`;
|
|
134
132
|
yield gap(typeof type === 'string' ? buildIdentifier(type) : type);
|
|
135
133
|
|
|
136
|
-
yield* when(
|
|
134
|
+
yield* when(literalValue, [t.ref`#`, ...buildSpace().tags]);
|
|
137
135
|
|
|
138
|
-
yield t.ref`
|
|
139
|
-
yield gap(
|
|
136
|
+
yield t.ref`literalValue`;
|
|
137
|
+
yield gap(literalValue ? buildString(literalValue) : buildNullNode());
|
|
140
138
|
|
|
141
139
|
let rootArr = getRootArray(attributes);
|
|
142
140
|
|
|
143
141
|
if (rootArr.length) {
|
|
144
142
|
yield t.ref`#`;
|
|
145
|
-
yield* buildSpace().
|
|
143
|
+
yield* buildSpace().tags;
|
|
146
144
|
yield* interpolateFragment(attributes, t.ref`attributes[]`, expressions);
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
yield t.ref`
|
|
147
|
+
yield t.ref`selfClosingToken`;
|
|
150
148
|
yield gap(buildToken('Punctuator', '/'));
|
|
151
149
|
yield t.ref`closeToken`;
|
|
152
150
|
yield gap(buildToken('Punctuator', '>'));
|
|
@@ -190,14 +188,14 @@ export const buildReferenceMatcher = (type, name, isArray, flags) => {
|
|
|
190
188
|
yield t.ref`sigilToken`;
|
|
191
189
|
yield gap(buildToken('Punctuator', ':'));
|
|
192
190
|
yield t.ref`#`;
|
|
193
|
-
yield*
|
|
191
|
+
yield* Tags.traverse(buildSpace().tags);
|
|
194
192
|
yield t.nodeClose();
|
|
195
193
|
})(),
|
|
196
194
|
{ expressions },
|
|
197
195
|
);
|
|
198
196
|
};
|
|
199
197
|
|
|
200
|
-
export const buildFragmentMatcher = (flags = buildNodeFlags({ fragment: true })) => {
|
|
198
|
+
export const buildFragmentMatcher = (flags = buildNodeFlags({ fragment: true, cover: true })) => {
|
|
201
199
|
const expressions = [];
|
|
202
200
|
const gap = buildFilledGapFunction(expressions);
|
|
203
201
|
|
|
@@ -205,7 +203,7 @@ export const buildFragmentMatcher = (flags = buildNodeFlags({ fragment: true }))
|
|
|
205
203
|
|
|
206
204
|
return treeFromStream(
|
|
207
205
|
(function* () {
|
|
208
|
-
yield t.nodeOpen(t.
|
|
206
|
+
yield t.nodeOpen(t.fragmentFlags, 'FragmentMatcher');
|
|
209
207
|
yield t.ref`openToken`;
|
|
210
208
|
yield gap(buildToken('Punctuator', '<'));
|
|
211
209
|
yield t.ref`flags`;
|
|
@@ -265,7 +263,7 @@ export const buildDoctypeTag = (attributes) => {
|
|
|
265
263
|
yield gap(buildKeyword('cstml'));
|
|
266
264
|
yield t.nodeClose();
|
|
267
265
|
|
|
268
|
-
yield* when(getRootArray(attributes).length, [t.ref`#`, ...buildSpace().
|
|
266
|
+
yield* when(getRootArray(attributes).length, [t.ref`#`, ...buildSpace().tags]);
|
|
269
267
|
yield* interpolateFragment(attributes, t.ref`attributes[]`, expressions);
|
|
270
268
|
|
|
271
269
|
yield t.ref`closeToken`;
|
|
@@ -340,7 +338,8 @@ export const buildLiteralTag = (value) => {
|
|
|
340
338
|
};
|
|
341
339
|
|
|
342
340
|
export const buildTerminalProps = (matcher) => {
|
|
343
|
-
const
|
|
341
|
+
const value = get('value', matcher);
|
|
342
|
+
const attributes = get('attributes', matcher);
|
|
344
343
|
|
|
345
344
|
return buildObject({ value, attributes });
|
|
346
345
|
};
|
|
@@ -350,20 +349,68 @@ export const buildSpace = () => {
|
|
|
350
349
|
};
|
|
351
350
|
|
|
352
351
|
export const buildIdentifier = (name) => {
|
|
353
|
-
|
|
354
|
-
|
|
352
|
+
let unquoted = /^[a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*$/uy.test(name);
|
|
355
353
|
const expressions = [];
|
|
356
354
|
const gap = buildFilledGapFunction(expressions);
|
|
357
355
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
356
|
+
if (unquoted) {
|
|
357
|
+
return treeFromStream(
|
|
358
|
+
[
|
|
359
|
+
t.nodeOpen(t.nodeFlags, 'Identifier'),
|
|
360
|
+
t.ref`content`,
|
|
361
|
+
gap(buildIdentifierContent(name)),
|
|
362
|
+
t.nodeClose(),
|
|
363
|
+
],
|
|
364
|
+
{ expressions },
|
|
365
|
+
);
|
|
366
|
+
} else {
|
|
367
|
+
return treeFromStream(
|
|
368
|
+
(function* () {
|
|
369
|
+
yield t.nodeOpen(t.nodeFlags, 'Identifier');
|
|
370
|
+
|
|
371
|
+
yield t.ref`openToken`;
|
|
372
|
+
yield gap(buildToken('Punctuator', '`'));
|
|
373
|
+
yield t.ref`content`;
|
|
374
|
+
yield t.nodeOpen(t.tokenFlags, 'IdentifierContent');
|
|
375
|
+
|
|
376
|
+
let lit = '';
|
|
377
|
+
|
|
378
|
+
let pieces = name.split(/[\\`]/g);
|
|
379
|
+
|
|
380
|
+
for (const piece of pieces) {
|
|
381
|
+
if (/[\\`]/y.test(piece)) {
|
|
382
|
+
let chr = piece;
|
|
383
|
+
if (lit) {
|
|
384
|
+
yield agastBuildLiteralTag(lit);
|
|
385
|
+
lit = '';
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
let value = buildKeyword(chr);
|
|
389
|
+
|
|
390
|
+
yield t.ref`@`;
|
|
391
|
+
yield t.nodeOpen(t.nodeFlags, 'EscapeSequence', { cooked: chr });
|
|
392
|
+
yield t.ref`escape`;
|
|
393
|
+
yield gap(buildToken('Punctuator', '\\'));
|
|
394
|
+
yield t.ref`value`;
|
|
395
|
+
yield gap(value);
|
|
396
|
+
yield t.nodeClose();
|
|
397
|
+
} else {
|
|
398
|
+
lit += piece;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (lit) yield agastBuildLiteralTag(lit);
|
|
403
|
+
lit = '';
|
|
404
|
+
|
|
405
|
+
yield t.nodeClose();
|
|
406
|
+
|
|
407
|
+
yield t.ref`closeToken`;
|
|
408
|
+
yield gap(buildToken('Punctuator', '`'));
|
|
409
|
+
yield t.nodeClose();
|
|
410
|
+
})(),
|
|
411
|
+
{ expressions },
|
|
412
|
+
);
|
|
413
|
+
}
|
|
367
414
|
};
|
|
368
415
|
|
|
369
416
|
export const buildIdentifierContent = (value) => {
|
|
@@ -633,6 +680,21 @@ export const buildNull = () => {
|
|
|
633
680
|
);
|
|
634
681
|
};
|
|
635
682
|
|
|
683
|
+
export const buildUndefined = () => {
|
|
684
|
+
const expressions = [];
|
|
685
|
+
const gap = buildFilledGapFunction(expressions);
|
|
686
|
+
|
|
687
|
+
return treeFromStream(
|
|
688
|
+
[
|
|
689
|
+
t.nodeOpen(t.nodeFlags, 'Undefined'),
|
|
690
|
+
t.ref`sigilToken`,
|
|
691
|
+
gap(buildToken('Keyword', 'undefined')),
|
|
692
|
+
t.nodeClose(),
|
|
693
|
+
],
|
|
694
|
+
{ expressions },
|
|
695
|
+
);
|
|
696
|
+
};
|
|
697
|
+
|
|
636
698
|
export const buildNullTag = () => {
|
|
637
699
|
const expressions = [];
|
|
638
700
|
const gap = buildFilledGapFunction(expressions);
|
|
@@ -672,14 +734,14 @@ export const buildArrayElements = (values) => {
|
|
|
672
734
|
(function* () {
|
|
673
735
|
yield t.doctype({ bablrLanguage: l.Instruction });
|
|
674
736
|
yield t.nodeOpen(t.nodeFlags);
|
|
675
|
-
yield*
|
|
737
|
+
yield* buildCommaSeparatedList(values, t.ref`.[]`, expressions);
|
|
676
738
|
yield t.nodeClose();
|
|
677
739
|
})(),
|
|
678
740
|
{ expressions },
|
|
679
741
|
);
|
|
680
742
|
};
|
|
681
743
|
|
|
682
|
-
export function*
|
|
744
|
+
export function* buildCommaSeparatedList(values, ref, expressions) {
|
|
683
745
|
const gap = buildFilledGapFunction(expressions);
|
|
684
746
|
|
|
685
747
|
if (!ref.value.isArray) throw new Error();
|
|
@@ -691,7 +753,7 @@ export function* buildSpaceSeparatedList(values, ref, expressions) {
|
|
|
691
753
|
for (const value of values) {
|
|
692
754
|
if (!first) {
|
|
693
755
|
yield t.buildReferenceTag('#');
|
|
694
|
-
yield gap(
|
|
756
|
+
yield gap(buildToken('Punctuator', ','));
|
|
695
757
|
}
|
|
696
758
|
yield freeze({ ...ref });
|
|
697
759
|
yield gap(value || buildNullNode());
|
|
@@ -705,7 +767,7 @@ export const buildObjectProperties = (properties) => {
|
|
|
705
767
|
return treeFromStream(
|
|
706
768
|
concat(
|
|
707
769
|
[t.doctype({ bablrLanguage: l.Instruction }), t.nodeOpen(t.nodeFlags)],
|
|
708
|
-
|
|
770
|
+
buildCommaSeparatedList(properties, t.ref`properties[]`, expressions),
|
|
709
771
|
[t.nodeClose()],
|
|
710
772
|
),
|
|
711
773
|
{ expressions },
|
|
@@ -876,6 +938,50 @@ export const buildElements = (elements) => {
|
|
|
876
938
|
);
|
|
877
939
|
};
|
|
878
940
|
|
|
941
|
+
export const buildJSExpressionDeep = (expr) => {
|
|
942
|
+
if (expr === null) {
|
|
943
|
+
return buildNull();
|
|
944
|
+
} else if (expr === undefined) {
|
|
945
|
+
return buildUndefined();
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
switch (typeof expr) {
|
|
949
|
+
case 'boolean':
|
|
950
|
+
return buildBoolean(expr);
|
|
951
|
+
|
|
952
|
+
case 'string':
|
|
953
|
+
return buildString(expr);
|
|
954
|
+
|
|
955
|
+
case 'number':
|
|
956
|
+
return buildInteger(expr);
|
|
957
|
+
|
|
958
|
+
case 'object': {
|
|
959
|
+
switch (Object.getPrototypeOf(expr)) {
|
|
960
|
+
case Array.prototype:
|
|
961
|
+
return buildArray(buildArrayElements(expr.map((e) => buildJSExpressionDeep(e))));
|
|
962
|
+
|
|
963
|
+
case Object.prototype:
|
|
964
|
+
return buildObject(
|
|
965
|
+
buildObjectProperties(
|
|
966
|
+
Object.entries(expr).map((e) =>
|
|
967
|
+
buildProperty(
|
|
968
|
+
/^[a-zA-Z_]+$/.test(e[0]) ? buildIdentifier(e[0]) : buildString(e[0]),
|
|
969
|
+
buildJSExpressionDeep(e[1]),
|
|
970
|
+
),
|
|
971
|
+
),
|
|
972
|
+
),
|
|
973
|
+
);
|
|
974
|
+
|
|
975
|
+
default:
|
|
976
|
+
throw new Error();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
default:
|
|
981
|
+
throw new Error();
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
|
|
879
985
|
export const buildTaggedString = (tag, content) => {
|
|
880
986
|
const expressions = [];
|
|
881
987
|
const gap = buildFilledGapFunction(expressions);
|
package/lib/productions.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* @macrome
|
|
2
2
|
* @generatedby @bablr/macrome-generator-bablr
|
|
3
|
-
* @generatedfrom ./productions.macro.js#
|
|
3
|
+
* @generatedfrom ./productions.macro.js#a661312b1d84c6cc48eac8794f36c3b607a57892
|
|
4
4
|
* This file is autogenerated. Please do not edit it directly.
|
|
5
5
|
* When editing run `npx macrome watch` then change the file this is generated from.
|
|
6
6
|
*/
|
|
7
7
|
import { spam as m } from '@bablr/boot';
|
|
8
|
-
import { getCooked } from '@bablr/agast-helpers/tree';
|
|
8
|
+
import { get, getCooked } from '@bablr/agast-helpers/tree';
|
|
9
9
|
import { eat, eatMatch } from './grammar.js';
|
|
10
|
-
import {
|
|
10
|
+
import { Matcher } from './symbols.js';
|
|
11
11
|
import { getEmbeddedMatcher } from '@bablr/agast-vm-helpers/deembed';
|
|
12
12
|
import { buildPropertyMatcher } from './builders.js';
|
|
13
13
|
import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
|
|
@@ -20,10 +20,10 @@ export function* List({
|
|
|
20
20
|
allowHoles = false,
|
|
21
21
|
allowTrailingSeparator = true
|
|
22
22
|
} = props;
|
|
23
|
-
if (
|
|
24
|
-
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(separator)
|
|
23
|
+
if (getCooked(get(['refMatcher', 'name', 'content'], getEmbeddedMatcher(separator)))) {
|
|
24
|
+
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(get('refMatcher', getEmbeddedMatcher(separator)), null, m.ArrayNodeMatcher`[]`)));
|
|
25
25
|
}
|
|
26
|
-
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)
|
|
26
|
+
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(get('refMatcher', getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)), null, m.ArrayNodeMatcher`[]`)));
|
|
27
27
|
let sep,
|
|
28
28
|
it,
|
|
29
29
|
anySep = false;
|
|
@@ -46,7 +46,7 @@ export function* Any({
|
|
|
46
46
|
for (const alternative of alternatives) {
|
|
47
47
|
if (Array.isArray(alternative)) {
|
|
48
48
|
if (yield eatMatch(...alternative)) break;
|
|
49
|
-
} else if (alternative.type ===
|
|
49
|
+
} else if (alternative.type === Matcher) {
|
|
50
50
|
if (yield eatMatch(alternative)) break;
|
|
51
51
|
} else {
|
|
52
52
|
throw new Error();
|
|
@@ -75,10 +75,10 @@ export function* Optional({
|
|
|
75
75
|
}
|
|
76
76
|
export function* Literal({
|
|
77
77
|
ctx,
|
|
78
|
-
|
|
78
|
+
literalValue
|
|
79
79
|
}) {
|
|
80
|
-
if (!
|
|
81
|
-
yield eat(ctx.sourceTextFor(
|
|
80
|
+
if (!literalValue) throw new Error('Intrinsic productions must have value');
|
|
81
|
+
yield eat(ctx.sourceTextFor(literalValue.value));
|
|
82
82
|
}
|
|
83
83
|
export const Keyword = Literal;
|
|
84
84
|
export const Punctuator = Literal;
|
package/lib/productions.macro.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spam as m } from '@bablr/boot';
|
|
2
|
-
import { getCooked } from '@bablr/agast-helpers/tree';
|
|
2
|
+
import { get, getCooked } from '@bablr/agast-helpers/tree';
|
|
3
3
|
import { eat, eatMatch } from './grammar.js';
|
|
4
|
-
import {
|
|
4
|
+
import { Matcher } from './symbols.js';
|
|
5
5
|
import { getEmbeddedMatcher } from '@bablr/agast-vm-helpers/deembed';
|
|
6
6
|
import { buildPropertyMatcher } from './builders.js';
|
|
7
7
|
import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
|
|
@@ -9,15 +9,11 @@ import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
|
|
|
9
9
|
export function* List({ props }) {
|
|
10
10
|
const { element, separator, allowHoles = false, allowTrailingSeparator = true } = props;
|
|
11
11
|
|
|
12
|
-
if (
|
|
13
|
-
!['#', '@'].includes(
|
|
14
|
-
getCooked(getEmbeddedMatcher(separator).properties.refMatcher?.node.properties.type?.node),
|
|
15
|
-
)
|
|
16
|
-
) {
|
|
12
|
+
if (getCooked(get(['refMatcher', 'name', 'content'], getEmbeddedMatcher(separator)))) {
|
|
17
13
|
yield eat(
|
|
18
14
|
buildEmbeddedMatcher(
|
|
19
15
|
buildPropertyMatcher(
|
|
20
|
-
getEmbeddedMatcher(separator)
|
|
16
|
+
get('refMatcher', getEmbeddedMatcher(separator)),
|
|
21
17
|
null,
|
|
22
18
|
m.ArrayNodeMatcher`[]`,
|
|
23
19
|
),
|
|
@@ -28,8 +24,7 @@ export function* List({ props }) {
|
|
|
28
24
|
yield eat(
|
|
29
25
|
buildEmbeddedMatcher(
|
|
30
26
|
buildPropertyMatcher(
|
|
31
|
-
getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)
|
|
32
|
-
?.node,
|
|
27
|
+
get('refMatcher', getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)),
|
|
33
28
|
null,
|
|
34
29
|
m.ArrayNodeMatcher`[]`,
|
|
35
30
|
),
|
|
@@ -55,7 +50,7 @@ export function* Any({ props: { value: alternatives } }) {
|
|
|
55
50
|
for (const alternative of alternatives) {
|
|
56
51
|
if (Array.isArray(alternative)) {
|
|
57
52
|
if (yield eatMatch(...alternative)) break;
|
|
58
|
-
} else if (alternative.type ===
|
|
53
|
+
} else if (alternative.type === Matcher) {
|
|
59
54
|
if (yield eatMatch(alternative)) break;
|
|
60
55
|
} else {
|
|
61
56
|
throw new Error();
|
|
@@ -77,10 +72,10 @@ export function* Optional({ props: { value: matcher } }) {
|
|
|
77
72
|
yield eatMatch(matcher);
|
|
78
73
|
}
|
|
79
74
|
|
|
80
|
-
export function* Literal({ ctx,
|
|
81
|
-
if (!
|
|
75
|
+
export function* Literal({ ctx, literalValue }) {
|
|
76
|
+
if (!literalValue) throw new Error('Intrinsic productions must have value');
|
|
82
77
|
|
|
83
|
-
yield eat(ctx.sourceTextFor(
|
|
78
|
+
yield eat(ctx.sourceTextFor(literalValue.value));
|
|
84
79
|
}
|
|
85
80
|
export const Keyword = Literal;
|
|
86
81
|
|
package/lib/trivia.js
CHANGED
|
@@ -3,9 +3,9 @@ import { spam as m } from '@bablr/boot';
|
|
|
3
3
|
import { Coroutine } from '@bablr/coroutine';
|
|
4
4
|
import { eat, eatMatch, mapOwnProductions, mapProductions, o } from './grammar.js';
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Matcher,
|
|
7
|
+
Regex,
|
|
8
|
+
Node,
|
|
9
9
|
OpenNodeTag,
|
|
10
10
|
CloseNodeTag,
|
|
11
11
|
ReferenceTag,
|
|
@@ -15,7 +15,7 @@ import { buildIdentifier, buildString } from './builders.js';
|
|
|
15
15
|
import { buildCall, buildEmbeddedInstruction } from '@bablr/agast-vm-helpers/builders';
|
|
16
16
|
import { getEmbeddedInstruction } from '@bablr/agast-vm-helpers/deembed';
|
|
17
17
|
import { reifyExpression } from '@bablr/agast-vm-helpers';
|
|
18
|
-
import { getCooked } from '@bablr/agast-helpers/tree';
|
|
18
|
+
import { get, getCooked } from '@bablr/agast-helpers/tree';
|
|
19
19
|
import { buildPathSegment } from '@bablr/agast-helpers/path';
|
|
20
20
|
|
|
21
21
|
const lookbehind = (context, s) => {
|
|
@@ -60,11 +60,8 @@ export const basicTriviaEnhancer = ({ triviaIsAllowed, triviaMatcher }, grammar)
|
|
|
60
60
|
if (
|
|
61
61
|
matcher &&
|
|
62
62
|
!isCovered &&
|
|
63
|
-
matcher.type ===
|
|
64
|
-
getCooked(
|
|
65
|
-
matcher.value.properties.refMatcher?.node.properties.type?.node.properties.value
|
|
66
|
-
?.node,
|
|
67
|
-
) !== '#'
|
|
63
|
+
matcher.type === Matcher &&
|
|
64
|
+
getCooked(get(['refMatcher', 'type', 'value'], matcher.value)) !== '#'
|
|
68
65
|
) {
|
|
69
66
|
const previous = lookbehind(ctx, s);
|
|
70
67
|
if (triviaIsAllowed(s) && (!previous || !matchedResults.has(previous))) {
|
|
@@ -87,9 +84,7 @@ export const basicTriviaEnhancer = ({ triviaIsAllowed, triviaMatcher }, grammar)
|
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
if (co.value) {
|
|
90
|
-
let realMatcher = reifyExpression(
|
|
91
|
-
co.value.arguments[0].value.properties.nodeMatcher.node,
|
|
92
|
-
);
|
|
87
|
+
let realMatcher = reifyExpression(get('nodeMatcher', co.value.arguments[0].value));
|
|
93
88
|
let { flags: matcherFlags } = realMatcher;
|
|
94
89
|
|
|
95
90
|
let isNode = matcherFlags && !matcherFlags.fragment;
|
|
@@ -107,7 +102,7 @@ export const basicTriviaEnhancer = ({ triviaIsAllowed, triviaMatcher }, grammar)
|
|
|
107
102
|
|
|
108
103
|
return co.value;
|
|
109
104
|
} else {
|
|
110
|
-
if (!s.depths.path && !flags.token && !
|
|
105
|
+
if (!s.depths.path && !flags.token && !isCovered) {
|
|
111
106
|
if (triviaIsAllowed(s)) {
|
|
112
107
|
yield eatMatch(triviaMatcher);
|
|
113
108
|
}
|
|
@@ -166,9 +161,9 @@ export const triviaEnhancer = (
|
|
|
166
161
|
const { 0: matcher, 1: props, 2: options } = args;
|
|
167
162
|
|
|
168
163
|
if (
|
|
169
|
-
matcher.type ===
|
|
164
|
+
matcher.type === Matcher &&
|
|
170
165
|
['ArrayNodeMatcher', 'NullNodeMatcher'].includes(
|
|
171
|
-
matcher.value.
|
|
166
|
+
get('nodeMatcher', matcher.value).type.description,
|
|
172
167
|
)
|
|
173
168
|
) {
|
|
174
169
|
returnValue = yield instr;
|
|
@@ -176,9 +171,9 @@ export const triviaEnhancer = (
|
|
|
176
171
|
}
|
|
177
172
|
|
|
178
173
|
if (
|
|
179
|
-
matcher.type ===
|
|
174
|
+
matcher.type === Regex ||
|
|
180
175
|
typeof matcher === 'string' ||
|
|
181
|
-
(matcher.type ===
|
|
176
|
+
(matcher.type === Node && matcher.value.flags.token)
|
|
182
177
|
) {
|
|
183
178
|
if (triviaIsAllowed(s) && !flags.token) {
|
|
184
179
|
let isString = typeof matcher === 'string';
|
|
@@ -188,7 +183,7 @@ export const triviaEnhancer = (
|
|
|
188
183
|
|
|
189
184
|
let tmi = buildEmbeddedInstruction(eatMatch(triviaMatcher));
|
|
190
185
|
|
|
191
|
-
let result = yield buildCall(verb, m`<
|
|
186
|
+
let result = yield buildCall(verb, m`<__${buildIdentifier(Wrapper_)} />`, [
|
|
192
187
|
tmi,
|
|
193
188
|
buildEmbeddedInstruction(eat(wrappedMatcher, props, options)),
|
|
194
189
|
]);
|
|
@@ -196,28 +191,27 @@ export const triviaEnhancer = (
|
|
|
196
191
|
let prop = null;
|
|
197
192
|
|
|
198
193
|
if (result) {
|
|
199
|
-
for (let child of result.
|
|
200
|
-
if (child.type === Property) prop = child;
|
|
194
|
+
for (let child of result.tagsInner) {
|
|
195
|
+
if (child.type === Property) prop = child.value;
|
|
201
196
|
}
|
|
202
197
|
}
|
|
203
198
|
|
|
204
|
-
returnValue = prop?.
|
|
199
|
+
returnValue = prop?.node;
|
|
205
200
|
} else {
|
|
206
201
|
returnValue = yield instr;
|
|
207
202
|
}
|
|
208
203
|
break;
|
|
209
204
|
}
|
|
210
205
|
|
|
211
|
-
let { type: refType } =
|
|
212
|
-
|
|
213
|
-
let realMatcher = reifyExpression(matcher.value.properties.nodeMatcher?.node);
|
|
206
|
+
let { type: refType } = reifyExpression(get('refMatcher', matcher.value)) || {};
|
|
207
|
+
let realMatcher = reifyExpression(get('nodeMatcher', matcher.value));
|
|
214
208
|
let { flags: matcherFlags } = realMatcher;
|
|
215
209
|
|
|
216
210
|
let isNode = matcherFlags && !matcherFlags.fragment;
|
|
217
211
|
let isCoverBoundary = matcherFlags && (matcherFlags.cover || (isNode && !isCovered));
|
|
218
212
|
if (
|
|
219
213
|
matcher &&
|
|
220
|
-
(matcher.type !==
|
|
214
|
+
(matcher.type !== Matcher || refType !== '#') &&
|
|
221
215
|
!s.holding &&
|
|
222
216
|
!flags.token &&
|
|
223
217
|
isCoverBoundary
|
|
@@ -231,7 +225,7 @@ export const triviaEnhancer = (
|
|
|
231
225
|
|
|
232
226
|
let result = yield buildCall(
|
|
233
227
|
verb,
|
|
234
|
-
m`<
|
|
228
|
+
m`<__${buildIdentifier(Wrapper_)} />`,
|
|
235
229
|
[tmi, buildEmbeddedInstruction(eat(matcher, props, options))],
|
|
236
230
|
o({ bind: options?.value.bind ?? false }),
|
|
237
231
|
);
|
|
@@ -239,15 +233,16 @@ export const triviaEnhancer = (
|
|
|
239
233
|
|
|
240
234
|
if (result && !result.isNull) {
|
|
241
235
|
if (isNode || isCoverBoundary) {
|
|
242
|
-
let
|
|
236
|
+
let refMatcher = get('refMatcher', matcher.value);
|
|
243
237
|
|
|
244
238
|
let name, isArray;
|
|
245
239
|
|
|
246
240
|
if (!refMatcher) {
|
|
247
241
|
({ name, isArray } = mergedReference);
|
|
248
242
|
} else {
|
|
249
|
-
let
|
|
250
|
-
|
|
243
|
+
let name_ = get('name', refMatcher);
|
|
244
|
+
let openIndexToken = get('openIndexToken', refMatcher);
|
|
245
|
+
name = name_ && ctx.sourceTextFor(name_);
|
|
251
246
|
isArray = !!openIndexToken;
|
|
252
247
|
}
|
|
253
248
|
|
|
@@ -288,7 +283,7 @@ export const triviaEnhancer = (
|
|
|
288
283
|
}
|
|
289
284
|
} else if (co.value) {
|
|
290
285
|
let matcher = co.value.arguments[0];
|
|
291
|
-
let realMatcher = reifyExpression(matcher.value
|
|
286
|
+
let realMatcher = reifyExpression(get('nodeMatcher', matcher.value));
|
|
292
287
|
let { flags: matcherFlags } = realMatcher;
|
|
293
288
|
|
|
294
289
|
let isNode = matcherFlags && !matcherFlags.fragment;
|
|
@@ -304,7 +299,7 @@ export const triviaEnhancer = (
|
|
|
304
299
|
let tmi = buildEmbeddedInstruction(
|
|
305
300
|
triviaIsRequired() ? eat(triviaMatcher) : eatMatch(triviaMatcher),
|
|
306
301
|
);
|
|
307
|
-
let result = yield buildCall(co.value.verb, m`<
|
|
302
|
+
let result = yield buildCall(co.value.verb, m`<__${buildIdentifier(Wrapper_)} />`, [
|
|
308
303
|
tmi,
|
|
309
304
|
buildEmbeddedInstruction(eat(co.value.arguments[0], co.value.arguments[1])),
|
|
310
305
|
]);
|
|
@@ -313,15 +308,16 @@ export const triviaEnhancer = (
|
|
|
313
308
|
|
|
314
309
|
if (result && !result.isNull) {
|
|
315
310
|
if (isNode || isCoverBoundary) {
|
|
316
|
-
let
|
|
311
|
+
let refMatcher = get('refMatcher', matcher.value);
|
|
317
312
|
|
|
318
313
|
let name, isArray;
|
|
319
314
|
|
|
320
315
|
if (!refMatcher) {
|
|
321
316
|
({ name, isArray } = mergedReference);
|
|
322
317
|
} else {
|
|
323
|
-
let
|
|
324
|
-
|
|
318
|
+
let name = get('name', refMatcher);
|
|
319
|
+
let openIndexToken = get('openIndexToken', refMatcher);
|
|
320
|
+
name = name && ctx.sourceTextFor(name);
|
|
325
321
|
isArray = !!openIndexToken;
|
|
326
322
|
}
|
|
327
323
|
|
|
@@ -378,8 +374,8 @@ export const triviaEnhancer = (
|
|
|
378
374
|
}
|
|
379
375
|
}
|
|
380
376
|
|
|
381
|
-
*[Literal_]({
|
|
382
|
-
yield eat(
|
|
377
|
+
*[Literal_]({ literalValue }) {
|
|
378
|
+
yield eat(literalValue);
|
|
383
379
|
}
|
|
384
380
|
};
|
|
385
381
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/helpers",
|
|
3
3
|
"description": "Command helpers for use in writing BABLR grammars",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.24.0",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"clean": "macrome clean"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@bablr/language_enhancer-debug-log": "0.
|
|
33
|
-
"@bablr/strategy_enhancer-debug-log": "0.
|
|
34
|
-
"@bablr/agast-helpers": "0.
|
|
35
|
-
"@bablr/agast-vm-helpers": "0.
|
|
36
|
-
"@bablr/boot": "0.
|
|
32
|
+
"@bablr/language_enhancer-debug-log": "0.11.1",
|
|
33
|
+
"@bablr/strategy_enhancer-debug-log": "0.10.0",
|
|
34
|
+
"@bablr/agast-helpers": "0.9.0",
|
|
35
|
+
"@bablr/agast-vm-helpers": "0.9.0",
|
|
36
|
+
"@bablr/boot": "0.10.0",
|
|
37
37
|
"@bablr/coroutine": "0.1.0",
|
|
38
|
-
"@iter-tools/imm-stack": "1.
|
|
38
|
+
"@iter-tools/imm-stack": "1.2.0",
|
|
39
39
|
"iter-tools-es": "^7.5.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|