@bablr/bablr-vm 0.15.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/spans.js +4 -5
- package/lib/state.js +44 -8
- package/lib/strategy.js +45 -46
- package/package.json +5 -5
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) {
|
|
@@ -48,6 +49,18 @@ export const StateFacade = class BABLRStateFacade {
|
|
|
48
49
|
get status() {
|
|
49
50
|
return actuals.get(this).status;
|
|
50
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
|
+
}
|
|
51
64
|
};
|
|
52
65
|
|
|
53
66
|
export const State = class BABLRState extends WeakStackFrame {
|
|
@@ -109,10 +122,37 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
109
122
|
return !!this.parent;
|
|
110
123
|
}
|
|
111
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
|
+
|
|
112
137
|
guardedMatch(pattern) {
|
|
113
|
-
let { span, spans, source } = this;
|
|
138
|
+
let { span, spans, source, node } = this;
|
|
114
139
|
let { guard } = span;
|
|
115
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
|
+
|
|
116
156
|
if (pattern?.intrinsicValue) {
|
|
117
157
|
// if (pattern.type === 'OpenNodeTag') {
|
|
118
158
|
|
|
@@ -120,15 +160,11 @@ export const State = class BABLRState extends WeakStackFrame {
|
|
|
120
160
|
// pattern = pattern.value;
|
|
121
161
|
// }
|
|
122
162
|
|
|
123
|
-
|
|
163
|
+
pattern = pattern.intrinsicValue || getCooked(pattern.children);
|
|
124
164
|
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
span = spans.prev.value;
|
|
128
|
-
({ guard } = span);
|
|
165
|
+
if (pattern.type === 'String') {
|
|
166
|
+
pattern = reifyExpression(pattern);
|
|
129
167
|
}
|
|
130
|
-
|
|
131
|
-
pattern = pattern.intrinsicValue || getCooked(pattern.children);
|
|
132
168
|
}
|
|
133
169
|
|
|
134
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, ctx.nodeForTag(openTag), '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,7 +177,7 @@ 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
|
|
|
@@ -205,7 +194,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
205
194
|
|
|
206
195
|
s.status = 'accepted';
|
|
207
196
|
|
|
208
|
-
const agastState = yield
|
|
197
|
+
const agastState = yield instr;
|
|
209
198
|
|
|
210
199
|
s = s.parent;
|
|
211
200
|
|
|
@@ -228,27 +217,37 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
228
217
|
|
|
229
218
|
s.status = 'rejected';
|
|
230
219
|
|
|
231
|
-
yield
|
|
220
|
+
yield instr;
|
|
232
221
|
|
|
233
222
|
s = s.parent;
|
|
234
223
|
|
|
235
224
|
if (s.path.depth && rejectedState.path.depth > s.path.depth) {
|
|
236
225
|
// const didShift = rejectedState.node.at(sNodeDepth) === s.node;
|
|
237
226
|
const didShift =
|
|
238
|
-
|
|
227
|
+
s.nodeForPath(s.path) && !s.nodeForPath(rejectedState.path.at(s.path.depth));
|
|
239
228
|
const lowPath = rejectedState.path.at(
|
|
240
|
-
Math.min(
|
|
229
|
+
Math.min(
|
|
230
|
+
s.path.depth + (didShift || s.result.type === 'Reference' ? 0 : 1),
|
|
231
|
+
rejectedState.path.depth,
|
|
232
|
+
),
|
|
241
233
|
);
|
|
242
234
|
const lowNode = s.node || s.parentNode;
|
|
243
235
|
|
|
244
236
|
const { name, isArray } = lowPath.reference?.value || {};
|
|
245
237
|
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
|
|
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)));
|
|
249
248
|
}
|
|
250
249
|
|
|
251
|
-
yield buildCall('advance', buildNull());
|
|
250
|
+
yield buildCall('advance', buildEmbeddedTag(buildNull()));
|
|
252
251
|
}
|
|
253
252
|
}
|
|
254
253
|
|
|
@@ -262,7 +261,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
|
|
|
262
261
|
|
|
263
262
|
case 'write':
|
|
264
263
|
case 'bindAttribute': {
|
|
265
|
-
returnValue = yield
|
|
264
|
+
returnValue = yield instr;
|
|
266
265
|
break;
|
|
267
266
|
}
|
|
268
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.
|
|
16
|
-
"@bablr/agast-vm-helpers": "0.
|
|
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"
|