@bablr/bablr-vm 0.14.0 → 0.16.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/source.js +4 -0
- package/lib/spans.js +4 -5
- package/lib/state.js +52 -8
- package/lib/strategy.js +51 -48
- package/package.json +5 -5
package/lib/source.js
CHANGED
package/lib/spans.js
CHANGED
|
@@ -10,7 +10,7 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
10
10
|
|
|
11
11
|
if (flags.intrinsic) {
|
|
12
12
|
if (s.path && balanced) {
|
|
13
|
-
|
|
13
|
+
s.spans = s.spans.push({
|
|
14
14
|
type: 'Lexical',
|
|
15
15
|
name: balancedSpan || s.span.name,
|
|
16
16
|
path: s.path,
|
|
@@ -37,7 +37,7 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
37
37
|
|
|
38
38
|
if (!s.balanced.size) throw new Error();
|
|
39
39
|
|
|
40
|
-
if (!balancedNode.
|
|
40
|
+
if (!balancedNode.children[0].value.attributes.balanced) {
|
|
41
41
|
throw new Error();
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -47,7 +47,7 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (balanced) {
|
|
50
|
-
s.balanced = s.balanced.push(
|
|
50
|
+
s.balanced = s.balanced.push(s.nodeForTag(s.result));
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (innerSpan) {
|
|
@@ -63,8 +63,7 @@ export function updateSpans(ctx, s, node, phase) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
case 'close': {
|
|
66
|
-
const {
|
|
67
|
-
const { attributes } = openTag.value;
|
|
66
|
+
const { flags, attributes } = node;
|
|
68
67
|
const { balancedSpan, span: innerSpan, closeSpan, balanced } = attributes || {};
|
|
69
68
|
|
|
70
69
|
if (balanced && !flags.intrinsic) {
|
package/lib/state.js
CHANGED
|
@@ -3,6 +3,7 @@ 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
5
|
import { facades, actuals } from './facades.js';
|
|
6
|
+
import { reifyExpression } from '@bablr/agast-vm-helpers';
|
|
6
7
|
|
|
7
8
|
export const StateFacade = class BABLRStateFacade {
|
|
8
9
|
constructor(state) {
|
|
@@ -33,6 +34,10 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
33
34
|
return actuals.get(this).node;
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
get parentNode() {
|
|
38
|
+
return actuals.get(this).parentNode;
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
get source() {
|
|
37
42
|
return facades.get(actuals.get(this).source);
|
|
38
43
|
}
|
|
@@ -44,6 +49,18 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
44
49
|
get status() {
|
|
45
50
|
return actuals.get(this).status;
|
|
46
51
|
}
|
|
52
|
+
|
|
53
|
+
nodeForPath(path) {
|
|
54
|
+
return actuals.get(this).nodeForPath(path);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pathForTag(tag) {
|
|
58
|
+
return actuals.get(this).pathForTag(tag);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
nodeForTag(tag) {
|
|
62
|
+
return actuals.get(this).nodeForTag(tag);
|
|
63
|
+
}
|
|
47
64
|
};
|
|
48
65
|
|
|
49
66
|
export const State = class BABLRState extends WeakStackFrame {
|
|
@@ -85,6 +102,10 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
85
102
|
return this.agast.node;
|
|
86
103
|
}
|
|
87
104
|
|
|
105
|
+
get parentNode() {
|
|
106
|
+
return this.agast.parentNode;
|
|
107
|
+
}
|
|
108
|
+
|
|
88
109
|
get holding() {
|
|
89
110
|
return this.agast.holding;
|
|
90
111
|
}
|
|
@@ -101,10 +122,37 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
101
122
|
return !!this.parent;
|
|
102
123
|
}
|
|
103
124
|
|
|
125
|
+
nodeForPath(path) {
|
|
126
|
+
return this.agast.nodeForPath(path);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
pathForTag(tag) {
|
|
130
|
+
return this.agast.pathForTag(tag);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
nodeForTag(tag) {
|
|
134
|
+
return this.agast.nodeForTag(tag);
|
|
135
|
+
}
|
|
136
|
+
|
|
104
137
|
guardedMatch(pattern) {
|
|
105
|
-
let { span, spans, source } = this;
|
|
138
|
+
let { span, spans, source, node } = this;
|
|
106
139
|
let { guard } = span;
|
|
107
140
|
|
|
141
|
+
if (pattern.type === 'EmbeddedNode') {
|
|
142
|
+
pattern = reifyExpression(pattern.value);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (
|
|
146
|
+
span.type === 'Lexical' &&
|
|
147
|
+
(node.flags.token
|
|
148
|
+
? node.attributes.balancer || node.attributes.balanced
|
|
149
|
+
: pattern.attributes?.balancer)
|
|
150
|
+
) {
|
|
151
|
+
// also check that the open node starts a lexical span?
|
|
152
|
+
span = spans.prev.value;
|
|
153
|
+
({ guard } = span);
|
|
154
|
+
}
|
|
155
|
+
|
|
108
156
|
if (pattern?.intrinsicValue) {
|
|
109
157
|
// if (pattern.type === 'OpenNodeTag') {
|
|
110
158
|
|
|
@@ -112,15 +160,11 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
112
160
|
// pattern = pattern.value;
|
|
113
161
|
// }
|
|
114
162
|
|
|
115
|
-
|
|
163
|
+
pattern = pattern.intrinsicValue || getCooked(pattern.children);
|
|
116
164
|
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
span = spans.prev.value;
|
|
120
|
-
({ guard } = span);
|
|
165
|
+
if (pattern.type === 'String') {
|
|
166
|
+
pattern = reifyExpression(pattern);
|
|
121
167
|
}
|
|
122
|
-
|
|
123
|
-
pattern = pattern.intrinsicValue || getCooked(pattern.children);
|
|
124
168
|
}
|
|
125
169
|
|
|
126
170
|
return match(pattern, guard ? guardWithPattern(guard, source) : source);
|
package/lib/strategy.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
buildCall,
|
|
4
|
+
buildReference,
|
|
5
|
+
buildNull,
|
|
6
|
+
buildEmbeddedTag,
|
|
7
|
+
} from '@bablr/agast-helpers/builders';
|
|
3
8
|
import { StreamGenerator } from '@bablr/agast-helpers/stream';
|
|
9
|
+
import { getOpenTag } from '@bablr/agast-helpers/tree';
|
|
4
10
|
import { buildTokens } from './utils/token.js';
|
|
5
11
|
import { formatType } from './utils/format.js';
|
|
6
12
|
import { facades } from './facades.js';
|
|
7
13
|
import { State } from './state.js';
|
|
8
14
|
import { updateSpans } from './spans.js';
|
|
9
15
|
|
|
16
|
+
const { hasOwn } = Object;
|
|
17
|
+
|
|
10
18
|
export const createBablrStrategy = (rootSource, strategy) => {
|
|
11
19
|
return (ctx, agastState) => {
|
|
12
20
|
return new StreamGenerator(__strategy(ctx, rootSource, agastState, strategy));
|
|
@@ -39,53 +47,32 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
39
47
|
|
|
40
48
|
if (co.done) break;
|
|
41
49
|
|
|
42
|
-
const
|
|
43
|
-
const instr = reifyExpression(sourceInstr);
|
|
50
|
+
const instr = co.value;
|
|
44
51
|
let returnValue = undefined;
|
|
45
52
|
|
|
46
53
|
const { verb } = instr;
|
|
47
54
|
|
|
48
55
|
switch (verb) {
|
|
49
56
|
case 'advance': {
|
|
50
|
-
const {
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
const { arguments: { 0: embeddedTerminal } = [] } = instr;
|
|
58
|
+
|
|
59
|
+
const terminal = embeddedTerminal.value;
|
|
53
60
|
|
|
54
61
|
switch (terminal?.type || 'Null') {
|
|
55
62
|
case 'DoctypeTag': {
|
|
56
|
-
const doctypeTag = yield
|
|
63
|
+
const doctypeTag = yield instr;
|
|
57
64
|
|
|
58
65
|
returnValue = doctypeTag;
|
|
59
66
|
break;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
case 'OpenNodeTag': {
|
|
63
|
-
const { type
|
|
70
|
+
const { type } = terminal.value;
|
|
64
71
|
|
|
65
|
-
const openTag = yield
|
|
72
|
+
const openTag = yield instr;
|
|
66
73
|
|
|
67
74
|
if (type) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (intrinsicResult instanceof Promise) {
|
|
71
|
-
intrinsicResult = yield intrinsicResult;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
updateSpans(ctx, s, intrinsicValue ? ctx.nodeForTag(openTag) : s.node, 'open');
|
|
75
|
-
|
|
76
|
-
if (intrinsicValue) {
|
|
77
|
-
if (!intrinsicResult) {
|
|
78
|
-
throw new Error('advance failed to match an intrinsic node');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const sourceStep = s.source.advance(intrinsicResult.length);
|
|
82
|
-
|
|
83
|
-
if (sourceStep instanceof Promise) {
|
|
84
|
-
yield sourceStep;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
updateSpans(ctx, s, ctx.nodeForTag(openTag), 'close');
|
|
88
|
-
}
|
|
75
|
+
updateSpans(ctx, s, s.node, 'open');
|
|
89
76
|
}
|
|
90
77
|
|
|
91
78
|
returnValue = openTag;
|
|
@@ -95,7 +82,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
95
82
|
case 'CloseNodeTag': {
|
|
96
83
|
const { node } = s;
|
|
97
84
|
|
|
98
|
-
const endTag = yield
|
|
85
|
+
const endTag = yield instr;
|
|
99
86
|
|
|
100
87
|
if (s.path) {
|
|
101
88
|
updateSpans(ctx, s, node, 'close');
|
|
@@ -129,7 +116,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
129
116
|
sourceStep = yield sourceStep;
|
|
130
117
|
}
|
|
131
118
|
|
|
132
|
-
returnValue = yield
|
|
119
|
+
returnValue = yield instr;
|
|
133
120
|
} else {
|
|
134
121
|
throw new Error('Failed to advance literal');
|
|
135
122
|
}
|
|
@@ -148,7 +135,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
148
135
|
}
|
|
149
136
|
}
|
|
150
137
|
|
|
151
|
-
returnValue = yield
|
|
138
|
+
returnValue = yield instr;
|
|
152
139
|
} else {
|
|
153
140
|
throw new Error('Failed to advance gap');
|
|
154
141
|
}
|
|
@@ -158,12 +145,12 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
158
145
|
case 'Shift': {
|
|
159
146
|
s.source.shift();
|
|
160
147
|
|
|
161
|
-
returnValue = yield
|
|
148
|
+
returnValue = yield instr;
|
|
162
149
|
break;
|
|
163
150
|
}
|
|
164
151
|
|
|
165
152
|
default: {
|
|
166
|
-
returnValue = yield
|
|
153
|
+
returnValue = yield instr;
|
|
167
154
|
break;
|
|
168
155
|
}
|
|
169
156
|
}
|
|
@@ -180,7 +167,9 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
180
167
|
result = yield result;
|
|
181
168
|
}
|
|
182
169
|
|
|
183
|
-
|
|
170
|
+
const tokens = result && ctx.buildRange(buildTokens(result));
|
|
171
|
+
|
|
172
|
+
returnValue = tokens || null;
|
|
184
173
|
break;
|
|
185
174
|
}
|
|
186
175
|
|
|
@@ -188,11 +177,13 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
188
177
|
const baseState = s;
|
|
189
178
|
let { source, agast, balanced, spans, node } = baseState;
|
|
190
179
|
|
|
191
|
-
agast = yield
|
|
180
|
+
agast = yield instr;
|
|
192
181
|
|
|
193
182
|
s = s.push(source.branch(), agast, balanced, spans);
|
|
194
183
|
|
|
195
|
-
|
|
184
|
+
if (node) {
|
|
185
|
+
resolvedLanguages.set(s.node, resolvedLanguages.get(node));
|
|
186
|
+
}
|
|
196
187
|
|
|
197
188
|
returnValue = facades.get(s);
|
|
198
189
|
break;
|
|
@@ -203,7 +194,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
203
194
|
|
|
204
195
|
s.status = 'accepted';
|
|
205
196
|
|
|
206
|
-
const agastState = yield
|
|
197
|
+
const agastState = yield instr;
|
|
207
198
|
|
|
208
199
|
s = s.parent;
|
|
209
200
|
|
|
@@ -226,25 +217,37 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
226
217
|
|
|
227
218
|
s.status = 'rejected';
|
|
228
219
|
|
|
229
|
-
yield
|
|
220
|
+
yield instr;
|
|
230
221
|
|
|
231
222
|
s = s.parent;
|
|
232
223
|
|
|
233
224
|
if (s.path.depth && rejectedState.path.depth > s.path.depth) {
|
|
234
|
-
const didShift = rejectedState.node.at(
|
|
225
|
+
// const didShift = rejectedState.node.at(sNodeDepth) === s.node;
|
|
226
|
+
const didShift =
|
|
227
|
+
s.nodeForPath(s.path) && !s.nodeForPath(rejectedState.path.at(s.path.depth));
|
|
235
228
|
const lowPath = rejectedState.path.at(
|
|
236
|
-
Math.min(
|
|
229
|
+
Math.min(
|
|
230
|
+
s.path.depth + (didShift || s.result.type === 'Reference' ? 0 : 1),
|
|
231
|
+
rejectedState.path.depth,
|
|
232
|
+
),
|
|
237
233
|
);
|
|
238
|
-
const lowNode = s.node;
|
|
234
|
+
const lowNode = s.node || s.parentNode;
|
|
239
235
|
|
|
240
236
|
const { name, isArray } = lowPath.reference?.value || {};
|
|
241
237
|
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
238
|
+
if (
|
|
239
|
+
!didShift &&
|
|
240
|
+
!hasOwn(lowNode.properties, name) &&
|
|
241
|
+
!(s.result.type === 'Reference' && s.result.value.name === name)
|
|
242
|
+
) {
|
|
243
|
+
if (
|
|
244
|
+
!getOpenTag(lowNode)?.value.flags.trivia &&
|
|
245
|
+
!getOpenTag(lowNode)?.value.flags.escape
|
|
246
|
+
) {
|
|
247
|
+
yield buildCall('advance', buildEmbeddedTag(buildReference(name, isArray)));
|
|
245
248
|
}
|
|
246
249
|
|
|
247
|
-
yield buildCall('advance', buildNull());
|
|
250
|
+
yield buildCall('advance', buildEmbeddedTag(buildNull()));
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
253
|
|
|
@@ -258,7 +261,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
258
261
|
|
|
259
262
|
case 'write':
|
|
260
263
|
case 'bindAttribute': {
|
|
261
|
-
returnValue = yield
|
|
264
|
+
returnValue = yield instr;
|
|
262
265
|
break;
|
|
263
266
|
}
|
|
264
267
|
|
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.16.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.1
|
|
16
|
-
"@bablr/agast-vm-helpers": "0.1
|
|
15
|
+
"@bablr/agast-helpers": "0.3.1",
|
|
16
|
+
"@bablr/agast-vm-helpers": "0.3.1",
|
|
17
17
|
"@bablr/coroutine": "0.1.0",
|
|
18
|
-
"@bablr/helpers": "0.
|
|
19
|
-
"@bablr/regex-vm": "0.
|
|
18
|
+
"@bablr/helpers": "0.18.0",
|
|
19
|
+
"@bablr/regex-vm": "0.6.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"
|