@bablr/agast-helpers 0.10.10 → 0.11.1
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/lib/b-list-keyed.js +1 -0
- package/lib/b-list.js +1 -0
- package/lib/b-map.js +1 -0
- package/lib/b-set.js +1 -0
- package/lib/builders.js +1000 -115
- package/lib/debug.js +39 -0
- package/lib/debug.register.js +5 -0
- package/lib/iterable.js +170 -0
- package/lib/object.js +52 -3
- package/lib/parse.js +30 -0
- package/lib/path.js +580 -634
- package/lib/print.js +52 -27
- package/lib/shorthand.js +4 -30
- package/lib/spans.js +0 -163
- package/lib/stream.js +345 -196
- package/lib/symbols.js +1 -0
- package/lib/tags.js +256 -77
- package/lib/template.js +19 -16
- package/lib/tree.js +49 -44
- package/package.json +14 -8
- package/lib/btree.js +0 -1
package/lib/print.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { freezeRecord } from '@bablr/record';
|
|
1
2
|
import {
|
|
2
3
|
DoctypeTag,
|
|
3
4
|
OpenNodeTag,
|
|
@@ -9,22 +10,25 @@ import {
|
|
|
9
10
|
LiteralTag,
|
|
10
11
|
AttributeDefinition,
|
|
11
12
|
BindingTag,
|
|
13
|
+
StreamTag,
|
|
12
14
|
} from './symbols.js';
|
|
13
|
-
import {
|
|
15
|
+
import { parseObject } from './builders.js';
|
|
16
|
+
import { arrayValues } from './iterable.js';
|
|
14
17
|
|
|
15
18
|
let { isInteger, isFinite } = Number;
|
|
16
19
|
let { isArray } = Array;
|
|
17
|
-
let { freeze } = Object;
|
|
20
|
+
let { freeze, entries } = Object;
|
|
18
21
|
let isString = (val) => typeof val === 'string';
|
|
19
22
|
let isNumber = (val) => typeof val === 'number';
|
|
20
23
|
let isObject = (val) => val && typeof val === 'object' && !isArray(val);
|
|
21
24
|
|
|
22
|
-
export const printArray = (arr) =>
|
|
25
|
+
export const printArray = (arr) =>
|
|
26
|
+
`[${[...arrayValues(arr)].map((v) => printExpression(v)).join(', ')}]`;
|
|
23
27
|
|
|
24
28
|
export const printObject = (obj) => {
|
|
25
|
-
let
|
|
26
|
-
return
|
|
27
|
-
? `{ ${
|
|
29
|
+
let entries_ = entries(obj);
|
|
30
|
+
return entries_.length
|
|
31
|
+
? `{ ${entries_.map(([k, v]) => `${k}: ${printExpression(v)}`).join(', ')} }`
|
|
28
32
|
: '{}';
|
|
29
33
|
};
|
|
30
34
|
|
|
@@ -46,19 +50,22 @@ export const printExpression = (expr) => {
|
|
|
46
50
|
}
|
|
47
51
|
} else if (isArray(expr)) {
|
|
48
52
|
return printArray(expr);
|
|
53
|
+
} else if (isObject(expr)) {
|
|
54
|
+
return printObject(expr);
|
|
49
55
|
} else {
|
|
50
56
|
throw new Error();
|
|
51
57
|
}
|
|
52
58
|
};
|
|
53
59
|
|
|
54
60
|
export const printAttributes = (attributes) => {
|
|
55
|
-
const printed =
|
|
61
|
+
const printed =
|
|
62
|
+
attributes && printObject(isString(attributes) ? parseObject(attributes) : attributes);
|
|
56
63
|
return !printed || printed === '{}' ? '' : printed;
|
|
57
64
|
};
|
|
58
65
|
|
|
59
66
|
export const printIdentifierPath = (path) => {
|
|
60
|
-
return
|
|
61
|
-
.
|
|
67
|
+
return Array.prototype.map
|
|
68
|
+
.call(path, (segment) => {
|
|
62
69
|
let { name, type } = segment;
|
|
63
70
|
if (name) {
|
|
64
71
|
return printIdentifier(name);
|
|
@@ -131,19 +138,12 @@ export const printReference = (ref) => {
|
|
|
131
138
|
};
|
|
132
139
|
|
|
133
140
|
export const printBinding = (binding) => {
|
|
134
|
-
let {
|
|
135
|
-
return `:${
|
|
136
|
-
segments.length ? segments.map((segment) => printBindingSegment(segment)).join('/') : ''
|
|
137
|
-
}:`;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export const printBindingSegment = (segment) => {
|
|
141
|
-
let { type, name } = segment;
|
|
141
|
+
let { type, name } = binding;
|
|
142
142
|
if (type) {
|
|
143
143
|
if (type !== '..') throw new Error();
|
|
144
|
-
return type
|
|
144
|
+
return `:${type}:`;
|
|
145
145
|
} else if (name) {
|
|
146
|
-
return printIdentifier(name)
|
|
146
|
+
return `:${printIdentifier(name.description)}:`;
|
|
147
147
|
} else {
|
|
148
148
|
throw new Error();
|
|
149
149
|
}
|
|
@@ -158,9 +158,7 @@ export const printBindingTag = (tag) => {
|
|
|
158
158
|
};
|
|
159
159
|
|
|
160
160
|
export const printNullTag = (tag) => {
|
|
161
|
-
if (tag && tag.type !== NullTag)
|
|
162
|
-
throw new Error();
|
|
163
|
-
}
|
|
161
|
+
if (tag && tag.type !== NullTag && tag !== 'null') throw new Error();
|
|
164
162
|
|
|
165
163
|
return 'null';
|
|
166
164
|
};
|
|
@@ -174,7 +172,7 @@ export const printName = (type) => {
|
|
|
174
172
|
};
|
|
175
173
|
|
|
176
174
|
export const printType = (type) => {
|
|
177
|
-
return typeof type === 'symbol' ? type.description : String(type);
|
|
175
|
+
return type == null ? '' : typeof type === 'symbol' ? type.description : String(type);
|
|
178
176
|
};
|
|
179
177
|
|
|
180
178
|
export const printDoctypeTag = (tag) => {
|
|
@@ -194,7 +192,14 @@ export const printLiteralTag = (tag) => {
|
|
|
194
192
|
return printString(tag.value);
|
|
195
193
|
};
|
|
196
194
|
|
|
197
|
-
|
|
195
|
+
let defaultFlags = freezeRecord({
|
|
196
|
+
array: false,
|
|
197
|
+
expression: false,
|
|
198
|
+
intrinsic: false,
|
|
199
|
+
hasGap: false,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
export const printReferenceFlags = (flags = defaultFlags) => {
|
|
198
203
|
let array = flags.array ? `[]` : '';
|
|
199
204
|
let plus = flags.expression ? '+' : '';
|
|
200
205
|
let star = flags.intrinsic ? '*' : '';
|
|
@@ -249,6 +254,14 @@ export const printSelfClosingNodeTag = (tag, literalValue) => {
|
|
|
249
254
|
return `<${printNodeFlags(flags)}${typeFrag}${nameFrag}${literalFrag}${attributesFrag} />`;
|
|
250
255
|
};
|
|
251
256
|
|
|
257
|
+
export const printStreamTag = (tag) => {
|
|
258
|
+
if (tag?.type !== StreamTag) throw new Error();
|
|
259
|
+
|
|
260
|
+
let { processPath, stream } = tag.value;
|
|
261
|
+
|
|
262
|
+
return `<${Array.prototype.join.call(processPath, '.')}-${stream}>`;
|
|
263
|
+
};
|
|
264
|
+
|
|
252
265
|
export const printCloseNodeTag = (tag) => {
|
|
253
266
|
if (tag?.type !== CloseNodeTag) throw new Error();
|
|
254
267
|
|
|
@@ -261,7 +274,7 @@ export const printAttributeDefinition = (tag) => {
|
|
|
261
274
|
let { path, value } = tag.value;
|
|
262
275
|
|
|
263
276
|
return `{ ${printIdentifierPath(
|
|
264
|
-
|
|
277
|
+
Array.prototype.map.call(path, (name) => freeze({ type: null, name })),
|
|
265
278
|
)}: ${printExpression(value)} }`;
|
|
266
279
|
};
|
|
267
280
|
|
|
@@ -275,13 +288,25 @@ const printers = {
|
|
|
275
288
|
[ReferenceTag]: printReferenceTag,
|
|
276
289
|
[OpenNodeTag]: printOpenNodeTag,
|
|
277
290
|
[CloseNodeTag]: printCloseNodeTag,
|
|
291
|
+
[StreamTag]: printStreamTag,
|
|
278
292
|
[AttributeDefinition]: printAttributeDefinition,
|
|
279
293
|
};
|
|
280
294
|
|
|
281
295
|
export const printTag = (tag) => {
|
|
296
|
+
if (tag == null || isString(tag)) return tag;
|
|
282
297
|
if (!isObject(tag)) throw new Error();
|
|
283
298
|
|
|
284
|
-
let printer = printers[tag
|
|
299
|
+
let printer = printers[tag.type];
|
|
300
|
+
|
|
301
|
+
return printer ? printer(tag) : tag;
|
|
302
|
+
};
|
|
285
303
|
|
|
286
|
-
|
|
304
|
+
export const printIOTag = (tag) => {
|
|
305
|
+
if (tag == null || isString(tag)) return tag;
|
|
306
|
+
if (!isObject(tag)) throw new Error();
|
|
307
|
+
|
|
308
|
+
if (tag.type === StreamTag) {
|
|
309
|
+
return printStreamTag(tag);
|
|
310
|
+
}
|
|
311
|
+
return printTag(tag);
|
|
287
312
|
};
|
package/lib/shorthand.js
CHANGED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
buildLiteralTag,
|
|
7
7
|
buildOpenFragmentTag,
|
|
8
8
|
buildOpenCoverTag,
|
|
9
|
+
parseReferenceTag,
|
|
9
10
|
} from './builders.js';
|
|
10
|
-
import {
|
|
11
|
-
import { buildReferenceTag, treeFromStreamSync } from './tree.js';
|
|
11
|
+
import { treeFromStream } from './tree.js';
|
|
12
12
|
|
|
13
13
|
export * from './builders.js';
|
|
14
14
|
|
|
@@ -25,34 +25,8 @@ const stripArray = (val) => {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export const parseReference = (str) => {
|
|
29
|
-
let {
|
|
30
|
-
1: type,
|
|
31
|
-
2: namedType,
|
|
32
|
-
3: name,
|
|
33
|
-
4: array,
|
|
34
|
-
5: expressionToken,
|
|
35
|
-
6: intrinsicToken,
|
|
36
|
-
7: hasGapToken,
|
|
37
|
-
} = /^\s*(?:([.#@_])|(#)?([a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*))\s*(\[\])?\s*(\+)?(\*)?(\$)?\s*$/u.exec(
|
|
38
|
-
str,
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
let flags = freeze({
|
|
42
|
-
array: !!array,
|
|
43
|
-
expression: !!expressionToken,
|
|
44
|
-
intrinsic: !!intrinsicToken,
|
|
45
|
-
hasGap: !!hasGapToken,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
type = type || namedType || null;
|
|
49
|
-
name = name || null;
|
|
50
|
-
|
|
51
|
-
return buildReferenceTag(type, name, flags);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
28
|
export const ref = (path) => {
|
|
55
|
-
return
|
|
29
|
+
return parseReferenceTag(isArray(path) ? path[0] : path);
|
|
56
30
|
};
|
|
57
31
|
|
|
58
32
|
export const lit = (str) => buildLiteralTag(stripArray(str));
|
|
@@ -63,4 +37,4 @@ export const nodeOpen = buildOpenNodeTag;
|
|
|
63
37
|
export const fragOpen = buildOpenFragmentTag;
|
|
64
38
|
export const coverOpen = buildOpenCoverTag;
|
|
65
39
|
export const nodeClose = buildCloseNodeTag;
|
|
66
|
-
export const tree = (...tags) =>
|
|
40
|
+
export const tree = (...tags) => treeFromStream(tags);
|
package/lib/spans.js
CHANGED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { buildModule, defaultNodeSize } from '@bablr/btree/enhanceable';
|
|
2
|
-
|
|
3
|
-
const { isArray } = Array;
|
|
4
|
-
const { freeze } = Object;
|
|
5
|
-
|
|
6
|
-
export { defaultNodeSize };
|
|
7
|
-
|
|
8
|
-
const __getAtName = (name, sortedArray, startIdx = 0, endIdx = sortedArray.length - 1) => {
|
|
9
|
-
if (!sortedArray.length || endIdx < startIdx) return null;
|
|
10
|
-
|
|
11
|
-
let idx = startIdx + Math.floor((endIdx - startIdx) / 2 + 0.1);
|
|
12
|
-
let entry = sortedArray[idx];
|
|
13
|
-
let { 0: key, 1: value } = entry;
|
|
14
|
-
|
|
15
|
-
let direction = compareNames(name, key);
|
|
16
|
-
|
|
17
|
-
if (direction === 0) {
|
|
18
|
-
return value;
|
|
19
|
-
} else {
|
|
20
|
-
if (startIdx === endIdx) return null;
|
|
21
|
-
|
|
22
|
-
if (direction > 0) {
|
|
23
|
-
return __getAtName(name, sortedArray, idx + 1, endIdx);
|
|
24
|
-
} else {
|
|
25
|
-
return __getAtName(name, sortedArray, startIdx, idx - 1);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const getAtName = (name, sortedArray, startIdx = 0, endIdx = sortedArray.length - 1) => {
|
|
31
|
-
return __getAtName(name, sortedArray, startIdx, endIdx);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const compareNames = (a, b) => (a > b ? 1 : b > a ? -1 : 0);
|
|
35
|
-
|
|
36
|
-
export const sumValues = (values) => {
|
|
37
|
-
let mapStats = values.reduce(
|
|
38
|
-
(acc, val) => {
|
|
39
|
-
const { names } = acc;
|
|
40
|
-
if (isArray(val)) {
|
|
41
|
-
let arr = getSums(val).names;
|
|
42
|
-
let map = names;
|
|
43
|
-
|
|
44
|
-
for (const { 0: key, 1: value } of arr) {
|
|
45
|
-
let count = map.get(key)?.[1] ?? 0;
|
|
46
|
-
|
|
47
|
-
map.set(key, freeze([key, count + value]));
|
|
48
|
-
}
|
|
49
|
-
} else if (val) {
|
|
50
|
-
let span = val;
|
|
51
|
-
|
|
52
|
-
const { name } = span;
|
|
53
|
-
|
|
54
|
-
if (name) {
|
|
55
|
-
let count = names.get(name)?.[1] ?? 0;
|
|
56
|
-
|
|
57
|
-
names.set(name, freeze([name, count + 1]));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return acc;
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
names: new Map(),
|
|
64
|
-
},
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
let stats = {
|
|
68
|
-
names: [...mapStats.names.values()].sort((a, b) => compareNames(a[0], b[0])),
|
|
69
|
-
};
|
|
70
|
-
freeze(stats);
|
|
71
|
-
freeze(stats.names);
|
|
72
|
-
return stats;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const module_ = buildModule(defaultNodeSize, sumValues);
|
|
76
|
-
|
|
77
|
-
const {
|
|
78
|
-
from,
|
|
79
|
-
fromValues,
|
|
80
|
-
push,
|
|
81
|
-
pop,
|
|
82
|
-
addAt,
|
|
83
|
-
isValidNode,
|
|
84
|
-
assertValidNode,
|
|
85
|
-
getSize,
|
|
86
|
-
getValues,
|
|
87
|
-
getSums,
|
|
88
|
-
setValues,
|
|
89
|
-
traverse,
|
|
90
|
-
traverseInner,
|
|
91
|
-
findPath,
|
|
92
|
-
getAt,
|
|
93
|
-
replaceAt,
|
|
94
|
-
removeAt,
|
|
95
|
-
} = module_;
|
|
96
|
-
|
|
97
|
-
const getSpan = (name, spans) => {
|
|
98
|
-
let nameCount = 0;
|
|
99
|
-
let node = spans;
|
|
100
|
-
let idx = -1;
|
|
101
|
-
let index = getAtName(name, getSums(spans).names);
|
|
102
|
-
|
|
103
|
-
// drill into subtrees, passing over subtrees with too few references of the desired name
|
|
104
|
-
outer: while (node) {
|
|
105
|
-
let sums = getSums(node);
|
|
106
|
-
|
|
107
|
-
if (!sums) return null;
|
|
108
|
-
|
|
109
|
-
let valueNameCount = getAtName(name, sums.names);
|
|
110
|
-
|
|
111
|
-
if (nameCount + valueNameCount < index) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
for (const value of getValues(node)) {
|
|
116
|
-
if (!isArray(value)) {
|
|
117
|
-
idx++;
|
|
118
|
-
let span = value;
|
|
119
|
-
|
|
120
|
-
if (name != null && span.name === name) {
|
|
121
|
-
nameCount += 1;
|
|
122
|
-
if (nameCount === index) {
|
|
123
|
-
return getAt(idx, spans);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
let valueSums = getSums(value);
|
|
128
|
-
if (nameCount + getAtName(name, valueSums.names) > index) {
|
|
129
|
-
node = value;
|
|
130
|
-
continue outer;
|
|
131
|
-
} else {
|
|
132
|
-
nameCount += getAtName(name, valueSums.names) ?? 0;
|
|
133
|
-
idx += getSize(value);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return null;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
export {
|
|
145
|
-
from,
|
|
146
|
-
fromValues,
|
|
147
|
-
push,
|
|
148
|
-
pop,
|
|
149
|
-
addAt,
|
|
150
|
-
isValidNode,
|
|
151
|
-
assertValidNode,
|
|
152
|
-
getSize,
|
|
153
|
-
getValues,
|
|
154
|
-
getSums,
|
|
155
|
-
setValues,
|
|
156
|
-
traverse,
|
|
157
|
-
traverseInner,
|
|
158
|
-
findPath,
|
|
159
|
-
getAt,
|
|
160
|
-
replaceAt,
|
|
161
|
-
removeAt,
|
|
162
|
-
getSpan,
|
|
163
|
-
};
|