@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
package/src/parser/Parser.ts
CHANGED
|
@@ -32,7 +32,7 @@ const tokenHandlers: Record<
|
|
|
32
32
|
/**
|
|
33
33
|
* The Parser is a state machine that converts tokens from the {@link Lexer}
|
|
34
34
|
* into an Abstract Syntax Tree (AST), capable of being evaluated in any
|
|
35
|
-
* context by
|
|
35
|
+
* context by {@link compileAst}. The Parser expects that all tokens
|
|
36
36
|
* provided to it are legal and typed properly according to the grammar, but
|
|
37
37
|
* accepts that the tokens may still be in an invalid order or in some other
|
|
38
38
|
* unparsable configuration that requires it to throw an Error.
|
|
@@ -52,13 +52,11 @@ class Parser {
|
|
|
52
52
|
_state: string
|
|
53
53
|
_tree: AstNode | null
|
|
54
54
|
_exprStr: string
|
|
55
|
-
_relative: boolean
|
|
56
55
|
_stopMap: Record<string, string>
|
|
57
56
|
_cursor?: AstNode | null
|
|
58
57
|
_subParser?: Parser
|
|
59
58
|
_parentStop?: boolean
|
|
60
59
|
_nextIdentEncapsulate?: boolean
|
|
61
|
-
_nextIdentRelative?: boolean
|
|
62
60
|
_curObjKey?: string
|
|
63
61
|
_sequenceExpressions?: AstNode[]
|
|
64
62
|
|
|
@@ -73,7 +71,6 @@ class Parser {
|
|
|
73
71
|
this._state = 'expectOperand'
|
|
74
72
|
this._tree = null
|
|
75
73
|
this._exprStr = prefix || ''
|
|
76
|
-
this._relative = false
|
|
77
74
|
this._stopMap = stopMap || {}
|
|
78
75
|
}
|
|
79
76
|
|
|
@@ -143,7 +140,7 @@ class Parser {
|
|
|
143
140
|
/**
|
|
144
141
|
* Marks this Parser instance as completed and retrieves the full AST.
|
|
145
142
|
* @returns {{}|null} a full expression tree, ready for evaluation by the
|
|
146
|
-
* {@link
|
|
143
|
+
* {@link compileAst} function, or null if no tokens were passed to
|
|
147
144
|
* the parser before complete was called
|
|
148
145
|
* @throws {Error} if the parser is not in a state where it's legal to end
|
|
149
146
|
* the expression, indicating that the expression is incomplete
|
|
@@ -179,14 +176,6 @@ class Parser {
|
|
|
179
176
|
return this._cursor ? this._tree : null
|
|
180
177
|
}
|
|
181
178
|
|
|
182
|
-
/**
|
|
183
|
-
* Indicates whether the expression tree contains a relative path identifier.
|
|
184
|
-
* @returns {boolean} true if a relative identifier exists false otherwise.
|
|
185
|
-
*/
|
|
186
|
-
isRelative() {
|
|
187
|
-
return this._relative
|
|
188
|
-
}
|
|
189
|
-
|
|
190
179
|
/**
|
|
191
180
|
* Ends a subexpression by completing the subParser and passing its result
|
|
192
181
|
* to the subHandler configured in the current state.
|
package/src/parser/handlers.ts
CHANGED
|
@@ -64,7 +64,7 @@ export function arrayVal(this: Parser, ast: AstNode | null) {
|
|
|
64
64
|
export function binaryOp(this: Parser, token: Token) {
|
|
65
65
|
if (token.value === '=') {
|
|
66
66
|
// `from` marks a member access such as `a.b`; only a bare name can be
|
|
67
|
-
// assigned to, since the
|
|
67
|
+
// assigned to, since the compiled closure writes straight into the context
|
|
68
68
|
if (
|
|
69
69
|
this._cursor?.type !== 'Identifier' ||
|
|
70
70
|
(this._cursor as Identifier).from
|
|
@@ -90,9 +90,15 @@ export function binaryOp(this: Parser, token: Token) {
|
|
|
90
90
|
if (!parentExpr.operator) {
|
|
91
91
|
break
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
// a prefix operator binds tighter than any binary one, so `-x ^ 2` groups
|
|
94
|
+
// as `(-x) ^ 2` — the same way `-2 ^ 2` already does, since the Lexer folds
|
|
95
|
+
// that sign into the literal. Looking `-` up in the grammar finds its
|
|
96
|
+
// binary precedence instead, which is lower than `^`'s and gave `-(x ^ 2)`
|
|
97
|
+
const parentPrecedence =
|
|
98
|
+
parent.type === 'UnaryExpression'
|
|
99
|
+
? Infinity
|
|
100
|
+
: precedenceOf(this._grammar.elements[parentExpr.operator])
|
|
101
|
+
if (parentPrecedence < precedence) {
|
|
96
102
|
break
|
|
97
103
|
}
|
|
98
104
|
this._cursor = parent
|
|
@@ -115,18 +121,20 @@ export function binaryOp(this: Parser, token: Token) {
|
|
|
115
121
|
*/
|
|
116
122
|
export function dot(this: Parser) {
|
|
117
123
|
const cursor = this._cursor
|
|
118
|
-
//
|
|
119
|
-
// still waiting on its right-hand side
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
// a dot continues an identifier chain. With nothing to continue — no cursor,
|
|
125
|
+
// or an operator still waiting on its right-hand side — it would instead open
|
|
126
|
+
// a relative path, the leading dot of `list[.price > 5]`. This fork removed
|
|
127
|
+
// array filtering expressions, which are the only construct that gives a
|
|
128
|
+
// relative path a root to resolve against, so it is rejected here rather than
|
|
129
|
+
// parsed into a tree that can only fail once it is evaluated.
|
|
130
|
+
if (
|
|
131
|
+
!cursor ||
|
|
132
|
+
cursor.type === 'UnaryExpression' ||
|
|
133
|
+
(cursor.type === 'BinaryExpression' && !cursor.right)
|
|
134
|
+
) {
|
|
135
|
+
throw new Error(`Relative paths are not supported: ${this._exprStr}`)
|
|
129
136
|
}
|
|
137
|
+
this._nextIdentEncapsulate = true
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
/**
|
|
@@ -138,7 +146,6 @@ export function filter(this: Parser, ast: AstNode | null) {
|
|
|
138
146
|
const node: FilterExpression = {
|
|
139
147
|
type: 'FilterExpression',
|
|
140
148
|
expr: ast!,
|
|
141
|
-
relative: this._subParser!.isRelative(),
|
|
142
149
|
subject: this._cursor!
|
|
143
150
|
}
|
|
144
151
|
this._placeBeforeCursor(node)
|
|
@@ -162,12 +169,11 @@ export function functionCall(this: Parser) {
|
|
|
162
169
|
// there is nothing to look up in the function pool
|
|
163
170
|
throw new Error(`Functions must be called by name: ${this._exprStr}`)
|
|
164
171
|
}
|
|
165
|
-
const { from } = cursor as Identifier
|
|
172
|
+
const { from, value } = cursor as Identifier
|
|
166
173
|
const node: FunctionCall = {
|
|
167
174
|
type: 'FunctionCall',
|
|
168
|
-
name:
|
|
169
|
-
args: from ? [from] : []
|
|
170
|
-
pool: 'functions'
|
|
175
|
+
name: value,
|
|
176
|
+
args: from ? [from] : []
|
|
171
177
|
}
|
|
172
178
|
this._placeBeforeCursor(node)
|
|
173
179
|
}
|
|
@@ -186,10 +192,6 @@ export function identifier(this: Parser, token: Token) {
|
|
|
186
192
|
this._placeBeforeCursor(node)
|
|
187
193
|
this._nextIdentEncapsulate = false
|
|
188
194
|
} else {
|
|
189
|
-
if (this._nextIdentRelative) {
|
|
190
|
-
node.relative = true
|
|
191
|
-
this._nextIdentRelative = false
|
|
192
|
-
}
|
|
193
195
|
this._placeAtCursor(node)
|
|
194
196
|
}
|
|
195
197
|
}
|
|
@@ -274,7 +276,7 @@ export function objStart(this: Parser) {
|
|
|
274
276
|
export function objVal(this: Parser, ast: AstNode | null) {
|
|
275
277
|
// defined rather than assigned so that the key "__proto__" becomes an
|
|
276
278
|
// ordinary entry of the node's key map instead of re-pointing its prototype,
|
|
277
|
-
// which dropped the entry before
|
|
279
|
+
// which dropped the entry before it could be compiled
|
|
278
280
|
Object.defineProperty(
|
|
279
281
|
(this._cursor as ObjectLiteral).value,
|
|
280
282
|
this._curObjKey!,
|
|
@@ -313,17 +315,32 @@ export function ternaryMid(this: Parser, ast: AstNode | null) {
|
|
|
313
315
|
}
|
|
314
316
|
|
|
315
317
|
/**
|
|
316
|
-
* Handles the start of a new ternary expression by encapsulating the
|
|
317
|
-
*
|
|
318
|
-
*
|
|
318
|
+
* Handles the start of a new ternary expression by encapsulating the tree so
|
|
319
|
+
* far in a ConditionalExpression node, and using it as the test element.
|
|
320
|
+
*
|
|
321
|
+
* Every operator binds tighter than the conditional and so belongs in the test
|
|
322
|
+
* — except `=`, which binds looser. `x = a ? b : c` therefore assigns the
|
|
323
|
+
* conditional rather than testing the assignment, which had stored `a` in `x`.
|
|
319
324
|
*/
|
|
320
325
|
export function ternaryStart(this: Parser) {
|
|
326
|
+
let assignment: AstNode | undefined
|
|
327
|
+
let test = this._tree!
|
|
328
|
+
while (test.type === 'AssignmentExpression' && test.right) {
|
|
329
|
+
assignment = test
|
|
330
|
+
test = test.right
|
|
331
|
+
}
|
|
332
|
+
|
|
321
333
|
const node: ConditionalExpression = {
|
|
322
334
|
type: 'ConditionalExpression',
|
|
323
|
-
test
|
|
335
|
+
test
|
|
336
|
+
}
|
|
337
|
+
if (assignment) {
|
|
338
|
+
assignment.right = node
|
|
339
|
+
this._setParent(node, assignment)
|
|
340
|
+
} else {
|
|
341
|
+
this._tree = node
|
|
324
342
|
}
|
|
325
|
-
this.
|
|
326
|
-
this._cursor = this._tree
|
|
343
|
+
this._cursor = node
|
|
327
344
|
}
|
|
328
345
|
|
|
329
346
|
/**
|
package/src/parser/states.ts
CHANGED
|
@@ -97,10 +97,6 @@ export const states: States = {
|
|
|
97
97
|
colon: { toState: 'objVal' }
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
|
-
postArgs: {
|
|
101
|
-
tokenTypes: afterOperand,
|
|
102
|
-
completable: true
|
|
103
|
-
},
|
|
104
100
|
identifier: {
|
|
105
101
|
tokenTypes: {
|
|
106
102
|
...afterOperand,
|
|
@@ -131,7 +127,9 @@ export const states: States = {
|
|
|
131
127
|
subHandler: h.argVal,
|
|
132
128
|
endStates: {
|
|
133
129
|
comma: 'argVal',
|
|
134
|
-
|
|
130
|
+
// a call's result is an ordinary operand: it can be operated on or
|
|
131
|
+
// drilled into, but not called again, since only a name can be called
|
|
132
|
+
closeParen: 'expectBinOp'
|
|
135
133
|
}
|
|
136
134
|
},
|
|
137
135
|
objVal: {
|
package/src/types.ts
CHANGED
|
@@ -38,7 +38,6 @@ export interface Identifier extends AstNode {
|
|
|
38
38
|
type: 'Identifier'
|
|
39
39
|
value: string
|
|
40
40
|
from?: AstNode
|
|
41
|
-
relative?: boolean
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
export interface BinaryExpression extends AstNode {
|
|
@@ -77,13 +76,11 @@ export interface FunctionCall extends AstNode {
|
|
|
77
76
|
type: 'FunctionCall'
|
|
78
77
|
name: string
|
|
79
78
|
args: AstNode[]
|
|
80
|
-
pool: 'functions'
|
|
81
79
|
}
|
|
82
80
|
|
|
83
81
|
export interface FilterExpression extends AstNode {
|
|
84
82
|
type: 'FilterExpression'
|
|
85
83
|
expr: AstNode
|
|
86
|
-
relative: boolean
|
|
87
84
|
subject: AstNode
|
|
88
85
|
}
|
|
89
86
|
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { Grammar } from '../grammar.ts';
|
|
2
|
-
import type { AstNode, JexlValue } from '../types.ts';
|
|
3
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
15
|
-
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
16
|
-
* tree
|
|
17
|
-
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
18
|
-
* accessed to resolve the value of each non-relative identifier.
|
|
19
|
-
* @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
|
|
20
|
-
* to resolve the value of a relative identifier.
|
|
21
|
-
*/
|
|
22
|
-
declare class Evaluator {
|
|
23
|
-
_grammar: Grammar;
|
|
24
|
-
_context: Record<string, JexlValue>;
|
|
25
|
-
_relContext: Record<string, JexlValue>;
|
|
26
|
-
constructor(grammar: Grammar, context?: Record<string, JexlValue>, relativeContext?: Record<string, JexlValue>);
|
|
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.
|
|
32
|
-
* @param {{}} ast An expression tree object
|
|
33
|
-
* @returns {*} the resulting value of the expression.
|
|
34
|
-
*/
|
|
35
|
-
eval(ast: AstNode): JexlValue;
|
|
36
|
-
}
|
|
37
|
-
export default Evaluator;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Jexl
|
|
4
|
-
* Copyright 2020 Tom Shawver
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const compile_ts_1 = require("./compile.js");
|
|
8
|
-
/**
|
|
9
|
-
* The Evaluator carries everything an expression is evaluated against: the
|
|
10
|
-
* grammar, the context, and a relative context to be used as the root for
|
|
11
|
-
* relative identifiers. When any of these change, a new instance is required.
|
|
12
|
-
* However, a single instance can be used to evaluate many different
|
|
13
|
-
* expressions, and does not have to be reinstantiated for each.
|
|
14
|
-
*
|
|
15
|
-
* The work of evaluation itself lives in {@link compileAst}, which lowers a
|
|
16
|
-
* tree to closures. Prefer compiling once and reusing the result — that is what
|
|
17
|
-
* {@link Expression} does — over calling {@link #eval}, which compiles the tree
|
|
18
|
-
* it is given every time.
|
|
19
|
-
*
|
|
20
|
-
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
21
|
-
* tree
|
|
22
|
-
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
23
|
-
* accessed to resolve the value of each non-relative identifier.
|
|
24
|
-
* @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
|
|
25
|
-
* to resolve the value of a relative identifier.
|
|
26
|
-
*/
|
|
27
|
-
class Evaluator {
|
|
28
|
-
_grammar;
|
|
29
|
-
_context;
|
|
30
|
-
_relContext;
|
|
31
|
-
constructor(grammar, context, relativeContext) {
|
|
32
|
-
this._grammar = grammar;
|
|
33
|
-
this._context = context || {};
|
|
34
|
-
this._relContext = relativeContext || this._context;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Compiles and evaluates an expression tree within the configured context.
|
|
38
|
-
* Convenient for a one-shot evaluation; for repeated evaluation of the same
|
|
39
|
-
* tree, hold onto the closure from {@link compileAst} instead so the tree is
|
|
40
|
-
* only lowered once.
|
|
41
|
-
* @param {{}} ast An expression tree object
|
|
42
|
-
* @returns {*} the resulting value of the expression.
|
|
43
|
-
*/
|
|
44
|
-
eval(ast) {
|
|
45
|
-
return (0, compile_ts_1.compileAst)(ast, this._grammar)(this);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
exports.default = Evaluator;
|
|
49
|
-
//# sourceMappingURL=Evaluator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Evaluator.js","sourceRoot":"","sources":["../../src/evaluator/Evaluator.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,6CAAyC;AAKzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,SAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAA2B;IACnC,WAAW,CAA2B;IAEtC,YACE,OAAgB,EAChB,OAAmC,EACnC,eAA2C;QAE3C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,GAAG,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAA;IACrD,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,GAAY;QACf,OAAO,IAAA,uBAAU,EAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;CACF;AAED,kBAAe,SAAS,CAAA"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { Grammar } from '../grammar.ts';
|
|
2
|
-
import type { AstNode, JexlValue } from '../types.ts';
|
|
3
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
15
|
-
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
16
|
-
* tree
|
|
17
|
-
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
18
|
-
* accessed to resolve the value of each non-relative identifier.
|
|
19
|
-
* @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
|
|
20
|
-
* to resolve the value of a relative identifier.
|
|
21
|
-
*/
|
|
22
|
-
declare class Evaluator {
|
|
23
|
-
_grammar: Grammar;
|
|
24
|
-
_context: Record<string, JexlValue>;
|
|
25
|
-
_relContext: Record<string, JexlValue>;
|
|
26
|
-
constructor(grammar: Grammar, context?: Record<string, JexlValue>, relativeContext?: Record<string, JexlValue>);
|
|
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.
|
|
32
|
-
* @param {{}} ast An expression tree object
|
|
33
|
-
* @returns {*} the resulting value of the expression.
|
|
34
|
-
*/
|
|
35
|
-
eval(ast: AstNode): JexlValue;
|
|
36
|
-
}
|
|
37
|
-
export default Evaluator;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Jexl
|
|
3
|
-
* Copyright 2020 Tom Shawver
|
|
4
|
-
*/
|
|
5
|
-
import { compileAst } from "./compile.js";
|
|
6
|
-
/**
|
|
7
|
-
* The Evaluator carries everything an expression is evaluated against: the
|
|
8
|
-
* grammar, the context, and a relative context to be used as the root for
|
|
9
|
-
* relative identifiers. When any of these change, a new instance is required.
|
|
10
|
-
* However, a single instance can be used to evaluate many different
|
|
11
|
-
* expressions, and does not have to be reinstantiated for each.
|
|
12
|
-
*
|
|
13
|
-
* The work of evaluation itself lives in {@link compileAst}, which lowers a
|
|
14
|
-
* tree to closures. Prefer compiling once and reusing the result — that is what
|
|
15
|
-
* {@link Expression} does — over calling {@link #eval}, which compiles the tree
|
|
16
|
-
* it is given every time.
|
|
17
|
-
*
|
|
18
|
-
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
19
|
-
* tree
|
|
20
|
-
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
21
|
-
* accessed to resolve the value of each non-relative identifier.
|
|
22
|
-
* @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
|
|
23
|
-
* to resolve the value of a relative identifier.
|
|
24
|
-
*/
|
|
25
|
-
class Evaluator {
|
|
26
|
-
_grammar;
|
|
27
|
-
_context;
|
|
28
|
-
_relContext;
|
|
29
|
-
constructor(grammar, context, relativeContext) {
|
|
30
|
-
this._grammar = grammar;
|
|
31
|
-
this._context = context || {};
|
|
32
|
-
this._relContext = relativeContext || this._context;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Compiles and evaluates an expression tree within the configured context.
|
|
36
|
-
* Convenient for a one-shot evaluation; for repeated evaluation of the same
|
|
37
|
-
* tree, hold onto the closure from {@link compileAst} instead so the tree is
|
|
38
|
-
* only lowered once.
|
|
39
|
-
* @param {{}} ast An expression tree object
|
|
40
|
-
* @returns {*} the resulting value of the expression.
|
|
41
|
-
*/
|
|
42
|
-
eval(ast) {
|
|
43
|
-
return compileAst(ast, this._grammar)(this);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
export default Evaluator;
|
|
47
|
-
//# sourceMappingURL=Evaluator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Evaluator.js","sourceRoot":"","sources":["../../src/evaluator/Evaluator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAKzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,SAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAA2B;IACnC,WAAW,CAA2B;IAEtC,YACE,OAAgB,EAChB,OAAmC,EACnC,eAA2C;QAE3C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,GAAG,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAA;IACrD,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,GAAY;QACf,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;CACF;AAED,eAAe,SAAS,CAAA"}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Jexl
|
|
3
|
-
* Copyright 2020 Tom Shawver
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { compileAst } from './compile.ts'
|
|
7
|
-
|
|
8
|
-
import type { Grammar } from '../grammar.ts'
|
|
9
|
-
import type { AstNode, JexlValue } from '../types.ts'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The Evaluator carries everything an expression is evaluated against: the
|
|
13
|
-
* grammar, the context, and a relative context to be used as the root for
|
|
14
|
-
* relative identifiers. When any of these change, a new instance is required.
|
|
15
|
-
* However, a single instance can be used to evaluate many different
|
|
16
|
-
* expressions, and does not have to be reinstantiated for each.
|
|
17
|
-
*
|
|
18
|
-
* The work of evaluation itself lives in {@link compileAst}, which lowers a
|
|
19
|
-
* tree to closures. Prefer compiling once and reusing the result — that is what
|
|
20
|
-
* {@link Expression} does — over calling {@link #eval}, which compiles the tree
|
|
21
|
-
* it is given every time.
|
|
22
|
-
*
|
|
23
|
-
* @param {{}} grammar A grammar object against which to evaluate the expression
|
|
24
|
-
* tree
|
|
25
|
-
* @param {{}} [context] A map of variable keys to their values. This will be
|
|
26
|
-
* accessed to resolve the value of each non-relative identifier.
|
|
27
|
-
* @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
|
|
28
|
-
* to resolve the value of a relative identifier.
|
|
29
|
-
*/
|
|
30
|
-
class Evaluator {
|
|
31
|
-
_grammar: Grammar
|
|
32
|
-
_context: Record<string, JexlValue>
|
|
33
|
-
_relContext: Record<string, JexlValue>
|
|
34
|
-
|
|
35
|
-
constructor(
|
|
36
|
-
grammar: Grammar,
|
|
37
|
-
context?: Record<string, JexlValue>,
|
|
38
|
-
relativeContext?: Record<string, JexlValue>
|
|
39
|
-
) {
|
|
40
|
-
this._grammar = grammar
|
|
41
|
-
this._context = context || {}
|
|
42
|
-
this._relContext = relativeContext || this._context
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Compiles and evaluates an expression tree within the configured context.
|
|
47
|
-
* Convenient for a one-shot evaluation; for repeated evaluation of the same
|
|
48
|
-
* tree, hold onto the closure from {@link compileAst} instead so the tree is
|
|
49
|
-
* only lowered once.
|
|
50
|
-
* @param {{}} ast An expression tree object
|
|
51
|
-
* @returns {*} the resulting value of the expression.
|
|
52
|
-
*/
|
|
53
|
-
eval(ast: AstNode): JexlValue {
|
|
54
|
-
return compileAst(ast, this._grammar)(this)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export default Evaluator
|