@bablr/helpers 0.20.6 → 0.21.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 +732 -500
- package/lib/decorators.js +2 -1
- package/lib/enhancers.js +4 -36
- package/lib/grammar.js +117 -11
- package/lib/productions.js +29 -92
- package/lib/productions.macro.js +46 -21
- package/lib/shorthand.js +1 -3
- package/lib/source.js +45 -3
- package/lib/stream.js +7 -9
- package/lib/trivia.js +19 -13
- package/package.json +7 -4
package/lib/decorators.js
CHANGED
|
@@ -14,8 +14,9 @@ export const AllowEmpty = (desc, context) => {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const CoveredBy = (type) => {
|
|
17
|
-
if (!/^[a-zA-Z]+$/.test(printType(type))) throw new Error();
|
|
18
17
|
return (desc, context) => {
|
|
18
|
+
if (!/^[a-zA-Z]+$/.test(printType(type))) throw new Error();
|
|
19
|
+
|
|
19
20
|
context.addInitializer(function () {
|
|
20
21
|
let covers = this.covers;
|
|
21
22
|
|
package/lib/enhancers.js
CHANGED
|
@@ -3,9 +3,7 @@ import {
|
|
|
3
3
|
enhanceStrategyBuilderWithEmittedLogging as logEmitted,
|
|
4
4
|
} from '@bablr/strategy_enhancer-debug-log';
|
|
5
5
|
import { enhanceProductionWithDebugLogging as createProductionLogger } from '@bablr/language_enhancer-debug-log';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const { getOwnPropertyNames, hasOwn } = Object;
|
|
6
|
+
import { mapProductions } from './grammar.js';
|
|
9
7
|
|
|
10
8
|
export const memoize = (original) => {
|
|
11
9
|
const cache = new WeakMap();
|
|
@@ -40,40 +38,10 @@ export const compose = (functions) => {
|
|
|
40
38
|
return f;
|
|
41
39
|
};
|
|
42
40
|
|
|
43
|
-
export const mapProductions = (fn, Grammar) => {
|
|
44
|
-
let { prototype } = Grammar;
|
|
45
|
-
|
|
46
|
-
class MappedGrammar extends Grammar {}
|
|
47
|
-
|
|
48
|
-
const mapped = MappedGrammar.prototype;
|
|
49
|
-
|
|
50
|
-
while (prototype && prototype !== Object.prototype) {
|
|
51
|
-
for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
|
|
52
|
-
if (!hasOwn(mapped, key)) {
|
|
53
|
-
mapped[key] = fn(prototype[key], key);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
prototype = getPrototypeOf(prototype);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return MappedGrammar;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export function* generateProductions(Grammar) {
|
|
63
|
-
let { prototype } = Grammar;
|
|
64
|
-
|
|
65
|
-
while (prototype && prototype !== Object.prototype) {
|
|
66
|
-
for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
|
|
67
|
-
let value = prototype[key];
|
|
68
|
-
if (key !== 'constructor') yield [key, value];
|
|
69
|
-
}
|
|
70
|
-
prototype = getPrototypeOf(prototype);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
41
|
export const debugEnhancers = {
|
|
75
|
-
//
|
|
76
|
-
createBablrStrategy: (strategy) =>
|
|
42
|
+
// bablr: (strategy) => logStrategy(strategy, '<<< '),
|
|
43
|
+
createBablrStrategy: (strategy) => (matcher, props) =>
|
|
44
|
+
logStrategy(strategy(matcher, props), ' >>> '),
|
|
77
45
|
bablrProduction: createProductionLogger('>>> '),
|
|
78
46
|
};
|
|
79
47
|
|
package/lib/grammar.js
CHANGED
|
@@ -1,15 +1,55 @@
|
|
|
1
1
|
import every from 'iter-tools-es/methods/every';
|
|
2
2
|
import isString from 'iter-tools-es/methods/is-string';
|
|
3
|
-
import { getPrototypeOf, objectEntries } from './object.js';
|
|
4
|
-
import { OpenNodeTag, CloseNodeTag } from './symbols.js';
|
|
3
|
+
import { getOwnPropertySymbols, getPrototypeOf, objectEntries } from './object.js';
|
|
4
|
+
import { OpenNodeTag, CloseNodeTag, NullTag } from './symbols.js';
|
|
5
|
+
import { buildExpression } from './builders.js';
|
|
6
|
+
import { buildEmbeddedObject } from '@bablr/agast-helpers/tree';
|
|
5
7
|
|
|
6
8
|
export * from './decorators.js';
|
|
7
9
|
|
|
10
|
+
const { getOwnPropertyNames, hasOwn } = Object;
|
|
11
|
+
|
|
8
12
|
const { isArray } = Array;
|
|
9
13
|
const isSymbol = (value) => typeof value === 'symbol';
|
|
10
14
|
const isType = (value) => isString(value) || isSymbol(value);
|
|
11
15
|
|
|
16
|
+
export const notNull = (facade) => {
|
|
17
|
+
return facade && (facade.type !== null || facade.openTag.type !== NullTag);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const mapProductions = (fn, Grammar) => {
|
|
21
|
+
let { prototype } = Grammar;
|
|
22
|
+
|
|
23
|
+
class MappedGrammar extends Grammar {}
|
|
24
|
+
|
|
25
|
+
const mapped = MappedGrammar.prototype;
|
|
26
|
+
|
|
27
|
+
while (prototype && prototype !== Object.prototype) {
|
|
28
|
+
for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
|
|
29
|
+
if (!hasOwn(mapped, key)) {
|
|
30
|
+
mapped[key] = fn(prototype[key], key);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
prototype = getPrototypeOf(prototype);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return MappedGrammar;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function* generateProductions(Grammar) {
|
|
40
|
+
let { prototype } = Grammar;
|
|
41
|
+
|
|
42
|
+
while (prototype && prototype !== Object.prototype) {
|
|
43
|
+
for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
|
|
44
|
+
let value = prototype[key];
|
|
45
|
+
if (key !== 'constructor') yield [key, value];
|
|
46
|
+
}
|
|
47
|
+
prototype = getPrototypeOf(prototype);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
12
51
|
export const resolveLanguage = (context, language, path) => {
|
|
52
|
+
const { languages } = context;
|
|
13
53
|
if (isString(path)) {
|
|
14
54
|
if (language.canonicalURL === path) {
|
|
15
55
|
return language;
|
|
@@ -24,16 +64,18 @@ export const resolveLanguage = (context, language, path) => {
|
|
|
24
64
|
throw new Error();
|
|
25
65
|
}
|
|
26
66
|
|
|
67
|
+
let segments = isString(path) ? [path] : isArray(path) ? path : null;
|
|
68
|
+
|
|
27
69
|
if (path == null) {
|
|
28
70
|
return language;
|
|
29
|
-
} else if (isString(path)) {
|
|
30
|
-
l = l.dependencies[path];
|
|
31
|
-
} else if (isArray(path)) {
|
|
32
|
-
for (const segment of path) {
|
|
33
|
-
l = l.dependencies[segment];
|
|
34
|
-
}
|
|
35
71
|
} else {
|
|
36
|
-
|
|
72
|
+
for (const segment of segments) {
|
|
73
|
+
if (isString(l.dependencies[segment])) {
|
|
74
|
+
l = languages.get(l.dependencies[segment]);
|
|
75
|
+
} else {
|
|
76
|
+
l = l.dependencies[segment];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
37
79
|
}
|
|
38
80
|
|
|
39
81
|
return l;
|
|
@@ -91,7 +133,11 @@ export const getProduction = (grammar, type) => {
|
|
|
91
133
|
};
|
|
92
134
|
|
|
93
135
|
const __buildDependentLanguages = (language, languages = new Map()) => {
|
|
136
|
+
languages.set(language.canonicalURL, language);
|
|
137
|
+
|
|
94
138
|
for (const dependentLanguage of Object.values(language.dependencies || {})) {
|
|
139
|
+
if (isString(dependentLanguage)) continue;
|
|
140
|
+
|
|
95
141
|
const { canonicalURL } = dependentLanguage;
|
|
96
142
|
if (languages.has(canonicalURL) && dependentLanguage !== languages.get(canonicalURL)) {
|
|
97
143
|
throw new Error();
|
|
@@ -101,15 +147,25 @@ const __buildDependentLanguages = (language, languages = new Map()) => {
|
|
|
101
147
|
__buildDependentLanguages(dependentLanguage, languages);
|
|
102
148
|
}
|
|
103
149
|
}
|
|
104
|
-
languages.set(language.canonicalURL, language);
|
|
105
150
|
|
|
106
151
|
return languages;
|
|
107
152
|
};
|
|
108
153
|
|
|
109
|
-
export const buildDependentLanguages = (language
|
|
154
|
+
export const buildDependentLanguages = (language) => {
|
|
110
155
|
return __buildDependentLanguages(language);
|
|
111
156
|
};
|
|
112
157
|
|
|
158
|
+
export const extendLanguage = (language, extension) => {
|
|
159
|
+
return {
|
|
160
|
+
...language,
|
|
161
|
+
dependencies: extension.dependencies
|
|
162
|
+
? { ...language.dependencies, ...extension.dependencies }
|
|
163
|
+
: language.dependencies,
|
|
164
|
+
canonicalURL: extension.canonicalURL || language.canonicalURL,
|
|
165
|
+
grammar: extension.grammar,
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
|
|
113
169
|
const arrayLast = (arr) => arr[arr.length - 1];
|
|
114
170
|
|
|
115
171
|
export function* zipLanguages(tags, rootLanguage) {
|
|
@@ -139,3 +195,53 @@ export function* zipLanguages(tags, rootLanguage) {
|
|
|
139
195
|
yield [tag, arrayLast(languages)];
|
|
140
196
|
}
|
|
141
197
|
}
|
|
198
|
+
|
|
199
|
+
const safeShallowEmbed = (value) => {
|
|
200
|
+
if (typeof value !== 'object') {
|
|
201
|
+
return buildExpression(value);
|
|
202
|
+
} else {
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const __buildCall = (verb, ...args) => {
|
|
208
|
+
while (args.length && args[args.length - 1] === undefined) {
|
|
209
|
+
args.pop();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return { verb, arguments: args };
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const eat = (matcher, value, options) => {
|
|
216
|
+
return __buildCall('eat', matcher, value, options);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export const eatMatch = (matcher, value, options) => {
|
|
220
|
+
return __buildCall('eatMatch', matcher, value, options);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export const match = (matcher, value, options) => {
|
|
224
|
+
return __buildCall('match', matcher, value, options);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export const guard = (matcher, value, options) => {
|
|
228
|
+
return __buildCall('guard', matcher, value, options);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export const holdForMatch = (matcher, value, options) => {
|
|
232
|
+
return __buildCall('holdForMatch', matcher, value, options);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export const fail = () => {
|
|
236
|
+
return __buildCall('fail');
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export const bindAttribute = (key, value) => {
|
|
240
|
+
return __buildCall('bindAttribute', key, value);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export const write = (value) => {
|
|
244
|
+
return __buildCall('write', value);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export const o = buildEmbeddedObject;
|
package/lib/productions.js
CHANGED
|
@@ -1,127 +1,64 @@
|
|
|
1
1
|
/* @macrome
|
|
2
2
|
* @generatedby @bablr/macrome-generator-bablr
|
|
3
|
-
* @generatedfrom ./productions.macro.js#
|
|
3
|
+
* @generatedfrom ./productions.macro.js#92256720d76d33560908ff2f462d2e33fc77b865
|
|
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
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
7
|
+
import { spam as m } from '@bablr/boot';
|
|
8
|
+
import { buildEmbeddedMatcher, getCooked } from '@bablr/agast-helpers/tree';
|
|
9
|
+
import { eat, eatMatch } from './grammar.js';
|
|
10
|
+
import { EmbeddedMatcher } from './symbols.js';
|
|
11
|
+
import { getEmbeddedMatcher, getEmbeddedObject } from '@bablr/agast-vm-helpers/deembed';
|
|
12
|
+
import { buildPropertyMatcher } from './builders.js';
|
|
10
13
|
export function* List({
|
|
11
|
-
value: props
|
|
12
|
-
ctx
|
|
14
|
+
value: props
|
|
13
15
|
}) {
|
|
14
16
|
const {
|
|
15
17
|
element,
|
|
16
18
|
separator,
|
|
17
19
|
allowHoles = false,
|
|
18
20
|
allowTrailingSeparator = true
|
|
19
|
-
} =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
values: [_t.node(_l.Instruction, "Array", [_t.ref`openToken`, _t.ref`closeToken`], {
|
|
25
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "["),
|
|
26
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", "]")
|
|
27
|
-
}, {}), _t.node(_l.CSTML, "String", [_t.ref`openToken`, _t.ref`content`, _t.ref`closeToken`], {
|
|
28
|
-
openToken: _t.s_node(_l.CSTML, "Punctuator", "'"),
|
|
29
|
-
content: _t.node(_l.CSTML, "Content", [_t.lit("separators[]")], {}, {}),
|
|
30
|
-
closeToken: _t.s_node(_l.CSTML, "Punctuator", "'")
|
|
31
|
-
}, {})],
|
|
32
|
-
separators: [_t.node(_l.Instruction, "Separator", [_t.embedded(_t.node(_l.Instruction, "Space", [_t.lit(" ")], {}, {}))], {}, {})],
|
|
33
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
34
|
-
}, {})
|
|
35
|
-
}, {});
|
|
21
|
+
} = getEmbeddedObject(props);
|
|
22
|
+
if (!['#', '@'].includes(getCooked(getEmbeddedMatcher(separator).properties.refMatcher.node.properties.name.node))) {
|
|
23
|
+
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(separator).properties.refMatcher.node, m.ArrayNodeMatcher`[]`)));
|
|
24
|
+
}
|
|
25
|
+
yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(element).properties.refMatcher.node, m.ArrayNodeMatcher`[]`)));
|
|
36
26
|
let sep,
|
|
37
27
|
it,
|
|
38
28
|
anySep = false;
|
|
39
29
|
for (;;) {
|
|
40
|
-
it = yield
|
|
41
|
-
verb: _t.s_node(_l.Instruction, "Identifier", "eatMatch"),
|
|
42
|
-
arguments: _t.node(_l.Instruction, "Tuple", [_t.ref`openToken`, _t.ref`values[]`, _t.arr(), ..._interpolateFragmentChildren(element, _t.ref`values[]`), _t.ref`closeToken`], {
|
|
43
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "("),
|
|
44
|
-
values: [..._interpolateArray(element)],
|
|
45
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
46
|
-
}, {})
|
|
47
|
-
}, {});
|
|
30
|
+
it = yield eatMatch(element);
|
|
48
31
|
if (it || allowTrailingSeparator) {
|
|
49
|
-
sep = yield
|
|
50
|
-
verb: _t.s_node(_l.Instruction, "Identifier", "eatMatch"),
|
|
51
|
-
arguments: _t.node(_l.Instruction, "Tuple", [9, [[_t.ref`openToken`, _t.ref`values[]`, _t.arr(), ..._interpolateFragmentChildren(separator, _t.ref`values[]`)], [_t.ref`separators[]`, _t.arr(), _t.ref`separators[]`, _t.ref`values[]`, _t.ref`closeToken`]]], {
|
|
52
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "("),
|
|
53
|
-
values: [..._interpolateArray(separator), _t.node(_l.CSTML, "String", [_t.ref`openToken`, _t.ref`content`, _t.ref`closeToken`], {
|
|
54
|
-
openToken: _t.s_node(_l.CSTML, "Punctuator", "'"),
|
|
55
|
-
content: _t.node(_l.CSTML, "Content", [_t.lit("separators[]")], {}, {}),
|
|
56
|
-
closeToken: _t.s_node(_l.CSTML, "Punctuator", "'")
|
|
57
|
-
}, {})],
|
|
58
|
-
separators: [_t.node(_l.Instruction, "Separator", [_t.embedded(_t.node(_l.Instruction, "Space", [_t.lit(" ")], {}, {}))], {}, {})],
|
|
59
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
60
|
-
}, {})
|
|
61
|
-
}, {});
|
|
32
|
+
sep = yield eatMatch(separator);
|
|
62
33
|
anySep ||= sep;
|
|
34
|
+
} else {
|
|
35
|
+
sep = null;
|
|
63
36
|
}
|
|
64
37
|
if (!(sep || allowHoles)) break;
|
|
65
38
|
}
|
|
66
39
|
}
|
|
67
40
|
export function* Any({
|
|
68
|
-
value:
|
|
69
|
-
ctx
|
|
41
|
+
value: alternatives
|
|
70
42
|
}) {
|
|
71
|
-
for (const
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
78
|
-
}, {})
|
|
79
|
-
}, {})) break;
|
|
43
|
+
for (const alternative of alternatives) {
|
|
44
|
+
if (alternative.type === EmbeddedMatcher) {
|
|
45
|
+
if (yield eatMatch(alternative)) break;
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error();
|
|
48
|
+
}
|
|
80
49
|
}
|
|
81
50
|
}
|
|
82
51
|
export function* All({
|
|
83
|
-
value: matchers
|
|
84
|
-
ctx
|
|
52
|
+
value: matchers
|
|
85
53
|
}) {
|
|
86
|
-
for (const matcher of
|
|
87
|
-
yield
|
|
88
|
-
verb: _t.s_node(_l.Instruction, "Identifier", "eat"),
|
|
89
|
-
arguments: _t.node(_l.Instruction, "Tuple", [_t.ref`openToken`, _t.ref`values[]`, _t.arr(), ..._interpolateFragmentChildren(matcher, _t.ref`values[]`), _t.ref`closeToken`], {
|
|
90
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "("),
|
|
91
|
-
values: [..._interpolateArray(matcher)],
|
|
92
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
93
|
-
}, {})
|
|
94
|
-
}, {});
|
|
54
|
+
for (const matcher of matchers) {
|
|
55
|
+
yield eat(m`.[]: ${getEmbeddedMatcher(matcher).properties.nodeMatcher.node}`);
|
|
95
56
|
}
|
|
96
57
|
}
|
|
97
58
|
export function* Punctuator({
|
|
98
59
|
intrinsicValue
|
|
99
60
|
}) {
|
|
100
61
|
if (!intrinsicValue) throw new Error('Intrinsic productions must have value');
|
|
101
|
-
yield
|
|
102
|
-
verb: _t.s_node(_l.Instruction, "Identifier", "eat"),
|
|
103
|
-
arguments: _t.node(_l.Instruction, "Tuple", [_t.ref`openToken`, _t.ref`values[]`, _t.arr(), ..._interpolateFragmentChildren(intrinsicValue, _t.ref`values[]`), _t.ref`closeToken`], {
|
|
104
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "("),
|
|
105
|
-
values: [..._interpolateArray(intrinsicValue)],
|
|
106
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
107
|
-
}, {})
|
|
108
|
-
}, {});
|
|
62
|
+
yield eat(intrinsicValue);
|
|
109
63
|
}
|
|
110
|
-
export const Keyword = Punctuator;
|
|
111
|
-
export function* Optional({
|
|
112
|
-
value: matchers,
|
|
113
|
-
ctx
|
|
114
|
-
}) {
|
|
115
|
-
const matchers_ = ctx.unbox(matchers);
|
|
116
|
-
if (matchers_.length > 1) {
|
|
117
|
-
throw new Error('Optional only allows one matcher');
|
|
118
|
-
}
|
|
119
|
-
yield _t.node(_l.Instruction, "Call", [_t.ref`verb`, _t.ref`arguments`], {
|
|
120
|
-
verb: _t.s_node(_l.Instruction, "Identifier", "eatMatch"),
|
|
121
|
-
arguments: _t.node(_l.Instruction, "Tuple", [_t.ref`openToken`, _t.ref`values[]`, _t.arr(), ..._interpolateFragmentChildren(matchers_[0], _t.ref`values[]`), _t.ref`closeToken`], {
|
|
122
|
-
openToken: _t.s_node(_l.Instruction, "Punctuator", "("),
|
|
123
|
-
values: [..._interpolateArray(matchers_[0])],
|
|
124
|
-
closeToken: _t.s_node(_l.Instruction, "Punctuator", ")")
|
|
125
|
-
}, {})
|
|
126
|
-
}, {});
|
|
127
|
-
}
|
|
64
|
+
export const Keyword = Punctuator;
|
package/lib/productions.macro.js
CHANGED
|
@@ -1,52 +1,77 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spam as m } from '@bablr/boot';
|
|
2
|
+
import { buildEmbeddedMatcher, getCooked } from '@bablr/agast-helpers/tree';
|
|
3
|
+
import { eat, eatMatch } from './grammar.js';
|
|
4
|
+
import { EmbeddedMatcher } from './symbols.js';
|
|
5
|
+
import { getEmbeddedMatcher, getEmbeddedObject } from '@bablr/agast-vm-helpers/deembed';
|
|
6
|
+
import { buildPropertyMatcher } from './builders.js';
|
|
2
7
|
|
|
3
|
-
export function* List({ value: props
|
|
8
|
+
export function* List({ value: props }) {
|
|
4
9
|
const {
|
|
5
10
|
element,
|
|
6
11
|
separator,
|
|
7
12
|
allowHoles = false,
|
|
8
13
|
allowTrailingSeparator = true,
|
|
9
|
-
} =
|
|
14
|
+
} = getEmbeddedObject(props);
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
if (
|
|
17
|
+
!['#', '@'].includes(
|
|
18
|
+
getCooked(getEmbeddedMatcher(separator).properties.refMatcher.node.properties.name.node),
|
|
19
|
+
)
|
|
20
|
+
) {
|
|
21
|
+
yield eat(
|
|
22
|
+
buildEmbeddedMatcher(
|
|
23
|
+
buildPropertyMatcher(
|
|
24
|
+
getEmbeddedMatcher(separator).properties.refMatcher.node,
|
|
25
|
+
m.ArrayNodeMatcher`[]`,
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
yield eat(
|
|
32
|
+
buildEmbeddedMatcher(
|
|
33
|
+
buildPropertyMatcher(
|
|
34
|
+
getEmbeddedMatcher(element).properties.refMatcher.node,
|
|
35
|
+
m.ArrayNodeMatcher`[]`,
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
);
|
|
12
39
|
|
|
13
40
|
let sep,
|
|
14
41
|
it,
|
|
15
42
|
anySep = false;
|
|
16
43
|
for (;;) {
|
|
17
|
-
it = yield
|
|
44
|
+
it = yield eatMatch(element);
|
|
18
45
|
if (it || allowTrailingSeparator) {
|
|
19
|
-
sep = yield
|
|
46
|
+
sep = yield eatMatch(separator);
|
|
20
47
|
anySep ||= sep;
|
|
48
|
+
} else {
|
|
49
|
+
sep = null;
|
|
21
50
|
}
|
|
22
51
|
if (!(sep || allowHoles)) break;
|
|
23
52
|
}
|
|
24
53
|
}
|
|
25
54
|
|
|
26
|
-
export function* Any({ value:
|
|
27
|
-
for (const
|
|
28
|
-
if (
|
|
55
|
+
export function* Any({ value: alternatives }) {
|
|
56
|
+
for (const alternative of alternatives) {
|
|
57
|
+
if (alternative.type === EmbeddedMatcher) {
|
|
58
|
+
if (yield eatMatch(alternative)) break;
|
|
59
|
+
} else {
|
|
60
|
+
throw new Error();
|
|
61
|
+
}
|
|
29
62
|
}
|
|
30
63
|
}
|
|
31
64
|
|
|
32
|
-
export function* All({ value: matchers
|
|
33
|
-
for (const matcher of
|
|
34
|
-
yield
|
|
65
|
+
export function* All({ value: matchers }) {
|
|
66
|
+
for (const matcher of matchers) {
|
|
67
|
+
yield eat(m`.[]: ${getEmbeddedMatcher(matcher).properties.nodeMatcher.node}`);
|
|
35
68
|
}
|
|
36
69
|
}
|
|
37
70
|
|
|
38
71
|
export function* Punctuator({ intrinsicValue }) {
|
|
39
72
|
if (!intrinsicValue) throw new Error('Intrinsic productions must have value');
|
|
40
73
|
|
|
41
|
-
yield
|
|
74
|
+
yield eat(intrinsicValue);
|
|
42
75
|
}
|
|
43
76
|
|
|
44
77
|
export const Keyword = Punctuator;
|
|
45
|
-
|
|
46
|
-
export function* Optional({ value: matchers, ctx }) {
|
|
47
|
-
const matchers_ = ctx.unbox(matchers);
|
|
48
|
-
if (matchers_.length > 1) {
|
|
49
|
-
throw new Error('Optional only allows one matcher');
|
|
50
|
-
}
|
|
51
|
-
yield i`eatMatch(${matchers_[0]})`;
|
|
52
|
-
}
|
package/lib/shorthand.js
CHANGED
package/lib/source.js
CHANGED
|
@@ -92,8 +92,50 @@ function* __embeddedSourceFrom(iterable) {
|
|
|
92
92
|
|
|
93
93
|
export const embeddedSourceFrom = (iterable) => new StreamIterable(__embeddedSourceFrom(iterable));
|
|
94
94
|
|
|
95
|
-
function*
|
|
96
|
-
let iter = getStreamIterator(
|
|
95
|
+
function* __printEmbeddedSource(chrs) {
|
|
96
|
+
let iter = getStreamIterator(chrs);
|
|
97
|
+
let part = '';
|
|
98
|
+
|
|
99
|
+
let step;
|
|
100
|
+
for (;;) {
|
|
101
|
+
step = iter.next();
|
|
102
|
+
|
|
103
|
+
if (step instanceof Promise) {
|
|
104
|
+
step = yield step;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (step.done) break;
|
|
108
|
+
|
|
109
|
+
const chr = step.value;
|
|
110
|
+
|
|
111
|
+
if (chr === null) {
|
|
112
|
+
if (part) {
|
|
113
|
+
yield `'`;
|
|
114
|
+
yield* part;
|
|
115
|
+
yield `'<//>`;
|
|
116
|
+
|
|
117
|
+
part = '';
|
|
118
|
+
}
|
|
119
|
+
} else if (chr === '\\' || chr === "'") {
|
|
120
|
+
part += `\\${chr}`;
|
|
121
|
+
} else {
|
|
122
|
+
part += chr;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (part) {
|
|
127
|
+
yield `'`;
|
|
128
|
+
yield* part;
|
|
129
|
+
yield `'`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const printEmbeddedSource = (chrs) => {
|
|
134
|
+
return __printEmbeddedSource(chrs);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
function* __sourceFromTokenStream(tags) {
|
|
138
|
+
let iter = getStreamIterator(tags);
|
|
97
139
|
let step;
|
|
98
140
|
|
|
99
141
|
for (;;) {
|
|
@@ -115,7 +157,7 @@ function* __sourceFromTokenStream(Tags) {
|
|
|
115
157
|
}
|
|
116
158
|
}
|
|
117
159
|
|
|
118
|
-
export const sourceFromTokenStream = (
|
|
160
|
+
export const sourceFromTokenStream = (tags) => new StreamIterable(__sourceFromTokenStream(tags));
|
|
119
161
|
|
|
120
162
|
function* __sourceFromQuasis(quasis) {
|
|
121
163
|
let first = true;
|
package/lib/stream.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
2
|
import {
|
|
3
|
-
generatePrettyCSTML as
|
|
4
|
-
generateCSTML as
|
|
3
|
+
generatePrettyCSTML as agastGeneratePrettyCSTML,
|
|
4
|
+
generateCSTML as agastGenerateCSTML,
|
|
5
5
|
stringFromStream,
|
|
6
6
|
getStreamIterator,
|
|
7
7
|
StreamIterable,
|
|
@@ -14,7 +14,6 @@ import { unresolveLanguage } from './grammar.js';
|
|
|
14
14
|
|
|
15
15
|
const { freeze } = Object;
|
|
16
16
|
|
|
17
|
-
// bad: wrecks tree by breaking weak linkages
|
|
18
17
|
function* __resolveTags(ctx, tags) {
|
|
19
18
|
const co = new Coroutine(getStreamIterator(tags));
|
|
20
19
|
let languages = emptyStack;
|
|
@@ -31,7 +30,7 @@ function* __resolveTags(ctx, tags) {
|
|
|
31
30
|
const tag = co.value;
|
|
32
31
|
|
|
33
32
|
if (tag.type === DoctypeTag) {
|
|
34
|
-
languages = languages.push(ctx.languages.get(tag.value.attributes
|
|
33
|
+
languages = languages.push(ctx.languages.get(tag.value.attributes.bablrLanguage));
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
if (tag.type === CloseNodeTag) {
|
|
@@ -69,20 +68,19 @@ export const resolveTags = (ctx, tags) => {
|
|
|
69
68
|
export const generatePrettyCSTML = (tags, options = {}) => {
|
|
70
69
|
const { ctx } = options;
|
|
71
70
|
|
|
72
|
-
return
|
|
71
|
+
return agastGeneratePrettyCSTML(ctx ? resolveTags(ctx, tags) : tags, options);
|
|
73
72
|
};
|
|
74
73
|
|
|
75
74
|
export const printPrettyCSTML = (tags, options = {}) => {
|
|
76
|
-
|
|
77
|
-
return stringFromStream(generatePrettyCSTMLStream(ctx ? resolveTags(ctx, tags) : tags, options));
|
|
75
|
+
return stringFromStream(generatePrettyCSTML(tags, options));
|
|
78
76
|
};
|
|
79
77
|
|
|
80
78
|
export const generateCSTML = (tags, options = {}) => {
|
|
81
79
|
const { ctx } = options;
|
|
82
80
|
|
|
83
|
-
return
|
|
81
|
+
return agastGenerateCSTML(ctx ? resolveTags(ctx, tags) : tags, options);
|
|
84
82
|
};
|
|
85
83
|
|
|
86
84
|
export const printCSTML = (tags, options = {}) => {
|
|
87
|
-
return stringFromStream(
|
|
85
|
+
return stringFromStream(generateCSTML(tags, options));
|
|
88
86
|
};
|