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