@bablr/bablr-vm 0.16.4 → 0.18.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 +75 -0
- package/lib/index.js +2 -0
- package/lib/node.js +97 -0
- package/lib/source.js +1 -1
- package/lib/spans.js +19 -25
- package/lib/state.js +24 -11
- package/lib/strategy.js +86 -40
- package/lib/utils/pattern.js +1 -1
- package/lib/utils/token.js +4 -4
- package/package.json +5 -5
- package/lib/facades.js +0 -3
- package/lib/symbols.js +0 -1
package/lib/context.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { buildDependentLanguages } from '@bablr/helpers/grammar';
|
|
2
|
+
import { facades, actuals } from '../../bablr-vm-strategy-parse/lib/facades.js';
|
|
3
|
+
import { getPrototypeOf } from '@bablr/helpers/object';
|
|
4
|
+
import { actuals as nodeActuals } from './node.js';
|
|
5
|
+
|
|
6
|
+
export const ContextFacade = class BABLRContextFacade {
|
|
7
|
+
get languages() {
|
|
8
|
+
return actuals.get(this).languages;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get grammars() {
|
|
12
|
+
return actuals.get(this).grammars;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get productionEnhancer() {
|
|
16
|
+
return actuals.get(this).productionEnhancer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get agast() {
|
|
20
|
+
return actuals.get(this).agast;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
getPreviousTag(token) {
|
|
24
|
+
return actuals.get(this).agast.getPreviousTag(token);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
allTagsFor(range) {
|
|
28
|
+
return actuals.get(this).agast.allTagsFor(range);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
ownTagsFor(range) {
|
|
32
|
+
return actuals.get(this).agast.ownTagsFor(range);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getCooked(node) {
|
|
36
|
+
return actuals.get(this).agast.getCooked(actuals.get(node));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
reifyExpression(value) {
|
|
40
|
+
return actuals.get(this).agast.reifyExpression(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
sourceTextFor(node) {
|
|
44
|
+
return actuals.get(this).agast.sourceTextFor(nodeActuals.get(node));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
unbox(value) {
|
|
48
|
+
return actuals.get(this).agast.unbox(value);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const Context = class BABLRContext {
|
|
53
|
+
static from(agastContext, language, productionEnhancer) {
|
|
54
|
+
return new Context(agastContext, buildDependentLanguages(language), productionEnhancer);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
constructor(agastContext, languages, productionEnhancer) {
|
|
58
|
+
this.agast = agastContext;
|
|
59
|
+
this.languages = languages;
|
|
60
|
+
this.productionEnhancer = productionEnhancer;
|
|
61
|
+
|
|
62
|
+
this.grammars = new WeakMap();
|
|
63
|
+
this.facade = new ContextFacade();
|
|
64
|
+
|
|
65
|
+
for (const { 1: language } of this.languages) {
|
|
66
|
+
let { prototype } = language.grammar;
|
|
67
|
+
while (prototype && prototype !== Object.prototype) {
|
|
68
|
+
prototype = getPrototypeOf(prototype);
|
|
69
|
+
}
|
|
70
|
+
this.grammars.set(language, new language.grammar());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
facades.set(this, this.facade);
|
|
74
|
+
}
|
|
75
|
+
};
|
package/lib/index.js
CHANGED
package/lib/node.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { parsePath } from '@bablr/agast-helpers/path';
|
|
2
|
+
import { ReferenceTag } from '@bablr/agast-helpers/symbols';
|
|
3
|
+
import {
|
|
4
|
+
buildGapTag,
|
|
5
|
+
buildStubNode,
|
|
6
|
+
get,
|
|
7
|
+
getCloseTag,
|
|
8
|
+
getOpenTag,
|
|
9
|
+
} from '@bablr/agast-helpers/tree';
|
|
10
|
+
import * as btree from '@bablr/agast-helpers/btree';
|
|
11
|
+
|
|
12
|
+
const { hasOwn } = Object;
|
|
13
|
+
|
|
14
|
+
export const contexts = new WeakMap();
|
|
15
|
+
export const actuals = new WeakMap();
|
|
16
|
+
// eslint-disable-next-line no-undef
|
|
17
|
+
export const transparentFacades = new WeakSet();
|
|
18
|
+
|
|
19
|
+
export const NodeFacade = class BABLRNodeFacade {
|
|
20
|
+
static wrap(node, context, transparent) {
|
|
21
|
+
if (!node || !context) throw new Error();
|
|
22
|
+
return node && new NodeFacade(node, context, transparent);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor(node, context, transparent) {
|
|
26
|
+
actuals.set(this, node);
|
|
27
|
+
contexts.set(this, context);
|
|
28
|
+
if (transparent) {
|
|
29
|
+
transparentFacades.add(this);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get isTransparent() {
|
|
34
|
+
return transparentFacades.has(this);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get children() {
|
|
38
|
+
const node = actuals.get(this);
|
|
39
|
+
const isTransparent = transparentFacades.has(this);
|
|
40
|
+
return {
|
|
41
|
+
*[Symbol.iterator]() {
|
|
42
|
+
if (isTransparent) {
|
|
43
|
+
yield* btree.traverse(node.children);
|
|
44
|
+
} else {
|
|
45
|
+
for (const child of btree.traverse(node.children)) {
|
|
46
|
+
const interpolated = false; // TODO
|
|
47
|
+
if (!interpolated) {
|
|
48
|
+
yield child;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get flags() {
|
|
57
|
+
return actuals.get(this).flags;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get language() {
|
|
61
|
+
return actuals.get(this).language;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get type() {
|
|
65
|
+
return actuals.get(this).type;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get attributes() {
|
|
69
|
+
return actuals.get(this).attributes;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get openTag() {
|
|
73
|
+
return getOpenTag(actuals.get(this));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get closeTag() {
|
|
77
|
+
return getCloseTag(actuals.get(this));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get(path) {
|
|
81
|
+
const context = contexts.get(this);
|
|
82
|
+
const node = get(actuals.get(this), path);
|
|
83
|
+
const isTransparent = transparentFacades.has(this);
|
|
84
|
+
|
|
85
|
+
const ref = node && context.agast.getPreviousTag(btree.getAt(0, node.children));
|
|
86
|
+
const node_ =
|
|
87
|
+
(ref && ref.type === ReferenceTag && !ref.value.hasGap) || isTransparent
|
|
88
|
+
? node
|
|
89
|
+
: buildStubNode(buildGapTag());
|
|
90
|
+
|
|
91
|
+
return node && NodeFacade.wrap(node_, context, isTransparent);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
has(path) {
|
|
95
|
+
return hasOwn(actuals.get(this).properties, parsePath(path).name);
|
|
96
|
+
}
|
|
97
|
+
};
|
package/lib/source.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WeakStackFrame } from '@bablr/weak-stack';
|
|
2
2
|
import { maybeWait, getStreamIterator, emptyStreamIterator } from '@bablr/agast-helpers/stream';
|
|
3
|
-
import { facades, actuals } from '
|
|
3
|
+
import { facades, actuals } from '../../bablr-vm-strategy-parse/lib/facades.js';
|
|
4
4
|
|
|
5
5
|
// Queue item instances are shared between all forks.
|
|
6
6
|
class QueueItem {
|
package/lib/spans.js
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
|
+
import { ReferenceTag } from '@bablr/agast-helpers/symbols';
|
|
2
|
+
import { getOpenTag } from '@bablr/agast-helpers/tree';
|
|
3
|
+
|
|
1
4
|
export function updateSpans(ctx, s, node, phase) {
|
|
5
|
+
const { flags, attributes } = node;
|
|
6
|
+
|
|
7
|
+
const openTag = getOpenTag(node);
|
|
8
|
+
|
|
9
|
+
const ref = ctx.agast.getPreviousTag(openTag);
|
|
10
|
+
|
|
11
|
+
const intrinsic = ref.type === ReferenceTag && !ref.hasGap;
|
|
12
|
+
|
|
2
13
|
switch (phase) {
|
|
3
14
|
case 'open': {
|
|
4
|
-
const {
|
|
5
|
-
const { span: innerSpan, balanced, balancedSpan, balancer, openSpan } = attributes || {};
|
|
15
|
+
const { balancedSpan, span: innerSpan, balanced, balancer, openSpan } = attributes || {};
|
|
6
16
|
|
|
7
|
-
if (!
|
|
17
|
+
if (!intrinsic && (balancer || balanced)) {
|
|
8
18
|
throw new Error('balanced tokens must be instrinsic');
|
|
9
19
|
}
|
|
10
20
|
|
|
11
|
-
if (
|
|
12
|
-
if (s.path && balanced) {
|
|
13
|
-
s.spans = s.spans.push({
|
|
14
|
-
type: 'Lexical',
|
|
15
|
-
name: balancedSpan || s.span.name,
|
|
16
|
-
path: s.path,
|
|
17
|
-
guard: balanced,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (innerSpan) {
|
|
21
|
-
throw new Error();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
21
|
+
if (balancedSpan && !balanced) throw new Error();
|
|
25
22
|
|
|
26
23
|
if (openSpan) {
|
|
27
24
|
s.spans = s.spans.push({
|
|
@@ -37,7 +34,7 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
37
34
|
|
|
38
35
|
if (!s.balanced.size) throw new Error();
|
|
39
36
|
|
|
40
|
-
if (!balancedNode.
|
|
37
|
+
if (!balancedNode.attributes.balanced) {
|
|
41
38
|
throw new Error();
|
|
42
39
|
}
|
|
43
40
|
|
|
@@ -46,10 +43,6 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
46
43
|
s.spans = s.spans.pop();
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
if (balanced) {
|
|
50
|
-
s.balanced = s.balanced.push(s.nodeForTag(s.result));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
46
|
if (innerSpan) {
|
|
54
47
|
s.spans = s.spans.push({
|
|
55
48
|
type: 'Inner',
|
|
@@ -63,15 +56,16 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
63
56
|
}
|
|
64
57
|
|
|
65
58
|
case 'close': {
|
|
66
|
-
const { flags, attributes } = node;
|
|
67
59
|
const { balancedSpan, span: innerSpan, closeSpan, balanced } = attributes || {};
|
|
68
60
|
|
|
69
|
-
if (balanced
|
|
61
|
+
if (balanced) {
|
|
62
|
+
s.balanced = s.balanced.push(s.nodeForTag(s.result));
|
|
63
|
+
|
|
70
64
|
s.spans = s.spans.push({
|
|
71
65
|
type: 'Lexical',
|
|
72
66
|
name: balancedSpan || s.span.name,
|
|
73
67
|
path: s.path,
|
|
74
|
-
guard: balanced,
|
|
68
|
+
guard: balanced === true ? null : balanced,
|
|
75
69
|
});
|
|
76
70
|
}
|
|
77
71
|
|
package/lib/state.js
CHANGED
|
@@ -2,8 +2,10 @@ import emptyStack from '@iter-tools/imm-stack';
|
|
|
2
2
|
import { WeakStackFrame } from '@bablr/weak-stack';
|
|
3
3
|
import { getCooked } from '@bablr/agast-helpers/stream';
|
|
4
4
|
import { match, guardWithPattern } from './utils/pattern.js';
|
|
5
|
-
import { facades, actuals } from '
|
|
5
|
+
import { facades, actuals } from '../../bablr-vm-strategy-parse/lib/facades.js';
|
|
6
6
|
import { reifyExpression } from '@bablr/agast-vm-helpers';
|
|
7
|
+
import { EmbeddedNode, GapTag } from '@bablr/agast-helpers/symbols';
|
|
8
|
+
import { NodeFacade } from './node.js';
|
|
7
9
|
|
|
8
10
|
export const StateFacade = class BABLRStateFacade {
|
|
9
11
|
constructor(state) {
|
|
@@ -14,6 +16,10 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
14
16
|
return State.from(actuals.get(source));
|
|
15
17
|
}
|
|
16
18
|
|
|
19
|
+
get ctx() {
|
|
20
|
+
return actuals.get(this).context;
|
|
21
|
+
}
|
|
22
|
+
|
|
17
23
|
get span() {
|
|
18
24
|
return actuals.get(this).span.name;
|
|
19
25
|
}
|
|
@@ -31,11 +37,11 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
get node() {
|
|
34
|
-
return actuals.get(this).node;
|
|
40
|
+
return NodeFacade.wrap(actuals.get(this).node, this.ctx);
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
get parentNode() {
|
|
38
|
-
return actuals.get(this).parentNode;
|
|
44
|
+
return NodeFacade.wrap(actuals.get(this).parentNode, this.ctx);
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
get source() {
|
|
@@ -51,7 +57,7 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
nodeForPath(path) {
|
|
54
|
-
return actuals.get(this).nodeForPath(path);
|
|
60
|
+
return NodeFacade.wrap(actuals.get(this).nodeForPath(path), this.ctx);
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
pathForTag(tag) {
|
|
@@ -59,18 +65,25 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
nodeForTag(tag) {
|
|
62
|
-
return actuals.get(this).nodeForTag(tag);
|
|
68
|
+
return NodeFacade.wrap(actuals.get(this).nodeForTag(tag), this.ctx);
|
|
63
69
|
}
|
|
64
70
|
};
|
|
65
71
|
|
|
66
72
|
export const State = class BABLRState extends WeakStackFrame {
|
|
67
|
-
constructor(
|
|
73
|
+
constructor(
|
|
74
|
+
source,
|
|
75
|
+
agast,
|
|
76
|
+
context,
|
|
77
|
+
balanced = emptyStack,
|
|
78
|
+
spans = emptyStack.push({ name: 'Bare' }),
|
|
79
|
+
) {
|
|
68
80
|
super();
|
|
69
81
|
|
|
70
82
|
if (!source || !agast) throw new Error('invalid args to State');
|
|
71
83
|
|
|
72
84
|
this.source = source;
|
|
73
85
|
this.agast = agast;
|
|
86
|
+
this.context = context;
|
|
74
87
|
this.balanced = balanced;
|
|
75
88
|
this.spans = spans;
|
|
76
89
|
|
|
@@ -79,8 +92,8 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
79
92
|
new StateFacade(this);
|
|
80
93
|
}
|
|
81
94
|
|
|
82
|
-
static from(source, agast) {
|
|
83
|
-
return State.create(source, agast);
|
|
95
|
+
static from(source, agast, context) {
|
|
96
|
+
return State.create(source, agast, context);
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
get guardedSource() {
|
|
@@ -115,7 +128,7 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
get isGap() {
|
|
118
|
-
return this.tag.type ===
|
|
131
|
+
return this.tag.type === GapTag;
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
get speculative() {
|
|
@@ -138,7 +151,7 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
138
151
|
let { span, spans, source, node } = this;
|
|
139
152
|
let { guard } = span;
|
|
140
153
|
|
|
141
|
-
if (pattern.type ===
|
|
154
|
+
if (pattern.type === EmbeddedNode) {
|
|
142
155
|
pattern = reifyExpression(pattern.value);
|
|
143
156
|
}
|
|
144
157
|
|
|
@@ -153,7 +166,7 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
153
166
|
}
|
|
154
167
|
|
|
155
168
|
if (pattern?.intrinsicValue) {
|
|
156
|
-
// if (pattern.type ===
|
|
169
|
+
// if (pattern.type === OpenNodeTag) {
|
|
157
170
|
|
|
158
171
|
// // TODO differntiate better between self-closing tags and matchers
|
|
159
172
|
// pattern = pattern.value;
|
package/lib/strategy.js
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
|
-
import size from 'iter-tools-es/methods/size';
|
|
2
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
3
2
|
import {
|
|
4
3
|
buildCall,
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
buildReferenceTag,
|
|
5
|
+
buildNullTag,
|
|
7
6
|
buildEmbeddedTag,
|
|
7
|
+
buildArrayTag,
|
|
8
8
|
} from '@bablr/agast-helpers/builders';
|
|
9
9
|
import { StreamGenerator } from '@bablr/agast-helpers/stream';
|
|
10
|
-
import { getOpenTag } from '@bablr/agast-helpers/tree';
|
|
11
|
-
import { buildTokens } from './utils/token.js';
|
|
12
10
|
import { formatType } from './utils/format.js';
|
|
13
|
-
import { facades } from '
|
|
11
|
+
import { facades } from '../../bablr-vm-strategy-parse/lib/facades.js';
|
|
14
12
|
import { State } from './state.js';
|
|
15
13
|
import { updateSpans } from './spans.js';
|
|
14
|
+
import {
|
|
15
|
+
DoctypeTag,
|
|
16
|
+
OpenNodeTag,
|
|
17
|
+
CloseNodeTag,
|
|
18
|
+
ReferenceTag,
|
|
19
|
+
ShiftTag,
|
|
20
|
+
GapTag,
|
|
21
|
+
NullTag,
|
|
22
|
+
LiteralTag,
|
|
23
|
+
} from '@bablr/agast-helpers/symbols';
|
|
24
|
+
import { NodeFacade } from './node.js';
|
|
25
|
+
import { treeFromStreamSync } from '@bablr/agast-helpers/tree';
|
|
26
|
+
|
|
27
|
+
const getSourceLength = (tags) => {
|
|
28
|
+
let i = 0;
|
|
29
|
+
for (const tag of tags) {
|
|
30
|
+
if (tag.type === LiteralTag) {
|
|
31
|
+
i += tag.value.length;
|
|
32
|
+
} else if (tag.type === GapTag) {
|
|
33
|
+
i += 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return i;
|
|
37
|
+
};
|
|
16
38
|
|
|
17
39
|
const { hasOwn } = Object;
|
|
18
40
|
|
|
19
|
-
export const createBablrStrategy = (rootSource, strategy) => {
|
|
20
|
-
return (
|
|
41
|
+
export const createBablrStrategy = (ctx, rootSource, strategy) => {
|
|
42
|
+
return (agastCtx, agastState) => {
|
|
43
|
+
if (agastCtx !== ctx.agast.facade) throw new Error();
|
|
21
44
|
return new StreamGenerator(__strategy(ctx, rootSource, agastState, strategy));
|
|
22
45
|
};
|
|
23
46
|
};
|
|
@@ -25,9 +48,9 @@ export const createBablrStrategy = (rootSource, strategy) => {
|
|
|
25
48
|
const resolvedLanguages = new WeakMap();
|
|
26
49
|
|
|
27
50
|
const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy) {
|
|
28
|
-
let s = State.from(rootSource, agastState);
|
|
51
|
+
let s = State.from(rootSource, agastState, ctx);
|
|
29
52
|
|
|
30
|
-
let co = new Coroutine(strategy(facades.get(s), ctx));
|
|
53
|
+
let co = new Coroutine(strategy(facades.get(s), facades.get(ctx)));
|
|
31
54
|
|
|
32
55
|
co.advance();
|
|
33
56
|
|
|
@@ -55,20 +78,20 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
55
78
|
|
|
56
79
|
switch (verb) {
|
|
57
80
|
case 'advance': {
|
|
58
|
-
const { arguments: { 0:
|
|
81
|
+
const { arguments: { 0: embeddedTag } = [] } = instr;
|
|
59
82
|
|
|
60
|
-
const
|
|
83
|
+
const tag = embeddedTag.value;
|
|
61
84
|
|
|
62
|
-
switch (
|
|
63
|
-
case
|
|
85
|
+
switch (tag?.type || NullTag) {
|
|
86
|
+
case DoctypeTag: {
|
|
64
87
|
const doctypeTag = yield instr;
|
|
65
88
|
|
|
66
89
|
returnValue = doctypeTag;
|
|
67
90
|
break;
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
case
|
|
71
|
-
const { type } =
|
|
93
|
+
case OpenNodeTag: {
|
|
94
|
+
const { type } = tag.value;
|
|
72
95
|
|
|
73
96
|
const openTag = yield instr;
|
|
74
97
|
|
|
@@ -80,10 +103,21 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
80
103
|
break;
|
|
81
104
|
}
|
|
82
105
|
|
|
83
|
-
case
|
|
106
|
+
case CloseNodeTag: {
|
|
84
107
|
const { node } = s;
|
|
85
108
|
|
|
86
|
-
|
|
109
|
+
if (node.flags.escape) {
|
|
110
|
+
const cooked = node.flags.hasGap
|
|
111
|
+
? null
|
|
112
|
+
: ctx.languages
|
|
113
|
+
.get(node.language)
|
|
114
|
+
.getCooked?.(NodeFacade.wrap(node, ctx, true), s.span.name, facades.get(ctx)) ||
|
|
115
|
+
null;
|
|
116
|
+
|
|
117
|
+
yield buildCall('bindAttribute', 'cooked', cooked);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const closeTag = yield instr;
|
|
87
121
|
|
|
88
122
|
if (s.path) {
|
|
89
123
|
updateSpans(ctx, s, node, 'close');
|
|
@@ -97,12 +131,12 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
97
131
|
}
|
|
98
132
|
}
|
|
99
133
|
|
|
100
|
-
returnValue =
|
|
134
|
+
returnValue = closeTag;
|
|
101
135
|
break;
|
|
102
136
|
}
|
|
103
137
|
|
|
104
|
-
case
|
|
105
|
-
const { value: pattern } =
|
|
138
|
+
case LiteralTag: {
|
|
139
|
+
const { value: pattern } = tag;
|
|
106
140
|
|
|
107
141
|
let result = s.guardedMatch(pattern);
|
|
108
142
|
|
|
@@ -111,7 +145,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
111
145
|
}
|
|
112
146
|
|
|
113
147
|
if (result) {
|
|
114
|
-
let sourceStep = s.source.advance(
|
|
148
|
+
let sourceStep = s.source.advance(getSourceLength(result));
|
|
115
149
|
|
|
116
150
|
if (sourceStep instanceof Promise) {
|
|
117
151
|
sourceStep = yield sourceStep;
|
|
@@ -124,7 +158,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
124
158
|
break;
|
|
125
159
|
}
|
|
126
160
|
|
|
127
|
-
case
|
|
161
|
+
case GapTag: {
|
|
128
162
|
if (s.source.value == null && !s.source.done) {
|
|
129
163
|
if (s.source.holding) {
|
|
130
164
|
s.source.unshift();
|
|
@@ -143,7 +177,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
143
177
|
break;
|
|
144
178
|
}
|
|
145
179
|
|
|
146
|
-
case
|
|
180
|
+
case ShiftTag: {
|
|
147
181
|
s.source.shift();
|
|
148
182
|
|
|
149
183
|
returnValue = yield instr;
|
|
@@ -168,19 +202,17 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
168
202
|
result = yield result;
|
|
169
203
|
}
|
|
170
204
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
returnValue = tokens || null;
|
|
205
|
+
returnValue = result && NodeFacade.wrap(treeFromStreamSync(result), ctx, true);
|
|
174
206
|
break;
|
|
175
207
|
}
|
|
176
208
|
|
|
177
209
|
case 'branch': {
|
|
178
210
|
const baseState = s;
|
|
179
|
-
let { source, agast, balanced, spans, node } = baseState;
|
|
211
|
+
let { source, agast, context, balanced, spans, node } = baseState;
|
|
180
212
|
|
|
181
213
|
agast = yield instr;
|
|
182
214
|
|
|
183
|
-
s = s.push(source.branch(), agast, balanced, spans);
|
|
215
|
+
s = s.push(source.branch(), agast, context, balanced, spans);
|
|
184
216
|
|
|
185
217
|
if (node) {
|
|
186
218
|
resolvedLanguages.set(s.node, resolvedLanguages.get(node));
|
|
@@ -222,33 +254,35 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
222
254
|
|
|
223
255
|
s = s.parent;
|
|
224
256
|
|
|
225
|
-
if (s.path.depth && rejectedState.path.depth
|
|
257
|
+
if (s.path.depth && rejectedState.path.depth >= s.path.depth) {
|
|
226
258
|
// const didShift = rejectedState.node.at(sNodeDepth) === s.node;
|
|
227
259
|
const didShift =
|
|
228
260
|
s.nodeForPath(s.path) && !s.nodeForPath(rejectedState.path.at(s.path.depth));
|
|
229
261
|
const lowPath = rejectedState.path.at(
|
|
230
262
|
Math.min(
|
|
231
|
-
s.path.depth + (didShift || s.result.type ===
|
|
263
|
+
s.path.depth + (didShift || s.result.type === ReferenceTag ? 0 : 1),
|
|
232
264
|
rejectedState.path.depth,
|
|
233
265
|
),
|
|
234
266
|
);
|
|
235
267
|
const lowNode = s.node || s.parentNode;
|
|
236
268
|
|
|
237
|
-
const { name, isArray } = lowPath.reference?.value || {};
|
|
269
|
+
const { name, isArray, hasGap } = lowPath.reference?.value || {};
|
|
238
270
|
|
|
239
271
|
if (
|
|
240
272
|
!didShift &&
|
|
241
273
|
!hasOwn(lowNode.properties, name) &&
|
|
242
|
-
!(s.result.type ===
|
|
274
|
+
!(s.result.type === ReferenceTag && s.result.value.name === name)
|
|
243
275
|
) {
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
yield buildCall(
|
|
276
|
+
if (isArray) {
|
|
277
|
+
yield buildCall('advance', buildEmbeddedTag(buildReferenceTag(name, true, hasGap)));
|
|
278
|
+
yield buildCall('advance', buildEmbeddedTag(buildArrayTag()));
|
|
279
|
+
} else {
|
|
280
|
+
yield buildCall(
|
|
281
|
+
'advance',
|
|
282
|
+
buildEmbeddedTag(buildReferenceTag(name, isArray, hasGap)),
|
|
283
|
+
);
|
|
284
|
+
yield buildCall('advance', buildEmbeddedTag(buildNullTag()));
|
|
249
285
|
}
|
|
250
|
-
|
|
251
|
-
yield buildCall('advance', buildEmbeddedTag(buildNull()));
|
|
252
286
|
}
|
|
253
287
|
}
|
|
254
288
|
|
|
@@ -260,6 +294,18 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
260
294
|
break;
|
|
261
295
|
}
|
|
262
296
|
|
|
297
|
+
case 'openSpan': {
|
|
298
|
+
let { arguments: { 0: name } = [] } = instr;
|
|
299
|
+
s.spans = s.spans.push({ guard: null, name, path: s.path, type: 'Instruction' });
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
case 'closeSpan': {
|
|
304
|
+
if (s.spans.value.type !== 'Instruction') throw new Error();
|
|
305
|
+
s.spans = s.spans.pop();
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
|
|
263
309
|
case 'write':
|
|
264
310
|
case 'bindAttribute': {
|
|
265
311
|
returnValue = yield instr;
|
package/lib/utils/pattern.js
CHANGED
|
@@ -57,7 +57,7 @@ class GuardedIterator {
|
|
|
57
57
|
const guardMatch = match(pattern, fork.clone());
|
|
58
58
|
|
|
59
59
|
return maybeWait(guardMatch, (guardMatch) => {
|
|
60
|
-
if (guardMatch ||
|
|
60
|
+
if (guardMatch || fork.done) {
|
|
61
61
|
this.done = true;
|
|
62
62
|
return { value: undefined, done: true };
|
|
63
63
|
} else {
|
package/lib/utils/token.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildLiteralTag, buildGapTag } from '@bablr/agast-helpers/builders';
|
|
2
2
|
|
|
3
3
|
export const isNewlineToken = (token) => /^\r|\r\n|\n$/.test(token.value);
|
|
4
4
|
|
|
@@ -15,16 +15,16 @@ export function* buildTokens(chrs) {
|
|
|
15
15
|
for (const chr of chrs) {
|
|
16
16
|
if (chr == null) {
|
|
17
17
|
if (str) {
|
|
18
|
-
yield
|
|
18
|
+
yield buildLiteralTag(str);
|
|
19
19
|
str = '';
|
|
20
20
|
}
|
|
21
|
-
yield
|
|
21
|
+
yield buildGapTag();
|
|
22
22
|
} else {
|
|
23
23
|
str += chr;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
if (str) {
|
|
28
|
-
yield
|
|
28
|
+
yield buildLiteralTag(str);
|
|
29
29
|
}
|
|
30
30
|
}
|
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.
|
|
4
|
+
"version": "0.18.0",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@bablr/agast-helpers": "0.
|
|
16
|
-
"@bablr/agast-vm-helpers": "0.
|
|
15
|
+
"@bablr/agast-helpers": "^0.5.0",
|
|
16
|
+
"@bablr/agast-vm-helpers": "^0.5.0",
|
|
17
17
|
"@bablr/coroutine": "0.1.0",
|
|
18
|
-
"@bablr/helpers": "0.
|
|
19
|
-
"@bablr/regex-vm": "0.
|
|
18
|
+
"@bablr/helpers": "^0.20.0",
|
|
19
|
+
"@bablr/regex-vm": "^0.9.0",
|
|
20
20
|
"@bablr/weak-stack": "0.1.0",
|
|
21
21
|
"@iter-tools/imm-stack": "1.1.0",
|
|
22
22
|
"iter-tools-es": "^7.5.3"
|
package/lib/facades.js
DELETED
package/lib/symbols.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const node = Symbol.for('@bablr/node');
|