@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/utils/pattern.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import isString from 'iter-tools-es/methods/is-string';
|
|
2
2
|
import isEmpty from 'iter-tools-es/methods/is-empty';
|
|
3
3
|
import { generateMatches } from '@bablr/regex-vm';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import {
|
|
5
|
+
getStreamIterator,
|
|
6
|
+
maybeWait,
|
|
7
|
+
printType,
|
|
8
|
+
StreamIterable,
|
|
9
|
+
} from '@bablr/agast-helpers/stream';
|
|
10
|
+
import * as Tags from '@bablr/agast-helpers/tags';
|
|
7
11
|
import {
|
|
8
12
|
buildAlternative,
|
|
9
13
|
buildAlternatives,
|
|
@@ -14,10 +18,41 @@ import {
|
|
|
14
18
|
} from '@bablr/helpers/builders';
|
|
15
19
|
import { buildEmbeddedRegex } from '@bablr/agast-vm-helpers/builders';
|
|
16
20
|
import { GapTag, LiteralTag } from '@bablr/agast-helpers/symbols';
|
|
21
|
+
import {
|
|
22
|
+
buildCloseNodeTag,
|
|
23
|
+
buildLiteralTag,
|
|
24
|
+
buildOpenNodeTag,
|
|
25
|
+
tokenFlags,
|
|
26
|
+
} from '@bablr/agast-helpers/builders';
|
|
27
|
+
import { streamIteratorSymbol } from '@bablr/stream-iterator';
|
|
28
|
+
|
|
29
|
+
function* __wrapSource(source) {
|
|
30
|
+
let source_ = source.source || source;
|
|
31
|
+
if ('\r\n'.includes(source_.prevValue)) {
|
|
32
|
+
yield '\n';
|
|
33
|
+
} else if (source_.index === 0) {
|
|
34
|
+
yield Symbol.for('BOS');
|
|
35
|
+
} else {
|
|
36
|
+
yield '';
|
|
37
|
+
}
|
|
38
|
+
let iter = getStreamIterator(source);
|
|
17
39
|
|
|
18
|
-
|
|
19
|
-
|
|
40
|
+
let step = iter.next();
|
|
41
|
+
while (!step.done) {
|
|
42
|
+
yield step.value;
|
|
43
|
+
step = iter.next();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
iter.return();
|
|
47
|
+
|
|
48
|
+
yield Symbol.for('EOS');
|
|
49
|
+
}
|
|
20
50
|
|
|
51
|
+
export const wrapSource = (source) => {
|
|
52
|
+
return new StreamIterable(__wrapSource(source));
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const assertValidRegex = (expr) => {
|
|
21
56
|
if (!expr.language === 'Spamex' && expr.type === 'Regex') {
|
|
22
57
|
throw new Error();
|
|
23
58
|
}
|
|
@@ -28,7 +63,7 @@ export const assertValidRegex = (expr) => {
|
|
|
28
63
|
const buildStringRegex = (str) => {
|
|
29
64
|
return buildPattern(
|
|
30
65
|
buildAlternatives([
|
|
31
|
-
buildAlternative(buildElements([...str].map((chr) => buildToken(
|
|
66
|
+
buildAlternative(buildElements([...str].map((chr) => buildToken('Character', chr)))),
|
|
32
67
|
]),
|
|
33
68
|
);
|
|
34
69
|
};
|
|
@@ -38,10 +73,10 @@ const buildFragmentRegex = (frag) => {
|
|
|
38
73
|
buildAlternatives([
|
|
39
74
|
buildAlternative(
|
|
40
75
|
buildElements(
|
|
41
|
-
[...
|
|
76
|
+
[...Tags.traverse(frag.tags)].flatMap((tag) => {
|
|
42
77
|
if (tag.type === LiteralTag) {
|
|
43
78
|
let str = tag.value;
|
|
44
|
-
return [...str].map((chr) => buildToken(
|
|
79
|
+
return [...str].map((chr) => buildToken('Character', chr));
|
|
45
80
|
} else if (tag.type === GapTag) {
|
|
46
81
|
return [buildRegexGap()];
|
|
47
82
|
} else {
|
|
@@ -54,7 +89,64 @@ const buildFragmentRegex = (frag) => {
|
|
|
54
89
|
);
|
|
55
90
|
};
|
|
56
91
|
|
|
92
|
+
const promiseCo = (gen) => {
|
|
93
|
+
return (...args) => {
|
|
94
|
+
let generator = gen(...args);
|
|
95
|
+
|
|
96
|
+
const fn = (step) => {
|
|
97
|
+
if (step.done) {
|
|
98
|
+
return step.value;
|
|
99
|
+
} else if (step.value instanceof Promise) {
|
|
100
|
+
return step.value.then((value) => {
|
|
101
|
+
return fn(generator.next(value));
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return fn(generator.next());
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
function* __stringEqual(str, iterable) {
|
|
111
|
+
let strIter = str[Symbol.iterator]();
|
|
112
|
+
let iter = getStreamIterator(iterable);
|
|
113
|
+
|
|
114
|
+
let strStep = strIter.next();
|
|
115
|
+
let step = iter.next();
|
|
116
|
+
|
|
117
|
+
while (!strStep.done) {
|
|
118
|
+
if (step instanceof Promise) {
|
|
119
|
+
step = yield step;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (step.value !== strStep.value) {
|
|
123
|
+
iter.return();
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
strStep = strIter.next();
|
|
128
|
+
step = iter.next();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
iter.return();
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const stringEqual = (str, iterable) => {
|
|
136
|
+
return promiseCo(__stringEqual)(str, iterable);
|
|
137
|
+
};
|
|
138
|
+
|
|
57
139
|
export const match = (pattern, source) => {
|
|
140
|
+
if (typeof pattern === 'string' && pattern.length === 1) {
|
|
141
|
+
return pattern === source.value
|
|
142
|
+
? [buildOpenNodeTag(tokenFlags), buildLiteralTag(pattern), buildCloseNodeTag()]
|
|
143
|
+
: null;
|
|
144
|
+
} else if (typeof pattern === 'string') {
|
|
145
|
+
return stringEqual(pattern, source)
|
|
146
|
+
? [buildOpenNodeTag(tokenFlags), buildLiteralTag(pattern), buildCloseNodeTag()]
|
|
147
|
+
: null;
|
|
148
|
+
}
|
|
149
|
+
|
|
58
150
|
const pattern_ =
|
|
59
151
|
pattern.type === null && pattern.flags.token
|
|
60
152
|
? buildFragmentRegex(pattern)
|
|
@@ -66,12 +158,13 @@ export const match = (pattern, source) => {
|
|
|
66
158
|
|
|
67
159
|
assertValidRegex(pattern_);
|
|
68
160
|
|
|
69
|
-
const iter = getStreamIterator(generateMatches(buildEmbeddedRegex(pattern_), source));
|
|
161
|
+
const iter = getStreamIterator(generateMatches(buildEmbeddedRegex(pattern_), wrapSource(source)));
|
|
70
162
|
|
|
71
163
|
const step = iter.next();
|
|
72
164
|
|
|
73
165
|
return maybeWait(step, (step) => {
|
|
74
166
|
const result = step.done ? null : step.value[0];
|
|
167
|
+
iter.return();
|
|
75
168
|
return isEmpty(result) ? null : result;
|
|
76
169
|
});
|
|
77
170
|
};
|
|
@@ -79,35 +172,40 @@ export const match = (pattern, source) => {
|
|
|
79
172
|
class GuardedIterator {
|
|
80
173
|
constructor(pattern, source) {
|
|
81
174
|
this.pattern = pattern;
|
|
82
|
-
this.
|
|
175
|
+
this.source = source.branch();
|
|
83
176
|
this.done = false;
|
|
84
177
|
}
|
|
85
178
|
|
|
179
|
+
get value() {
|
|
180
|
+
return this.source.value;
|
|
181
|
+
}
|
|
182
|
+
|
|
86
183
|
next() {
|
|
87
|
-
const { pattern,
|
|
184
|
+
const { pattern, source } = this;
|
|
88
185
|
|
|
89
|
-
const guardMatch = match(pattern,
|
|
186
|
+
const guardMatch = match(pattern, source);
|
|
90
187
|
|
|
91
188
|
return maybeWait(guardMatch, (guardMatch) => {
|
|
92
|
-
if (guardMatch ||
|
|
189
|
+
if (guardMatch || source.done) {
|
|
93
190
|
this.done = true;
|
|
191
|
+
source.release();
|
|
94
192
|
return { value: undefined, done: true };
|
|
95
193
|
} else {
|
|
96
|
-
const { value } =
|
|
97
|
-
return maybeWait(
|
|
194
|
+
const { value } = source;
|
|
195
|
+
return maybeWait(source.advance(), (_) => ({ value, done: false }));
|
|
98
196
|
}
|
|
99
197
|
});
|
|
100
198
|
}
|
|
101
199
|
|
|
102
200
|
return() {
|
|
103
|
-
this.
|
|
201
|
+
this.source.release();
|
|
104
202
|
}
|
|
105
203
|
|
|
106
|
-
[
|
|
204
|
+
[streamIteratorSymbol]() {
|
|
107
205
|
return this;
|
|
108
206
|
}
|
|
109
207
|
}
|
|
110
208
|
|
|
111
209
|
export const guardWithPattern = (pattern, source) => {
|
|
112
|
-
return new GuardedIterator(pattern, source
|
|
210
|
+
return new GuardedIterator(pattern, source);
|
|
113
211
|
};
|
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.22.0",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@bablr/agast-helpers": "0.
|
|
16
|
-
"@bablr/agast-vm": "0.
|
|
17
|
-
"@bablr/agast-vm-helpers": "0.
|
|
15
|
+
"@bablr/agast-helpers": "0.9.0",
|
|
16
|
+
"@bablr/agast-vm": "0.10.0",
|
|
17
|
+
"@bablr/agast-vm-helpers": "0.9.0",
|
|
18
18
|
"@bablr/coroutine": "0.1.0",
|
|
19
|
-
"@bablr/helpers": "0.
|
|
20
|
-
"@bablr/regex-vm": "0.
|
|
21
|
-
"@bablr/weak-stack": "1.0.
|
|
22
|
-
"@iter-tools/imm-stack": "1.
|
|
19
|
+
"@bablr/helpers": "0.24.0",
|
|
20
|
+
"@bablr/regex-vm": "0.13.0",
|
|
21
|
+
"@bablr/weak-stack": "1.0.1",
|
|
22
|
+
"@iter-tools/imm-stack": "1.2.0",
|
|
23
23
|
"iter-tools-es": "7.5.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
package/lib/utils/array.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const isArray = Array;
|
|
2
|
-
|
|
3
|
-
export const notEmpty = (arr) => arr != null && arr.length > 0;
|
|
4
|
-
|
|
5
|
-
export const nullOr = (arr) => (arr.length === 0 ? null : arr);
|
|
6
|
-
|
|
7
|
-
export function* arraySlice(arr, start, end) {
|
|
8
|
-
const increment = end > start ? 1 : -1;
|
|
9
|
-
|
|
10
|
-
for (let i = start; i < end; i += increment) {
|
|
11
|
-
yield arr[i];
|
|
12
|
-
}
|
|
13
|
-
}
|
package/lib/utils/format.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const formatType = (type) => {
|
|
2
|
-
return typeof type === 'symbol' ? `${type.description.replace(/^@bablr\//y, '')}` : `'${type}'`;
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
export const formatGraveString = (str) => {
|
|
6
|
-
return `\`${str
|
|
7
|
-
.replace(/`/g, '\\`')
|
|
8
|
-
.replace(/[\r\n\u{00}\u{08}\u{0B}\u{0C}\u{0E}-\u{1F}]/gu, '')}\``;
|
|
9
|
-
};
|
package/lib/utils/object.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
export const { hasOwn, freeze, isFrozen, seal, isSealed, getOwnPropertySymbols } = Object;
|
|
2
|
-
export const { isArray } = Array;
|
|
3
|
-
|
|
4
|
-
const intFrom = (str) => {
|
|
5
|
-
const value = parseInt(str, 10);
|
|
6
|
-
return isNaN(value) ? null : value;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const has = (obj, property) => {
|
|
10
|
-
let value = obj;
|
|
11
|
-
for (const part of property.split('.')) {
|
|
12
|
-
if (!hasOwn(value, part)) return false;
|
|
13
|
-
value = value[part];
|
|
14
|
-
}
|
|
15
|
-
return true;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const get = (obj, property) => {
|
|
19
|
-
let value = obj;
|
|
20
|
-
for (const part of property.split('.')) {
|
|
21
|
-
value = value[part];
|
|
22
|
-
}
|
|
23
|
-
return value;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const set = (obj, property, value) => {
|
|
27
|
-
const parts = property.split('.');
|
|
28
|
-
let obj_ = obj;
|
|
29
|
-
|
|
30
|
-
let lastKey;
|
|
31
|
-
for (let i = 0; i < parts.length; i++) {
|
|
32
|
-
const intKey = intFrom(parts[i]);
|
|
33
|
-
const key = intKey !== null ? intKey : parts[i];
|
|
34
|
-
let value = obj_[key];
|
|
35
|
-
|
|
36
|
-
if (parts.length - 1 === i) {
|
|
37
|
-
lastKey = key;
|
|
38
|
-
} else if (value !== undefined) {
|
|
39
|
-
obj_ = value;
|
|
40
|
-
} else if (intFrom(parts[i + 1]) !== null) {
|
|
41
|
-
obj_ = value = obj_[key] = [];
|
|
42
|
-
} else {
|
|
43
|
-
throw new Error(`Unable to set {property: '${property}'} in obj`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
obj_[lastKey] = value;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export function objectKeys(obj) {
|
|
51
|
-
return {
|
|
52
|
-
*[Symbol.iterator]() {
|
|
53
|
-
for (let key in obj) if (hasOwn(obj, key)) yield key;
|
|
54
|
-
yield* getOwnPropertySymbols(obj);
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function objectValues(obj) {
|
|
60
|
-
return {
|
|
61
|
-
*[Symbol.iterator]() {
|
|
62
|
-
for (let key in obj) if (hasOwn(obj, key)) yield obj[key];
|
|
63
|
-
yield* getOwnPropertySymbols(obj).map((sym) => obj[sym]);
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function objectEntries(obj) {
|
|
69
|
-
return {
|
|
70
|
-
*[Symbol.iterator]() {
|
|
71
|
-
for (let key in obj) if (hasOwn(obj, key)) yield [key, obj[key]];
|
|
72
|
-
yield* getOwnPropertySymbols(obj).map((sym) => [sym, obj[sym]]);
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export const isObject = (obj) => obj !== null && typeof obj === 'object';
|
|
78
|
-
export const isFunction = (obj) => typeof obj === 'function';
|
|
79
|
-
export const isSymbol = (obj) => typeof obj === 'symbol';
|
|
80
|
-
export const isString = (obj) => typeof obj === 'string';
|
|
81
|
-
export const isType = (obj) => isSymbol(obj) || isString(obj);
|
|
82
|
-
export const isRegex = (obj) => obj instanceof RegExp;
|
|
83
|
-
export const isPattern = (obj) => isString(obj) || isRegex(obj);
|
|
84
|
-
|
|
85
|
-
export const memoize = (fn) => {
|
|
86
|
-
const cache = new WeakMap();
|
|
87
|
-
return (obj) => {
|
|
88
|
-
let result;
|
|
89
|
-
if (cache.has(obj)) {
|
|
90
|
-
result = cache.get(obj);
|
|
91
|
-
} else {
|
|
92
|
-
result = fn(obj);
|
|
93
|
-
cache.set(obj, result);
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
96
|
-
};
|
|
97
|
-
};
|
package/lib/utils/pump.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export class Pump {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.held = [];
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
queue(value) {
|
|
7
|
-
this.held.push(value);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
next() {
|
|
11
|
-
const held = this.held[0];
|
|
12
|
-
if (!held) throw new Error();
|
|
13
|
-
this.held.shift();
|
|
14
|
-
return { done: false, value: held };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
[Symbol.iterator]() {
|
|
18
|
-
return this;
|
|
19
|
-
}
|
|
20
|
-
}
|
package/lib/utils/token.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { buildLiteralTag, buildGapTag } from '@bablr/agast-helpers/builders';
|
|
2
|
-
|
|
3
|
-
export const isNewlineToken = (token) => /^\r|\r\n|\n$/.test(token.value);
|
|
4
|
-
|
|
5
|
-
export function* ownChildrenFor(range) {
|
|
6
|
-
throw new Error('unimplemented');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function* allChildrenFor(range) {
|
|
10
|
-
throw new Error('unimplemented');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function* buildTokens(chrs) {
|
|
14
|
-
let str = '';
|
|
15
|
-
for (const chr of chrs) {
|
|
16
|
-
if (chr == null) {
|
|
17
|
-
if (str) {
|
|
18
|
-
yield buildLiteralTag(str);
|
|
19
|
-
str = '';
|
|
20
|
-
}
|
|
21
|
-
yield buildGapTag();
|
|
22
|
-
} else {
|
|
23
|
-
str += chr;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (str) {
|
|
28
|
-
yield buildLiteralTag(str);
|
|
29
|
-
}
|
|
30
|
-
}
|