@jbrowse/jexl 3.0.1 → 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 +24 -25
- 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 +61 -19
- 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 +33 -5
- 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 +5 -21
- 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 +61 -19
- 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 +33 -5
- 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 +5 -21
- package/esm/parser/states.js.map +1 -1
- package/esm/types.d.ts +18 -7
- package/package.json +27 -29
- package/src/Expression.ts +33 -13
- package/src/Jexl.ts +59 -21
- package/src/Lexer.ts +63 -28
- 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 +35 -21
- package/src/parser/handlers.ts +96 -73
- package/src/parser/states.ts +7 -23
- 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
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;
|
package/esm/Jexl.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Copyright 2020 Tom Shawver
|
|
4
4
|
*/
|
|
5
5
|
import Expression from "./Expression.js";
|
|
6
|
+
import Lexer from "./Lexer.js";
|
|
6
7
|
import { getGrammar } from "./grammar.js";
|
|
7
8
|
/**
|
|
8
9
|
* Jexl is the Javascript Expression Language, capable of parsing and
|
|
@@ -11,35 +12,25 @@ import { getGrammar } from "./grammar.js";
|
|
|
11
12
|
* @constructor
|
|
12
13
|
*/
|
|
13
14
|
class Jexl {
|
|
15
|
+
_grammar;
|
|
16
|
+
// shared by every Expression this instance creates, so that the expensive
|
|
17
|
+
// element-splitting regex is built once rather than per compile
|
|
18
|
+
_lexer;
|
|
14
19
|
constructor() {
|
|
15
20
|
this._grammar = getGrammar();
|
|
21
|
+
this._lexer = new Lexer(this._grammar);
|
|
16
22
|
this.expr = this.expr.bind(this);
|
|
17
23
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Adds a binary operator to Jexl at the specified precedence. The higher the
|
|
20
|
-
* precedence, the earlier the operator is applied in the order of operations.
|
|
21
|
-
* For example, * has a higher precedence than +, because multiplication comes
|
|
22
|
-
* before division.
|
|
23
|
-
*
|
|
24
|
-
* Please see grammar.js for a listing of all default operators and their
|
|
25
|
-
* precedence values in order to choose the appropriate precedence for the
|
|
26
|
-
* new operator.
|
|
27
|
-
* @param {string} operator The operator string to be added
|
|
28
|
-
* @param {number} precedence The operator's precedence
|
|
29
|
-
* @param {function} fn A function to run to calculate the result. The function
|
|
30
|
-
* will be called with two arguments: left and right, denoting the values
|
|
31
|
-
* on either side of the operator. It should return the resulting value.
|
|
32
|
-
* @param {boolean} [manualEval] If true, the `left` and `right` arguments
|
|
33
|
-
* will be wrapped in objects with an `eval` function. Calling
|
|
34
|
-
* left.eval() or right.eval() will return that operand's actual value.
|
|
35
|
-
* This is useful to conditionally evaluate operands.
|
|
36
|
-
*/
|
|
37
24
|
addBinaryOp(operator, precedence, fn, manualEval) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
// the overloads above pair `fn` with `manualEval`; the implementation
|
|
26
|
+
// signature can't express that correlation, hence the assertions
|
|
27
|
+
this._addGrammarElement(operator, manualEval
|
|
28
|
+
? {
|
|
29
|
+
type: 'binaryOp',
|
|
30
|
+
precedence,
|
|
31
|
+
evalOnDemand: fn
|
|
32
|
+
}
|
|
33
|
+
: { type: 'binaryOp', precedence, eval: fn });
|
|
43
34
|
}
|
|
44
35
|
/**
|
|
45
36
|
* Adds or replaces an expression function in this Jexl instance.
|
|
@@ -72,7 +63,7 @@ class Jexl {
|
|
|
72
63
|
addUnaryOp(operator, fn) {
|
|
73
64
|
this._addGrammarElement(operator, {
|
|
74
65
|
type: 'unaryOp',
|
|
75
|
-
|
|
66
|
+
precedence: Infinity,
|
|
76
67
|
eval: fn
|
|
77
68
|
});
|
|
78
69
|
}
|
|
@@ -95,7 +86,7 @@ class Jexl {
|
|
|
95
86
|
* @returns {Expression} The Expression object representing the given string
|
|
96
87
|
*/
|
|
97
88
|
createExpression(expression) {
|
|
98
|
-
return new Expression(this._grammar, expression);
|
|
89
|
+
return new Expression(this._grammar, expression, this._lexer);
|
|
99
90
|
}
|
|
100
91
|
/**
|
|
101
92
|
* Retrieves a previously set expression function.
|
|
@@ -125,10 +116,18 @@ class Jexl {
|
|
|
125
116
|
*/
|
|
126
117
|
expr(strs, ...args) {
|
|
127
118
|
let exprStr = '';
|
|
128
|
-
for (
|
|
129
|
-
exprStr +=
|
|
119
|
+
for (const [idx, str] of strs.entries()) {
|
|
120
|
+
exprStr += str;
|
|
130
121
|
if (idx < args.length) {
|
|
131
|
-
|
|
122
|
+
const arg = args[idx];
|
|
123
|
+
if (typeof arg === 'string' ||
|
|
124
|
+
typeof arg === 'number' ||
|
|
125
|
+
typeof arg === 'boolean') {
|
|
126
|
+
exprStr += String(arg);
|
|
127
|
+
}
|
|
128
|
+
else if (arg != null) {
|
|
129
|
+
exprStr += JSON.stringify(arg);
|
|
130
|
+
}
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
return this.createExpression(exprStr);
|
|
@@ -139,8 +138,9 @@ class Jexl {
|
|
|
139
138
|
*/
|
|
140
139
|
removeOp(operator) {
|
|
141
140
|
const elem = this._grammar.elements[operator];
|
|
142
|
-
if (elem
|
|
141
|
+
if (elem?.type === 'binaryOp' || elem?.type === 'unaryOp') {
|
|
143
142
|
Reflect.deleteProperty(this._grammar.elements, operator);
|
|
143
|
+
this._lexer._clearCache();
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
@@ -152,6 +152,7 @@ class Jexl {
|
|
|
152
152
|
*/
|
|
153
153
|
_addGrammarElement(str, obj) {
|
|
154
154
|
this._grammar.elements[str] = obj;
|
|
155
|
+
this._lexer._clearCache();
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
const jexlInstance = new Jexl();
|
package/esm/Jexl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Jexl.js","sourceRoot":"","sources":["../src/Jexl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,UAAU,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"Jexl.js","sourceRoot":"","sources":["../src/Jexl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,UAAU,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAUzC;;;;;GAKG;AACH,MAAM,IAAI;IACR,QAAQ,CAAS;IACjB,0EAA0E;IAC1E,gEAAgE;IAChE,MAAM,CAAO;IAEb;QACE,IAAI,CAAC,QAAQ,GAAG,UAAU,EAAE,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAiCD,WAAW,CACT,QAAgB,EAChB,UAAkB,EAClB,EAAuC,EACvC,UAAoB;QAEpB,sEAAsE;QACtE,iEAAiE;QACjE,IAAI,CAAC,kBAAkB,CACrB,QAAQ,EACR,UAAU;YACR,CAAC,CAAC;gBACE,IAAI,EAAE,UAAU;gBAChB,UAAU;gBACV,YAAY,EAAE,EAA0B;aACzC;YACH,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,EAAkB,EAAE,CAC/D,CAAA;IACH,CAAC;IAED;;;;;;;OAOG;IACH,WAAW,CAAC,IAAY,EAAE,EAAuC;QAC/D,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;IACpC,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,GAAwD;QACnE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;IAC7C,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,QAAgB,EAAE,EAAmC;QAC9D,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;YAChC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,QAAQ;YACpB,IAAI,EAAE,EAAE;SACT,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,UAAkB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAA;QACjD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,UAAkB;QACjC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/D,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACtC,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,UAAkB,EAAE,OAAO,GAAG,EAAE;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAA;QACjD,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAA0B,EAAE,GAAG,IAAiB;QACnD,IAAI,OAAO,GAAG,EAAE,CAAA;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACxC,OAAO,IAAI,GAAG,CAAA;YACd,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;gBACrB,IACE,OAAO,GAAG,KAAK,QAAQ;oBACvB,OAAO,GAAG,KAAK,QAAQ;oBACvB,OAAO,GAAG,KAAK,SAAS,EACxB,CAAC;oBACD,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAA;gBACxB,CAAC;qBAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;oBACvB,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,QAAgB;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC7C,IAAI,IAAI,EAAE,IAAI,KAAK,UAAU,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACxD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA;QAC3B,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,kBAAkB,CAAC,GAAW,EAAE,GAAmB;QACjD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;QACjC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA;IAC3B,CAAC;CACF;AAED,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAA;AAC/B,eAAe,YAAY,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,CAAA"}
|
package/esm/Lexer.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
elements: Record<string, any>;
|
|
4
|
-
}
|
|
1
|
+
import type { Grammar } from './grammar.ts';
|
|
2
|
+
import type { TemplatePart, Token } from './types.ts';
|
|
5
3
|
/**
|
|
6
4
|
* Lexer is a collection of stateless, statically-accessed functions for the
|
|
7
5
|
* lexical parsing of a Jexl string. Its responsibility is to identify the
|
|
@@ -17,6 +15,12 @@ declare class Lexer {
|
|
|
17
15
|
_splitRegex?: RegExp;
|
|
18
16
|
_escQuoteRegexCache: Map<string, RegExp>;
|
|
19
17
|
constructor(grammar: Grammar);
|
|
18
|
+
/**
|
|
19
|
+
* Discards the memoized split regex, so that it is rebuilt on the next
|
|
20
|
+
* tokenize. Must be called whenever the grammar's elements change, since the
|
|
21
|
+
* regex is derived from their keys.
|
|
22
|
+
*/
|
|
23
|
+
_clearCache(): void;
|
|
20
24
|
/**
|
|
21
25
|
* Splits a Jexl expression string into an array of expression elements.
|
|
22
26
|
* @param {string} str A Jexl expression string
|
|
@@ -121,10 +125,7 @@ declare class Lexer {
|
|
|
121
125
|
* @private
|
|
122
126
|
*/
|
|
123
127
|
_unquote(str: string): string;
|
|
124
|
-
_parseTemplateString(str: string):
|
|
125
|
-
type: "static" | "interpolation";
|
|
126
|
-
value: string;
|
|
127
|
-
}[];
|
|
128
|
+
_parseTemplateString(str: string): TemplatePart[];
|
|
128
129
|
_unescapeTemplateString(str: string): string;
|
|
129
130
|
}
|
|
130
131
|
export default Lexer;
|
package/esm/Lexer.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const numericRegex = /^-?(?:(?:[0-9]*\.[0-9]+)|[0-9]+)$/;
|
|
6
6
|
const identRegex = /^[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][a-zA-Zа-яА-Я0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*$/;
|
|
7
|
-
const escEscRegex =
|
|
7
|
+
const escEscRegex = /\\\\/g;
|
|
8
8
|
const whitespaceRegex = /^\s*$/;
|
|
9
9
|
const preOpRegexElems = [
|
|
10
10
|
// Template strings
|
|
@@ -24,13 +24,20 @@ const postOpRegexElems = [
|
|
|
24
24
|
// Numerics (without negative symbol)
|
|
25
25
|
String.raw `(?:(?:[0-9]*\.[0-9]+)|[0-9]+)`
|
|
26
26
|
];
|
|
27
|
+
const unaryMinusToken = () => ({
|
|
28
|
+
type: 'unaryOp',
|
|
29
|
+
value: '-',
|
|
30
|
+
raw: '-'
|
|
31
|
+
});
|
|
27
32
|
const minusNegatesAfter = new Set([
|
|
28
33
|
'binaryOp',
|
|
29
34
|
'unaryOp',
|
|
30
35
|
'openParen',
|
|
31
36
|
'openBracket',
|
|
32
37
|
'question',
|
|
33
|
-
'colon'
|
|
38
|
+
'colon',
|
|
39
|
+
'comma',
|
|
40
|
+
'semicolon'
|
|
34
41
|
]);
|
|
35
42
|
/**
|
|
36
43
|
* Lexer is a collection of stateless, statically-accessed functions for the
|
|
@@ -43,10 +50,20 @@ const minusNegatesAfter = new Set([
|
|
|
43
50
|
* @type {{}}
|
|
44
51
|
*/
|
|
45
52
|
class Lexer {
|
|
53
|
+
_grammar;
|
|
54
|
+
_splitRegex;
|
|
55
|
+
_escQuoteRegexCache = new Map();
|
|
46
56
|
constructor(grammar) {
|
|
47
|
-
this._escQuoteRegexCache = new Map();
|
|
48
57
|
this._grammar = grammar;
|
|
49
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Discards the memoized split regex, so that it is rebuilt on the next
|
|
61
|
+
* tokenize. Must be called whenever the grammar's elements change, since the
|
|
62
|
+
* regex is derived from their keys.
|
|
63
|
+
*/
|
|
64
|
+
_clearCache() {
|
|
65
|
+
this._splitRegex = undefined;
|
|
66
|
+
}
|
|
50
67
|
/**
|
|
51
68
|
* Splits a Jexl expression string into an array of expression elements.
|
|
52
69
|
* @param {string} str A Jexl expression string
|
|
@@ -70,21 +87,35 @@ class Lexer {
|
|
|
70
87
|
getTokens(elements) {
|
|
71
88
|
const tokens = [];
|
|
72
89
|
let negate = false;
|
|
73
|
-
for (
|
|
74
|
-
if (this._isWhitespace(
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
for (const element of elements) {
|
|
91
|
+
if (this._isWhitespace(element)) {
|
|
92
|
+
const last = tokens.at(-1);
|
|
93
|
+
if (last) {
|
|
94
|
+
last.raw += element;
|
|
77
95
|
}
|
|
78
96
|
}
|
|
79
|
-
else if (
|
|
97
|
+
else if (element === '-' && this._isNegative(tokens)) {
|
|
98
|
+
// a second prefix minus in a row ("- -x"): emit the pending one as a
|
|
99
|
+
// unary operator so this one can negate whatever comes next
|
|
100
|
+
if (negate) {
|
|
101
|
+
tokens.push(unaryMinusToken());
|
|
102
|
+
}
|
|
80
103
|
negate = true;
|
|
81
104
|
}
|
|
82
|
-
else {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
else if (negate) {
|
|
106
|
+
negate = false;
|
|
107
|
+
if (numericRegex.exec(element)) {
|
|
108
|
+
// fold the sign into the number, so "-1" stays a single literal
|
|
109
|
+
tokens.push(this._createToken('-' + element));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// anything else gets a standalone prefix operator, letting "-x",
|
|
113
|
+
// "-(a + b)" and "-foo.bar" negate a computed value
|
|
114
|
+
tokens.push(unaryMinusToken(), this._createToken(element));
|
|
86
115
|
}
|
|
87
|
-
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
tokens.push(this._createToken(element));
|
|
88
119
|
}
|
|
89
120
|
}
|
|
90
121
|
// Catch a - at the end of the string. Let the parser handle that issue.
|
|
@@ -154,7 +185,7 @@ class Lexer {
|
|
|
154
185
|
else if (element === 'true' || element === 'false') {
|
|
155
186
|
token.value = element === 'true';
|
|
156
187
|
}
|
|
157
|
-
else if (this._grammar.elements
|
|
188
|
+
else if (Object.hasOwn(this._grammar.elements, element)) {
|
|
158
189
|
token.type = this._grammar.elements[element].type;
|
|
159
190
|
}
|
|
160
191
|
else if (identRegex.exec(element)) {
|
|
@@ -252,8 +283,8 @@ class Lexer {
|
|
|
252
283
|
}
|
|
253
284
|
return str
|
|
254
285
|
.slice(1, -1)
|
|
255
|
-
.
|
|
256
|
-
.
|
|
286
|
+
.replaceAll(escQuoteRegex, quote)
|
|
287
|
+
.replaceAll(escEscRegex, '\\');
|
|
257
288
|
}
|
|
258
289
|
_parseTemplateString(str) {
|
|
259
290
|
const parts = [];
|
|
@@ -275,14 +306,25 @@ class Lexer {
|
|
|
275
306
|
const interpStart = current + 2;
|
|
276
307
|
current += 2;
|
|
277
308
|
while (current < str.length && braceDepth > 0) {
|
|
278
|
-
|
|
309
|
+
const char = str[current];
|
|
310
|
+
if (char === '\\') {
|
|
279
311
|
current += 2;
|
|
280
312
|
continue;
|
|
281
313
|
}
|
|
282
|
-
|
|
314
|
+
// skip over string literals so that braces inside them, as in
|
|
315
|
+
// `${ f('}') }`, don't unbalance the depth count
|
|
316
|
+
if (char === '"' || char === "'") {
|
|
317
|
+
current++;
|
|
318
|
+
while (current < str.length && str[current] !== char) {
|
|
319
|
+
current += str[current] === '\\' ? 2 : 1;
|
|
320
|
+
}
|
|
321
|
+
current++;
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (char === '{') {
|
|
283
325
|
braceDepth++;
|
|
284
326
|
}
|
|
285
|
-
if (
|
|
327
|
+
else if (char === '}') {
|
|
286
328
|
braceDepth--;
|
|
287
329
|
}
|
|
288
330
|
current++;
|
package/esm/Lexer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Lexer.js","sourceRoot":"","sources":["../src/Lexer.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"Lexer.js","sourceRoot":"","sources":["../src/Lexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
elements: Record<string, any>;
|
|
4
|
-
[key: string]: any;
|
|
5
|
-
}
|
|
1
|
+
import type { Grammar } from '../grammar.ts';
|
|
2
|
+
import type { AstNode, JexlValue } from '../types.ts';
|
|
6
3
|
/**
|
|
7
|
-
* The Evaluator
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* When any of these things change, a new instance is required. However, a
|
|
12
|
-
* single instance can be used to simultaneously evaluate many different
|
|
4
|
+
* The Evaluator carries everything an expression is evaluated against: the
|
|
5
|
+
* grammar, the context, and a relative context to be used as the root for
|
|
6
|
+
* relative identifiers. When any of these change, a new instance is required.
|
|
7
|
+
* However, a single instance can be used to evaluate many different
|
|
13
8
|
* expressions, and does not have to be reinstantiated for each.
|
|
9
|
+
*
|
|
10
|
+
* The work of evaluation itself lives in {@link compileAst}, which lowers a
|
|
11
|
+
* tree to closures. Prefer compiling once and reusing the result — that is what
|
|
12
|
+
* {@link Expression} does — over calling {@link #eval}, which compiles the tree
|
|
13
|
+
* it is given every time.
|
|
14
|
+
*
|
|
14
15
|
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
15
16
|
* tree
|
|
16
17
|
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
@@ -20,32 +21,17 @@ interface Grammar {
|
|
|
20
21
|
*/
|
|
21
22
|
declare class Evaluator {
|
|
22
23
|
_grammar: Grammar;
|
|
23
|
-
_context:
|
|
24
|
-
_relContext:
|
|
25
|
-
constructor(grammar: Grammar, context?:
|
|
24
|
+
_context: Record<string, JexlValue>;
|
|
25
|
+
_relContext: Record<string, JexlValue>;
|
|
26
|
+
constructor(grammar: Grammar, context?: Record<string, JexlValue>, relativeContext?: Record<string, JexlValue>);
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
+
* Compiles and evaluates an expression tree within the configured context.
|
|
29
|
+
* Convenient for a one-shot evaluation; for repeated evaluation of the same
|
|
30
|
+
* tree, hold onto the closure from {@link compileAst} instead so the tree is
|
|
31
|
+
* only lowered once.
|
|
28
32
|
* @param {{}} ast An expression tree object
|
|
29
33
|
* @returns {*} the resulting value of the expression.
|
|
30
34
|
*/
|
|
31
|
-
eval(ast: AstNode):
|
|
32
|
-
/**
|
|
33
|
-
* Evaluates each expression within an array, and delivers the response as an
|
|
34
|
-
* array with the resulting values at the same indexes as their originating
|
|
35
|
-
* expressions.
|
|
36
|
-
* @param {Array<string>} arr An array of expression strings to be evaluated
|
|
37
|
-
* @returns {Array<{}>} the result array
|
|
38
|
-
*/
|
|
39
|
-
evalArray(arr: AstNode[]): any[];
|
|
40
|
-
/**
|
|
41
|
-
* Evaluates each expression within a map, and delivers the response as a map
|
|
42
|
-
* with the same keys, but with the evaluated result for each as their value.
|
|
43
|
-
* @param {{}} map A map of expression names to expression trees to be
|
|
44
|
-
* evaluated
|
|
45
|
-
* @returns {{}} the result map.
|
|
46
|
-
*/
|
|
47
|
-
evalMap(map: Record<string, AstNode>): {
|
|
48
|
-
[k: string]: any;
|
|
49
|
-
};
|
|
35
|
+
eval(ast: AstNode): JexlValue;
|
|
50
36
|
}
|
|
51
37
|
export default Evaluator;
|