@bablr/bablr-vm 0.23.1 → 0.23.3
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 +22 -20
- package/lib/evaluate.js +46 -47
- package/lib/facades.js +23 -12
- package/lib/match.js +106 -134
- package/lib/spans.js +4 -17
- package/lib/state.js +45 -24
- package/package.json +6 -7
package/lib/context.js
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { buildDependentLanguages } from '@bablr/helpers/grammar';
|
|
2
|
-
import {
|
|
2
|
+
import { getGapNode } from './facades.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
constructor(actual) {
|
|
6
|
-
facades.set(actual, this);
|
|
7
|
-
Object.freeze(this);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
get languages() {
|
|
11
|
-
return actuals.get(this).languages;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
get grammars() {
|
|
15
|
-
return actuals.get(this).grammars;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get productionEnhancer() {
|
|
19
|
-
return actuals.get(this).productionEnhancer;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
4
|
+
let facades = new WeakMap();
|
|
22
5
|
|
|
23
6
|
export const Context = class BABLRContext {
|
|
24
7
|
static from(language, productionEnhancer) {
|
|
@@ -28,11 +11,13 @@ export const Context = class BABLRContext {
|
|
|
28
11
|
constructor(languages, productionEnhancer) {
|
|
29
12
|
this.languages = languages;
|
|
30
13
|
this.productionEnhancer = productionEnhancer;
|
|
14
|
+
this.getGrammar = (language) => this.grammars.get(language);
|
|
15
|
+
|
|
16
|
+
Object.freeze(productionEnhancer);
|
|
31
17
|
|
|
32
18
|
this.unboxedValues = new WeakMap();
|
|
33
19
|
|
|
34
20
|
this.grammars = new WeakMap();
|
|
35
|
-
this.facade = new ContextFacade(this);
|
|
36
21
|
|
|
37
22
|
for (const { 1: language } of this.languages) {
|
|
38
23
|
if (!language) throw new Error();
|
|
@@ -40,4 +25,21 @@ export const Context = class BABLRContext {
|
|
|
40
25
|
this.grammars.set(language, new language.grammar());
|
|
41
26
|
}
|
|
42
27
|
}
|
|
28
|
+
|
|
29
|
+
getPublic() {
|
|
30
|
+
let value = facades.get(this);
|
|
31
|
+
if (value) return value;
|
|
32
|
+
|
|
33
|
+
let { productionEnhancer, getGrammar } = this;
|
|
34
|
+
|
|
35
|
+
value = Object.freeze({
|
|
36
|
+
getGrammar,
|
|
37
|
+
getGapNode,
|
|
38
|
+
productionEnhancer,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
facades.set(this, value);
|
|
42
|
+
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
43
45
|
};
|
package/lib/evaluate.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/* global WeakSet */
|
|
2
2
|
import { Coroutine } from '@bablr/coroutine';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildAttributeDefinition,
|
|
5
|
+
buildCloseNodeTag,
|
|
6
|
+
buildTypedSpan,
|
|
7
|
+
deepFreeze,
|
|
8
|
+
} from '@bablr/agast-helpers/builders';
|
|
4
9
|
import { getStreamIterator, printType, StreamIterable, wait } from '@bablr/agast-helpers/stream';
|
|
5
|
-
import { facades } from './facades.js';
|
|
6
10
|
import { State } from './state.js';
|
|
7
11
|
import {
|
|
8
12
|
OpenNodeTag,
|
|
@@ -22,12 +26,7 @@ import { buildWriteEffect } from '@bablr/agast-vm-helpers/builders';
|
|
|
22
26
|
import { has } from '@bablr/agast-helpers/object';
|
|
23
27
|
import { reifyBablrOptions } from '@bablr/agast-vm-helpers';
|
|
24
28
|
import { buildNode, getTags } from '@bablr/agast-helpers/path';
|
|
25
|
-
|
|
26
|
-
const validNodesByLanguage = new Map();
|
|
27
|
-
|
|
28
|
-
export const isKnownValid = (language, node) => {
|
|
29
|
-
return !!validNodesByLanguage.get(language)?.has(node);
|
|
30
|
-
};
|
|
29
|
+
import * as Spans from '@bablr/agast-helpers/spans';
|
|
31
30
|
|
|
32
31
|
const getSourceLength = (tags) => {
|
|
33
32
|
let i = 0;
|
|
@@ -41,11 +40,18 @@ const getSourceLength = (tags) => {
|
|
|
41
40
|
return i;
|
|
42
41
|
};
|
|
43
42
|
|
|
44
|
-
export const bablr = (
|
|
45
|
-
|
|
43
|
+
export const bablr = (
|
|
44
|
+
ctx,
|
|
45
|
+
rootSource,
|
|
46
|
+
language,
|
|
47
|
+
strategy,
|
|
48
|
+
options = {},
|
|
49
|
+
registerNode = () => {},
|
|
50
|
+
) => {
|
|
51
|
+
return new StreamIterable(__bablr(ctx, rootSource, language, strategy, options, registerNode));
|
|
46
52
|
};
|
|
47
53
|
|
|
48
|
-
function* __bablr(ctx, rootSource, strategy, options) {
|
|
54
|
+
function* __bablr(ctx, rootSource, rootLanguage, strategy, options, registerNode) {
|
|
49
55
|
let s = null;
|
|
50
56
|
let m = null;
|
|
51
57
|
let finishedMatch = null;
|
|
@@ -53,14 +59,22 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
53
59
|
|
|
54
60
|
let getState = () => s.getPublic();
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
s = State.from(rootSource, ctx, rootLanguage, options.expressions, options.spans);
|
|
63
|
+
|
|
64
|
+
s.source.advance();
|
|
65
|
+
|
|
66
|
+
if (options.holdUndefinedAttributes) {
|
|
67
|
+
throw new Error('holdUndefinedAttributes not implemented');
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
let co = new Coroutine(getStreamIterator(strategy(
|
|
70
|
+
let co = new Coroutine(getStreamIterator(strategy(ctx.getPublic(), rootLanguage, getState)));
|
|
61
71
|
|
|
62
72
|
co.advance();
|
|
63
73
|
|
|
74
|
+
if (s.source.head.step instanceof Promise) {
|
|
75
|
+
yield wait(s.source.head.step);
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
for (;;) {
|
|
65
79
|
if (co.current instanceof Promise) {
|
|
66
80
|
co.current = yield wait(co.current);
|
|
@@ -71,6 +85,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
71
85
|
throw new Error(`parse ate ${s.source.index} characters but the input was not consumed`);
|
|
72
86
|
}
|
|
73
87
|
|
|
88
|
+
if (m) throw new Error();
|
|
89
|
+
|
|
74
90
|
let { exchange } = s.source;
|
|
75
91
|
|
|
76
92
|
s.source.release();
|
|
@@ -79,7 +95,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
79
95
|
throw new Error('Source did not close all forks: ' + exchange.sources);
|
|
80
96
|
}
|
|
81
97
|
|
|
82
|
-
return
|
|
98
|
+
return options.tree === undefined || options.tree ? finishedMatch.node : undefined;
|
|
83
99
|
}
|
|
84
100
|
|
|
85
101
|
const instr = co.value;
|
|
@@ -229,8 +245,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
229
245
|
s.node = m.node;
|
|
230
246
|
}
|
|
231
247
|
|
|
232
|
-
validNodesByLanguage.get(language).add(node);
|
|
233
|
-
|
|
234
248
|
break;
|
|
235
249
|
}
|
|
236
250
|
|
|
@@ -327,14 +341,15 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
327
341
|
}
|
|
328
342
|
|
|
329
343
|
case 'startSpan': {
|
|
330
|
-
let { arguments: { 0: name, 1: guard = null } = [] } = instr;
|
|
331
|
-
|
|
344
|
+
let { arguments: { 0: name, 1: guard = null, 2: { value: props } } = [] } = instr;
|
|
345
|
+
deepFreeze(props);
|
|
346
|
+
s.spans = Spans.push(s.spans, buildTypedSpan('Instruction', name, guard, props));
|
|
332
347
|
break;
|
|
333
348
|
}
|
|
334
349
|
|
|
335
350
|
case 'endSpan': {
|
|
336
|
-
if (s.
|
|
337
|
-
s.spans = s.spans
|
|
351
|
+
if (s.span.type !== 'Instruction') throw new Error();
|
|
352
|
+
s.spans = Spans.pop(s.spans);
|
|
338
353
|
break;
|
|
339
354
|
}
|
|
340
355
|
|
|
@@ -347,7 +362,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
347
362
|
|
|
348
363
|
yield* m.emit(outerOptions);
|
|
349
364
|
|
|
350
|
-
returnValue =
|
|
365
|
+
returnValue = m.getPublic();
|
|
351
366
|
break;
|
|
352
367
|
}
|
|
353
368
|
|
|
@@ -359,6 +374,10 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
359
374
|
m = m.endFrame(outerOptions);
|
|
360
375
|
s = m ? m.state : s;
|
|
361
376
|
|
|
377
|
+
if (finishedMatch.isNode) {
|
|
378
|
+
registerNode(m.language, m.node);
|
|
379
|
+
}
|
|
380
|
+
|
|
362
381
|
if (m) {
|
|
363
382
|
m.running = null;
|
|
364
383
|
if (finishedMatch.shiftMatch) {
|
|
@@ -367,7 +386,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
367
386
|
yield* m.emit(outerOptions);
|
|
368
387
|
}
|
|
369
388
|
|
|
370
|
-
returnValue = m &&
|
|
389
|
+
returnValue = m && m.getPublic();
|
|
371
390
|
break;
|
|
372
391
|
}
|
|
373
392
|
|
|
@@ -377,7 +396,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
377
396
|
|
|
378
397
|
let parentMatch = m;
|
|
379
398
|
|
|
380
|
-
if (finishedMatch.type
|
|
399
|
+
if (finishedMatch.type === '__') throw new Error();
|
|
381
400
|
|
|
382
401
|
m = Match.startFrame(
|
|
383
402
|
ctx,
|
|
@@ -395,7 +414,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
395
414
|
|
|
396
415
|
yield* finishedMatch.emit(outerOptions);
|
|
397
416
|
|
|
398
|
-
returnValue = m &&
|
|
417
|
+
returnValue = m && m.getPublic();
|
|
399
418
|
break;
|
|
400
419
|
}
|
|
401
420
|
|
|
@@ -410,32 +429,12 @@ function* __bablr(ctx, rootSource, strategy, options) {
|
|
|
410
429
|
s = m.state;
|
|
411
430
|
}
|
|
412
431
|
|
|
413
|
-
returnValue = m &&
|
|
432
|
+
returnValue = m && m.getPublic();
|
|
414
433
|
break;
|
|
415
434
|
}
|
|
416
435
|
|
|
417
436
|
case 'getState': {
|
|
418
|
-
returnValue =
|
|
419
|
-
break;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
case 'init': {
|
|
423
|
-
let { arguments: { 0: canonicalURL } = [] } = instr;
|
|
424
|
-
|
|
425
|
-
if (s !== null) throw new Error();
|
|
426
|
-
|
|
427
|
-
// TODO get rid of ctx.languages
|
|
428
|
-
s = State.from(rootSource, ctx, ctx.languages.get(canonicalURL), options.expressions);
|
|
429
|
-
|
|
430
|
-
s.source.advance();
|
|
431
|
-
|
|
432
|
-
const sourceStep = s.source.head.step;
|
|
433
|
-
|
|
434
|
-
if (sourceStep instanceof Promise) {
|
|
435
|
-
yield wait(sourceStep);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
returnValue = facades.get(s);
|
|
437
|
+
returnValue = s.getPublic();
|
|
439
438
|
break;
|
|
440
439
|
}
|
|
441
440
|
|
package/lib/facades.js
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
import * as Tags from '@bablr/agast-helpers/tags';
|
|
2
|
-
import { buildGapTag,
|
|
2
|
+
import { buildGapTag, buildPropertyTag } from '@bablr/agast-helpers/builders';
|
|
3
3
|
import { buildFacadeLayer } from '@bablr/agast-vm-helpers/facades';
|
|
4
|
-
import { buildNode, getTags } from '@bablr/agast-helpers/path';
|
|
4
|
+
import { buildNode, getTags, isStubNode } from '@bablr/agast-helpers/path';
|
|
5
5
|
import { Property } from '@bablr/agast-helpers/symbols';
|
|
6
6
|
|
|
7
7
|
export const { facades, actuals } = buildFacadeLayer();
|
|
8
8
|
|
|
9
|
+
let gapNodes = new WeakMap();
|
|
10
|
+
|
|
11
|
+
export const getGapNode = (gap) => gapNodes.get(gap);
|
|
12
|
+
|
|
9
13
|
export const buildFacadeNode = (node) => {
|
|
14
|
+
if (!node) return null;
|
|
15
|
+
|
|
10
16
|
let facadeTags = Tags.fromValues([]);
|
|
11
17
|
|
|
18
|
+
if (isStubNode(node)) {
|
|
19
|
+
return node;
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
for (let tag of Tags.traverse(getTags(node))) {
|
|
13
23
|
if (tag.type === Property) {
|
|
14
24
|
let property = tag;
|
|
15
|
-
let { reference,
|
|
16
|
-
|
|
17
|
-
let property_ = property;
|
|
25
|
+
let { reference, shift, node, tags } = property.value;
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
let tags_;
|
|
28
|
+
if (reference?.flags.intrinsic || ['_', '#', '@'].includes(reference?.type)) {
|
|
29
|
+
tags_ = [tags[0], tags[1], buildFacadeNode(node)];
|
|
30
|
+
} else {
|
|
20
31
|
let gapNode = buildNode(buildGapTag());
|
|
21
|
-
if (!reference
|
|
22
|
-
|
|
32
|
+
if (!reference?.flags.hasGap) {
|
|
33
|
+
gapNodes.set(gapNode, node);
|
|
23
34
|
}
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
property_ = buildProperty(tags_);
|
|
36
|
+
tags_ = [tags[0], tags[1], gapNode];
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
tags_ = tags_.slice(0, tags.length);
|
|
40
|
+
|
|
41
|
+
facadeTags = Tags.push(facadeTags, buildPropertyTag(tags_, shift));
|
|
31
42
|
} else {
|
|
32
43
|
facadeTags = Tags.push(facadeTags, tag);
|
|
33
44
|
}
|
package/lib/match.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getProduction } from '@bablr/helpers/grammar';
|
|
2
|
-
import { WeakStackFrame } from '@bablr/weak-stack';
|
|
3
2
|
|
|
4
3
|
import { agast } from '@bablr/agast-vm';
|
|
5
4
|
import * as Tags from '@bablr/agast-helpers/tags';
|
|
@@ -14,11 +13,10 @@ import {
|
|
|
14
13
|
buildPropertyTag,
|
|
15
14
|
buildOpenFragmentTag,
|
|
16
15
|
nodeFlags,
|
|
17
|
-
streamFromTree,
|
|
18
16
|
} from '@bablr/agast-helpers/tree';
|
|
19
17
|
import { effectsFor, reifyExpression, shouldBranch } from '@bablr/agast-vm-helpers';
|
|
20
18
|
|
|
21
|
-
import {
|
|
19
|
+
import { buildFacadeNode } from './facades.js';
|
|
22
20
|
import {
|
|
23
21
|
CloseNodeTag,
|
|
24
22
|
OpenNodeTag,
|
|
@@ -41,134 +39,13 @@ import {
|
|
|
41
39
|
} from '@bablr/agast-helpers/path';
|
|
42
40
|
import { updateSpans } from './spans.js';
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
constructor(match) {
|
|
46
|
-
facades.set(match, this);
|
|
47
|
-
Object.freeze(this);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get language() {
|
|
51
|
-
return actuals.get(this).language;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get matcher() {
|
|
55
|
-
return actuals.get(this).matcher;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
get options() {
|
|
59
|
-
return actuals.get(this).options;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get mergedReference() {
|
|
63
|
-
return actuals.get(this).mergedReference;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
get propertyMatcher() {
|
|
67
|
-
return actuals.get(this).propertyMatcher;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
get rawPropertyMatcher() {
|
|
71
|
-
return actuals.get(this).rawPropertyMatcher;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
get depth() {
|
|
75
|
-
return actuals.get(this).depth;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get path() {
|
|
79
|
-
return actuals.get(this).path;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
get fragment() {
|
|
83
|
-
return actuals.get(this).fragment;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
get pathDepth() {
|
|
87
|
-
return actuals.get(this).depths.path;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
get pathName() {
|
|
91
|
-
return actuals.get(this).pathName;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
get node() {
|
|
95
|
-
return actuals.get(this).node;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
get props() {
|
|
99
|
-
return actuals.get(this).props;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
get type() {
|
|
103
|
-
return actuals.get(this).type;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
get isNode() {
|
|
107
|
-
return actuals.get(this).isNode;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
get isCover() {
|
|
111
|
-
return actuals.get(this).isCover;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
get allowEmpty() {
|
|
115
|
-
return actuals.get(this).allowEmpty;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
get didShift() {
|
|
119
|
-
return actuals.get(this).didShift;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
get isCoverBoundary() {
|
|
123
|
-
return actuals.get(this).isCoverBoundary;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
get coveredBoundary() {
|
|
127
|
-
return facades.get(actuals.get(this).coveredBoundary);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
get nodeMatch() {
|
|
131
|
-
return facades.get(actuals.get(this).nodeMatch);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
get cover() {
|
|
135
|
-
return facades.get(actuals.get(this).cover);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
get shiftMatch() {
|
|
139
|
-
return facades.get(actuals.get(this).coveredBoundary.shiftMatch);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
get effects() {
|
|
143
|
-
return actuals.get(this).effects;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
get parent() {
|
|
147
|
-
return facades.get(actuals.get(this).parent);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
get grammar() {
|
|
151
|
-
return actuals.get(this).grammar;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
get state() {
|
|
155
|
-
return actuals.get(this).s.getPublic();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
get s() {
|
|
159
|
-
return actuals.get(this).s.getPublic();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
ancestors(...args) {
|
|
163
|
-
return actuals.get(this).ancestors(...args);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
42
|
+
let facades = new WeakMap();
|
|
166
43
|
|
|
167
44
|
const normalizeBindingPath = (path) => {
|
|
168
45
|
if (path.length <= 1) return path;
|
|
169
46
|
};
|
|
170
47
|
|
|
171
|
-
export class Match
|
|
48
|
+
export class Match {
|
|
172
49
|
static startFrame(ctx, s, m, finishedMatch, verb, matcher, options) {
|
|
173
50
|
let effects = effectsFor(verb.description);
|
|
174
51
|
let isShift = verb.description.startsWith('shift'); // should this be didShift?
|
|
@@ -230,8 +107,7 @@ export class Match extends WeakStackFrame {
|
|
|
230
107
|
}
|
|
231
108
|
let matcher = reifyExpression(rawMatcher);
|
|
232
109
|
|
|
233
|
-
|
|
234
|
-
|
|
110
|
+
this.parent = parent;
|
|
235
111
|
this.context = context;
|
|
236
112
|
this.state = state;
|
|
237
113
|
this.rawPropertyMatcher = rawMatcher;
|
|
@@ -240,6 +116,7 @@ export class Match extends WeakStackFrame {
|
|
|
240
116
|
this.shiftMatch = shiftMatch;
|
|
241
117
|
this.emittedMatch = parent?.emittedMatch || this;
|
|
242
118
|
|
|
119
|
+
this.depth = !parent ? 0 : parent.depth + 1;
|
|
243
120
|
this.agast = null;
|
|
244
121
|
this.cover = null;
|
|
245
122
|
this.running = null;
|
|
@@ -290,12 +167,10 @@ export class Match extends WeakStackFrame {
|
|
|
290
167
|
this.agast.vm.next(shiftMatch.rootNode);
|
|
291
168
|
}
|
|
292
169
|
this.rootNode = this.agast.getState().node;
|
|
293
|
-
|
|
294
|
-
new MatchFacade(this);
|
|
295
170
|
}
|
|
296
171
|
|
|
297
172
|
static from(context, state, matcher, props, options) {
|
|
298
|
-
return Match
|
|
173
|
+
return new Match(null, context, state, matcher, effectsFor('eat'), props, options);
|
|
299
174
|
}
|
|
300
175
|
|
|
301
176
|
get language() {
|
|
@@ -363,7 +238,7 @@ export class Match extends WeakStackFrame {
|
|
|
363
238
|
get path() {
|
|
364
239
|
let { agast } = this;
|
|
365
240
|
|
|
366
|
-
return agast.getState().path || agast.getState().resultPath?.path;
|
|
241
|
+
return Path.wrap(agast.getState().path || agast.getState().resultPath?.path);
|
|
367
242
|
}
|
|
368
243
|
|
|
369
244
|
get coveredBoundary() {
|
|
@@ -410,6 +285,10 @@ export class Match extends WeakStackFrame {
|
|
|
410
285
|
return this.propertyMatcher.nodeMatcher.type === '_';
|
|
411
286
|
}
|
|
412
287
|
|
|
288
|
+
push(context, state, rawMatcher, effects, shiftMatch, options) {
|
|
289
|
+
return new Match(this, context, state, rawMatcher, effects, shiftMatch, options);
|
|
290
|
+
}
|
|
291
|
+
|
|
413
292
|
advance(tag) {
|
|
414
293
|
let { vm, getState } = this.agast;
|
|
415
294
|
let s = this.state;
|
|
@@ -426,9 +305,9 @@ export class Match extends WeakStackFrame {
|
|
|
426
305
|
s.depths.result--;
|
|
427
306
|
}
|
|
428
307
|
|
|
429
|
-
this.rootNode = agastState.path.atDepth(0).node;
|
|
308
|
+
this.rootNode = Path.wrap(agastState.path).atDepth(0).node;
|
|
430
309
|
|
|
431
|
-
s.resultPath = agastState.resultPath;
|
|
310
|
+
s.resultPath = TagPath.wrap(agastState.resultPath);
|
|
432
311
|
|
|
433
312
|
// if (this.emitted?.depth > 1) throw new Error();
|
|
434
313
|
|
|
@@ -799,4 +678,97 @@ export class Match extends WeakStackFrame {
|
|
|
799
678
|
}
|
|
800
679
|
}
|
|
801
680
|
}
|
|
681
|
+
|
|
682
|
+
getPublic() {
|
|
683
|
+
let cached = facades.get(this);
|
|
684
|
+
if (cached) {
|
|
685
|
+
return cached;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
let {
|
|
689
|
+
parent,
|
|
690
|
+
cover,
|
|
691
|
+
nodeMatch,
|
|
692
|
+
shiftMatch,
|
|
693
|
+
coveredBoundary,
|
|
694
|
+
mergedReference,
|
|
695
|
+
matcher,
|
|
696
|
+
propertyMatcher,
|
|
697
|
+
rawPropertyMatcher,
|
|
698
|
+
language,
|
|
699
|
+
isNode,
|
|
700
|
+
isCover,
|
|
701
|
+
isCoverBoundary,
|
|
702
|
+
effects,
|
|
703
|
+
options,
|
|
704
|
+
allowEmpty,
|
|
705
|
+
depth,
|
|
706
|
+
state,
|
|
707
|
+
} = this;
|
|
708
|
+
|
|
709
|
+
let getParent = () => {
|
|
710
|
+
let value = parent;
|
|
711
|
+
if (parent) facades.set((value = facades.get(parent) || parent.getPublic()));
|
|
712
|
+
return value;
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
let getCover = () => {
|
|
716
|
+
let value = cover;
|
|
717
|
+
if (cover) facades.set((value = facades.get(cover) || cover.getPublic()));
|
|
718
|
+
return value;
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
let getCoveredBoundary = () => {
|
|
722
|
+
let value = coveredBoundary;
|
|
723
|
+
if (coveredBoundary)
|
|
724
|
+
facades.set((value = facades.get(coveredBoundary) || coveredBoundary.getPublic()));
|
|
725
|
+
return value;
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
let getNodeMatch = () => {
|
|
729
|
+
let value = nodeMatch;
|
|
730
|
+
if (nodeMatch) facades.set((value = facades.get(nodeMatch) || nodeMatch.getPublic()));
|
|
731
|
+
return value;
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
let getShiftMatch = () => {
|
|
735
|
+
let value = shiftMatch;
|
|
736
|
+
if (shiftMatch) facades.set((value = facades.get(shiftMatch) || shiftMatch.getPublic()));
|
|
737
|
+
return value;
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
let getState = () => {
|
|
741
|
+
return state.getPublic();
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
let getNode = () => {
|
|
745
|
+
return buildFacadeNode(this.node);
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
cached = {
|
|
749
|
+
getParent,
|
|
750
|
+
getCover,
|
|
751
|
+
getCoveredBoundary,
|
|
752
|
+
getNodeMatch,
|
|
753
|
+
getShiftMatch,
|
|
754
|
+
getState,
|
|
755
|
+
getNode,
|
|
756
|
+
mergedReference,
|
|
757
|
+
matcher,
|
|
758
|
+
propertyMatcher,
|
|
759
|
+
rawPropertyMatcher,
|
|
760
|
+
language,
|
|
761
|
+
isNode,
|
|
762
|
+
isCover,
|
|
763
|
+
isCoverBoundary,
|
|
764
|
+
effects,
|
|
765
|
+
options,
|
|
766
|
+
allowEmpty,
|
|
767
|
+
depth,
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
facades.set(this, cached);
|
|
771
|
+
|
|
772
|
+
return cached;
|
|
773
|
+
}
|
|
802
774
|
}
|
package/lib/spans.js
CHANGED
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
import { ReferenceTag } from '@bablr/agast-helpers/symbols';
|
|
2
|
-
import * as
|
|
2
|
+
import * as Spans from '@bablr/agast-helpers/spans';
|
|
3
|
+
import { buildTypedSpan } from '@bablr/agast-helpers/builders';
|
|
3
4
|
|
|
4
5
|
const popSpan = (s) => {
|
|
5
|
-
s.spans = s.spans
|
|
6
|
+
s.spans = Spans.pop(s.spans);
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
const pushSpan = (s, type, name, guard) => {
|
|
9
|
-
|
|
10
|
-
let topFrame = s.spans.value;
|
|
11
|
-
|
|
12
|
-
// if (isSubspan) {
|
|
13
|
-
// let buildGuard = () => {
|
|
14
|
-
// return buildPattern();
|
|
15
|
-
// };
|
|
16
|
-
// let name_ = topFrame.name + name;
|
|
17
|
-
// let subframes = BTree.push(topFrame.subframes, topFrame);
|
|
18
|
-
// let guard_ = guard;
|
|
19
|
-
|
|
20
|
-
// s.spans = s.spans.push({ type, name: name_, guard: guard_, subframes });
|
|
21
|
-
// } else {
|
|
22
|
-
s.spans = s.spans.push({ type, name, guard, subframes: BTree.fromValues([]) });
|
|
23
|
-
// }
|
|
10
|
+
s.spans = Spans.push(s.spans, buildTypedSpan(type, name, guard));
|
|
24
11
|
};
|
|
25
12
|
|
|
26
13
|
export function updateSpans(m, phase) {
|
package/lib/state.js
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
import emptyStack from '@iter-tools/imm-stack';
|
|
2
|
-
import {
|
|
3
|
-
import { getCooked, maybeWait } from '@bablr/agast-helpers/stream';
|
|
2
|
+
import { maybeWait } from '@bablr/agast-helpers/stream';
|
|
4
3
|
import * as BTree from '@bablr/agast-helpers/btree';
|
|
4
|
+
import * as Spans from '@bablr/agast-helpers/spans';
|
|
5
5
|
import { reifyExpression } from '@bablr/agast-vm-helpers';
|
|
6
|
-
import { Matcher, Node, Regex
|
|
6
|
+
import { Matcher, Node, Regex } from '@bablr/agast-vm-helpers/symbols';
|
|
7
7
|
import { match, guardWithPattern } from './utils/pattern.js';
|
|
8
8
|
import { getOpenTag } from '@bablr/agast-helpers/path';
|
|
9
9
|
|
|
10
10
|
export const nodeStates = new WeakMap();
|
|
11
11
|
|
|
12
|
-
export const State = class BABLRState
|
|
12
|
+
export const State = class BABLRState {
|
|
13
|
+
static from(source, context, language, expressions = [], spans = Spans.fromValues([])) {
|
|
14
|
+
return new State(
|
|
15
|
+
null,
|
|
16
|
+
source,
|
|
17
|
+
context,
|
|
18
|
+
BTree.fromValues([language]),
|
|
19
|
+
emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
|
|
20
|
+
spans,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
constructor(
|
|
14
25
|
parent,
|
|
15
26
|
source,
|
|
16
27
|
context,
|
|
17
28
|
languages,
|
|
18
29
|
expressions = emptyStack,
|
|
30
|
+
spans = Spans.fromValues([]),
|
|
19
31
|
balanced = emptyStack,
|
|
20
|
-
spans = emptyStack,
|
|
21
32
|
resultPath = null,
|
|
22
33
|
depths = { path: -1, result: -1, emitted: -1, shift: 0, nodeShift: 0 },
|
|
23
34
|
held = null,
|
|
24
35
|
node = null,
|
|
25
36
|
) {
|
|
26
|
-
super(parent);
|
|
27
|
-
|
|
28
37
|
if (!source) throw new Error('invalid args to State');
|
|
29
38
|
|
|
39
|
+
this.parent = parent;
|
|
30
40
|
this.source = source;
|
|
31
41
|
this.context = context;
|
|
32
42
|
this.languages = languages;
|
|
@@ -38,18 +48,10 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
38
48
|
this.held = held;
|
|
39
49
|
this.node = node;
|
|
40
50
|
|
|
51
|
+
this.depth = !parent ? 0 : parent.depth + 1;
|
|
41
52
|
this.status = 'active';
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
static from(source, context, language, expressions = []) {
|
|
45
|
-
return State.create(
|
|
46
|
-
source,
|
|
47
|
-
context,
|
|
48
|
-
BTree.fromValues([language]),
|
|
49
|
-
emptyStack.push(...emptyStack.push(...expressions).valuesReverse()),
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
55
|
get language() {
|
|
54
56
|
return BTree.getAt(-1, this.languages);
|
|
55
57
|
}
|
|
@@ -62,7 +64,7 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
get span() {
|
|
65
|
-
return this.spans
|
|
67
|
+
return Spans.getAt(-1, this.spans);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
get result() {
|
|
@@ -77,12 +79,30 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
77
79
|
return !!this.parent;
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
push(source, context, languages, expressions, spans, balanced, resultPath, depths, held, node) {
|
|
83
|
+
return new State(
|
|
84
|
+
this,
|
|
85
|
+
source,
|
|
86
|
+
context,
|
|
87
|
+
languages,
|
|
88
|
+
expressions,
|
|
89
|
+
spans,
|
|
90
|
+
balanced,
|
|
91
|
+
resultPath,
|
|
92
|
+
depths,
|
|
93
|
+
held,
|
|
94
|
+
node,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
80
98
|
getPublic() {
|
|
81
99
|
let { languages, spans, depths, held, node, source, result, resultPath, status } = this;
|
|
82
|
-
|
|
100
|
+
|
|
101
|
+
return Object.freeze({
|
|
83
102
|
languages,
|
|
84
|
-
span:
|
|
85
|
-
|
|
103
|
+
span: Spans.getAt(-1, spans),
|
|
104
|
+
spans: spans,
|
|
105
|
+
depths: Object.freeze({ ...depths }),
|
|
86
106
|
holding: !!held,
|
|
87
107
|
held,
|
|
88
108
|
node,
|
|
@@ -90,9 +110,9 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
90
110
|
done: source.done,
|
|
91
111
|
sourceIndex: source.index,
|
|
92
112
|
result,
|
|
93
|
-
resultPath,
|
|
113
|
+
resultPath: resultPath?.frames || null,
|
|
94
114
|
status,
|
|
95
|
-
};
|
|
115
|
+
});
|
|
96
116
|
}
|
|
97
117
|
|
|
98
118
|
guardedMatch(pattern) {
|
|
@@ -101,6 +121,7 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
101
121
|
|
|
102
122
|
let branchedSource = false;
|
|
103
123
|
let pattern_ = pattern;
|
|
124
|
+
|
|
104
125
|
if (pattern.type === Matcher) {
|
|
105
126
|
let { nodeMatcher } = reifyExpression(pattern.value);
|
|
106
127
|
|
|
@@ -143,8 +164,8 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
143
164
|
let {
|
|
144
165
|
source,
|
|
145
166
|
context,
|
|
146
|
-
balanced,
|
|
147
167
|
spans,
|
|
168
|
+
balanced,
|
|
148
169
|
resultPath,
|
|
149
170
|
depths,
|
|
150
171
|
held,
|
|
@@ -158,8 +179,8 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
158
179
|
context,
|
|
159
180
|
languages,
|
|
160
181
|
expressions,
|
|
161
|
-
balanced,
|
|
162
182
|
spans,
|
|
183
|
+
balanced,
|
|
163
184
|
resultPath,
|
|
164
185
|
{ ...depths },
|
|
165
186
|
held,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/bablr-vm",
|
|
3
3
|
"description": "A VM for parsing using BABLR languages",
|
|
4
|
-
"version": "0.23.
|
|
4
|
+
"version": "0.23.3",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -12,14 +12,13 @@
|
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@bablr/agast-helpers": "0.10.
|
|
16
|
-
"@bablr/agast-vm": "0.11.
|
|
17
|
-
"@bablr/agast-vm-helpers": "0.10.
|
|
15
|
+
"@bablr/agast-helpers": "0.10.4",
|
|
16
|
+
"@bablr/agast-vm": "0.11.2",
|
|
17
|
+
"@bablr/agast-vm-helpers": "0.10.4",
|
|
18
18
|
"@bablr/coroutine": "0.1.0",
|
|
19
|
-
"@bablr/helpers": "0.25.
|
|
20
|
-
"@bablr/regex-vm": "0.14.
|
|
19
|
+
"@bablr/helpers": "0.25.2",
|
|
20
|
+
"@bablr/regex-vm": "0.14.2",
|
|
21
21
|
"@bablr/stream-iterator": "2.0.0",
|
|
22
|
-
"@bablr/weak-stack": "1.0.1",
|
|
23
22
|
"@iter-tools/imm-stack": "1.2.0",
|
|
24
23
|
"iter-tools-es": "7.5.3"
|
|
25
24
|
},
|