@jbrowse/jexl 3.0.2 → 3.1.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/README.md +11 -2
- package/dist/Expression.d.ts +16 -6
- package/dist/Expression.js +34 -8
- package/dist/Expression.js.map +1 -1
- package/dist/Jexl.d.ts +13 -12
- package/dist/Jexl.js +31 -30
- package/dist/Jexl.js.map +1 -1
- package/dist/Lexer.d.ts +9 -8
- package/dist/Lexer.js +58 -18
- package/dist/Lexer.js.map +1 -1
- package/dist/evaluator/Evaluator.d.ts +20 -34
- package/dist/evaluator/Evaluator.js +19 -64
- package/dist/evaluator/Evaluator.js.map +1 -1
- package/dist/evaluator/compile.d.ts +27 -0
- package/dist/evaluator/compile.js +261 -0
- package/dist/evaluator/compile.js.map +1 -0
- package/dist/grammar.d.ts +29 -9
- package/dist/grammar.js +19 -3
- package/dist/grammar.js.map +1 -1
- package/dist/parser/Parser.d.ts +5 -7
- package/dist/parser/Parser.js +17 -2
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/handlers.d.ts +0 -6
- package/dist/parser/handlers.js +54 -46
- package/dist/parser/handlers.js.map +1 -1
- package/dist/parser/states.d.ts +2 -2
- package/dist/parser/states.js +0 -20
- package/dist/parser/states.js.map +1 -1
- package/dist/types.d.ts +18 -7
- package/esm/Expression.d.ts +16 -6
- package/esm/Expression.js +34 -8
- package/esm/Expression.js.map +1 -1
- package/esm/Jexl.d.ts +13 -12
- package/esm/Jexl.js +31 -30
- package/esm/Jexl.js.map +1 -1
- package/esm/Lexer.d.ts +9 -8
- package/esm/Lexer.js +58 -18
- package/esm/Lexer.js.map +1 -1
- package/esm/evaluator/Evaluator.d.ts +20 -34
- package/esm/evaluator/Evaluator.js +19 -31
- package/esm/evaluator/Evaluator.js.map +1 -1
- package/esm/evaluator/compile.d.ts +27 -0
- package/esm/evaluator/compile.js +258 -0
- package/esm/evaluator/compile.js.map +1 -0
- package/esm/grammar.d.ts +29 -9
- package/esm/grammar.js +18 -3
- package/esm/grammar.js.map +1 -1
- package/esm/parser/Parser.d.ts +5 -7
- package/esm/parser/Parser.js +17 -2
- package/esm/parser/Parser.js.map +1 -1
- package/esm/parser/handlers.d.ts +0 -6
- package/esm/parser/handlers.js +54 -45
- package/esm/parser/handlers.js.map +1 -1
- package/esm/parser/states.d.ts +2 -2
- package/esm/parser/states.js +0 -20
- package/esm/parser/states.js.map +1 -1
- package/esm/types.d.ts +18 -7
- package/package.json +25 -28
- package/src/Expression.ts +33 -13
- package/src/Jexl.ts +59 -21
- package/src/Lexer.ts +60 -27
- package/src/evaluator/Evaluator.ts +27 -44
- package/src/evaluator/compile.ts +310 -0
- package/src/grammar.ts +66 -17
- package/src/parser/Parser.ts +24 -20
- package/src/parser/handlers.ts +96 -73
- package/src/parser/states.ts +2 -22
- package/src/types.ts +22 -7
- package/CHANGELOG.md +0 -249
- package/dist/evaluator/handlers.d.ts +0 -112
- package/dist/evaluator/handlers.js +0 -208
- package/dist/evaluator/handlers.js.map +0 -1
- package/esm/evaluator/handlers.d.ts +0 -112
- package/esm/evaluator/handlers.js +0 -194
- package/esm/evaluator/handlers.js.map +0 -1
- package/src/evaluator/handlers.ts +0 -212
|
@@ -94,12 +94,6 @@ export declare function ternaryMid(this: Parser, ast: AstNode | null): void;
|
|
|
94
94
|
* test element.
|
|
95
95
|
*/
|
|
96
96
|
export declare function ternaryStart(this: Parser): void;
|
|
97
|
-
/**
|
|
98
|
-
* Handles identifier tokens when used to indicate the name of a transform to
|
|
99
|
-
* be applied.
|
|
100
|
-
* @param {{type: <string>}} token A token object
|
|
101
|
-
*/
|
|
102
|
-
export declare function transform(this: Parser, token: Token): void;
|
|
103
97
|
/**
|
|
104
98
|
* Handles token of type 'unaryOp', indicating that the operation has only
|
|
105
99
|
* one input: a right side.
|
package/dist/parser/handlers.js
CHANGED
|
@@ -21,9 +21,9 @@ exports.subExpression = subExpression;
|
|
|
21
21
|
exports.ternaryEnd = ternaryEnd;
|
|
22
22
|
exports.ternaryMid = ternaryMid;
|
|
23
23
|
exports.ternaryStart = ternaryStart;
|
|
24
|
-
exports.transform = transform;
|
|
25
24
|
exports.unaryOp = unaryOp;
|
|
26
25
|
exports.semicolon = semicolon;
|
|
26
|
+
const grammar_ts_1 = require("../grammar.js");
|
|
27
27
|
/**
|
|
28
28
|
* Handles a subexpression that's used to define a transform argument's value.
|
|
29
29
|
* @param {{type: <string>}} ast The subexpression tree
|
|
@@ -39,10 +39,11 @@ function argVal(ast) {
|
|
|
39
39
|
* initialized with an empty array.
|
|
40
40
|
*/
|
|
41
41
|
function arrayStart() {
|
|
42
|
-
|
|
42
|
+
const node = {
|
|
43
43
|
type: 'ArrayLiteral',
|
|
44
44
|
value: []
|
|
45
|
-
}
|
|
45
|
+
};
|
|
46
|
+
this._placeAtCursor(node);
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Handles a subexpression representing an element of an array literal.
|
|
@@ -61,7 +62,10 @@ function arrayVal(ast) {
|
|
|
61
62
|
*/
|
|
62
63
|
function binaryOp(token) {
|
|
63
64
|
if (token.value === '=') {
|
|
64
|
-
|
|
65
|
+
// `from` marks a member access such as `a.b`; only a bare name can be
|
|
66
|
+
// assigned to, since the Evaluator writes straight into the context
|
|
67
|
+
if (this._cursor?.type !== 'Identifier' ||
|
|
68
|
+
this._cursor.from) {
|
|
65
69
|
throw new Error('Left side of assignment must be a variable name');
|
|
66
70
|
}
|
|
67
71
|
const node = {
|
|
@@ -73,17 +77,23 @@ function binaryOp(token) {
|
|
|
73
77
|
this._placeAtCursor(node);
|
|
74
78
|
return;
|
|
75
79
|
}
|
|
76
|
-
const
|
|
80
|
+
const tokenValue = token.value;
|
|
81
|
+
const precedence = (0, grammar_ts_1.precedenceOf)(this._grammar.elements[tokenValue]);
|
|
77
82
|
let parent = this._cursor?._parent;
|
|
78
|
-
while (parent
|
|
79
|
-
parent
|
|
80
|
-
|
|
83
|
+
while (parent) {
|
|
84
|
+
const parentExpr = parent;
|
|
85
|
+
if (!parentExpr.operator) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if ((0, grammar_ts_1.precedenceOf)(this._grammar.elements[parentExpr.operator]) < precedence) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
81
91
|
this._cursor = parent;
|
|
82
92
|
parent = parent._parent;
|
|
83
93
|
}
|
|
84
94
|
const node = {
|
|
85
95
|
type: 'BinaryExpression',
|
|
86
|
-
operator:
|
|
96
|
+
operator: tokenValue,
|
|
87
97
|
left: this._cursor
|
|
88
98
|
};
|
|
89
99
|
this._setParent(this._cursor, node);
|
|
@@ -96,13 +106,15 @@ function binaryOp(token) {
|
|
|
96
106
|
* AST.
|
|
97
107
|
*/
|
|
98
108
|
function dot() {
|
|
99
|
-
const
|
|
109
|
+
const cursor = this._cursor;
|
|
110
|
+
// the dot continues an identifier chain unless the cursor is an operator
|
|
111
|
+
// still waiting on its right-hand side, in which case it opens a relative
|
|
112
|
+
// path instead — as in the leading dot of `list[.price > 5]`
|
|
100
113
|
this._nextIdentEncapsulate =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(
|
|
104
|
-
|
|
105
|
-
this._nextIdentRelative = !this._cursor || !this._nextIdentEncapsulate;
|
|
114
|
+
!!cursor &&
|
|
115
|
+
cursor.type !== 'UnaryExpression' &&
|
|
116
|
+
(cursor.type !== 'BinaryExpression' || !!cursor.right);
|
|
117
|
+
this._nextIdentRelative = !this._nextIdentEncapsulate;
|
|
106
118
|
if (this._nextIdentRelative) {
|
|
107
119
|
this._relative = true;
|
|
108
120
|
}
|
|
@@ -113,12 +125,13 @@ function dot() {
|
|
|
113
125
|
* @param {{type: <string>}} ast The subexpression tree
|
|
114
126
|
*/
|
|
115
127
|
function filter(ast) {
|
|
116
|
-
|
|
128
|
+
const node = {
|
|
117
129
|
type: 'FilterExpression',
|
|
118
130
|
expr: ast,
|
|
119
131
|
relative: this._subParser.isRelative(),
|
|
120
132
|
subject: this._cursor
|
|
121
|
-
}
|
|
133
|
+
};
|
|
134
|
+
this._placeBeforeCursor(node);
|
|
122
135
|
}
|
|
123
136
|
/**
|
|
124
137
|
* Handles identifier tokens when used to indicate the name of a function to
|
|
@@ -126,12 +139,13 @@ function filter(ast) {
|
|
|
126
139
|
* @param {{type: <string>}} token A token object
|
|
127
140
|
*/
|
|
128
141
|
function functionCall() {
|
|
129
|
-
|
|
142
|
+
const node = {
|
|
130
143
|
type: 'FunctionCall',
|
|
131
144
|
name: this._cursor.value,
|
|
132
145
|
args: [],
|
|
133
146
|
pool: 'functions'
|
|
134
|
-
}
|
|
147
|
+
};
|
|
148
|
+
this._placeBeforeCursor(node);
|
|
135
149
|
}
|
|
136
150
|
/**
|
|
137
151
|
* Handles identifier tokens by adding them as a new node in the AST.
|
|
@@ -161,10 +175,11 @@ function identifier(token) {
|
|
|
161
175
|
* @param {{type: <string>}} token A token object
|
|
162
176
|
*/
|
|
163
177
|
function literal(token) {
|
|
164
|
-
|
|
178
|
+
const node = {
|
|
165
179
|
type: 'Literal',
|
|
166
180
|
value: token.value
|
|
167
|
-
}
|
|
181
|
+
};
|
|
182
|
+
this._placeAtCursor(node);
|
|
168
183
|
}
|
|
169
184
|
/**
|
|
170
185
|
* Handles template string tokens by parsing their interpolation expressions
|
|
@@ -173,7 +188,8 @@ function literal(token) {
|
|
|
173
188
|
*/
|
|
174
189
|
function templateString(token) {
|
|
175
190
|
const parts = [];
|
|
176
|
-
|
|
191
|
+
const tokenParts = Array.isArray(token.value) ? token.value : [];
|
|
192
|
+
for (const part of tokenParts) {
|
|
177
193
|
if (part.type === 'static') {
|
|
178
194
|
parts.push({
|
|
179
195
|
type: 'static',
|
|
@@ -182,7 +198,8 @@ function templateString(token) {
|
|
|
182
198
|
}
|
|
183
199
|
else {
|
|
184
200
|
const subTokens = this._lexer.tokenize(part.value);
|
|
185
|
-
const
|
|
201
|
+
const ParserClass = this.constructor;
|
|
202
|
+
const subParser = new ParserClass(this._grammar, this._lexer);
|
|
186
203
|
subParser.addTokens(subTokens);
|
|
187
204
|
const subAst = subParser.complete();
|
|
188
205
|
if (!subAst) {
|
|
@@ -194,10 +211,11 @@ function templateString(token) {
|
|
|
194
211
|
});
|
|
195
212
|
}
|
|
196
213
|
}
|
|
197
|
-
|
|
214
|
+
const node = {
|
|
198
215
|
type: 'TemplateLiteral',
|
|
199
|
-
parts
|
|
200
|
-
}
|
|
216
|
+
parts
|
|
217
|
+
};
|
|
218
|
+
this._placeAtCursor(node);
|
|
201
219
|
}
|
|
202
220
|
/**
|
|
203
221
|
* Queues a new object literal key to be written once a value is collected.
|
|
@@ -211,10 +229,11 @@ function objKey(token) {
|
|
|
211
229
|
* initialized with an empty object.
|
|
212
230
|
*/
|
|
213
231
|
function objStart() {
|
|
214
|
-
|
|
232
|
+
const node = {
|
|
215
233
|
type: 'ObjectLiteral',
|
|
216
234
|
value: {}
|
|
217
|
-
}
|
|
235
|
+
};
|
|
236
|
+
this._placeAtCursor(node);
|
|
218
237
|
}
|
|
219
238
|
/**
|
|
220
239
|
* Handles an object value by adding its AST to the queued key on the object
|
|
@@ -239,7 +258,7 @@ function subExpression(ast) {
|
|
|
239
258
|
*/
|
|
240
259
|
function ternaryEnd(ast) {
|
|
241
260
|
;
|
|
242
|
-
this._cursor.alternate = ast;
|
|
261
|
+
this._cursor.alternate = ast ?? undefined;
|
|
243
262
|
}
|
|
244
263
|
/**
|
|
245
264
|
* Handles a completed consequent subexpression of a ternary operator.
|
|
@@ -247,7 +266,7 @@ function ternaryEnd(ast) {
|
|
|
247
266
|
*/
|
|
248
267
|
function ternaryMid(ast) {
|
|
249
268
|
;
|
|
250
|
-
this._cursor.consequent = ast;
|
|
269
|
+
this._cursor.consequent = ast ?? undefined;
|
|
251
270
|
}
|
|
252
271
|
/**
|
|
253
272
|
* Handles the start of a new ternary expression by encapsulating the entire
|
|
@@ -255,35 +274,24 @@ function ternaryMid(ast) {
|
|
|
255
274
|
* test element.
|
|
256
275
|
*/
|
|
257
276
|
function ternaryStart() {
|
|
258
|
-
|
|
277
|
+
const node = {
|
|
259
278
|
type: 'ConditionalExpression',
|
|
260
279
|
test: this._tree
|
|
261
280
|
};
|
|
281
|
+
this._tree = node;
|
|
262
282
|
this._cursor = this._tree;
|
|
263
283
|
}
|
|
264
|
-
/**
|
|
265
|
-
* Handles identifier tokens when used to indicate the name of a transform to
|
|
266
|
-
* be applied.
|
|
267
|
-
* @param {{type: <string>}} token A token object
|
|
268
|
-
*/
|
|
269
|
-
function transform(token) {
|
|
270
|
-
this._placeBeforeCursor({
|
|
271
|
-
type: 'FunctionCall',
|
|
272
|
-
name: token.value,
|
|
273
|
-
args: [this._cursor],
|
|
274
|
-
pool: 'transforms'
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
284
|
/**
|
|
278
285
|
* Handles token of type 'unaryOp', indicating that the operation has only
|
|
279
286
|
* one input: a right side.
|
|
280
287
|
* @param {{type: <string>}} token A token object
|
|
281
288
|
*/
|
|
282
289
|
function unaryOp(token) {
|
|
283
|
-
|
|
290
|
+
const node = {
|
|
284
291
|
type: 'UnaryExpression',
|
|
285
292
|
operator: token.value
|
|
286
|
-
}
|
|
293
|
+
};
|
|
294
|
+
this._placeAtCursor(node);
|
|
287
295
|
}
|
|
288
296
|
/**
|
|
289
297
|
* Handles semicolon separator between expressions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/parser/states.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { AstNode } from '../types.ts';
|
|
1
|
+
import type { AstNode, Token } from '../types.ts';
|
|
2
2
|
import type Parser from './Parser.ts';
|
|
3
3
|
interface TokenTypeOptions {
|
|
4
4
|
toState?: string;
|
|
5
|
-
handler?: (this: Parser,
|
|
5
|
+
handler?: (this: Parser, token: Token) => void;
|
|
6
6
|
}
|
|
7
7
|
interface StateDefinition {
|
|
8
8
|
tokenTypes?: Record<string, TokenTypeOptions>;
|
package/dist/parser/states.js
CHANGED
|
@@ -87,7 +87,6 @@ exports.states = {
|
|
|
87
87
|
expectBinOp: {
|
|
88
88
|
tokenTypes: {
|
|
89
89
|
binaryOp: { toState: 'expectOperand' },
|
|
90
|
-
pipe: { toState: 'expectTransform' },
|
|
91
90
|
dot: { toState: 'traverse' },
|
|
92
91
|
openBracket: { toState: 'filter' },
|
|
93
92
|
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
@@ -95,11 +94,6 @@ exports.states = {
|
|
|
95
94
|
},
|
|
96
95
|
completable: true
|
|
97
96
|
},
|
|
98
|
-
expectTransform: {
|
|
99
|
-
tokenTypes: {
|
|
100
|
-
identifier: { toState: 'postTransform', handler: h.transform }
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
97
|
expectObjKey: {
|
|
104
98
|
tokenTypes: {
|
|
105
99
|
literal: { toState: 'expectKeyValSep', handler: h.objKey },
|
|
@@ -112,24 +106,11 @@ exports.states = {
|
|
|
112
106
|
colon: { toState: 'objVal' }
|
|
113
107
|
}
|
|
114
108
|
},
|
|
115
|
-
postTransform: {
|
|
116
|
-
tokenTypes: {
|
|
117
|
-
openParen: { toState: 'argVal' },
|
|
118
|
-
binaryOp: { toState: 'expectOperand' },
|
|
119
|
-
dot: { toState: 'traverse' },
|
|
120
|
-
openBracket: { toState: 'filter' },
|
|
121
|
-
pipe: { toState: 'expectTransform' },
|
|
122
|
-
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
123
|
-
semicolon: { handler: h.semicolon }
|
|
124
|
-
},
|
|
125
|
-
completable: true
|
|
126
|
-
},
|
|
127
109
|
postArgs: {
|
|
128
110
|
tokenTypes: {
|
|
129
111
|
binaryOp: { toState: 'expectOperand' },
|
|
130
112
|
dot: { toState: 'traverse' },
|
|
131
113
|
openBracket: { toState: 'filter' },
|
|
132
|
-
pipe: { toState: 'expectTransform' },
|
|
133
114
|
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
134
115
|
semicolon: { handler: h.semicolon }
|
|
135
116
|
},
|
|
@@ -141,7 +122,6 @@ exports.states = {
|
|
|
141
122
|
dot: { toState: 'traverse' },
|
|
142
123
|
openBracket: { toState: 'filter' },
|
|
143
124
|
openParen: { toState: 'argVal', handler: h.functionCall },
|
|
144
|
-
pipe: { toState: 'expectTransform' },
|
|
145
125
|
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
146
126
|
semicolon: { handler: h.semicolon }
|
|
147
127
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/parser/states.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,iDAAkC;AAmBlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACU,QAAA,MAAM,GAAW;IAC5B,aAAa,EAAE;QACb,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE;YACnC,cAAc,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE;YAC1C,UAAU,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE;YACrC,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE;YACvC,QAAQ,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;YAC1D,GAAG,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;YAC5B,WAAW,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,UAAU,EAAE;SAC5D;KACF;IACD,WAAW,EAAE;QACX,UAAU,EAAE;YACV,QAAQ,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE;YACtC,
|
|
1
|
+
{"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/parser/states.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
export interface TemplatePart {
|
|
2
|
+
type: 'static' | 'interpolation';
|
|
3
|
+
value: string;
|
|
4
|
+
}
|
|
5
|
+
export type JexlValue = string | number | boolean | null | undefined | JexlValue[] | {
|
|
6
|
+
[key: string]: JexlValue;
|
|
7
|
+
};
|
|
1
8
|
export interface Token {
|
|
2
9
|
type: string;
|
|
3
|
-
value:
|
|
10
|
+
value: string | number | boolean | TemplatePart[];
|
|
4
11
|
raw: string;
|
|
5
12
|
}
|
|
6
13
|
export interface AstNode {
|
|
7
14
|
type: string;
|
|
8
15
|
_parent?: AstNode;
|
|
16
|
+
right?: AstNode;
|
|
9
17
|
}
|
|
10
18
|
export interface Literal extends AstNode {
|
|
11
19
|
type: 'Literal';
|
|
@@ -36,18 +44,22 @@ export interface ObjectLiteral extends AstNode {
|
|
|
36
44
|
type: 'ObjectLiteral';
|
|
37
45
|
value: Record<string, AstNode>;
|
|
38
46
|
}
|
|
47
|
+
export type TemplateLiteralPart = {
|
|
48
|
+
type: 'static';
|
|
49
|
+
value: string;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'expression';
|
|
52
|
+
value: AstNode;
|
|
53
|
+
};
|
|
39
54
|
export interface TemplateLiteral extends AstNode {
|
|
40
55
|
type: 'TemplateLiteral';
|
|
41
|
-
parts:
|
|
42
|
-
type: 'static' | 'expression';
|
|
43
|
-
value: string | AstNode;
|
|
44
|
-
}[];
|
|
56
|
+
parts: TemplateLiteralPart[];
|
|
45
57
|
}
|
|
46
58
|
export interface FunctionCall extends AstNode {
|
|
47
59
|
type: 'FunctionCall';
|
|
48
60
|
name: string;
|
|
49
61
|
args: AstNode[];
|
|
50
|
-
pool: 'functions'
|
|
62
|
+
pool: 'functions';
|
|
51
63
|
}
|
|
52
64
|
export interface FilterExpression extends AstNode {
|
|
53
65
|
type: 'FilterExpression';
|
|
@@ -69,7 +81,6 @@ export interface AssignmentExpression extends AstNode {
|
|
|
69
81
|
type: 'AssignmentExpression';
|
|
70
82
|
operator: '=';
|
|
71
83
|
left: Identifier;
|
|
72
|
-
right: AstNode;
|
|
73
84
|
}
|
|
74
85
|
export type AstNodeUnion = Literal | Identifier | BinaryExpression | UnaryExpression | ArrayLiteral | ObjectLiteral | TemplateLiteral | FunctionCall | FilterExpression | ConditionalExpression | SequenceExpression | AssignmentExpression;
|
|
75
86
|
export type NodeByType<T extends AstNodeUnion['type']> = Extract<AstNodeUnion, {
|
package/esm/Expression.d.ts
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
|
+
import Lexer from './Lexer.ts';
|
|
2
|
+
import type { CompiledNode } from './evaluator/compile.ts';
|
|
3
|
+
import type { Grammar } from './grammar.ts';
|
|
1
4
|
import type { AstNode } from './types.ts';
|
|
2
|
-
interface Grammar {
|
|
3
|
-
elements: Record<string, any>;
|
|
4
|
-
[key: string]: any;
|
|
5
|
-
}
|
|
6
5
|
declare class Expression {
|
|
7
6
|
_grammar: Grammar;
|
|
8
7
|
_exprStr: string;
|
|
9
8
|
_ast: AstNode | null;
|
|
10
|
-
|
|
9
|
+
_lexer: Lexer;
|
|
10
|
+
_compiled: boolean;
|
|
11
|
+
_fn: CompiledNode | null;
|
|
12
|
+
/**
|
|
13
|
+
* @param {{}} grammar The grammar to compile and evaluate against
|
|
14
|
+
* @param {string} exprStr The Jexl expression string
|
|
15
|
+
* @param {Lexer} [lexer] A Lexer to reuse. Lexers memoize the regex used to
|
|
16
|
+
* split expressions, which is expensive to build, so passing a shared
|
|
17
|
+
* one avoids paying that cost per expression. It must be invalidated
|
|
18
|
+
* via {@link Lexer#_clearCache} whenever the grammar's elements change.
|
|
19
|
+
*/
|
|
20
|
+
constructor(grammar: Grammar, exprStr: string, lexer?: Lexer);
|
|
11
21
|
/**
|
|
12
22
|
* Forces a compilation of the expression string that this Expression object
|
|
13
23
|
* was constructed with. This function can be called multiple times; useful
|
|
@@ -22,7 +32,7 @@ declare class Expression {
|
|
|
22
32
|
* @returns {*} the result of the evaluation.
|
|
23
33
|
* @throws {*} on error
|
|
24
34
|
*/
|
|
25
|
-
eval(context?: {}):
|
|
35
|
+
eval(context?: {}): import("./types.ts").JexlValue;
|
|
26
36
|
_getAst(): AstNode | null;
|
|
27
37
|
}
|
|
28
38
|
export default Expression;
|
package/esm/Expression.js
CHANGED
|
@@ -4,12 +4,29 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import Lexer from "./Lexer.js";
|
|
6
6
|
import Evaluator from "./evaluator/Evaluator.js";
|
|
7
|
+
import { compileAst } from "./evaluator/compile.js";
|
|
7
8
|
import Parser from "./parser/Parser.js";
|
|
8
9
|
class Expression {
|
|
9
|
-
|
|
10
|
+
_grammar;
|
|
11
|
+
_exprStr;
|
|
12
|
+
_ast;
|
|
13
|
+
_lexer;
|
|
14
|
+
_compiled = false;
|
|
15
|
+
// the AST lowered to closures, so repeated eval() calls skip node dispatch
|
|
16
|
+
_fn = null;
|
|
17
|
+
/**
|
|
18
|
+
* @param {{}} grammar The grammar to compile and evaluate against
|
|
19
|
+
* @param {string} exprStr The Jexl expression string
|
|
20
|
+
* @param {Lexer} [lexer] A Lexer to reuse. Lexers memoize the regex used to
|
|
21
|
+
* split expressions, which is expensive to build, so passing a shared
|
|
22
|
+
* one avoids paying that cost per expression. It must be invalidated
|
|
23
|
+
* via {@link Lexer#_clearCache} whenever the grammar's elements change.
|
|
24
|
+
*/
|
|
25
|
+
constructor(grammar, exprStr, lexer) {
|
|
10
26
|
this._grammar = grammar;
|
|
11
27
|
this._exprStr = exprStr;
|
|
12
28
|
this._ast = null;
|
|
29
|
+
this._lexer = lexer ?? new Lexer(grammar);
|
|
13
30
|
}
|
|
14
31
|
/**
|
|
15
32
|
* Forces a compilation of the expression string that this Expression object
|
|
@@ -18,11 +35,13 @@ class Expression {
|
|
|
18
35
|
* @returns {Expression} this Expression instance, for convenience
|
|
19
36
|
*/
|
|
20
37
|
compile() {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const tokens = lexer.tokenize(this._exprStr);
|
|
38
|
+
const parser = new Parser(this._grammar, this._lexer);
|
|
39
|
+
const tokens = this._lexer.tokenize(this._exprStr);
|
|
24
40
|
parser.addTokens(tokens);
|
|
25
41
|
this._ast = parser.complete();
|
|
42
|
+
// lower the tree to closures once, here, so that eval() is just a call
|
|
43
|
+
this._fn = this._ast ? compileAst(this._ast, this._grammar) : null;
|
|
44
|
+
this._compiled = true;
|
|
26
45
|
return this;
|
|
27
46
|
}
|
|
28
47
|
/**
|
|
@@ -33,12 +52,19 @@ class Expression {
|
|
|
33
52
|
* @throws {*} on error
|
|
34
53
|
*/
|
|
35
54
|
eval(context = {}) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
55
|
+
if (!this._compiled) {
|
|
56
|
+
this.compile();
|
|
57
|
+
}
|
|
58
|
+
// an expression with no tokens (empty or whitespace-only) has no AST
|
|
59
|
+
if (!this._fn) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return this._fn(new Evaluator(this._grammar, context));
|
|
39
63
|
}
|
|
40
64
|
_getAst() {
|
|
41
|
-
|
|
65
|
+
// tracked separately from _ast, which is legitimately null for an
|
|
66
|
+
// expression with no tokens and would otherwise recompile on every eval
|
|
67
|
+
if (!this._compiled) {
|
|
42
68
|
this.compile();
|
|
43
69
|
}
|
|
44
70
|
return this._ast;
|
package/esm/Expression.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,SAAS,MAAM,0BAA0B,CAAA;AAChD,OAAO,MAAM,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,SAAS,MAAM,0BAA0B,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,MAAM,MAAM,oBAAoB,CAAA;AAMvC,MAAM,UAAU;IACd,QAAQ,CAAS;IACjB,QAAQ,CAAQ;IAChB,IAAI,CAAgB;IACpB,MAAM,CAAO;IACb,SAAS,GAAG,KAAK,CAAA;IACjB,2EAA2E;IAC3E,GAAG,GAAwB,IAAI,CAAA;IAE/B;;;;;;;OAOG;IACH,YAAY,OAAgB,EAAE,OAAe,EAAE,KAAa;QAC1D,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;QAC7B,uEAAuE;QACvE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAClE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,GAAG,EAAE;QACf,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,qEAAqE;QACrE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;IACxD,CAAC;IAED,OAAO;QACL,kEAAkE;QAClE,wEAAwE;QACxE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;CACF;AAED,eAAe,UAAU,CAAA"}
|
package/esm/Jexl.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Expression from './Expression.ts';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
2
|
+
import Lexer from './Lexer.ts';
|
|
3
|
+
import type { BinaryOpEval, BinaryOpEvalOnDemand, Grammar, GrammarElement } from './grammar.ts';
|
|
4
|
+
import type { JexlValue } from './types.ts';
|
|
6
5
|
/**
|
|
7
6
|
* Jexl is the Javascript Expression Language, capable of parsing and
|
|
8
7
|
* evaluating basic to complex expression strings, combined with advanced
|
|
@@ -11,6 +10,7 @@ interface Grammar {
|
|
|
11
10
|
*/
|
|
12
11
|
declare class Jexl {
|
|
13
12
|
_grammar: Grammar;
|
|
13
|
+
_lexer: Lexer;
|
|
14
14
|
constructor();
|
|
15
15
|
/**
|
|
16
16
|
* Adds a binary operator to Jexl at the specified precedence. The higher the
|
|
@@ -31,7 +31,8 @@ declare class Jexl {
|
|
|
31
31
|
* left.eval() or right.eval() will return that operand's actual value.
|
|
32
32
|
* This is useful to conditionally evaluate operands.
|
|
33
33
|
*/
|
|
34
|
-
addBinaryOp(operator: string, precedence: number, fn:
|
|
34
|
+
addBinaryOp(operator: string, precedence: number, fn: BinaryOpEval, manualEval?: false): void;
|
|
35
|
+
addBinaryOp(operator: string, precedence: number, fn: BinaryOpEvalOnDemand, manualEval: true): void;
|
|
35
36
|
/**
|
|
36
37
|
* Adds or replaces an expression function in this Jexl instance.
|
|
37
38
|
* @param {string} name The name of the expression function, as it will be
|
|
@@ -40,14 +41,14 @@ declare class Jexl {
|
|
|
40
41
|
* expression function is invoked. It will be provided with each argument
|
|
41
42
|
* supplied in the expression, in the same order.
|
|
42
43
|
*/
|
|
43
|
-
addFunction(name: string, fn: (...args:
|
|
44
|
+
addFunction(name: string, fn: (...args: JexlValue[]) => JexlValue): void;
|
|
44
45
|
/**
|
|
45
46
|
* Syntactic sugar for calling {@link #addFunction} repeatedly. This function
|
|
46
47
|
* accepts a map of one or more expression function names to their javascript
|
|
47
48
|
* function counterpart.
|
|
48
49
|
* @param {{}} map A map of expression function names to javascript functions
|
|
49
50
|
*/
|
|
50
|
-
addFunctions(map: Record<string, (...args:
|
|
51
|
+
addFunctions(map: Record<string, (...args: JexlValue[]) => JexlValue>): void;
|
|
51
52
|
/**
|
|
52
53
|
* Adds a unary operator to Jexl. Unary operators are currently only supported
|
|
53
54
|
* on the left side of the value on which it will operate.
|
|
@@ -56,7 +57,7 @@ declare class Jexl {
|
|
|
56
57
|
* will be called with one argument: the literal value to the right of the
|
|
57
58
|
* operator. It should return the resulting value.
|
|
58
59
|
*/
|
|
59
|
-
addUnaryOp(operator: string, fn: (right:
|
|
60
|
+
addUnaryOp(operator: string, fn: (right: JexlValue) => JexlValue): void;
|
|
60
61
|
/**
|
|
61
62
|
* Creates an Expression object from the given Jexl expression string, and
|
|
62
63
|
* immediately compiles it. The returned Expression object can then be
|
|
@@ -78,7 +79,7 @@ declare class Jexl {
|
|
|
78
79
|
* @param {string} name The name of the expression function
|
|
79
80
|
* @returns {function} The expression function
|
|
80
81
|
*/
|
|
81
|
-
getFunction(name: string): (...args:
|
|
82
|
+
getFunction(name: string): ((...args: JexlValue[]) => JexlValue) | undefined;
|
|
82
83
|
/**
|
|
83
84
|
* Evaluates a Jexl string within an optional context.
|
|
84
85
|
* @param {string} expression The Jexl expression to be evaluated
|
|
@@ -87,14 +88,14 @@ declare class Jexl {
|
|
|
87
88
|
* @returns {*} the result of the evaluation.
|
|
88
89
|
* @throws {*} on error
|
|
89
90
|
*/
|
|
90
|
-
eval(expression: string, context?: {}):
|
|
91
|
+
eval(expression: string, context?: {}): JexlValue;
|
|
91
92
|
/**
|
|
92
93
|
* A JavaScript template literal to allow expressions to be defined by the
|
|
93
94
|
* syntax: expr`40 + 2`
|
|
94
95
|
* @param {Array<string>} strs
|
|
95
96
|
* @param {...any} args
|
|
96
97
|
*/
|
|
97
|
-
expr(strs: TemplateStringsArray, ...args:
|
|
98
|
+
expr(strs: TemplateStringsArray, ...args: JexlValue[]): Expression;
|
|
98
99
|
/**
|
|
99
100
|
* Removes a binary or unary operator from the Jexl grammar.
|
|
100
101
|
* @param {string} operator The operator string to be removed
|
|
@@ -107,7 +108,7 @@ declare class Jexl {
|
|
|
107
108
|
* grammar element
|
|
108
109
|
* @private
|
|
109
110
|
*/
|
|
110
|
-
_addGrammarElement(str: string, obj:
|
|
111
|
+
_addGrammarElement(str: string, obj: GrammarElement): void;
|
|
111
112
|
}
|
|
112
113
|
declare const jexlInstance: Jexl;
|
|
113
114
|
export default jexlInstance;
|