@bablr/bablr-vm 0.22.1 → 0.23.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/lib/context.js +2 -44
- package/lib/evaluate.js +147 -378
- package/lib/facades.js +34 -0
- package/lib/match.js +468 -325
- package/lib/source.js +9 -58
- package/lib/spans.js +29 -68
- package/lib/state.js +58 -336
- package/lib/utils/pattern.js +58 -28
- package/package.json +11 -8
- package/lib/node.js +0 -327
package/lib/evaluate.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
+
/* global WeakSet */
|
|
1
2
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
buildBindingTag,
|
|
5
|
-
buildChild,
|
|
6
|
-
buildCloseNodeTag,
|
|
7
|
-
buildFacadeProperty,
|
|
8
|
-
buildProperty,
|
|
9
|
-
} from '@bablr/agast-helpers/builders';
|
|
10
|
-
import { getStreamIterator, printType, StreamIterable } from '@bablr/agast-helpers/stream';
|
|
3
|
+
import { buildAttributeDefinition, buildCloseNodeTag } from '@bablr/agast-helpers/builders';
|
|
4
|
+
import { getStreamIterator, printType, StreamIterable, wait } from '@bablr/agast-helpers/stream';
|
|
11
5
|
import { facades } from './facades.js';
|
|
12
6
|
import { State } from './state.js';
|
|
13
|
-
import { updateSpans } from './spans.js';
|
|
14
7
|
import {
|
|
15
8
|
OpenNodeTag,
|
|
16
9
|
CloseNodeTag,
|
|
@@ -18,34 +11,22 @@ import {
|
|
|
18
11
|
BindingTag,
|
|
19
12
|
LiteralTag,
|
|
20
13
|
ReferenceTag,
|
|
21
|
-
NullTag,
|
|
22
14
|
ShiftTag,
|
|
23
|
-
InitializerTag,
|
|
24
15
|
AttributeDefinition,
|
|
25
|
-
Property,
|
|
26
16
|
} from '@bablr/agast-helpers/symbols';
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
buildOpenNodeTag,
|
|
32
|
-
buildReferenceTag,
|
|
33
|
-
buildStubNode,
|
|
34
|
-
getFlagsWithGap,
|
|
35
|
-
getRoot,
|
|
36
|
-
treeFromStreamSync,
|
|
37
|
-
} from '@bablr/agast-helpers/tree';
|
|
38
|
-
import { getEmbeddedObject, getEmbeddedTag } from '@bablr/agast-vm-helpers/deembed';
|
|
17
|
+
import { getRoot, treeFromStreamSync } from '@bablr/agast-helpers/tree';
|
|
18
|
+
import * as Tags from '@bablr/agast-helpers/tags';
|
|
19
|
+
import { getEmbeddedTag } from '@bablr/agast-vm-helpers/deembed';
|
|
39
20
|
import { Match } from './match.js';
|
|
40
|
-
import {
|
|
41
|
-
import { getProduction } from '@bablr/helpers/grammar';
|
|
42
|
-
import { buildEmbeddedNode, buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
21
|
+
import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
43
22
|
import { has } from '@bablr/agast-helpers/object';
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
23
|
+
import { reifyBablrOptions } from '@bablr/agast-vm-helpers';
|
|
24
|
+
import { buildNode, getTags } from '@bablr/agast-helpers/path';
|
|
25
|
+
|
|
26
|
+
const validNodesByLanguage = new Map();
|
|
46
27
|
|
|
47
|
-
const
|
|
48
|
-
|
|
28
|
+
export const isKnownValid = (language, node) => {
|
|
29
|
+
return !!validNodesByLanguage.get(language)?.has(node);
|
|
49
30
|
};
|
|
50
31
|
|
|
51
32
|
const getSourceLength = (tags) => {
|
|
@@ -67,16 +48,22 @@ export const bablr = (ctx, rootSource, strategy, options = {}) => {
|
|
|
67
48
|
function* __bablr(ctx, rootSource, strategy, options) {
|
|
68
49
|
let s = null;
|
|
69
50
|
let m = null;
|
|
70
|
-
let language = null;
|
|
71
51
|
let finishedMatch = null;
|
|
52
|
+
let outerOptions = options;
|
|
72
53
|
|
|
73
|
-
let
|
|
54
|
+
let getState = () => s.getPublic();
|
|
55
|
+
|
|
56
|
+
for (const language of ctx.languages.values()) {
|
|
57
|
+
validNodesByLanguage.set(language, validNodesByLanguage.get(language) || new WeakSet());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let co = new Coroutine(getStreamIterator(strategy(facades.get(ctx), getState)));
|
|
74
61
|
|
|
75
62
|
co.advance();
|
|
76
63
|
|
|
77
64
|
for (;;) {
|
|
78
65
|
if (co.current instanceof Promise) {
|
|
79
|
-
co.current = yield co.current;
|
|
66
|
+
co.current = yield wait(co.current);
|
|
80
67
|
}
|
|
81
68
|
|
|
82
69
|
if (co.done) {
|
|
@@ -88,11 +75,11 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
88
75
|
|
|
89
76
|
s.source.release();
|
|
90
77
|
|
|
91
|
-
if (exchange
|
|
78
|
+
if (exchange?.sources > 0) {
|
|
92
79
|
throw new Error('Source did not close all forks: ' + exchange.sources);
|
|
93
80
|
}
|
|
94
81
|
|
|
95
|
-
return co.value
|
|
82
|
+
return co.value;
|
|
96
83
|
}
|
|
97
84
|
|
|
98
85
|
const instr = co.value;
|
|
@@ -113,15 +100,15 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
113
100
|
case 'match': {
|
|
114
101
|
let { arguments: { 0: pattern } = [] } = instr;
|
|
115
102
|
|
|
116
|
-
let result = s.guardedMatch(pattern
|
|
103
|
+
let result = s.guardedMatch(pattern);
|
|
117
104
|
|
|
118
105
|
if (result instanceof Promise) {
|
|
119
|
-
result = yield result;
|
|
106
|
+
result = yield wait(result);
|
|
120
107
|
}
|
|
121
108
|
|
|
122
109
|
let node = result && treeFromStreamSync(result);
|
|
123
110
|
|
|
124
|
-
returnValue = node
|
|
111
|
+
returnValue = node;
|
|
125
112
|
break;
|
|
126
113
|
}
|
|
127
114
|
|
|
@@ -130,80 +117,44 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
130
117
|
|
|
131
118
|
const tag = getEmbeddedTag(embeddedTags);
|
|
132
119
|
|
|
133
|
-
if (tag.type !== ReferenceTag) {
|
|
134
|
-
s.referenceTagPath = null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (
|
|
138
|
-
!m.isNode &&
|
|
139
|
-
m.coveredBoundary !== m &&
|
|
140
|
-
!((s.holding && tag.type === GapTag) || tag.type === OpenNodeTag)
|
|
141
|
-
) {
|
|
142
|
-
throw new Error('cannot advance inside a cover');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
120
|
switch (tag.type) {
|
|
146
121
|
case ReferenceTag: {
|
|
147
|
-
if (
|
|
148
|
-
if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
|
|
149
|
-
if (!referencesAreEqual(s.node.tags.at(1).value, tag.value) || s.node.tags.size > 3) {
|
|
150
|
-
throw new Error();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
122
|
+
// if (m.didShift) throw new Error();
|
|
153
123
|
|
|
154
124
|
m.advance(tag, s);
|
|
155
125
|
|
|
156
|
-
s.referenceTagPath = TagPath.from(s.path, -1, 0);
|
|
157
|
-
if (s.referenceTagPath.tag.type === BindingTag) throw new Error();
|
|
158
126
|
break;
|
|
159
127
|
}
|
|
160
128
|
|
|
161
129
|
case ShiftTag: {
|
|
162
|
-
let
|
|
163
|
-
let refTag = s.node.tags.at(-1, 0);
|
|
164
|
-
let lastShiftTag = refTag;
|
|
165
|
-
|
|
166
|
-
if (refTag.type === ShiftTag) {
|
|
167
|
-
refTag = s.node.tags.at(-refTag.value.index - 1, 0);
|
|
168
|
-
}
|
|
130
|
+
let lastProp = Tags.getAt(-1, m.rootNode.value.tags);
|
|
169
131
|
|
|
170
|
-
|
|
132
|
+
m.advance(tag, s);
|
|
171
133
|
|
|
172
|
-
|
|
173
|
-
s.depths.nodeShift = index;
|
|
134
|
+
let shiftProp = Tags.getAt(-1, m.rootNode.value.tags);
|
|
174
135
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
136
|
+
let {
|
|
137
|
+
shift: { height, index },
|
|
138
|
+
} = shiftProp.value;
|
|
178
139
|
|
|
179
|
-
s.
|
|
180
|
-
s.held = buildFacadeProperty(
|
|
181
|
-
refTag.value,
|
|
182
|
-
s.resultPath.tag.value,
|
|
183
|
-
s.resultPath.nextSibling.tag.value.node,
|
|
184
|
-
);
|
|
140
|
+
s.held = lastProp.value.node;
|
|
185
141
|
|
|
186
|
-
|
|
187
|
-
s.
|
|
142
|
+
s.depths.shift = height;
|
|
143
|
+
s.depths.nodeShift = index;
|
|
188
144
|
break;
|
|
189
145
|
}
|
|
190
146
|
|
|
191
147
|
case BindingTag: {
|
|
192
148
|
m.advance(tag, s);
|
|
193
|
-
|
|
194
|
-
let propertyChild = buildChild(
|
|
195
|
-
sym.Property,
|
|
196
|
-
buildProperty(s.held.reference, tag.value, s.held.node.node),
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
m.agastFragment.vm.next(propertyChild);
|
|
200
|
-
|
|
201
|
-
s.held = null;
|
|
202
149
|
break;
|
|
203
150
|
}
|
|
204
151
|
|
|
205
152
|
case OpenNodeTag: {
|
|
206
|
-
let { literalValue, selfClosing } = tag.value;
|
|
153
|
+
let { type, literalValue, selfClosing } = tag.value;
|
|
154
|
+
|
|
155
|
+
if (literalValue && s.held) {
|
|
156
|
+
// throw new Error('cannot advance literal while holding');
|
|
157
|
+
}
|
|
207
158
|
|
|
208
159
|
s.depths.path++;
|
|
209
160
|
s.depths.nodeShift = 0;
|
|
@@ -212,33 +163,25 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
212
163
|
s.depths.shift = 0;
|
|
213
164
|
}
|
|
214
165
|
|
|
215
|
-
s.agast = m.agast;
|
|
216
|
-
|
|
217
166
|
m.advance(tag, s);
|
|
218
|
-
|
|
167
|
+
|
|
168
|
+
if (!type || !s.node) {
|
|
169
|
+
s.node = m.node;
|
|
170
|
+
}
|
|
219
171
|
|
|
220
172
|
if (selfClosing) {
|
|
221
173
|
if (literalValue) {
|
|
222
|
-
let result;
|
|
223
|
-
if (
|
|
224
|
-
s.resultPath.tag.type === OpenNodeTag &&
|
|
225
|
-
s.resultPath.tag.value.attributes.balancer &&
|
|
226
|
-
s.balanced.value?.attributes.balanced === literalValue
|
|
227
|
-
) {
|
|
228
|
-
result = s.match(literalValue, tag.value.attributes);
|
|
229
|
-
} else {
|
|
230
|
-
result = s.guardedMatch(literalValue, tag.value.attributes);
|
|
231
|
-
}
|
|
174
|
+
let result = s.guardedMatch(literalValue);
|
|
232
175
|
|
|
233
176
|
if (result instanceof Promise) {
|
|
234
|
-
result = yield result;
|
|
177
|
+
result = yield wait(result);
|
|
235
178
|
}
|
|
236
179
|
|
|
237
180
|
if (result) {
|
|
238
181
|
let sourceStep = s.source.advance(getSourceLength(result));
|
|
239
182
|
|
|
240
183
|
if (sourceStep instanceof Promise) {
|
|
241
|
-
sourceStep = yield sourceStep;
|
|
184
|
+
sourceStep = yield wait(sourceStep);
|
|
242
185
|
}
|
|
243
186
|
} else {
|
|
244
187
|
throw new Error('Failed to advance literal');
|
|
@@ -249,134 +192,64 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
249
192
|
s.depths.nodeShift = 0;
|
|
250
193
|
s.depths.shift = 0;
|
|
251
194
|
|
|
252
|
-
s.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
binding: null,
|
|
256
|
-
node: s.resultPath.node,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (s.depths.path === 0) {
|
|
261
|
-
m.setRangePreviousIndex(0);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (tag.value.type) {
|
|
265
|
-
updateSpans(m, s.resultPath.node, 'open');
|
|
266
|
-
}
|
|
267
|
-
if (literalValue) {
|
|
268
|
-
updateSpans(m, s.resultPath.node, 'close');
|
|
195
|
+
// s.held = literalValue
|
|
196
|
+
// ? new NodeFacade(s.resultPath.tag.value.property.node)
|
|
197
|
+
// : s.resultPath.node;
|
|
269
198
|
}
|
|
270
199
|
|
|
271
200
|
break;
|
|
272
201
|
}
|
|
273
202
|
|
|
274
203
|
case CloseNodeTag: {
|
|
275
|
-
|
|
204
|
+
let { node, language } = m;
|
|
276
205
|
|
|
277
206
|
s.depths.path--;
|
|
278
207
|
s.depths.nodeShift = 0;
|
|
279
208
|
s.depths.shift = 0;
|
|
280
209
|
|
|
281
|
-
if (m.
|
|
282
|
-
|
|
283
|
-
s.depths.
|
|
210
|
+
if (m.shiftMatch) {
|
|
211
|
+
let { shift } = Tags.getAt(-1, m.rootNode.value.children).value;
|
|
212
|
+
s.depths.nodeShift = shift.index;
|
|
213
|
+
s.depths.shift = shift.height;
|
|
284
214
|
}
|
|
285
215
|
|
|
286
|
-
|
|
287
|
-
const refPath = m.referencePath;
|
|
288
|
-
|
|
289
|
-
m.advance(tag, s);
|
|
290
|
-
let gaplessNode = null;
|
|
291
|
-
|
|
292
|
-
if (refPath?.tag.value.type === '@') {
|
|
293
|
-
let { vm: escapeVm, state: escapeState } = agast();
|
|
294
|
-
|
|
295
|
-
let tagPath = PathFacade.from(node).tagPathAt(0);
|
|
296
|
-
|
|
297
|
-
while (tagPath) {
|
|
298
|
-
if (tagPath.tag.type === GapTag) {
|
|
299
|
-
throw new Error();
|
|
300
|
-
}
|
|
301
|
-
if (tagPath.tag.type === OpenNodeTag) {
|
|
302
|
-
let { flags, type, attributes, literalValue } = tagPath.tag.value;
|
|
303
|
-
|
|
304
|
-
escapeVm.next(
|
|
305
|
-
buildOpenNodeTag(
|
|
306
|
-
getFlagsWithGap(flags, false),
|
|
307
|
-
type,
|
|
308
|
-
attributes,
|
|
309
|
-
literalValue,
|
|
310
|
-
),
|
|
311
|
-
);
|
|
312
|
-
} else if (tagPath.tag.type === ReferenceTag && tagPath.tag.value.flags.hasGap) {
|
|
313
|
-
let { flags, name, type, isArray, index } = tagPath.tag.value;
|
|
314
|
-
|
|
315
|
-
flags = getFlagsWithGap(flags, false);
|
|
316
|
-
|
|
317
|
-
escapeVm.next(buildReferenceTag(type, name, isArray, flags, index));
|
|
318
|
-
} else {
|
|
319
|
-
escapeVm.next(tagPath.tag);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (tagPath.tag.type === CloseNodeTag && !tagPath.nextUnshifted) {
|
|
323
|
-
gaplessNode = escapeState.resultPath.node;
|
|
324
|
-
}
|
|
216
|
+
m.advance(tag, s);
|
|
325
217
|
|
|
326
|
-
|
|
327
|
-
|
|
218
|
+
if (!m.parent) {
|
|
219
|
+
if (!s.source.done) {
|
|
220
|
+
throw new Error('Parser failed to consume input');
|
|
328
221
|
}
|
|
329
222
|
|
|
330
|
-
s.
|
|
331
|
-
|
|
332
|
-
s.held = Object.freeze({
|
|
333
|
-
reference: refPath?.tag.value,
|
|
334
|
-
binding: null,
|
|
335
|
-
node: gaplessNode || m.node,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
updateSpans(m, s.resultPath.node, 'close');
|
|
339
|
-
|
|
340
|
-
if (!m.parent) {
|
|
341
|
-
if (!s.source.done) {
|
|
342
|
-
throw new Error('Parser failed to consume input');
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (s.balanced.size) {
|
|
346
|
-
throw new Error('Parser did not match all balanced nodes');
|
|
347
|
-
}
|
|
223
|
+
if (s.balanced.size) {
|
|
224
|
+
throw new Error('Parser did not match all balanced nodes');
|
|
348
225
|
}
|
|
349
|
-
} else {
|
|
350
|
-
m.advance(tag, s);
|
|
351
|
-
s.agast = m.agastFragment;
|
|
352
226
|
}
|
|
353
227
|
|
|
228
|
+
if (!node.value.type) {
|
|
229
|
+
s.node = m.node;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
validNodesByLanguage.get(language).add(node);
|
|
233
|
+
|
|
354
234
|
break;
|
|
355
235
|
}
|
|
356
236
|
|
|
357
237
|
case LiteralTag: {
|
|
358
238
|
const { value: pattern } = tag;
|
|
359
239
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
s.resultPath.tag.value.attributes.balancer &&
|
|
364
|
-
s.balanced.value?.attributes.balanced === pattern
|
|
365
|
-
) {
|
|
366
|
-
result = s.match(pattern);
|
|
367
|
-
} else {
|
|
368
|
-
result = s.guardedMatch(pattern);
|
|
369
|
-
}
|
|
240
|
+
// if (s.held) throw new Error('cannot advance literal while holding');
|
|
241
|
+
|
|
242
|
+
let result = s.guardedMatch(pattern);
|
|
370
243
|
|
|
371
244
|
if (result instanceof Promise) {
|
|
372
|
-
result = yield result;
|
|
245
|
+
result = yield wait(result);
|
|
373
246
|
}
|
|
374
247
|
|
|
375
248
|
if (result) {
|
|
376
249
|
let sourceStep = s.source.advance(getSourceLength(result));
|
|
377
250
|
|
|
378
251
|
if (sourceStep instanceof Promise) {
|
|
379
|
-
sourceStep = yield sourceStep;
|
|
252
|
+
sourceStep = yield wait(sourceStep);
|
|
380
253
|
}
|
|
381
254
|
|
|
382
255
|
m.advance(tag, s);
|
|
@@ -387,79 +260,48 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
387
260
|
}
|
|
388
261
|
|
|
389
262
|
case GapTag: {
|
|
390
|
-
if (s.source.value == null &&
|
|
391
|
-
if (s.
|
|
392
|
-
s.source.unshift();
|
|
393
|
-
} else {
|
|
263
|
+
if (s.source.value == null && !s.done) {
|
|
264
|
+
if (!s.held) {
|
|
394
265
|
const sourceStep = s.source.advance(1);
|
|
395
266
|
|
|
396
267
|
if (sourceStep instanceof Promise) {
|
|
397
|
-
yield sourceStep;
|
|
268
|
+
yield wait(sourceStep);
|
|
398
269
|
}
|
|
399
270
|
}
|
|
271
|
+
}
|
|
400
272
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
buildChild(
|
|
405
|
-
Property,
|
|
406
|
-
buildProperty(m.referencePath.tag.value, null, buildStubNode(tag)),
|
|
407
|
-
),
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
s.resultPath = TagPath.from(s.resultPath.path, -1);
|
|
411
|
-
|
|
412
|
-
s.held = null;
|
|
413
|
-
break;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (s.expressions.size) {
|
|
417
|
-
let expression = s.expressions.value;
|
|
418
|
-
let node = getRoot(isPlainObject(expression) ? expression : expression.node);
|
|
419
|
-
|
|
420
|
-
let mergedBinding = buildBindingTag(m.mergedLanguagePath);
|
|
421
|
-
|
|
422
|
-
s.agast.vm.next(mergedBinding);
|
|
423
|
-
s.agast.vm.next(
|
|
424
|
-
buildChild(
|
|
425
|
-
Property,
|
|
426
|
-
buildProperty(s.resultPath.tag.value, mergedBinding.value, node),
|
|
427
|
-
),
|
|
428
|
-
);
|
|
273
|
+
if (s.held) {
|
|
274
|
+
if (!m.agast.getState().held) throw new Error();
|
|
275
|
+
m.advance(buildNode(tag));
|
|
429
276
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
277
|
+
s.held = null;
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
433
280
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
m.add(m.node);
|
|
281
|
+
if (s.expressions.size) {
|
|
282
|
+
let expression = s.expressions.value;
|
|
283
|
+
let node = getRoot(expression);
|
|
438
284
|
|
|
439
|
-
|
|
440
|
-
}
|
|
285
|
+
m.advance(node);
|
|
441
286
|
|
|
442
|
-
s.
|
|
287
|
+
s.expressions = s.expressions.pop();
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
443
290
|
|
|
444
|
-
|
|
291
|
+
if (Tags.getSize(getTags(s.node))) {
|
|
292
|
+
m.advance(tag, s);
|
|
445
293
|
} else {
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
break;
|
|
449
|
-
}
|
|
294
|
+
m.add(m.node);
|
|
450
295
|
|
|
451
|
-
|
|
452
|
-
if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
|
|
453
|
-
throw new Error();
|
|
296
|
+
m.advance(tag, s);
|
|
454
297
|
}
|
|
455
|
-
m.advance(tag, s);
|
|
456
298
|
break;
|
|
457
299
|
}
|
|
458
300
|
|
|
459
301
|
case AttributeDefinition: {
|
|
460
302
|
const { path, value } = tag.value;
|
|
461
303
|
|
|
462
|
-
if (!has(m.node.attributes, path)) {
|
|
304
|
+
if (!has(m.node.value.attributes, path)) {
|
|
463
305
|
throw new Error('undefined attributes must be declared');
|
|
464
306
|
}
|
|
465
307
|
|
|
@@ -467,7 +309,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
467
309
|
|
|
468
310
|
if (value && typeof value === 'object') throw new Error('unimplemented');
|
|
469
311
|
|
|
470
|
-
|
|
312
|
+
m.advance(buildAttributeDefinition(path, value));
|
|
313
|
+
|
|
471
314
|
break;
|
|
472
315
|
}
|
|
473
316
|
|
|
@@ -476,156 +319,81 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
476
319
|
}
|
|
477
320
|
|
|
478
321
|
if (s.depth === 0 && (s.node || s.resultPath?.node)) {
|
|
479
|
-
yield* m.emit(
|
|
322
|
+
yield* m.emit(outerOptions);
|
|
480
323
|
}
|
|
481
324
|
|
|
482
325
|
returnValue = tag;
|
|
483
326
|
break;
|
|
484
327
|
}
|
|
485
328
|
|
|
486
|
-
case '
|
|
487
|
-
let { arguments: { 0: name } = [] } = instr;
|
|
488
|
-
s.spans = s.spans.push({
|
|
329
|
+
case 'startSpan': {
|
|
330
|
+
let { arguments: { 0: name, 1: guard = null } = [] } = instr;
|
|
331
|
+
s.spans = s.spans.push({ type: 'Instruction', name, guard });
|
|
489
332
|
break;
|
|
490
333
|
}
|
|
491
334
|
|
|
492
|
-
case '
|
|
335
|
+
case 'endSpan': {
|
|
493
336
|
if (s.spans.value.type !== 'Instruction') throw new Error();
|
|
494
337
|
s.spans = s.spans.pop();
|
|
495
338
|
break;
|
|
496
339
|
}
|
|
497
340
|
|
|
498
|
-
case '
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
// m.node = s.agast.node;
|
|
502
|
-
|
|
503
|
-
returnValue = facades.get(s);
|
|
504
|
-
break;
|
|
505
|
-
}
|
|
341
|
+
case 'startFrame': {
|
|
342
|
+
let { arguments: { 0: verb, 1: { value: matcher } = {}, 2: options = ' ' } = [] } =
|
|
343
|
+
instr;
|
|
506
344
|
|
|
507
|
-
|
|
508
|
-
s =
|
|
345
|
+
m = Match.startFrame(ctx, s, m, null, verb, matcher, reifyBablrOptions(options));
|
|
346
|
+
s = m.state;
|
|
509
347
|
|
|
510
|
-
|
|
511
|
-
yield* m.emit(options);
|
|
512
|
-
}
|
|
348
|
+
yield* m.emit(outerOptions);
|
|
513
349
|
|
|
514
|
-
returnValue = facades.get(
|
|
350
|
+
returnValue = facades.get(m);
|
|
515
351
|
break;
|
|
516
352
|
}
|
|
517
353
|
|
|
518
|
-
case '
|
|
519
|
-
|
|
520
|
-
const { arguments: { 0: embeddedOptions } = [] } = instr;
|
|
521
|
-
let options = getEmbeddedObject(embeddedOptions);
|
|
354
|
+
case 'endFrame': {
|
|
355
|
+
finishedMatch = m;
|
|
522
356
|
|
|
523
|
-
|
|
524
|
-
finishedMatch,
|
|
525
|
-
// finishedMatch.effects.success === 'none',
|
|
526
|
-
options,
|
|
527
|
-
);
|
|
357
|
+
finishedMatch.advance(buildCloseNodeTag());
|
|
528
358
|
|
|
529
|
-
|
|
359
|
+
m = m.endFrame(outerOptions);
|
|
360
|
+
s = m ? m.state : s;
|
|
530
361
|
|
|
531
|
-
if (
|
|
532
|
-
|
|
362
|
+
if (m) {
|
|
363
|
+
m.running = null;
|
|
364
|
+
if (finishedMatch.shiftMatch) {
|
|
365
|
+
finishedMatch.shiftMatch.running = null;
|
|
366
|
+
}
|
|
367
|
+
yield* m.emit(outerOptions);
|
|
533
368
|
}
|
|
534
369
|
|
|
535
|
-
returnValue = facades.get(
|
|
370
|
+
returnValue = m && facades.get(m);
|
|
536
371
|
break;
|
|
537
372
|
}
|
|
538
373
|
|
|
539
|
-
case '
|
|
540
|
-
let {
|
|
541
|
-
|
|
542
|
-
} = instr;
|
|
543
|
-
|
|
544
|
-
let effects = effectsFor(verb.description);
|
|
545
|
-
let didShift = verb.description.startsWith('shift');
|
|
374
|
+
case 'shiftFrame': {
|
|
375
|
+
let { arguments: { 0: verb, 1: { value: matcher } = {}, 2: options = ' ' } = [] } =
|
|
376
|
+
instr;
|
|
546
377
|
|
|
547
378
|
let parentMatch = m;
|
|
548
379
|
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
let matcher_ = reifyExpression(matcher);
|
|
552
|
-
|
|
553
|
-
if (didShift && !parentMatch) throw new Error();
|
|
554
|
-
|
|
555
|
-
m = parentMatch
|
|
556
|
-
? parentMatch.startFrame(s, matcher_, effects, didShift ? finishedMatch : null, options)
|
|
557
|
-
: Match.from(ctx, language, s, matcher_, null, options);
|
|
380
|
+
if (finishedMatch.type !== '_') throw new Error();
|
|
558
381
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (matcher_.refMatcher) {
|
|
570
|
-
let m = matcher_.refMatcher;
|
|
571
|
-
if (!['.', '#'].includes(m.type) || m.flags.expression || m.flags.hasGap || m.isArray) {
|
|
572
|
-
throw new Error('no references inside covers');
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
if (didShift) {
|
|
578
|
-
if (s.node.tags.at(-1, 0)?.type !== ShiftTag) {
|
|
579
|
-
throw new Error('advance shift tag before starting new held frame');
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
let broken = !parentMatch || effects.success === 'none' || s.agast.state.node.type === null;
|
|
584
|
-
|
|
585
|
-
if (effects.success !== 'none') {
|
|
586
|
-
m.agastFragment = s.agast;
|
|
587
|
-
} else {
|
|
588
|
-
s.agast = m.agastFragment = m.agast;
|
|
589
|
-
s.referenceTagPath = null;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
({ language } = m);
|
|
593
|
-
|
|
594
|
-
let offset = [ReferenceTag, ShiftTag].includes(s.resultPath?.tag.type) ? -1 : 0;
|
|
595
|
-
|
|
596
|
-
if (!broken) {
|
|
597
|
-
let previousIndex = [CloseNodeTag, NullTag, GapTag].includes(s.resultPath.tag.type)
|
|
598
|
-
? m.fragmentNode.tags.size - 1
|
|
599
|
-
: s.resultPath.tagsIndex;
|
|
600
|
-
|
|
601
|
-
m.setRangePreviousIndex(previousIndex + offset);
|
|
602
|
-
} else if (parentMatch) {
|
|
603
|
-
m.setRangePreviousIndex(m.fragmentNode.tags.size - 1 + offset);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
returnValue = facades.get(m);
|
|
607
|
-
|
|
608
|
-
m.range;
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
case 'endFrame': {
|
|
613
|
-
finishedMatch = m;
|
|
614
|
-
|
|
615
|
-
m = m.endFrame();
|
|
382
|
+
m = Match.startFrame(
|
|
383
|
+
ctx,
|
|
384
|
+
s,
|
|
385
|
+
parentMatch,
|
|
386
|
+
finishedMatch,
|
|
387
|
+
verb,
|
|
388
|
+
matcher,
|
|
389
|
+
reifyBablrOptions(options),
|
|
390
|
+
);
|
|
391
|
+
s = m ? m.state : s;
|
|
616
392
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
} else {
|
|
620
|
-
finishedMatch.agastFragment.vm.next(buildCloseNodeTag());
|
|
621
|
-
s.agast = m.agast;
|
|
622
|
-
s.referenceTagPath = m.referencePath;
|
|
623
|
-
}
|
|
393
|
+
finishedMatch.parent.running = m;
|
|
394
|
+
finishedMatch.running = m;
|
|
624
395
|
|
|
625
|
-
|
|
626
|
-
returnValue = m;
|
|
627
|
-
break;
|
|
628
|
-
}
|
|
396
|
+
yield* finishedMatch.emit(outerOptions);
|
|
629
397
|
|
|
630
398
|
returnValue = m && facades.get(m);
|
|
631
399
|
break;
|
|
@@ -636,8 +404,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
636
404
|
|
|
637
405
|
m = m.throw_();
|
|
638
406
|
|
|
639
|
-
if (m
|
|
640
|
-
|
|
407
|
+
if (m) {
|
|
408
|
+
yield* m.emit(outerOptions);
|
|
409
|
+
|
|
410
|
+
s = m.state;
|
|
641
411
|
}
|
|
642
412
|
|
|
643
413
|
returnValue = m && facades.get(m);
|
|
@@ -652,20 +422,19 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
652
422
|
case 'init': {
|
|
653
423
|
let { arguments: { 0: canonicalURL } = [] } = instr;
|
|
654
424
|
|
|
655
|
-
if (
|
|
425
|
+
if (s !== null) throw new Error();
|
|
656
426
|
|
|
657
|
-
|
|
427
|
+
// TODO get rid of ctx.languages
|
|
428
|
+
s = State.from(rootSource, ctx, ctx.languages.get(canonicalURL), options.expressions);
|
|
658
429
|
|
|
659
430
|
s.source.advance();
|
|
660
431
|
|
|
661
432
|
const sourceStep = s.source.head.step;
|
|
662
433
|
|
|
663
434
|
if (sourceStep instanceof Promise) {
|
|
664
|
-
yield sourceStep;
|
|
435
|
+
yield wait(sourceStep);
|
|
665
436
|
}
|
|
666
437
|
|
|
667
|
-
language = ctx.languages.get(canonicalURL);
|
|
668
|
-
|
|
669
438
|
returnValue = facades.get(s);
|
|
670
439
|
break;
|
|
671
440
|
}
|