@jbrowse/jexl 3.3.0 → 4.0.1
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/dist/Expression.js +1 -2
- package/dist/Expression.js.map +1 -1
- package/dist/Jexl.d.ts +2 -2
- package/dist/Lexer.d.ts +10 -8
- package/dist/Lexer.js +46 -35
- package/dist/Lexer.js.map +1 -1
- package/dist/evaluator/compile.d.ts +6 -4
- package/dist/evaluator/compile.js +91 -55
- package/dist/evaluator/compile.js.map +1 -1
- package/dist/grammar.js +1 -1
- package/dist/parser/Parser.d.ts +2 -9
- package/dist/parser/Parser.js +2 -12
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/handlers.d.ts +6 -3
- package/dist/parser/handlers.js +45 -28
- package/dist/parser/handlers.js.map +1 -1
- package/dist/parser/states.js +3 -5
- package/dist/parser/states.js.map +1 -1
- package/dist/types.d.ts +0 -3
- package/esm/Expression.js +1 -2
- package/esm/Expression.js.map +1 -1
- package/esm/Jexl.d.ts +2 -2
- package/esm/Lexer.d.ts +10 -8
- package/esm/Lexer.js +46 -35
- package/esm/Lexer.js.map +1 -1
- package/esm/evaluator/compile.d.ts +6 -4
- package/esm/evaluator/compile.js +91 -55
- package/esm/evaluator/compile.js.map +1 -1
- package/esm/grammar.js +1 -1
- package/esm/parser/Parser.d.ts +2 -9
- package/esm/parser/Parser.js +2 -12
- package/esm/parser/Parser.js.map +1 -1
- package/esm/parser/handlers.d.ts +6 -3
- package/esm/parser/handlers.js +45 -28
- package/esm/parser/handlers.js.map +1 -1
- package/esm/parser/states.js +3 -5
- package/esm/parser/states.js.map +1 -1
- package/esm/types.d.ts +0 -3
- package/package.json +2 -1
- package/src/Expression.ts +1 -2
- package/src/Jexl.ts +2 -2
- package/src/Lexer.ts +47 -36
- package/src/evaluator/compile.ts +108 -71
- package/src/grammar.ts +1 -1
- package/src/parser/Parser.ts +2 -13
- package/src/parser/handlers.ts +48 -31
- package/src/parser/states.ts +3 -5
- package/src/types.ts +0 -3
- package/dist/evaluator/Evaluator.d.ts +0 -37
- package/dist/evaluator/Evaluator.js +0 -49
- package/dist/evaluator/Evaluator.js.map +0 -1
- package/esm/evaluator/Evaluator.d.ts +0 -37
- package/esm/evaluator/Evaluator.js +0 -47
- package/esm/evaluator/Evaluator.js.map +0 -1
- package/src/evaluator/Evaluator.ts +0 -58
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Grammar } from '../grammar.ts';
|
|
2
2
|
import type { AstNode, JexlValue } from '../types.ts';
|
|
3
|
-
|
|
3
|
+
/** The variables an expression is evaluated against. */
|
|
4
|
+
export type Context = Record<string, JexlValue>;
|
|
4
5
|
/**
|
|
5
|
-
* An AST node lowered to a closure. Calling it with
|
|
6
|
-
*
|
|
6
|
+
* An AST node lowered to a closure. Calling it with a context produces the
|
|
7
|
+
* node's value. The grammar is captured when the closure is built, so it is not
|
|
8
|
+
* a parameter.
|
|
7
9
|
*/
|
|
8
|
-
export type CompiledNode = (
|
|
10
|
+
export type CompiledNode = (context: Context) => JexlValue;
|
|
9
11
|
/**
|
|
10
12
|
* Lowers an expression tree into a tree of closures, resolving each node's type
|
|
11
13
|
* and its operator's implementation once, at compile time, rather than
|
package/esm/evaluator/compile.js
CHANGED
|
@@ -20,6 +20,30 @@ function defineOwn(target, key, value) {
|
|
|
20
20
|
function assignOwn(target, key, value) {
|
|
21
21
|
target[key] = value;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* The key a bracket index that is neither a string nor a number reads under:
|
|
25
|
+
* its string form, when it has one worth using.
|
|
26
|
+
*
|
|
27
|
+
* A boolean and an array of primitives do — `['a']` is the key `'a'`, exactly
|
|
28
|
+
* as JS would index by it. A plain object does not, since '[object Object]' is
|
|
29
|
+
* not a key anything is stored under, so it and an array holding one answer
|
|
30
|
+
* `undefined` instead; indexing by either reached that lookup and missed
|
|
31
|
+
* anyway. null and undefined are the same case.
|
|
32
|
+
*/
|
|
33
|
+
function indexKey(value) {
|
|
34
|
+
if (typeof value === 'boolean') {
|
|
35
|
+
return String(value);
|
|
36
|
+
}
|
|
37
|
+
return Array.isArray(value) && value.every(isKeyPart)
|
|
38
|
+
? value.join(',')
|
|
39
|
+
: undefined;
|
|
40
|
+
}
|
|
41
|
+
function isKeyPart(value) {
|
|
42
|
+
return (value == null ||
|
|
43
|
+
typeof value === 'string' ||
|
|
44
|
+
typeof value === 'number' ||
|
|
45
|
+
typeof value === 'boolean');
|
|
46
|
+
}
|
|
23
47
|
/** Renders an interpolated value for a template literal. */
|
|
24
48
|
function stringify(value) {
|
|
25
49
|
if (value == null) {
|
|
@@ -63,21 +87,17 @@ export function compileAst(ast, grammar) {
|
|
|
63
87
|
case 'Identifier': {
|
|
64
88
|
const name = node.value;
|
|
65
89
|
if (!node.from) {
|
|
66
|
-
return
|
|
67
|
-
? (ev) => ev._relContext[name]
|
|
68
|
-
: (ev) => ev._context[name];
|
|
90
|
+
return (ctx) => ctx[name];
|
|
69
91
|
}
|
|
70
92
|
const from = compileAst(node.from, grammar);
|
|
71
|
-
return (
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
93
|
+
return (ctx) => {
|
|
94
|
+
const subject = from(ctx);
|
|
95
|
+
if (subject == null) {
|
|
74
96
|
return undefined;
|
|
75
97
|
}
|
|
76
98
|
// an identifier chained off an array reads through its first element
|
|
77
|
-
const
|
|
78
|
-
return
|
|
79
|
-
? undefined
|
|
80
|
-
: ctx[name];
|
|
99
|
+
const target = Array.isArray(subject) ? subject[0] : subject;
|
|
100
|
+
return target == null ? undefined : target[name];
|
|
81
101
|
};
|
|
82
102
|
}
|
|
83
103
|
case 'BinaryExpression': {
|
|
@@ -93,17 +113,17 @@ export function compileAst(ast, grammar) {
|
|
|
93
113
|
if (evalOnDemand) {
|
|
94
114
|
// operands stay unevaluated behind an `eval` thunk, so operators such
|
|
95
115
|
// as && and || can short-circuit
|
|
96
|
-
return (
|
|
116
|
+
return (ctx) => evalOnDemand({ eval: () => left(ctx) }, { eval: () => right(ctx) });
|
|
97
117
|
}
|
|
98
118
|
const fn = op.eval;
|
|
99
119
|
if (!fn) {
|
|
100
|
-
return (
|
|
101
|
-
left(
|
|
102
|
-
right(
|
|
120
|
+
return (ctx) => {
|
|
121
|
+
left(ctx);
|
|
122
|
+
right(ctx);
|
|
103
123
|
return undefined;
|
|
104
124
|
};
|
|
105
125
|
}
|
|
106
|
-
return (
|
|
126
|
+
return (ctx) => fn(left(ctx), right(ctx));
|
|
107
127
|
}
|
|
108
128
|
case 'UnaryExpression': {
|
|
109
129
|
const right = compileAst(node.right, grammar);
|
|
@@ -115,12 +135,12 @@ export function compileAst(ast, grammar) {
|
|
|
115
135
|
: undefined;
|
|
116
136
|
if (!fn) {
|
|
117
137
|
// the operand is still evaluated for an unknown operator, as before
|
|
118
|
-
return (
|
|
119
|
-
right(
|
|
138
|
+
return (ctx) => {
|
|
139
|
+
right(ctx);
|
|
120
140
|
return undefined;
|
|
121
141
|
};
|
|
122
142
|
}
|
|
123
|
-
return (
|
|
143
|
+
return (ctx) => fn(right(ctx));
|
|
124
144
|
}
|
|
125
145
|
case 'ConditionalExpression': {
|
|
126
146
|
const test = compileAst(node.test, grammar);
|
|
@@ -130,42 +150,58 @@ export function compileAst(ast, grammar) {
|
|
|
130
150
|
const alternate = node.alternate
|
|
131
151
|
? compileAst(node.alternate, grammar)
|
|
132
152
|
: undefined;
|
|
133
|
-
return (
|
|
134
|
-
const res = test(
|
|
153
|
+
return (ctx) => {
|
|
154
|
+
const res = test(ctx);
|
|
135
155
|
if (res) {
|
|
136
156
|
// an omitted consequent ("a ?: b") yields the test result
|
|
137
|
-
return consequent ? consequent(
|
|
157
|
+
return consequent ? consequent(ctx) : res;
|
|
138
158
|
}
|
|
139
|
-
return alternate ? alternate(
|
|
159
|
+
return alternate ? alternate(ctx) : undefined;
|
|
140
160
|
};
|
|
141
161
|
}
|
|
142
162
|
case 'FilterExpression': {
|
|
143
|
-
if (node.relative) {
|
|
144
|
-
// thrown on evaluation rather than compilation, as before
|
|
145
|
-
return () => {
|
|
146
|
-
throw new Error('Relative filter expressions are not supported');
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
163
|
const subject = compileAst(node.subject, grammar);
|
|
150
164
|
const index = compileAst(node.expr, grammar);
|
|
151
|
-
return (
|
|
152
|
-
const subjectVal = subject(
|
|
153
|
-
const indexVal = index(
|
|
165
|
+
return (ctx) => {
|
|
166
|
+
const subjectVal = subject(ctx);
|
|
167
|
+
const indexVal = index(ctx);
|
|
154
168
|
if (subjectVal == null) {
|
|
155
169
|
return undefined;
|
|
156
170
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
171
|
+
if (typeof indexVal === 'string' || typeof indexVal === 'number') {
|
|
172
|
+
return subjectVal[indexVal];
|
|
173
|
+
}
|
|
174
|
+
// A value with a meaningful string form is indexed by it, which is what
|
|
175
|
+
// JS does and what this did until the evaluator was lowered to closures
|
|
176
|
+
// — the tree-walking version was a bare `subject?.[index]`. Answering
|
|
177
|
+
// `undefined` for everything else reads as a deliberate strictness and
|
|
178
|
+
// is not: nothing wanted it, and the shape it rejects is common.
|
|
179
|
+
//
|
|
180
|
+
// That shape is a one-element array. Every `@gmod/vcf` INFO value is a
|
|
181
|
+
// list — `Number=1` included, so `CLNSIG=Pathogenic` parses to
|
|
182
|
+
// `['Pathogenic']` — and the natural way to colour by one is a lookup
|
|
183
|
+
// table indexed by it. The miss is silent, because such an expression
|
|
184
|
+
// always carries a `|| fallback` for the values it has no entry for,
|
|
185
|
+
// and that fallback then answers for every record.
|
|
186
|
+
//
|
|
187
|
+
// A multi-valued list still misses — `['a','b']` is the key 'a,b' —
|
|
188
|
+
// which is the honest answer rather than a lucky one: reading through
|
|
189
|
+
// to the first element would be the index guessing which value was
|
|
190
|
+
// meant. `Identifier` above does read through a one-element array, but
|
|
191
|
+
// it is navigating rather than selecting, so it has nothing to guess.
|
|
192
|
+
const key = indexKey(indexVal);
|
|
193
|
+
return key === undefined
|
|
194
|
+
? undefined
|
|
195
|
+
: subjectVal[key];
|
|
160
196
|
};
|
|
161
197
|
}
|
|
162
198
|
case 'ArrayLiteral': {
|
|
163
199
|
const items = node.value.map((item) => compileAst(item, grammar));
|
|
164
200
|
const len = items.length;
|
|
165
|
-
return (
|
|
201
|
+
return (ctx) => {
|
|
166
202
|
const out = new Array(len);
|
|
167
203
|
for (let i = 0; i < len; i++) {
|
|
168
|
-
out[i] = items[i](
|
|
204
|
+
out[i] = items[i](ctx);
|
|
169
205
|
}
|
|
170
206
|
return out;
|
|
171
207
|
};
|
|
@@ -177,10 +213,10 @@ export function compileAst(ast, grammar) {
|
|
|
177
213
|
const len = keys.length;
|
|
178
214
|
// resolved once, here, so the common case keeps its plain store
|
|
179
215
|
const store = keys.includes('__proto__') ? defineOwn : assignOwn;
|
|
180
|
-
return (
|
|
216
|
+
return (ctx) => {
|
|
181
217
|
const out = {};
|
|
182
218
|
for (let i = 0; i < len; i++) {
|
|
183
|
-
store(out, keys[i], values[i](
|
|
219
|
+
store(out, keys[i], values[i](ctx));
|
|
184
220
|
}
|
|
185
221
|
return out;
|
|
186
222
|
};
|
|
@@ -193,12 +229,12 @@ export function compileAst(ast, grammar) {
|
|
|
193
229
|
return () => value;
|
|
194
230
|
}
|
|
195
231
|
const expr = compileAst(part.value, grammar);
|
|
196
|
-
return (
|
|
232
|
+
return (ctx) => stringify(expr(ctx));
|
|
197
233
|
});
|
|
198
|
-
return (
|
|
234
|
+
return (ctx) => {
|
|
199
235
|
let out = '';
|
|
200
236
|
for (const part of parts) {
|
|
201
|
-
out += part(
|
|
237
|
+
out += part(ctx);
|
|
202
238
|
}
|
|
203
239
|
return out;
|
|
204
240
|
};
|
|
@@ -210,8 +246,8 @@ export function compileAst(ast, grammar) {
|
|
|
210
246
|
// and `constructor` aren't callable as Jexl functions. Resolved per call
|
|
211
247
|
// rather than baked in, since functions are routinely registered after
|
|
212
248
|
// an expression has been compiled.
|
|
213
|
-
const lookup = (
|
|
214
|
-
const { functions } =
|
|
249
|
+
const lookup = () => {
|
|
250
|
+
const { functions } = grammar;
|
|
215
251
|
if (!Object.hasOwn(functions, name)) {
|
|
216
252
|
throw new Error(`Jexl Function ${name} is not defined.`);
|
|
217
253
|
}
|
|
@@ -221,28 +257,28 @@ export function compileAst(ast, grammar) {
|
|
|
221
257
|
// argument array and needs no spread
|
|
222
258
|
switch (args.length) {
|
|
223
259
|
case 0: {
|
|
224
|
-
return (
|
|
260
|
+
return () => lookup()();
|
|
225
261
|
}
|
|
226
262
|
case 1: {
|
|
227
263
|
const [a0] = args;
|
|
228
|
-
return (
|
|
264
|
+
return (ctx) => lookup()(a0(ctx));
|
|
229
265
|
}
|
|
230
266
|
case 2: {
|
|
231
267
|
const [a0, a1] = args;
|
|
232
|
-
return (
|
|
268
|
+
return (ctx) => lookup()(a0(ctx), a1(ctx));
|
|
233
269
|
}
|
|
234
270
|
case 3: {
|
|
235
271
|
const [a0, a1, a2] = args;
|
|
236
|
-
return (
|
|
272
|
+
return (ctx) => lookup()(a0(ctx), a1(ctx), a2(ctx));
|
|
237
273
|
}
|
|
238
274
|
default: {
|
|
239
275
|
const len = args.length;
|
|
240
|
-
return (
|
|
276
|
+
return (ctx) => {
|
|
241
277
|
const vals = new Array(len);
|
|
242
278
|
for (let i = 0; i < len; i++) {
|
|
243
|
-
vals[i] = args[i](
|
|
279
|
+
vals[i] = args[i](ctx);
|
|
244
280
|
}
|
|
245
|
-
return lookup(
|
|
281
|
+
return lookup()(...vals);
|
|
246
282
|
};
|
|
247
283
|
}
|
|
248
284
|
}
|
|
@@ -250,10 +286,10 @@ export function compileAst(ast, grammar) {
|
|
|
250
286
|
case 'SequenceExpression': {
|
|
251
287
|
const exprs = node.expressions.map((expr) => compileAst(expr, grammar));
|
|
252
288
|
const len = exprs.length;
|
|
253
|
-
return (
|
|
289
|
+
return (ctx) => {
|
|
254
290
|
let last;
|
|
255
291
|
for (let i = 0; i < len; i++) {
|
|
256
|
-
last = exprs[i](
|
|
292
|
+
last = exprs[i](ctx);
|
|
257
293
|
}
|
|
258
294
|
return last;
|
|
259
295
|
};
|
|
@@ -262,9 +298,9 @@ export function compileAst(ast, grammar) {
|
|
|
262
298
|
const name = node.left.value;
|
|
263
299
|
const right = compileAst(node.right, grammar);
|
|
264
300
|
const store = name === '__proto__' ? defineOwn : assignOwn;
|
|
265
|
-
return (
|
|
266
|
-
const value = right(
|
|
267
|
-
store(
|
|
301
|
+
return (ctx) => {
|
|
302
|
+
const value = right(ctx);
|
|
303
|
+
store(ctx, name, value);
|
|
268
304
|
return value;
|
|
269
305
|
};
|
|
270
306
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/evaluator/compile.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/evaluator/compile.ts"],"names":[],"mappings":"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"}
|
package/esm/grammar.js
CHANGED
|
@@ -150,7 +150,7 @@ export const getGrammar = () => ({
|
|
|
150
150
|
},
|
|
151
151
|
/**
|
|
152
152
|
* A map of function names to javascript functions. A Jexl function
|
|
153
|
-
* takes zero
|
|
153
|
+
* takes zero or more arguments:
|
|
154
154
|
*
|
|
155
155
|
* - {*} ...args: A variable number of arguments passed to this function.
|
|
156
156
|
* All of these are pre-evaluated to their actual values before calling
|
package/esm/parser/Parser.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { AstNode, Token } from '../types.ts';
|
|
|
4
4
|
/**
|
|
5
5
|
* The Parser is a state machine that converts tokens from the {@link Lexer}
|
|
6
6
|
* into an Abstract Syntax Tree (AST), capable of being evaluated in any
|
|
7
|
-
* context by
|
|
7
|
+
* context by {@link compileAst}. The Parser expects that all tokens
|
|
8
8
|
* provided to it are legal and typed properly according to the grammar, but
|
|
9
9
|
* accepts that the tokens may still be in an invalid order or in some other
|
|
10
10
|
* unparsable configuration that requires it to throw an Error.
|
|
@@ -24,13 +24,11 @@ declare class Parser {
|
|
|
24
24
|
_state: string;
|
|
25
25
|
_tree: AstNode | null;
|
|
26
26
|
_exprStr: string;
|
|
27
|
-
_relative: boolean;
|
|
28
27
|
_stopMap: Record<string, string>;
|
|
29
28
|
_cursor?: AstNode | null;
|
|
30
29
|
_subParser?: Parser;
|
|
31
30
|
_parentStop?: boolean;
|
|
32
31
|
_nextIdentEncapsulate?: boolean;
|
|
33
|
-
_nextIdentRelative?: boolean;
|
|
34
32
|
_curObjKey?: string;
|
|
35
33
|
_sequenceExpressions?: AstNode[];
|
|
36
34
|
constructor(grammar: Grammar, lexer: Lexer, prefix?: string, stopMap?: Record<string, string>);
|
|
@@ -55,17 +53,12 @@ declare class Parser {
|
|
|
55
53
|
/**
|
|
56
54
|
* Marks this Parser instance as completed and retrieves the full AST.
|
|
57
55
|
* @returns {{}|null} a full expression tree, ready for evaluation by the
|
|
58
|
-
* {@link
|
|
56
|
+
* {@link compileAst} function, or null if no tokens were passed to
|
|
59
57
|
* the parser before complete was called
|
|
60
58
|
* @throws {Error} if the parser is not in a state where it's legal to end
|
|
61
59
|
* the expression, indicating that the expression is incomplete
|
|
62
60
|
*/
|
|
63
61
|
complete(): AstNode | null;
|
|
64
|
-
/**
|
|
65
|
-
* Indicates whether the expression tree contains a relative path identifier.
|
|
66
|
-
* @returns {boolean} true if a relative identifier exists false otherwise.
|
|
67
|
-
*/
|
|
68
|
-
isRelative(): boolean;
|
|
69
62
|
/**
|
|
70
63
|
* Ends a subexpression by completing the subParser and passing its result
|
|
71
64
|
* to the subHandler configured in the current state.
|
package/esm/parser/Parser.js
CHANGED
|
@@ -22,7 +22,7 @@ const tokenHandlers = {
|
|
|
22
22
|
/**
|
|
23
23
|
* The Parser is a state machine that converts tokens from the {@link Lexer}
|
|
24
24
|
* into an Abstract Syntax Tree (AST), capable of being evaluated in any
|
|
25
|
-
* context by
|
|
25
|
+
* context by {@link compileAst}. The Parser expects that all tokens
|
|
26
26
|
* provided to it are legal and typed properly according to the grammar, but
|
|
27
27
|
* accepts that the tokens may still be in an invalid order or in some other
|
|
28
28
|
* unparsable configuration that requires it to throw an Error.
|
|
@@ -42,13 +42,11 @@ class Parser {
|
|
|
42
42
|
_state;
|
|
43
43
|
_tree;
|
|
44
44
|
_exprStr;
|
|
45
|
-
_relative;
|
|
46
45
|
_stopMap;
|
|
47
46
|
_cursor;
|
|
48
47
|
_subParser;
|
|
49
48
|
_parentStop;
|
|
50
49
|
_nextIdentEncapsulate;
|
|
51
|
-
_nextIdentRelative;
|
|
52
50
|
_curObjKey;
|
|
53
51
|
_sequenceExpressions;
|
|
54
52
|
constructor(grammar, lexer, prefix, stopMap) {
|
|
@@ -57,7 +55,6 @@ class Parser {
|
|
|
57
55
|
this._state = 'expectOperand';
|
|
58
56
|
this._tree = null;
|
|
59
57
|
this._exprStr = prefix || '';
|
|
60
|
-
this._relative = false;
|
|
61
58
|
this._stopMap = stopMap || {};
|
|
62
59
|
}
|
|
63
60
|
/**
|
|
@@ -128,7 +125,7 @@ class Parser {
|
|
|
128
125
|
/**
|
|
129
126
|
* Marks this Parser instance as completed and retrieves the full AST.
|
|
130
127
|
* @returns {{}|null} a full expression tree, ready for evaluation by the
|
|
131
|
-
* {@link
|
|
128
|
+
* {@link compileAst} function, or null if no tokens were passed to
|
|
132
129
|
* the parser before complete was called
|
|
133
130
|
* @throws {Error} if the parser is not in a state where it's legal to end
|
|
134
131
|
* the expression, indicating that the expression is incomplete
|
|
@@ -159,13 +156,6 @@ class Parser {
|
|
|
159
156
|
this._state = 'complete';
|
|
160
157
|
return this._cursor ? this._tree : null;
|
|
161
158
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Indicates whether the expression tree contains a relative path identifier.
|
|
164
|
-
* @returns {boolean} true if a relative identifier exists false otherwise.
|
|
165
|
-
*/
|
|
166
|
-
isRelative() {
|
|
167
|
-
return this._relative;
|
|
168
|
-
}
|
|
169
159
|
/**
|
|
170
160
|
* Ends a subexpression by completing the subParser and passing its result
|
|
171
161
|
* to the subHandler configured in the current state.
|
package/esm/parser/Parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../src/parser/Parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMpC;;;;;GAKG;AACH,MAAM,aAAa,GAGf;IACF,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,GAAG,EAAE,QAAQ,CAAC,GAAG;IACjB,UAAU,EAAE,QAAQ,CAAC,UAAU;IAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;IACzB,SAAS,EAAE,QAAQ,CAAC,SAAS;IAC7B,cAAc,EAAE,QAAQ,CAAC,cAAc;IACvC,OAAO,EAAE,QAAQ,CAAC,OAAO;CAC1B,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM;IACV,QAAQ,CAAS;IACjB,MAAM,CAAO;IACb,MAAM,CAAQ;IACd,KAAK,CAAgB;IACrB,QAAQ,CAAQ;IAChB,
|
|
1
|
+
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../src/parser/Parser.ts"],"names":[],"mappings":"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"}
|
package/esm/parser/handlers.d.ts
CHANGED
|
@@ -95,9 +95,12 @@ export declare function ternaryEnd(this: Parser, ast: AstNode | null): void;
|
|
|
95
95
|
*/
|
|
96
96
|
export declare function ternaryMid(this: Parser, ast: AstNode | null): void;
|
|
97
97
|
/**
|
|
98
|
-
* Handles the start of a new ternary expression by encapsulating the
|
|
99
|
-
*
|
|
100
|
-
*
|
|
98
|
+
* Handles the start of a new ternary expression by encapsulating the tree so
|
|
99
|
+
* far in a ConditionalExpression node, and using it as the test element.
|
|
100
|
+
*
|
|
101
|
+
* Every operator binds tighter than the conditional and so belongs in the test
|
|
102
|
+
* — except `=`, which binds looser. `x = a ? b : c` therefore assigns the
|
|
103
|
+
* conditional rather than testing the assignment, which had stored `a` in `x`.
|
|
101
104
|
*/
|
|
102
105
|
export declare function ternaryStart(this: Parser): void;
|
|
103
106
|
/**
|
package/esm/parser/handlers.js
CHANGED
|
@@ -45,7 +45,7 @@ export function arrayVal(ast) {
|
|
|
45
45
|
export function binaryOp(token) {
|
|
46
46
|
if (token.value === '=') {
|
|
47
47
|
// `from` marks a member access such as `a.b`; only a bare name can be
|
|
48
|
-
// assigned to, since the
|
|
48
|
+
// assigned to, since the compiled closure writes straight into the context
|
|
49
49
|
if (this._cursor?.type !== 'Identifier' ||
|
|
50
50
|
this._cursor.from) {
|
|
51
51
|
throw new Error('Left side of assignment must be a variable name');
|
|
@@ -67,7 +67,14 @@ export function binaryOp(token) {
|
|
|
67
67
|
if (!parentExpr.operator) {
|
|
68
68
|
break;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
// a prefix operator binds tighter than any binary one, so `-x ^ 2` groups
|
|
71
|
+
// as `(-x) ^ 2` — the same way `-2 ^ 2` already does, since the Lexer folds
|
|
72
|
+
// that sign into the literal. Looking `-` up in the grammar finds its
|
|
73
|
+
// binary precedence instead, which is lower than `^`'s and gave `-(x ^ 2)`
|
|
74
|
+
const parentPrecedence = parent.type === 'UnaryExpression'
|
|
75
|
+
? Infinity
|
|
76
|
+
: precedenceOf(this._grammar.elements[parentExpr.operator]);
|
|
77
|
+
if (parentPrecedence < precedence) {
|
|
71
78
|
break;
|
|
72
79
|
}
|
|
73
80
|
this._cursor = parent;
|
|
@@ -89,17 +96,18 @@ export function binaryOp(token) {
|
|
|
89
96
|
*/
|
|
90
97
|
export function dot() {
|
|
91
98
|
const cursor = this._cursor;
|
|
92
|
-
//
|
|
93
|
-
// still waiting on its right-hand side
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
this.
|
|
99
|
+
// a dot continues an identifier chain. With nothing to continue — no cursor,
|
|
100
|
+
// or an operator still waiting on its right-hand side — it would instead open
|
|
101
|
+
// a relative path, the leading dot of `list[.price > 5]`. This fork removed
|
|
102
|
+
// array filtering expressions, which are the only construct that gives a
|
|
103
|
+
// relative path a root to resolve against, so it is rejected here rather than
|
|
104
|
+
// parsed into a tree that can only fail once it is evaluated.
|
|
105
|
+
if (!cursor ||
|
|
106
|
+
cursor.type === 'UnaryExpression' ||
|
|
107
|
+
(cursor.type === 'BinaryExpression' && !cursor.right)) {
|
|
108
|
+
throw new Error(`Relative paths are not supported: ${this._exprStr}`);
|
|
102
109
|
}
|
|
110
|
+
this._nextIdentEncapsulate = true;
|
|
103
111
|
}
|
|
104
112
|
/**
|
|
105
113
|
* Handles a subexpression used for filtering an array returned by an
|
|
@@ -110,7 +118,6 @@ export function filter(ast) {
|
|
|
110
118
|
const node = {
|
|
111
119
|
type: 'FilterExpression',
|
|
112
120
|
expr: ast,
|
|
113
|
-
relative: this._subParser.isRelative(),
|
|
114
121
|
subject: this._cursor
|
|
115
122
|
};
|
|
116
123
|
this._placeBeforeCursor(node);
|
|
@@ -133,12 +140,11 @@ export function functionCall() {
|
|
|
133
140
|
// there is nothing to look up in the function pool
|
|
134
141
|
throw new Error(`Functions must be called by name: ${this._exprStr}`);
|
|
135
142
|
}
|
|
136
|
-
const { from } = cursor;
|
|
143
|
+
const { from, value } = cursor;
|
|
137
144
|
const node = {
|
|
138
145
|
type: 'FunctionCall',
|
|
139
|
-
name:
|
|
140
|
-
args: from ? [from] : []
|
|
141
|
-
pool: 'functions'
|
|
146
|
+
name: value,
|
|
147
|
+
args: from ? [from] : []
|
|
142
148
|
};
|
|
143
149
|
this._placeBeforeCursor(node);
|
|
144
150
|
}
|
|
@@ -157,10 +163,6 @@ export function identifier(token) {
|
|
|
157
163
|
this._nextIdentEncapsulate = false;
|
|
158
164
|
}
|
|
159
165
|
else {
|
|
160
|
-
if (this._nextIdentRelative) {
|
|
161
|
-
node.relative = true;
|
|
162
|
-
this._nextIdentRelative = false;
|
|
163
|
-
}
|
|
164
166
|
this._placeAtCursor(node);
|
|
165
167
|
}
|
|
166
168
|
}
|
|
@@ -237,7 +239,7 @@ export function objStart() {
|
|
|
237
239
|
export function objVal(ast) {
|
|
238
240
|
// defined rather than assigned so that the key "__proto__" becomes an
|
|
239
241
|
// ordinary entry of the node's key map instead of re-pointing its prototype,
|
|
240
|
-
// which dropped the entry before
|
|
242
|
+
// which dropped the entry before it could be compiled
|
|
241
243
|
Object.defineProperty(this._cursor.value, this._curObjKey, {
|
|
242
244
|
value: ast,
|
|
243
245
|
writable: true,
|
|
@@ -270,17 +272,32 @@ export function ternaryMid(ast) {
|
|
|
270
272
|
this._cursor.consequent = ast ?? undefined;
|
|
271
273
|
}
|
|
272
274
|
/**
|
|
273
|
-
* Handles the start of a new ternary expression by encapsulating the
|
|
274
|
-
*
|
|
275
|
-
*
|
|
275
|
+
* Handles the start of a new ternary expression by encapsulating the tree so
|
|
276
|
+
* far in a ConditionalExpression node, and using it as the test element.
|
|
277
|
+
*
|
|
278
|
+
* Every operator binds tighter than the conditional and so belongs in the test
|
|
279
|
+
* — except `=`, which binds looser. `x = a ? b : c` therefore assigns the
|
|
280
|
+
* conditional rather than testing the assignment, which had stored `a` in `x`.
|
|
276
281
|
*/
|
|
277
282
|
export function ternaryStart() {
|
|
283
|
+
let assignment;
|
|
284
|
+
let test = this._tree;
|
|
285
|
+
while (test.type === 'AssignmentExpression' && test.right) {
|
|
286
|
+
assignment = test;
|
|
287
|
+
test = test.right;
|
|
288
|
+
}
|
|
278
289
|
const node = {
|
|
279
290
|
type: 'ConditionalExpression',
|
|
280
|
-
test
|
|
291
|
+
test
|
|
281
292
|
};
|
|
282
|
-
|
|
283
|
-
|
|
293
|
+
if (assignment) {
|
|
294
|
+
assignment.right = node;
|
|
295
|
+
this._setParent(node, assignment);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
this._tree = node;
|
|
299
|
+
}
|
|
300
|
+
this._cursor = node;
|
|
284
301
|
}
|
|
285
302
|
/**
|
|
286
303
|
* Handles token of type 'unaryOp', indicating that the operation has only
|