@bablr/bablr-vm 0.20.0 → 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/context.js +6 -6
- package/lib/evaluate.js +297 -149
- package/lib/match.js +252 -103
- package/lib/node.js +100 -99
- package/lib/source.js +110 -110
- package/lib/state.js +121 -167
- package/lib/utils/pattern.js +80 -13
- package/package.json +7 -7
- package/lib/utils/array.js +0 -13
- package/lib/utils/format.js +0 -9
- package/lib/utils/object.js +0 -97
- package/lib/utils/pump.js +0 -20
- package/lib/utils/token.js +0 -30
package/lib/match.js
CHANGED
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { resolveLanguage } from '@bablr/helpers/grammar';
|
|
2
2
|
import { WeakStackFrame } from '@bablr/weak-stack';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
|
|
4
|
+
import { agast, TagPathFacade as TagPath, PathFacade as Path } from '@bablr/agast-vm';
|
|
5
|
+
import {
|
|
6
|
+
buildOpenNodeTag,
|
|
7
|
+
buildProperty,
|
|
8
|
+
buildReferenceTag,
|
|
9
|
+
fragmentFlags,
|
|
10
|
+
mergeReferenceTags,
|
|
11
|
+
} from '@bablr/agast-helpers/tree';
|
|
7
12
|
import { effectsFor } from '@bablr/agast-vm-helpers';
|
|
8
|
-
import {
|
|
13
|
+
import { FragmentFacade } from './node.js';
|
|
9
14
|
|
|
10
15
|
import { facades, actuals } from './facades.js';
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
import {
|
|
17
|
+
CloseNodeTag,
|
|
18
|
+
OpenNodeTag,
|
|
19
|
+
ReferenceTag,
|
|
20
|
+
ShiftTag,
|
|
21
|
+
AttributeDefinition,
|
|
22
|
+
Property,
|
|
23
|
+
InitializerTag,
|
|
24
|
+
BindingTag,
|
|
25
|
+
LiteralTag,
|
|
26
|
+
} from '@bablr/agast-helpers/symbols';
|
|
18
27
|
|
|
19
28
|
export class MatchFacade {
|
|
20
29
|
constructor(match) {
|
|
21
30
|
facades.set(match, this);
|
|
31
|
+
Object.freeze(this);
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
get language() {
|
|
@@ -49,16 +59,19 @@ export class MatchFacade {
|
|
|
49
59
|
return actuals.get(this).path;
|
|
50
60
|
}
|
|
51
61
|
|
|
52
|
-
get
|
|
53
|
-
return actuals.get(this).
|
|
62
|
+
get inner() {
|
|
63
|
+
return actuals.get(this).inner;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
get fragment() {
|
|
57
67
|
const {
|
|
58
68
|
ctx,
|
|
69
|
+
effects,
|
|
59
70
|
path,
|
|
71
|
+
isCoverBoundary,
|
|
60
72
|
isNode,
|
|
61
73
|
fragmentNode,
|
|
74
|
+
node,
|
|
62
75
|
mergedReference,
|
|
63
76
|
rangePreviousIndex,
|
|
64
77
|
rangeFinalIndex,
|
|
@@ -66,19 +79,26 @@ export class MatchFacade {
|
|
|
66
79
|
|
|
67
80
|
const { name, isArray } = mergedReference.value;
|
|
68
81
|
|
|
69
|
-
|
|
82
|
+
let prev =
|
|
83
|
+
rangePreviousIndex != null
|
|
84
|
+
? (fragmentNode || node).children.at(rangePreviousIndex)
|
|
85
|
+
: rangePreviousIndex;
|
|
86
|
+
|
|
87
|
+
let offset = [ReferenceTag, ShiftTag].includes(prev?.type) ? 0 : 1;
|
|
88
|
+
|
|
89
|
+
if ((isNode || isCoverBoundary) && name) {
|
|
70
90
|
return new FragmentFacade(
|
|
71
|
-
fragmentNode,
|
|
91
|
+
effects.success !== 'none' ? fragmentNode : null,
|
|
72
92
|
ctx,
|
|
73
93
|
false,
|
|
74
94
|
true,
|
|
75
|
-
[rangePreviousIndex +
|
|
76
|
-
mergedReference,
|
|
77
|
-
isArray ? getChildPropertyIndex(
|
|
95
|
+
[rangePreviousIndex + offset, rangeFinalIndex],
|
|
96
|
+
mergedReference.value,
|
|
97
|
+
isArray ? fragmentNode.getChildPropertyIndex(rangePreviousIndex + offset) : null,
|
|
78
98
|
);
|
|
79
99
|
} else {
|
|
80
100
|
return new FragmentFacade(fragmentNode || path.node, ctx, false, true, [
|
|
81
|
-
rangePreviousIndex +
|
|
101
|
+
rangePreviousIndex + offset,
|
|
82
102
|
rangeFinalIndex,
|
|
83
103
|
]);
|
|
84
104
|
}
|
|
@@ -129,12 +149,16 @@ export class MatchFacade {
|
|
|
129
149
|
return actuals.get(this).isCoverBoundary;
|
|
130
150
|
}
|
|
131
151
|
|
|
152
|
+
get coveredBoundary() {
|
|
153
|
+
return facades.get(actuals.get(this).coveredBoundary);
|
|
154
|
+
}
|
|
155
|
+
|
|
132
156
|
get cover() {
|
|
133
157
|
return facades.get(actuals.get(this).cover);
|
|
134
158
|
}
|
|
135
159
|
|
|
136
160
|
get shiftMatch() {
|
|
137
|
-
return facades.get(actuals.get(this).shiftMatch);
|
|
161
|
+
return facades.get(actuals.get(this).coveredBoundary.shiftMatch);
|
|
138
162
|
}
|
|
139
163
|
|
|
140
164
|
get captured() {
|
|
@@ -142,7 +166,8 @@ export class MatchFacade {
|
|
|
142
166
|
}
|
|
143
167
|
|
|
144
168
|
get range() {
|
|
145
|
-
|
|
169
|
+
let { range } = actuals.get(this);
|
|
170
|
+
return range && [range[0], range[1]];
|
|
146
171
|
}
|
|
147
172
|
|
|
148
173
|
get effects() {
|
|
@@ -185,6 +210,10 @@ export class MatchFacade {
|
|
|
185
210
|
return actuals.get(this).rangeFinalIndex;
|
|
186
211
|
}
|
|
187
212
|
|
|
213
|
+
get mergedLanguagePath() {
|
|
214
|
+
return actuals.get(this).mergedLanguagePath;
|
|
215
|
+
}
|
|
216
|
+
|
|
188
217
|
ancestors(...args) {
|
|
189
218
|
return actuals.get(this).ancestors(...args);
|
|
190
219
|
}
|
|
@@ -207,39 +236,39 @@ export class Match extends WeakStackFrame {
|
|
|
207
236
|
|
|
208
237
|
this.rangePreviousIndex = null;
|
|
209
238
|
this.rangeFinalIndex = null;
|
|
239
|
+
this.agast = null;
|
|
240
|
+
this.agastFragment = null; // why do it this way?
|
|
210
241
|
this.node = null;
|
|
211
|
-
this.fragmentNode = null; // why do it this way?
|
|
212
242
|
this.cover = null;
|
|
243
|
+
this.running = null;
|
|
213
244
|
this.options = options;
|
|
214
245
|
|
|
215
|
-
let
|
|
216
|
-
let
|
|
217
|
-
const { grammar, type } = this;
|
|
218
|
-
let isCover = grammar.covers?.has(type);
|
|
246
|
+
let isNode = !matcher.nodeMatcher.flags.fragment;
|
|
247
|
+
let isCover = matcher.nodeMatcher.flags.cover;
|
|
219
248
|
|
|
220
|
-
this.
|
|
249
|
+
this.agast = isNode ? null : state.agast ?? null;
|
|
250
|
+
this.node = isNode ? null : parent?.node;
|
|
251
|
+
this.cover =
|
|
252
|
+
isNode || effects.success === 'none' ? null : parent?.cover || (isCover ? this : null);
|
|
221
253
|
|
|
222
254
|
let isCoverBoundary = ((isNode || isCover) && !this.cover) || !parent;
|
|
223
255
|
|
|
224
256
|
if (isCoverBoundary) {
|
|
225
|
-
|
|
226
|
-
|
|
257
|
+
let held = null;
|
|
258
|
+
// TODO wat
|
|
259
|
+
if (this.coveredBoundary.shiftMatch) {
|
|
260
|
+
let { reference, binding, node } = state.held;
|
|
261
|
+
held = buildProperty(reference, binding, node.node);
|
|
262
|
+
}
|
|
263
|
+
this.agast = agast({ held });
|
|
227
264
|
} else {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
this.node = internalState.path.node;
|
|
235
|
-
|
|
236
|
-
if (this.isNode) {
|
|
237
|
-
this.node.type = Symbol.for(this.type);
|
|
238
|
-
this.node.language = this.language.canonicalURL;
|
|
265
|
+
this.agast = parent.agast;
|
|
266
|
+
if (effects.success === 'none') {
|
|
267
|
+
this.agast = agast();
|
|
268
|
+
this.agast.vm.next(buildOpenNodeTag(fragmentFlags));
|
|
269
|
+
}
|
|
239
270
|
}
|
|
240
271
|
|
|
241
|
-
internalStates.set(this.node, internalState);
|
|
242
|
-
|
|
243
272
|
new MatchFacade(this);
|
|
244
273
|
}
|
|
245
274
|
|
|
@@ -248,28 +277,34 @@ export class Match extends WeakStackFrame {
|
|
|
248
277
|
}
|
|
249
278
|
|
|
250
279
|
get isCoverBoundary() {
|
|
251
|
-
return (this.isNode && !this.parent.cover) || this.cover === this;
|
|
280
|
+
return (this.isNode && this.parent && !this.parent.cover) || this.cover === this;
|
|
252
281
|
}
|
|
253
282
|
|
|
254
283
|
get matcher() {
|
|
255
284
|
return this.propertyMatcher?.nodeMatcher;
|
|
256
285
|
}
|
|
257
286
|
|
|
287
|
+
get vm() {
|
|
288
|
+
return this.agast.vm;
|
|
289
|
+
}
|
|
290
|
+
|
|
258
291
|
get mergedReference() {
|
|
259
292
|
let ref = buildReferenceTag('.');
|
|
260
293
|
|
|
261
294
|
let first = true;
|
|
262
295
|
let m = this;
|
|
263
296
|
let lastName = null;
|
|
297
|
+
let lastRefType = null;
|
|
264
298
|
do {
|
|
265
299
|
if (m.isNode && !first) break;
|
|
266
300
|
if (m.propertyMatcher.refMatcher) {
|
|
267
|
-
const { name, isArray, flags } = m.propertyMatcher.refMatcher;
|
|
268
|
-
const parentRef = buildReferenceTag(name, isArray, flags);
|
|
269
|
-
if (lastName && lastName !== name) break;
|
|
270
|
-
ref = ['#', '@'].includes(ref.value.
|
|
271
|
-
if (
|
|
301
|
+
const { type: refType, name, isArray, flags } = m.propertyMatcher.refMatcher;
|
|
302
|
+
const parentRef = buildReferenceTag(refType, name, isArray, flags);
|
|
303
|
+
if (lastName && (lastName !== name || lastRefType !== refType)) break;
|
|
304
|
+
ref = ['#', '@'].includes(ref.value.type) ? ref : mergeReferenceTags(ref, parentRef);
|
|
305
|
+
if (refType !== '.') {
|
|
272
306
|
lastName = name;
|
|
307
|
+
lastRefType = refType;
|
|
273
308
|
}
|
|
274
309
|
}
|
|
275
310
|
first = false;
|
|
@@ -278,13 +313,30 @@ export class Match extends WeakStackFrame {
|
|
|
278
313
|
return ref;
|
|
279
314
|
}
|
|
280
315
|
|
|
316
|
+
get mergedLanguagePath() {
|
|
317
|
+
let languagePath = [];
|
|
318
|
+
|
|
319
|
+
let first = true;
|
|
320
|
+
let m = this;
|
|
321
|
+
do {
|
|
322
|
+
if (m.isNode && !first) break;
|
|
323
|
+
if (m.propertyMatcher.bindingMatcher) {
|
|
324
|
+
languagePath = m.propertyMatcher.bindingMatcher.languagePath.concat(languagePath);
|
|
325
|
+
}
|
|
326
|
+
first = false;
|
|
327
|
+
} while ((m = m.shiftMatch || m.parent));
|
|
328
|
+
|
|
329
|
+
return Object.freeze(languagePath);
|
|
330
|
+
}
|
|
331
|
+
|
|
281
332
|
get pathName() {
|
|
282
333
|
return this.mergedReference.value.name;
|
|
283
334
|
}
|
|
284
335
|
|
|
285
336
|
get path() {
|
|
286
|
-
let {
|
|
287
|
-
|
|
337
|
+
let { agast } = this.coveredBoundary.parent ?? this;
|
|
338
|
+
|
|
339
|
+
return agast.state.path || agast.state.resultPath?.path;
|
|
288
340
|
}
|
|
289
341
|
|
|
290
342
|
get pathParent() {
|
|
@@ -297,7 +349,7 @@ export class Match extends WeakStackFrame {
|
|
|
297
349
|
}
|
|
298
350
|
|
|
299
351
|
get coveredBoundary() {
|
|
300
|
-
return this.isNode ? this.parent
|
|
352
|
+
return this.isNode ? this.parent?.cover || this : this.cover || this;
|
|
301
353
|
}
|
|
302
354
|
|
|
303
355
|
get parentPath() {
|
|
@@ -332,33 +384,56 @@ export class Match extends WeakStackFrame {
|
|
|
332
384
|
return !!this.grammar.emptyables?.has(this.type) || this.options.allowEmpty;
|
|
333
385
|
}
|
|
334
386
|
|
|
387
|
+
get fragmentNode() {
|
|
388
|
+
if (!this.agastFragment) return null;
|
|
389
|
+
|
|
390
|
+
let { node, resultPath } = this.agastFragment.state;
|
|
391
|
+
return resultPath?.tag.type === CloseNodeTag ? resultPath.node : node;
|
|
392
|
+
}
|
|
393
|
+
|
|
335
394
|
get rangePrevious() {
|
|
336
|
-
|
|
395
|
+
let node = this.fragmentNode || this.node;
|
|
396
|
+
|
|
397
|
+
return this.rangePreviousIndex == null || node == null
|
|
337
398
|
? null
|
|
338
|
-
: TagPath.
|
|
399
|
+
: TagPath.fromNode(node, this.rangePreviousIndex);
|
|
339
400
|
}
|
|
340
401
|
|
|
341
402
|
setRangePreviousIndex(value) {
|
|
403
|
+
if ((value != null && !Number.isFinite(value)) || value < 0) throw new Error();
|
|
342
404
|
this.rangePreviousIndex = value;
|
|
343
|
-
|
|
405
|
+
if (
|
|
406
|
+
value != null &&
|
|
407
|
+
(!this.rangePrevious ||
|
|
408
|
+
(this.isNode &&
|
|
409
|
+
![OpenNodeTag, Property, InitializerTag, LiteralTag, AttributeDefinition].includes(
|
|
410
|
+
this.rangePrevious.tag.type,
|
|
411
|
+
)))
|
|
412
|
+
)
|
|
413
|
+
throw new Error();
|
|
344
414
|
}
|
|
345
415
|
|
|
346
416
|
setRangeFinalIndex(value) {
|
|
417
|
+
if (value != null && !Number.isFinite(value)) throw new Error();
|
|
347
418
|
this.rangeFinalIndex = value;
|
|
348
419
|
this.rangeFinal;
|
|
349
420
|
}
|
|
350
421
|
|
|
351
422
|
get rangeFinal() {
|
|
352
|
-
|
|
423
|
+
let node = this.fragmentNode || this.node;
|
|
353
424
|
|
|
354
|
-
return this.rangeFinalIndex == null
|
|
425
|
+
return this.rangeFinalIndex == null || node == null
|
|
426
|
+
? null
|
|
427
|
+
: TagPath.fromNode(node, this.rangeFinalIndex);
|
|
355
428
|
}
|
|
356
429
|
|
|
357
430
|
get rangeInitial() {
|
|
358
|
-
const { rangePrevious } = this;
|
|
431
|
+
const { rangePrevious, isNode, fragmentNode, node, rangePreviousIndex } = this;
|
|
359
432
|
|
|
360
433
|
if (!rangePrevious) return rangePrevious;
|
|
361
434
|
|
|
435
|
+
if (isNode) return TagPath.fromNode(fragmentNode || node, rangePreviousIndex + 1);
|
|
436
|
+
|
|
362
437
|
return rangePrevious?.nextSibling;
|
|
363
438
|
}
|
|
364
439
|
|
|
@@ -371,59 +446,76 @@ export class Match extends WeakStackFrame {
|
|
|
371
446
|
return !!this.shiftMatch;
|
|
372
447
|
}
|
|
373
448
|
|
|
374
|
-
get
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (!this.isNode) {
|
|
449
|
+
get referencePath() {
|
|
450
|
+
if (!(this.isNode || this.isCoverBoundary || this.cover) || this.state.depths.path < 0) {
|
|
378
451
|
return null;
|
|
379
452
|
}
|
|
380
453
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
454
|
+
let offset = this.isNode ? 1 : 0;
|
|
455
|
+
|
|
456
|
+
let ref = TagPath.fromNode(this.fragmentNode || this.node, this.rangePreviousIndex + offset);
|
|
384
457
|
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
458
|
+
if (!ref) return null;
|
|
459
|
+
|
|
460
|
+
if (ref.tag.type === ShiftTag) {
|
|
461
|
+
let refIndex = ref.childrenIndex - ref.tag.value.index * 3;
|
|
462
|
+
ref = ref.siblingAt(refIndex);
|
|
388
463
|
}
|
|
389
464
|
|
|
390
|
-
|
|
465
|
+
if (ref && ref.tag.type !== ReferenceTag) throw new Error();
|
|
466
|
+
return ref;
|
|
391
467
|
}
|
|
392
468
|
|
|
393
469
|
get isNode() {
|
|
394
|
-
let { flags
|
|
395
|
-
return !
|
|
470
|
+
let { flags } = this.matcher;
|
|
471
|
+
return !this.parent || !flags.fragment;
|
|
396
472
|
}
|
|
397
473
|
|
|
398
474
|
get isCover() {
|
|
399
475
|
return this.cover === this;
|
|
400
476
|
}
|
|
401
477
|
|
|
402
|
-
get
|
|
403
|
-
return
|
|
478
|
+
get inner() {
|
|
479
|
+
return Path.from(this.node);
|
|
404
480
|
}
|
|
405
481
|
|
|
406
|
-
|
|
407
|
-
let
|
|
408
|
-
const { expressionsPump, instructionsPump, agast, agastState } = internalState;
|
|
482
|
+
advance(tag, s = this.state) {
|
|
483
|
+
let { vm, state: agastState } = s.agast;
|
|
409
484
|
|
|
410
|
-
|
|
411
|
-
instructionsPump.queue(buildCall('advance', buildEmbeddedTag(buildGapTag())));
|
|
485
|
+
let result = vm.next(tag);
|
|
412
486
|
|
|
413
|
-
|
|
487
|
+
if (tag.type === OpenNodeTag) {
|
|
488
|
+
s.depths.result++;
|
|
489
|
+
this.node = s.node;
|
|
490
|
+
} else if (tag.type === CloseNodeTag) {
|
|
491
|
+
s.depths.result--;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
s.resultPath =
|
|
495
|
+
(agastState.node || agastState.resultPath?.node) &&
|
|
496
|
+
TagPath.fromNode(agastState.node || agastState.resultPath?.node, -1);
|
|
497
|
+
return result.value;
|
|
414
498
|
}
|
|
415
499
|
|
|
416
|
-
startFrame(state, propertyMatcher, effects,
|
|
500
|
+
startFrame(state, propertyMatcher, effects, shiftMatch, options) {
|
|
417
501
|
let { context } = this;
|
|
418
|
-
const {
|
|
502
|
+
const { bindingMatcher } = propertyMatcher;
|
|
419
503
|
|
|
420
|
-
|
|
504
|
+
let language = shiftMatch?.language ?? this.language;
|
|
421
505
|
|
|
422
|
-
if (
|
|
423
|
-
|
|
506
|
+
if (bindingMatcher) {
|
|
507
|
+
language = resolveLanguage(context, language, bindingMatcher.languagePath);
|
|
508
|
+
|
|
509
|
+
if (!language) {
|
|
510
|
+
throw new Error(`Unknown language ${bindingMatcher.languagePath.join('.')}`);
|
|
511
|
+
}
|
|
424
512
|
}
|
|
425
513
|
|
|
426
|
-
|
|
514
|
+
let m = this.push(context, language, state, propertyMatcher, effects, shiftMatch, options);
|
|
515
|
+
|
|
516
|
+
this.running = m;
|
|
517
|
+
|
|
518
|
+
return m;
|
|
427
519
|
}
|
|
428
520
|
|
|
429
521
|
endFrame() {
|
|
@@ -432,9 +524,9 @@ export class Match extends WeakStackFrame {
|
|
|
432
524
|
|
|
433
525
|
if (!m) return m;
|
|
434
526
|
|
|
435
|
-
finishedMatch.setRangeFinalIndex(
|
|
436
|
-
|
|
437
|
-
|
|
527
|
+
finishedMatch.setRangeFinalIndex((finishedMatch.fragmentNode || m.node).children.size - 1);
|
|
528
|
+
|
|
529
|
+
m.running = null;
|
|
438
530
|
|
|
439
531
|
return m;
|
|
440
532
|
}
|
|
@@ -445,40 +537,54 @@ export class Match extends WeakStackFrame {
|
|
|
445
537
|
|
|
446
538
|
if (!m) return m;
|
|
447
539
|
|
|
540
|
+
m.running = null;
|
|
541
|
+
|
|
448
542
|
finishedMatch.setRangePreviousIndex(null);
|
|
449
543
|
|
|
450
544
|
return m;
|
|
451
545
|
}
|
|
452
546
|
|
|
453
|
-
*emit() {
|
|
547
|
+
*emit(options) {
|
|
454
548
|
let { state } = this;
|
|
549
|
+
let { emitted } = state;
|
|
455
550
|
|
|
456
|
-
|
|
457
|
-
let { node, emitted } = state;
|
|
551
|
+
let m = emitted?.match ?? this;
|
|
458
552
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
}
|
|
553
|
+
if (!state.depth) {
|
|
554
|
+
let { node } = m;
|
|
462
555
|
|
|
463
|
-
|
|
556
|
+
// if (!node) {
|
|
557
|
+
// node = resultPath.node;
|
|
558
|
+
// }
|
|
464
559
|
|
|
465
|
-
let
|
|
560
|
+
let path = Path.from(node);
|
|
466
561
|
|
|
467
|
-
|
|
468
|
-
// emitted can move
|
|
469
|
-
// emitted cannot move
|
|
562
|
+
let tagPath = emitted?.tagPath || (path.node.children.size ? TagPath.from(path, 0) : null);
|
|
470
563
|
|
|
471
564
|
while (tagPath) {
|
|
472
565
|
if (
|
|
566
|
+
options.holdUndefinedAttributes &&
|
|
473
567
|
tagPath.tag.type === OpenNodeTag &&
|
|
474
568
|
tagPath.tag.value.type &&
|
|
475
|
-
|
|
569
|
+
(m.node.undefinedAttributes ?? 0) > 0
|
|
476
570
|
) {
|
|
477
571
|
break;
|
|
478
572
|
}
|
|
479
573
|
|
|
480
|
-
if (
|
|
481
|
-
|
|
574
|
+
if (
|
|
575
|
+
tagPath.tag.type === OpenNodeTag &&
|
|
576
|
+
m.referencePath?.tag.value.type === '@' &&
|
|
577
|
+
tagPath.node.flags.hasGap
|
|
578
|
+
)
|
|
579
|
+
break;
|
|
580
|
+
|
|
581
|
+
let holdShifted =
|
|
582
|
+
options.holdShiftedNodes &&
|
|
583
|
+
tagPath.tag.type === ReferenceTag &&
|
|
584
|
+
tagPath.tag.value.flags.expression;
|
|
585
|
+
|
|
586
|
+
if (!state.emitted || !tagPath.equalTo(state.emitted.tagPath)) {
|
|
587
|
+
state.emitted = emitted = { match: m, tagPath };
|
|
482
588
|
|
|
483
589
|
if (tagPath.tag.type === OpenNodeTag) {
|
|
484
590
|
state.depths.emitted++;
|
|
@@ -486,10 +592,53 @@ export class Match extends WeakStackFrame {
|
|
|
486
592
|
state.depths.emitted--;
|
|
487
593
|
}
|
|
488
594
|
|
|
489
|
-
|
|
595
|
+
if (
|
|
596
|
+
!(
|
|
597
|
+
(tagPath.tag.type === BindingTag && !tagPath.tag.value.languagePath?.length) ||
|
|
598
|
+
(tagPath.tag.type === AttributeDefinition && options.holdUndefinedAttributes)
|
|
599
|
+
)
|
|
600
|
+
) {
|
|
601
|
+
yield tagPath.tag;
|
|
602
|
+
}
|
|
490
603
|
}
|
|
491
604
|
|
|
492
|
-
tagPath
|
|
605
|
+
if (tagPath.tag.type === CloseNodeTag && !tagPath.next) {
|
|
606
|
+
tagPath = TagPath.fromNode(m.fragmentNode, m.rangeInitial.childrenIndex + 3);
|
|
607
|
+
|
|
608
|
+
do {
|
|
609
|
+
m = m.parent;
|
|
610
|
+
} while (m && !m.isNode);
|
|
611
|
+
|
|
612
|
+
if (!m) break;
|
|
613
|
+
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (!holdShifted && tagPath.tag.type === ReferenceTag && !tagPath.nextSibling) {
|
|
618
|
+
let { running } = m;
|
|
619
|
+
|
|
620
|
+
while (running && !running.isNode) {
|
|
621
|
+
if (running.state.depth > 0) {
|
|
622
|
+
running = null;
|
|
623
|
+
break;
|
|
624
|
+
} else {
|
|
625
|
+
running = running.running;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (running) {
|
|
630
|
+
m = running;
|
|
631
|
+
} else {
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
tagPath = TagPath.fromNode(m.node, 0);
|
|
635
|
+
} else {
|
|
636
|
+
if (holdShifted) {
|
|
637
|
+
tagPath = tagPath.nextUnshifted;
|
|
638
|
+
} else {
|
|
639
|
+
tagPath = tagPath.next;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
493
642
|
}
|
|
494
643
|
}
|
|
495
644
|
}
|