@jbrowse/jexl 3.2.0 → 4.0.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/dist/Expression.js +1 -2
- package/dist/Expression.js.map +1 -1
- package/dist/Jexl.d.ts +8 -8
- package/dist/Jexl.js +7 -1
- package/dist/Jexl.js.map +1 -1
- 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 +42 -52
- package/dist/evaluator/compile.js.map +1 -1
- package/dist/grammar.d.ts +19 -2
- package/dist/grammar.js +1 -1
- package/dist/grammar.js.map +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 +8 -8
- package/esm/Jexl.js +7 -1
- package/esm/Jexl.js.map +1 -1
- 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 +42 -52
- package/esm/evaluator/compile.js.map +1 -1
- package/esm/grammar.d.ts +19 -2
- package/esm/grammar.js +1 -1
- package/esm/grammar.js.map +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 +20 -11
- package/src/Lexer.ts +47 -36
- package/src/evaluator/compile.ts +53 -68
- package/src/grammar.ts +23 -3
- 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
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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,+EAA+E;AAC/E,8DAA8D;AAC9D,OAAO,MAAM,MAAM,aAAa,CAAA;AAkBhC;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAe,GAAmB;IACtD,IAAI,GAAG,EAAE,CAAC;QACR,CAAC;QAAC,IAAI,CAAC,OAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAChD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAiB;QACzB,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE,EAAE;KACV,CAAA;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAe,GAAmB;IACxD,IAAI,GAAG,EAAE,CAAC;QACR,CAAC;QAAC,IAAI,CAAC,OAAwB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACjD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAe,KAAY;IACjD,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;QACxB,sEAAsE;QACtE,
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":"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"}
|
package/esm/parser/states.js
CHANGED
|
@@ -77,10 +77,6 @@ export const states = {
|
|
|
77
77
|
colon: { toState: 'objVal' }
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
|
-
postArgs: {
|
|
81
|
-
tokenTypes: afterOperand,
|
|
82
|
-
completable: true
|
|
83
|
-
},
|
|
84
80
|
identifier: {
|
|
85
81
|
tokenTypes: {
|
|
86
82
|
...afterOperand,
|
|
@@ -111,7 +107,9 @@ export const states = {
|
|
|
111
107
|
subHandler: h.argVal,
|
|
112
108
|
endStates: {
|
|
113
109
|
comma: 'argVal',
|
|
114
|
-
|
|
110
|
+
// a call's result is an ordinary operand: it can be operated on or
|
|
111
|
+
// drilled into, but not called again, since only a name can be called
|
|
112
|
+
closeParen: 'expectBinOp'
|
|
115
113
|
}
|
|
116
114
|
},
|
|
117
115
|
objVal: {
|
package/esm/parser/states.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/parser/states.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,CAAC,MAAM,eAAe,CAAA;AAmBlC;;;;;GAKG;AACH,MAAM,YAAY,GAAqC;IACrD,QAAQ,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE;IACtC,GAAG,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;IAC5B,WAAW,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAClC,QAAQ,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,YAAY,EAAE;IAC5D,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE;CACpC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,MAAM,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,YAAY;QACxB,WAAW,EAAE,IAAI;KAClB;IACD,YAAY,EAAE;QACZ,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YAC1D,UAAU,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YAC7D,SAAS,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE;SACtC;KACF;IACD,eAAe,EAAE;QACf,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;SAC7B;KACF;IACD,
|
|
1
|
+
{"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/parser/states.ts"],"names":[],"mappings":"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"}
|
package/esm/types.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export interface Identifier extends AstNode {
|
|
|
23
23
|
type: 'Identifier';
|
|
24
24
|
value: string;
|
|
25
25
|
from?: AstNode;
|
|
26
|
-
relative?: boolean;
|
|
27
26
|
}
|
|
28
27
|
export interface BinaryExpression extends AstNode {
|
|
29
28
|
type: 'BinaryExpression';
|
|
@@ -59,12 +58,10 @@ export interface FunctionCall extends AstNode {
|
|
|
59
58
|
type: 'FunctionCall';
|
|
60
59
|
name: string;
|
|
61
60
|
args: AstNode[];
|
|
62
|
-
pool: 'functions';
|
|
63
61
|
}
|
|
64
62
|
export interface FilterExpression extends AstNode {
|
|
65
63
|
type: 'FilterExpression';
|
|
66
64
|
expr: AstNode;
|
|
67
|
-
relative: boolean;
|
|
68
65
|
subject: AstNode;
|
|
69
66
|
}
|
|
70
67
|
export interface ConditionalExpression extends AstNode {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/jexl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A fork of the jexl lang for jbrowse",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test": "vitest",
|
|
18
|
+
"bench": "vitest bench --run",
|
|
18
19
|
"coverage": "pnpm test --coverage",
|
|
19
20
|
"clean": "rimraf dist esm",
|
|
20
21
|
"format": "prettier --write .",
|
package/src/Expression.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import Lexer from './Lexer.ts'
|
|
7
|
-
import Evaluator from './evaluator/Evaluator.ts'
|
|
8
7
|
import { compileAst } from './evaluator/compile.ts'
|
|
9
8
|
import Parser from './parser/Parser.ts'
|
|
10
9
|
|
|
@@ -71,7 +70,7 @@ class Expression {
|
|
|
71
70
|
if (!this._fn) {
|
|
72
71
|
return undefined
|
|
73
72
|
}
|
|
74
|
-
return this._fn(
|
|
73
|
+
return this._fn(context)
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
76
|
|
package/src/Jexl.ts
CHANGED
|
@@ -11,7 +11,10 @@ import type {
|
|
|
11
11
|
BinaryOpEval,
|
|
12
12
|
BinaryOpEvalOnDemand,
|
|
13
13
|
Grammar,
|
|
14
|
-
GrammarElement
|
|
14
|
+
GrammarElement,
|
|
15
|
+
GrammarFn,
|
|
16
|
+
UnaryOpEval,
|
|
17
|
+
UncheckedFn
|
|
15
18
|
} from './grammar.ts'
|
|
16
19
|
import type { JexlValue } from './types.ts'
|
|
17
20
|
|
|
@@ -37,9 +40,9 @@ class Jexl {
|
|
|
37
40
|
* Adds a binary operator to Jexl at the specified precedence. The higher the
|
|
38
41
|
* precedence, the earlier the operator is applied in the order of operations.
|
|
39
42
|
* For example, * has a higher precedence than +, because multiplication comes
|
|
40
|
-
* before
|
|
43
|
+
* before addition.
|
|
41
44
|
*
|
|
42
|
-
* Please see grammar.
|
|
45
|
+
* Please see grammar.ts for a listing of all default operators and their
|
|
43
46
|
* precedence values in order to choose the appropriate precedence for the
|
|
44
47
|
* new operator.
|
|
45
48
|
* @param {string} operator The operator string to be added
|
|
@@ -55,7 +58,7 @@ class Jexl {
|
|
|
55
58
|
addBinaryOp(
|
|
56
59
|
operator: string,
|
|
57
60
|
precedence: number,
|
|
58
|
-
fn:
|
|
61
|
+
fn: UncheckedFn,
|
|
59
62
|
manualEval?: false
|
|
60
63
|
): void
|
|
61
64
|
addBinaryOp(
|
|
@@ -67,7 +70,7 @@ class Jexl {
|
|
|
67
70
|
addBinaryOp(
|
|
68
71
|
operator: string,
|
|
69
72
|
precedence: number,
|
|
70
|
-
fn:
|
|
73
|
+
fn: UncheckedFn | BinaryOpEvalOnDemand,
|
|
71
74
|
manualEval?: boolean
|
|
72
75
|
) {
|
|
73
76
|
// the overloads above pair `fn` with `manualEval`; the implementation
|
|
@@ -80,7 +83,11 @@ class Jexl {
|
|
|
80
83
|
precedence,
|
|
81
84
|
evalOnDemand: fn as BinaryOpEvalOnDemand
|
|
82
85
|
}
|
|
83
|
-
: {
|
|
86
|
+
: {
|
|
87
|
+
type: 'binaryOp',
|
|
88
|
+
precedence,
|
|
89
|
+
eval: fn as unknown as BinaryOpEval
|
|
90
|
+
}
|
|
84
91
|
)
|
|
85
92
|
}
|
|
86
93
|
|
|
@@ -92,8 +99,10 @@ class Jexl {
|
|
|
92
99
|
* expression function is invoked. It will be provided with each argument
|
|
93
100
|
* supplied in the expression, in the same order.
|
|
94
101
|
*/
|
|
95
|
-
addFunction(name: string, fn:
|
|
96
|
-
|
|
102
|
+
addFunction(name: string, fn: UncheckedFn) {
|
|
103
|
+
// jexl hands the function whatever the operands evaluated to, which it
|
|
104
|
+
// cannot reconcile with the caller's parameter types — see UncheckedFn
|
|
105
|
+
this._grammar.functions[name] = fn as unknown as GrammarFn
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
/**
|
|
@@ -102,7 +111,7 @@ class Jexl {
|
|
|
102
111
|
* function counterpart.
|
|
103
112
|
* @param {{}} map A map of expression function names to javascript functions
|
|
104
113
|
*/
|
|
105
|
-
addFunctions(map: Record<string,
|
|
114
|
+
addFunctions(map: Record<string, UncheckedFn>) {
|
|
106
115
|
Object.assign(this._grammar.functions, map)
|
|
107
116
|
}
|
|
108
117
|
|
|
@@ -114,11 +123,11 @@ class Jexl {
|
|
|
114
123
|
* will be called with one argument: the literal value to the right of the
|
|
115
124
|
* operator. It should return the resulting value.
|
|
116
125
|
*/
|
|
117
|
-
addUnaryOp(operator: string, fn:
|
|
126
|
+
addUnaryOp(operator: string, fn: UncheckedFn) {
|
|
118
127
|
this._addGrammarElement(operator, {
|
|
119
128
|
type: 'unaryOp',
|
|
120
129
|
precedence: Infinity,
|
|
121
|
-
eval: fn
|
|
130
|
+
eval: fn as unknown as UnaryOpEval
|
|
122
131
|
})
|
|
123
132
|
}
|
|
124
133
|
|
package/src/Lexer.ts
CHANGED
|
@@ -6,13 +6,26 @@
|
|
|
6
6
|
import type { Grammar } from './grammar.ts'
|
|
7
7
|
import type { TemplatePart, Token } from './types.ts'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
// what an identifier and a number look like, written once: the split regex
|
|
10
|
+
// below carves elements out of the expression with these, and _createToken
|
|
11
|
+
// then re-tests the elements it produced. Two spellings of either would
|
|
12
|
+
// disagree on some input, and each disagreement is an "Invalid expression
|
|
13
|
+
// token" for something the splitter was happy to produce.
|
|
14
|
+
const identChars = String.raw`a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$`
|
|
15
|
+
const identPattern = `[${identChars}][${identChars}0-9]*`
|
|
16
|
+
// unsigned: whether a leading '-' negates is decided separately, in getTokens
|
|
17
|
+
const numberPattern = String.raw`(?:(?:[0-9]*\.[0-9]+)|[0-9]+)`
|
|
18
|
+
|
|
19
|
+
const numericRegex = new RegExp(`^-?${numberPattern}$`)
|
|
20
|
+
const identRegex = new RegExp(`^${identPattern}$`)
|
|
12
21
|
const escEscRegex = /\\\\/g
|
|
13
22
|
// a string literal opens with one of exactly two quote characters, so the two
|
|
14
23
|
// unescaping regexes can just be named rather than built and cached per quote
|
|
15
24
|
const escQuoteRegex = { "'": /\\'/g, '"': /\\"/g }
|
|
25
|
+
// the escapes a template string's static text recognizes. One pass, so the
|
|
26
|
+
// backslash an escaped backslash yields can't be re-read as the start of the
|
|
27
|
+
// escape that follows it
|
|
28
|
+
const templateEscRegex = /\\([`$\\])/g
|
|
16
29
|
const whitespaceRegex = /^\s*$/
|
|
17
30
|
const preOpRegexElems = [
|
|
18
31
|
// Template strings
|
|
@@ -26,12 +39,7 @@ const preOpRegexElems = [
|
|
|
26
39
|
String.raw`\btrue\b`,
|
|
27
40
|
String.raw`\bfalse\b`
|
|
28
41
|
]
|
|
29
|
-
const postOpRegexElems = [
|
|
30
|
-
// Identifiers
|
|
31
|
-
'[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\\$][a-zA-Z0-9а-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\\$]*',
|
|
32
|
-
// Numerics (without negative symbol)
|
|
33
|
-
String.raw`(?:(?:[0-9]*\.[0-9]+)|[0-9]+)`
|
|
34
|
-
]
|
|
42
|
+
const postOpRegexElems = [identPattern, numberPattern]
|
|
35
43
|
const unaryMinusToken = (): Token => ({
|
|
36
44
|
type: 'unaryOp',
|
|
37
45
|
value: '-',
|
|
@@ -49,14 +57,16 @@ const minusNegatesAfter = new Set([
|
|
|
49
57
|
])
|
|
50
58
|
|
|
51
59
|
/**
|
|
52
|
-
* Lexer
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
+
* Lexer handles the lexical parsing of a Jexl string. Its responsibility is to
|
|
61
|
+
* identify the "parts of speech" of a Jexl expression, and tokenize and label
|
|
62
|
+
* each, but to do only the most minimal syntax checking; the only errors the
|
|
63
|
+
* Lexer should be concerned with are if it's unable to identify the utility of
|
|
64
|
+
* any of its tokens. Errors stemming from these tokens not being in a sensible
|
|
65
|
+
* configuration should be left for the Parser to handle.
|
|
66
|
+
*
|
|
67
|
+
* An instance is bound to one grammar and memoizes the regex that splits an
|
|
68
|
+
* expression into elements, which is expensive to build; {@link #_clearCache}
|
|
69
|
+
* discards it when the grammar's elements change.
|
|
60
70
|
*/
|
|
61
71
|
class Lexer {
|
|
62
72
|
_grammar: Grammar
|
|
@@ -98,37 +108,43 @@ class Lexer {
|
|
|
98
108
|
*/
|
|
99
109
|
getTokens(elements: string[]) {
|
|
100
110
|
const tokens: Token[] = []
|
|
101
|
-
|
|
111
|
+
// a prefix minus, held back until the element it applies to is known. It
|
|
112
|
+
// carries its own raw so that whitespace arriving before that element ("-
|
|
113
|
+
// 1") accumulates on the minus rather than on the token before it, which
|
|
114
|
+
// is what lets the parser's error messages quote the expression verbatim.
|
|
115
|
+
let pendingMinus: Token | undefined
|
|
102
116
|
for (const element of elements) {
|
|
103
117
|
if (this._isWhitespace(element)) {
|
|
104
|
-
const last = tokens.at(-1)
|
|
118
|
+
const last = pendingMinus ?? tokens.at(-1)
|
|
105
119
|
if (last) {
|
|
106
120
|
last.raw += element
|
|
107
121
|
}
|
|
108
122
|
} else if (element === '-' && this._isNegative(tokens)) {
|
|
109
123
|
// a second prefix minus in a row ("- -x"): emit the pending one as a
|
|
110
124
|
// unary operator so this one can negate whatever comes next
|
|
111
|
-
if (
|
|
112
|
-
tokens.push(
|
|
125
|
+
if (pendingMinus) {
|
|
126
|
+
tokens.push(pendingMinus)
|
|
113
127
|
}
|
|
114
|
-
|
|
115
|
-
} else if (
|
|
116
|
-
negate = false
|
|
128
|
+
pendingMinus = unaryMinusToken()
|
|
129
|
+
} else if (pendingMinus) {
|
|
117
130
|
if (numericRegex.exec(element)) {
|
|
118
131
|
// fold the sign into the number, so "-1" stays a single literal
|
|
119
|
-
|
|
132
|
+
const token = this._createToken('-' + element)
|
|
133
|
+
token.raw = pendingMinus.raw + element
|
|
134
|
+
tokens.push(token)
|
|
120
135
|
} else {
|
|
121
136
|
// anything else gets a standalone prefix operator, letting "-x",
|
|
122
137
|
// "-(a + b)" and "-foo.bar" negate a computed value
|
|
123
|
-
tokens.push(
|
|
138
|
+
tokens.push(pendingMinus, this._createToken(element))
|
|
124
139
|
}
|
|
140
|
+
pendingMinus = undefined
|
|
125
141
|
} else {
|
|
126
142
|
tokens.push(this._createToken(element))
|
|
127
143
|
}
|
|
128
144
|
}
|
|
129
145
|
// Catch a - at the end of the string. Let the parser handle that issue.
|
|
130
|
-
if (
|
|
131
|
-
tokens.push(
|
|
146
|
+
if (pendingMinus) {
|
|
147
|
+
tokens.push(pendingMinus)
|
|
132
148
|
}
|
|
133
149
|
return tokens
|
|
134
150
|
}
|
|
@@ -256,10 +272,8 @@ class Lexer {
|
|
|
256
272
|
* @private
|
|
257
273
|
*/
|
|
258
274
|
_isNegative(tokens: Token[]) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
return minusNegatesAfter.has(tokens[tokens.length - 1]!.type)
|
|
275
|
+
const last = tokens.at(-1)
|
|
276
|
+
return !last || minusNegatesAfter.has(last.type)
|
|
263
277
|
}
|
|
264
278
|
|
|
265
279
|
/**
|
|
@@ -366,10 +380,7 @@ class Lexer {
|
|
|
366
380
|
}
|
|
367
381
|
|
|
368
382
|
_unescapeTemplateString(str: string) {
|
|
369
|
-
return str
|
|
370
|
-
.replaceAll('\\`', '`')
|
|
371
|
-
.replaceAll(String.raw`\$`, '$')
|
|
372
|
-
.replaceAll('\\\\', '\\')
|
|
383
|
+
return str.replaceAll(templateEscRegex, '$1')
|
|
373
384
|
}
|
|
374
385
|
}
|
|
375
386
|
|