@jbrowse/jexl 2.3.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/CHANGELOG.md +222 -0
- package/LICENSE.txt +19 -0
- package/README.md +216 -0
- package/dist/Expression.d.ts +38 -0
- package/dist/Expression.js +75 -0
- package/dist/Expression.js.map +1 -0
- package/dist/Jexl.d.ts +148 -0
- package/dist/Jexl.js +208 -0
- package/dist/Jexl.js.map +1 -0
- package/dist/Lexer.d.ts +130 -0
- package/dist/Lexer.js +321 -0
- package/dist/Lexer.js.map +1 -0
- package/dist/PromiseSync.d.ts +13 -0
- package/dist/PromiseSync.js +80 -0
- package/dist/PromiseSync.js.map +1 -0
- package/dist/evaluator/Evaluator.d.ts +92 -0
- package/dist/evaluator/Evaluator.js +153 -0
- package/dist/evaluator/Evaluator.js.map +1 -0
- package/dist/evaluator/handlers.d.ts +111 -0
- package/dist/evaluator/handlers.js +216 -0
- package/dist/evaluator/handlers.js.map +1 -0
- package/dist/grammar.d.ts +25 -0
- package/dist/grammar.js +179 -0
- package/dist/grammar.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +1 -0
- package/dist/parser/Parser.d.ts +112 -0
- package/dist/parser/Parser.js +233 -0
- package/dist/parser/Parser.js.map +1 -0
- package/dist/parser/handlers.d.ts +112 -0
- package/dist/parser/handlers.js +302 -0
- package/dist/parser/handlers.js.map +1 -0
- package/dist/parser/states.d.ts +47 -0
- package/dist/parser/states.js +195 -0
- package/dist/parser/states.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/esm/Expression.d.ts +38 -0
- package/esm/Expression.js +70 -0
- package/esm/Expression.js.map +1 -0
- package/esm/Jexl.d.ts +148 -0
- package/esm/Jexl.js +202 -0
- package/esm/Jexl.js.map +1 -0
- package/esm/Lexer.d.ts +130 -0
- package/esm/Lexer.js +319 -0
- package/esm/Lexer.js.map +1 -0
- package/esm/PromiseSync.d.ts +13 -0
- package/esm/PromiseSync.js +78 -0
- package/esm/PromiseSync.js.map +1 -0
- package/esm/evaluator/Evaluator.d.ts +92 -0
- package/esm/evaluator/Evaluator.js +118 -0
- package/esm/evaluator/Evaluator.js.map +1 -0
- package/esm/evaluator/handlers.d.ts +111 -0
- package/esm/evaluator/handlers.js +202 -0
- package/esm/evaluator/handlers.js.map +1 -0
- package/esm/grammar.d.ts +25 -0
- package/esm/grammar.js +175 -0
- package/esm/grammar.js.map +1 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +9 -0
- package/esm/index.js.map +1 -0
- package/esm/parser/Parser.d.ts +112 -0
- package/esm/parser/Parser.js +198 -0
- package/esm/parser/Parser.js.map +1 -0
- package/esm/parser/handlers.d.ts +112 -0
- package/esm/parser/handlers.js +280 -0
- package/esm/parser/handlers.js.map +1 -0
- package/esm/parser/states.d.ts +47 -0
- package/esm/parser/states.js +159 -0
- package/esm/parser/states.js.map +1 -0
- package/esm/types.d.ts +77 -0
- package/esm/types.js +6 -0
- package/esm/types.js.map +1 -0
- package/package.json +67 -0
- package/src/Expression.ts +95 -0
- package/src/Jexl.ts +232 -0
- package/src/Lexer.ts +344 -0
- package/src/PromiseSync.ts +86 -0
- package/src/evaluator/Evaluator.ts +153 -0
- package/src/evaluator/handlers.ts +226 -0
- package/src/grammar.ts +200 -0
- package/src/index.ts +10 -0
- package/src/parser/Parser.ts +235 -0
- package/src/parser/handlers.ts +309 -0
- package/src/parser/states.ts +177 -0
- package/src/types.ts +107 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Jexl
|
|
3
|
+
* Copyright 2020 Tom Shawver
|
|
4
|
+
*/
|
|
5
|
+
import Lexer from "./Lexer.js";
|
|
6
|
+
import PromiseSync from "./PromiseSync.js";
|
|
7
|
+
import Evaluator from "./evaluator/Evaluator.js";
|
|
8
|
+
import Parser from "./parser/Parser.js";
|
|
9
|
+
class Expression {
|
|
10
|
+
constructor(grammar, exprStr) {
|
|
11
|
+
this._grammar = grammar;
|
|
12
|
+
this._exprStr = exprStr;
|
|
13
|
+
this._ast = null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Forces a compilation of the expression string that this Expression object
|
|
17
|
+
* was constructed with. This function can be called multiple times; useful
|
|
18
|
+
* if the language elements of the associated Jexl instance change.
|
|
19
|
+
* @returns {Expression} this Expression instance, for convenience
|
|
20
|
+
*/
|
|
21
|
+
compile() {
|
|
22
|
+
const lexer = new Lexer(this._grammar);
|
|
23
|
+
const parser = new Parser(this._grammar, lexer);
|
|
24
|
+
const tokens = lexer.tokenize(this._exprStr);
|
|
25
|
+
parser.addTokens(tokens);
|
|
26
|
+
this._ast = parser.complete();
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Asynchronously evaluates the expression within an optional context.
|
|
31
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
32
|
+
* made accessible to the Jexl expression when evaluating it
|
|
33
|
+
* @returns {Promise<*>} resolves with the result of the evaluation.
|
|
34
|
+
*/
|
|
35
|
+
eval(context = {}) {
|
|
36
|
+
return this._eval(context, Promise);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Synchronously evaluates the expression within an optional context.
|
|
40
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
41
|
+
* made accessible to the Jexl expression when evaluating it
|
|
42
|
+
* @returns {*} the result of the evaluation.
|
|
43
|
+
* @throws {*} on error
|
|
44
|
+
*/
|
|
45
|
+
evalSync(context = {}) {
|
|
46
|
+
const res = this._eval(context, PromiseSync);
|
|
47
|
+
if (res.error) {
|
|
48
|
+
if (res.error instanceof Error) {
|
|
49
|
+
throw res.error;
|
|
50
|
+
}
|
|
51
|
+
throw new Error(typeof res.error === 'string' ? res.error : JSON.stringify(res.error));
|
|
52
|
+
}
|
|
53
|
+
return res.value;
|
|
54
|
+
}
|
|
55
|
+
_eval(context, promise) {
|
|
56
|
+
return promise.resolve().then(() => {
|
|
57
|
+
const ast = this._getAst();
|
|
58
|
+
const evaluator = new Evaluator(this._grammar, context, undefined, promise);
|
|
59
|
+
return evaluator.eval(ast);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
_getAst() {
|
|
63
|
+
if (!this._ast) {
|
|
64
|
+
this.compile();
|
|
65
|
+
}
|
|
66
|
+
return this._ast;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export default Expression;
|
|
70
|
+
//# sourceMappingURL=Expression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,WAAW,MAAM,kBAAkB,CAAA;AAC1C,OAAO,SAAS,MAAM,0BAA0B,CAAA;AAChD,OAAO,MAAM,MAAM,oBAAoB,CAAA;AAWvC,MAAM,UAAU;IAKd,YAAY,OAAgB,EAAE,OAAe;QAC3C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,OAAO,GAAG,EAAE;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,GAAG,EAAE;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,WAAkB,CAAgB,CAAA;QAClE,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,GAAG,CAAC,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC/B,MAAM,GAAG,CAAC,KAAK,CAAA;YACjB,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;QACxF,CAAC;QACD,OAAO,GAAG,CAAC,KAAK,CAAA;IAClB,CAAC;IAED,KAAK,CAAC,OAAY,EAAE,OAA2B;QAC7C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YACjC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;YAC1B,MAAM,SAAS,GAAG,IAAI,SAAS,CAC7B,IAAI,CAAC,QAAQ,EACb,OAAO,EACP,SAAS,EACT,OAAO,CACR,CAAA;YACD,OAAO,SAAS,CAAC,IAAI,CAAC,GAAI,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,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
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import Expression from './Expression.ts';
|
|
2
|
+
interface Grammar {
|
|
3
|
+
elements: Record<string, any>;
|
|
4
|
+
functions: Record<string, (...args: any[]) => any>;
|
|
5
|
+
transforms: Record<string, (val: any, ...args: any[]) => any>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Jexl is the Javascript Expression Language, capable of parsing and
|
|
9
|
+
* evaluating basic to complex expression strings, combined with advanced
|
|
10
|
+
* xpath-like drilldown into native Javascript objects.
|
|
11
|
+
* @constructor
|
|
12
|
+
*/
|
|
13
|
+
declare class Jexl {
|
|
14
|
+
_grammar: Grammar;
|
|
15
|
+
constructor();
|
|
16
|
+
/**
|
|
17
|
+
* Adds a binary operator to Jexl at the specified precedence. The higher the
|
|
18
|
+
* precedence, the earlier the operator is applied in the order of operations.
|
|
19
|
+
* For example, * has a higher precedence than +, because multiplication comes
|
|
20
|
+
* before division.
|
|
21
|
+
*
|
|
22
|
+
* Please see grammar.js for a listing of all default operators and their
|
|
23
|
+
* precedence values in order to choose the appropriate precedence for the
|
|
24
|
+
* new operator.
|
|
25
|
+
* @param {string} operator The operator string to be added
|
|
26
|
+
* @param {number} precedence The operator's precedence
|
|
27
|
+
* @param {function} fn A function to run to calculate the result. The function
|
|
28
|
+
* will be called with two arguments: left and right, denoting the values
|
|
29
|
+
* on either side of the operator. It should return either the resulting
|
|
30
|
+
* value, or a Promise that resolves with the resulting value.
|
|
31
|
+
* @param {boolean} [manualEval] If true, the `left` and `right` arguments
|
|
32
|
+
* will be wrapped in objects with an `eval` function. Calling
|
|
33
|
+
* left.eval() or right.eval() will return a promise that resolves to
|
|
34
|
+
* that operand's actual value. This is useful to conditionally evaluate
|
|
35
|
+
* operands.
|
|
36
|
+
*/
|
|
37
|
+
addBinaryOp(operator: string, precedence: number, fn: (left: any, right: any) => any, manualEval?: boolean): void;
|
|
38
|
+
/**
|
|
39
|
+
* Adds or replaces an expression function in this Jexl instance.
|
|
40
|
+
* @param {string} name The name of the expression function, as it will be
|
|
41
|
+
* used within Jexl expressions
|
|
42
|
+
* @param {function} fn The javascript function to be executed when this
|
|
43
|
+
* expression function is invoked. It will be provided with each argument
|
|
44
|
+
* supplied in the expression, in the same order.
|
|
45
|
+
*/
|
|
46
|
+
addFunction(name: string, fn: (...args: any[]) => any): void;
|
|
47
|
+
/**
|
|
48
|
+
* Syntactic sugar for calling {@link #addFunction} repeatedly. This function
|
|
49
|
+
* accepts a map of one or more expression function names to their javascript
|
|
50
|
+
* function counterpart.
|
|
51
|
+
* @param {{}} map A map of expression function names to javascript functions
|
|
52
|
+
*/
|
|
53
|
+
addFunctions(map: Record<string, (...args: any[]) => any>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Adds a unary operator to Jexl. Unary operators are currently only supported
|
|
56
|
+
* on the left side of the value on which it will operate.
|
|
57
|
+
* @param {string} operator The operator string to be added
|
|
58
|
+
* @param {function} fn A function to run to calculate the result. The function
|
|
59
|
+
* will be called with one argument: the literal value to the right of the
|
|
60
|
+
* operator. It should return either the resulting value, or a Promise
|
|
61
|
+
* that resolves with the resulting value.
|
|
62
|
+
*/
|
|
63
|
+
addUnaryOp(operator: string, fn: (right: any) => any): void;
|
|
64
|
+
/**
|
|
65
|
+
* Adds or replaces a transform function in this Jexl instance.
|
|
66
|
+
* @param {string} name The name of the transform function, as it will be used
|
|
67
|
+
* within Jexl expressions
|
|
68
|
+
* @param {function} fn The function to be executed when this transform is
|
|
69
|
+
* invoked. It will be provided with at least one argument:
|
|
70
|
+
* - {*} value: The value to be transformed
|
|
71
|
+
* - {...*} args: The arguments for this transform
|
|
72
|
+
*/
|
|
73
|
+
addTransform(name: string, fn: (val: any, ...args: any[]) => any): void;
|
|
74
|
+
/**
|
|
75
|
+
* Syntactic sugar for calling {@link #addTransform} repeatedly. This function
|
|
76
|
+
* accepts a map of one or more transform names to their transform function.
|
|
77
|
+
* @param {{}} map A map of transform names to transform functions
|
|
78
|
+
*/
|
|
79
|
+
addTransforms(map: Record<string, (val: any, ...args: any[]) => any>): void;
|
|
80
|
+
/**
|
|
81
|
+
* Creates an Expression object from the given Jexl expression string, and
|
|
82
|
+
* immediately compiles it. The returned Expression object can then be
|
|
83
|
+
* evaluated multiple times with new contexts, without generating any
|
|
84
|
+
* additional string processing overhead.
|
|
85
|
+
* @param {string} expression The Jexl expression to be compiled
|
|
86
|
+
* @returns {Expression} The compiled Expression object
|
|
87
|
+
*/
|
|
88
|
+
compile(expression: string): Expression;
|
|
89
|
+
/**
|
|
90
|
+
* Constructs an Expression object from a Jexl expression string.
|
|
91
|
+
* @param {string} expression The Jexl expression to be wrapped in an
|
|
92
|
+
* Expression object
|
|
93
|
+
* @returns {Expression} The Expression object representing the given string
|
|
94
|
+
*/
|
|
95
|
+
createExpression(expression: string): Expression;
|
|
96
|
+
/**
|
|
97
|
+
* Retrieves a previously set expression function.
|
|
98
|
+
* @param {string} name The name of the expression function
|
|
99
|
+
* @returns {function} The expression function
|
|
100
|
+
*/
|
|
101
|
+
getFunction(name: string): (...args: any[]) => any;
|
|
102
|
+
/**
|
|
103
|
+
* Retrieves a previously set transform function.
|
|
104
|
+
* @param {string} name The name of the transform function
|
|
105
|
+
* @returns {function} The transform function
|
|
106
|
+
*/
|
|
107
|
+
getTransform(name: string): (val: any, ...args: any[]) => any;
|
|
108
|
+
/**
|
|
109
|
+
* Asynchronously evaluates a Jexl string within an optional context.
|
|
110
|
+
* @param {string} expression The Jexl expression to be evaluated
|
|
111
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
112
|
+
* made accessible to the Jexl expression when evaluating it
|
|
113
|
+
* @returns {Promise<*>} resolves with the result of the evaluation.
|
|
114
|
+
*/
|
|
115
|
+
eval(expression: string, context?: {}): Promise<any> | import("./PromiseSync.ts").default<any>;
|
|
116
|
+
/**
|
|
117
|
+
* Synchronously evaluates a Jexl string within an optional context.
|
|
118
|
+
* @param {string} expression The Jexl expression to be evaluated
|
|
119
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
120
|
+
* made accessible to the Jexl expression when evaluating it
|
|
121
|
+
* @returns {*} the result of the evaluation.
|
|
122
|
+
* @throws {*} on error
|
|
123
|
+
*/
|
|
124
|
+
evalSync(expression: string, context?: {}): unknown;
|
|
125
|
+
/**
|
|
126
|
+
* A JavaScript template literal to allow expressions to be defined by the
|
|
127
|
+
* syntax: expr`40 + 2`
|
|
128
|
+
* @param {Array<string>} strs
|
|
129
|
+
* @param {...any} args
|
|
130
|
+
*/
|
|
131
|
+
expr(strs: TemplateStringsArray, ...args: any[]): Expression;
|
|
132
|
+
/**
|
|
133
|
+
* Removes a binary or unary operator from the Jexl grammar.
|
|
134
|
+
* @param {string} operator The operator string to be removed
|
|
135
|
+
*/
|
|
136
|
+
removeOp(operator: string): void;
|
|
137
|
+
/**
|
|
138
|
+
* Adds an element to the grammar map used by this Jexl instance.
|
|
139
|
+
* @param {string} str The key string to be added
|
|
140
|
+
* @param {{type: <string>}} obj A map of configuration options for this
|
|
141
|
+
* grammar element
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
_addGrammarElement(str: string, obj: any): void;
|
|
145
|
+
}
|
|
146
|
+
declare const jexlInstance: Jexl;
|
|
147
|
+
export default jexlInstance;
|
|
148
|
+
export { Jexl };
|
package/esm/Jexl.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Jexl
|
|
3
|
+
* Copyright 2020 Tom Shawver
|
|
4
|
+
*/
|
|
5
|
+
import Expression from "./Expression.js";
|
|
6
|
+
import { getGrammar } from "./grammar.js";
|
|
7
|
+
/**
|
|
8
|
+
* Jexl is the Javascript Expression Language, capable of parsing and
|
|
9
|
+
* evaluating basic to complex expression strings, combined with advanced
|
|
10
|
+
* xpath-like drilldown into native Javascript objects.
|
|
11
|
+
* @constructor
|
|
12
|
+
*/
|
|
13
|
+
class Jexl {
|
|
14
|
+
constructor() {
|
|
15
|
+
this._grammar = getGrammar();
|
|
16
|
+
this.expr = this.expr.bind(this);
|
|
17
|
+
}
|
|
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 either the resulting
|
|
32
|
+
* value, or a Promise that resolves with the resulting value.
|
|
33
|
+
* @param {boolean} [manualEval] If true, the `left` and `right` arguments
|
|
34
|
+
* will be wrapped in objects with an `eval` function. Calling
|
|
35
|
+
* left.eval() or right.eval() will return a promise that resolves to
|
|
36
|
+
* that operand's actual value. This is useful to conditionally evaluate
|
|
37
|
+
* operands.
|
|
38
|
+
*/
|
|
39
|
+
addBinaryOp(operator, precedence, fn, manualEval) {
|
|
40
|
+
this._addGrammarElement(operator, {
|
|
41
|
+
type: 'binaryOp',
|
|
42
|
+
precedence: precedence,
|
|
43
|
+
[manualEval ? 'evalOnDemand' : 'eval']: fn
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Adds or replaces an expression function in this Jexl instance.
|
|
48
|
+
* @param {string} name The name of the expression function, as it will be
|
|
49
|
+
* used within Jexl expressions
|
|
50
|
+
* @param {function} fn The javascript function to be executed when this
|
|
51
|
+
* expression function is invoked. It will be provided with each argument
|
|
52
|
+
* supplied in the expression, in the same order.
|
|
53
|
+
*/
|
|
54
|
+
addFunction(name, fn) {
|
|
55
|
+
this._grammar.functions[name] = fn;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Syntactic sugar for calling {@link #addFunction} repeatedly. This function
|
|
59
|
+
* accepts a map of one or more expression function names to their javascript
|
|
60
|
+
* function counterpart.
|
|
61
|
+
* @param {{}} map A map of expression function names to javascript functions
|
|
62
|
+
*/
|
|
63
|
+
addFunctions(map) {
|
|
64
|
+
Object.assign(this._grammar.functions, map);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Adds a unary operator to Jexl. Unary operators are currently only supported
|
|
68
|
+
* on the left side of the value on which it will operate.
|
|
69
|
+
* @param {string} operator The operator string to be added
|
|
70
|
+
* @param {function} fn A function to run to calculate the result. The function
|
|
71
|
+
* will be called with one argument: the literal value to the right of the
|
|
72
|
+
* operator. It should return either the resulting value, or a Promise
|
|
73
|
+
* that resolves with the resulting value.
|
|
74
|
+
*/
|
|
75
|
+
addUnaryOp(operator, fn) {
|
|
76
|
+
this._addGrammarElement(operator, {
|
|
77
|
+
type: 'unaryOp',
|
|
78
|
+
weight: Infinity,
|
|
79
|
+
eval: fn
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Adds or replaces a transform function in this Jexl instance.
|
|
84
|
+
* @param {string} name The name of the transform function, as it will be used
|
|
85
|
+
* within Jexl expressions
|
|
86
|
+
* @param {function} fn The function to be executed when this transform is
|
|
87
|
+
* invoked. It will be provided with at least one argument:
|
|
88
|
+
* - {*} value: The value to be transformed
|
|
89
|
+
* - {...*} args: The arguments for this transform
|
|
90
|
+
*/
|
|
91
|
+
addTransform(name, fn) {
|
|
92
|
+
this._grammar.transforms[name] = fn;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Syntactic sugar for calling {@link #addTransform} repeatedly. This function
|
|
96
|
+
* accepts a map of one or more transform names to their transform function.
|
|
97
|
+
* @param {{}} map A map of transform names to transform functions
|
|
98
|
+
*/
|
|
99
|
+
addTransforms(map) {
|
|
100
|
+
Object.assign(this._grammar.transforms, map);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Creates an Expression object from the given Jexl expression string, and
|
|
104
|
+
* immediately compiles it. The returned Expression object can then be
|
|
105
|
+
* evaluated multiple times with new contexts, without generating any
|
|
106
|
+
* additional string processing overhead.
|
|
107
|
+
* @param {string} expression The Jexl expression to be compiled
|
|
108
|
+
* @returns {Expression} The compiled Expression object
|
|
109
|
+
*/
|
|
110
|
+
compile(expression) {
|
|
111
|
+
const exprObj = this.createExpression(expression);
|
|
112
|
+
return exprObj.compile();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Constructs an Expression object from a Jexl expression string.
|
|
116
|
+
* @param {string} expression The Jexl expression to be wrapped in an
|
|
117
|
+
* Expression object
|
|
118
|
+
* @returns {Expression} The Expression object representing the given string
|
|
119
|
+
*/
|
|
120
|
+
createExpression(expression) {
|
|
121
|
+
return new Expression(this._grammar, expression);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Retrieves a previously set expression function.
|
|
125
|
+
* @param {string} name The name of the expression function
|
|
126
|
+
* @returns {function} The expression function
|
|
127
|
+
*/
|
|
128
|
+
getFunction(name) {
|
|
129
|
+
return this._grammar.functions[name];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Retrieves a previously set transform function.
|
|
133
|
+
* @param {string} name The name of the transform function
|
|
134
|
+
* @returns {function} The transform function
|
|
135
|
+
*/
|
|
136
|
+
getTransform(name) {
|
|
137
|
+
return this._grammar.transforms[name];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Asynchronously evaluates a Jexl string within an optional context.
|
|
141
|
+
* @param {string} expression The Jexl expression to be evaluated
|
|
142
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
143
|
+
* made accessible to the Jexl expression when evaluating it
|
|
144
|
+
* @returns {Promise<*>} resolves with the result of the evaluation.
|
|
145
|
+
*/
|
|
146
|
+
eval(expression, context = {}) {
|
|
147
|
+
const exprObj = this.createExpression(expression);
|
|
148
|
+
return exprObj.eval(context);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Synchronously evaluates a Jexl string within an optional context.
|
|
152
|
+
* @param {string} expression The Jexl expression to be evaluated
|
|
153
|
+
* @param {Object} [context] A mapping of variables to values, which will be
|
|
154
|
+
* made accessible to the Jexl expression when evaluating it
|
|
155
|
+
* @returns {*} the result of the evaluation.
|
|
156
|
+
* @throws {*} on error
|
|
157
|
+
*/
|
|
158
|
+
evalSync(expression, context = {}) {
|
|
159
|
+
const exprObj = this.createExpression(expression);
|
|
160
|
+
return exprObj.evalSync(context);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* A JavaScript template literal to allow expressions to be defined by the
|
|
164
|
+
* syntax: expr`40 + 2`
|
|
165
|
+
* @param {Array<string>} strs
|
|
166
|
+
* @param {...any} args
|
|
167
|
+
*/
|
|
168
|
+
expr(strs, ...args) {
|
|
169
|
+
let exprStr = '';
|
|
170
|
+
for (let idx = 0; idx < strs.length; idx++) {
|
|
171
|
+
exprStr += strs[idx];
|
|
172
|
+
if (idx < args.length) {
|
|
173
|
+
exprStr += args[idx];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return this.createExpression(exprStr);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Removes a binary or unary operator from the Jexl grammar.
|
|
180
|
+
* @param {string} operator The operator string to be removed
|
|
181
|
+
*/
|
|
182
|
+
removeOp(operator) {
|
|
183
|
+
const elem = this._grammar.elements[operator];
|
|
184
|
+
if (elem && (elem.type === 'binaryOp' || elem.type === 'unaryOp')) {
|
|
185
|
+
Reflect.deleteProperty(this._grammar.elements, operator);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Adds an element to the grammar map used by this Jexl instance.
|
|
190
|
+
* @param {string} str The key string to be added
|
|
191
|
+
* @param {{type: <string>}} obj A map of configuration options for this
|
|
192
|
+
* grammar element
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
_addGrammarElement(str, obj) {
|
|
196
|
+
this._grammar.elements[str] = obj;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const jexlInstance = new Jexl();
|
|
200
|
+
export default jexlInstance;
|
|
201
|
+
export { Jexl };
|
|
202
|
+
//# sourceMappingURL=Jexl.js.map
|
package/esm/Jexl.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Jexl.js","sourceRoot":"","sources":["../src/Jexl.ts"],"names":[],"mappings":"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"}
|
package/esm/Lexer.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { Token } from './types.ts';
|
|
2
|
+
interface Grammar {
|
|
3
|
+
elements: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Lexer is a collection of stateless, statically-accessed functions for the
|
|
7
|
+
* lexical parsing of a Jexl string. Its responsibility is to identify the
|
|
8
|
+
* "parts of speech" of a Jexl expression, and tokenize and label each, but
|
|
9
|
+
* to do only the most minimal syntax checking; the only errors the Lexer
|
|
10
|
+
* should be concerned with are if it's unable to identify the utility of
|
|
11
|
+
* any of its tokens. Errors stemming from these tokens not being in a
|
|
12
|
+
* sensible configuration should be left for the Parser to handle.
|
|
13
|
+
* @type {{}}
|
|
14
|
+
*/
|
|
15
|
+
declare class Lexer {
|
|
16
|
+
_grammar: Grammar;
|
|
17
|
+
_splitRegex?: RegExp;
|
|
18
|
+
_escQuoteRegexCache: Map<string, RegExp>;
|
|
19
|
+
constructor(grammar: Grammar);
|
|
20
|
+
/**
|
|
21
|
+
* Splits a Jexl expression string into an array of expression elements.
|
|
22
|
+
* @param {string} str A Jexl expression string
|
|
23
|
+
* @returns {Array<string>} An array of substrings defining the functional
|
|
24
|
+
* elements of the expression.
|
|
25
|
+
*/
|
|
26
|
+
getElements(str: string): string[];
|
|
27
|
+
/**
|
|
28
|
+
* Converts an array of expression elements into an array of tokens. Note that
|
|
29
|
+
* the resulting array may not equal the element array in length, as any
|
|
30
|
+
* elements that consist only of whitespace get appended to the previous
|
|
31
|
+
* token's "raw" property. For the structure of a token object, please see
|
|
32
|
+
* {@link Lexer#tokenize}.
|
|
33
|
+
* @param {Array<string>} elements An array of Jexl expression elements to be
|
|
34
|
+
* converted to tokens
|
|
35
|
+
* @returns {Array<{type, value, raw}>} an array of token objects.
|
|
36
|
+
*/
|
|
37
|
+
getTokens(elements: string[]): Token[];
|
|
38
|
+
/**
|
|
39
|
+
* Converts a Jexl string into an array of tokens. Each token is an object
|
|
40
|
+
* in the following format:
|
|
41
|
+
*
|
|
42
|
+
* {
|
|
43
|
+
* type: <string>,
|
|
44
|
+
* [name]: <string>,
|
|
45
|
+
* value: <boolean|number|string>,
|
|
46
|
+
* raw: <string>
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* Type is one of the following:
|
|
50
|
+
*
|
|
51
|
+
* literal, identifier, binaryOp, unaryOp
|
|
52
|
+
*
|
|
53
|
+
* OR, if the token is a control character its type is the name of the element
|
|
54
|
+
* defined in the Grammar.
|
|
55
|
+
*
|
|
56
|
+
* Name appears only if the token is a control string found in
|
|
57
|
+
* {@link grammar#elements}, and is set to the name of the element.
|
|
58
|
+
*
|
|
59
|
+
* Value is the value of the token in the correct type (boolean or numeric as
|
|
60
|
+
* appropriate). Raw is the string representation of this value taken directly
|
|
61
|
+
* from the expression string, including any trailing spaces.
|
|
62
|
+
* @param {string} str The Jexl string to be tokenized
|
|
63
|
+
* @returns {Array<{type, value, raw}>} an array of token objects.
|
|
64
|
+
* @throws {Error} if the provided string contains an invalid token.
|
|
65
|
+
*/
|
|
66
|
+
tokenize(str: string): Token[];
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new token object from an element of a Jexl string. See
|
|
69
|
+
* {@link Lexer#tokenize} for a description of the token object.
|
|
70
|
+
* @param {string} element The element from which a token should be made
|
|
71
|
+
* @returns {{value: number|boolean|string, [name]: string, type: string,
|
|
72
|
+
* raw: string}} a token object describing the provided element.
|
|
73
|
+
* @throws {Error} if the provided string is not a valid expression element.
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
_createToken(element: string): Token;
|
|
77
|
+
/**
|
|
78
|
+
* Escapes a string so that it can be treated as a string literal within a
|
|
79
|
+
* regular expression.
|
|
80
|
+
* @param {string} str The string to be escaped
|
|
81
|
+
* @returns {string} the RegExp-escaped string.
|
|
82
|
+
* @see https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
_escapeRegExp(str: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* Gets a RegEx object appropriate for splitting a Jexl string into its core
|
|
88
|
+
* elements.
|
|
89
|
+
* @returns {RegExp} An element-splitting RegExp object
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
_getSplitRegex(): RegExp;
|
|
93
|
+
/**
|
|
94
|
+
* Determines whether the addition of a '-' token should be interpreted as a
|
|
95
|
+
* negative symbol for an upcoming number, given an array of tokens already
|
|
96
|
+
* processed.
|
|
97
|
+
* @param {Array<Object>} tokens An array of tokens already processed
|
|
98
|
+
* @returns {boolean} true if adding a '-' should be considered a negative
|
|
99
|
+
* symbol; false otherwise
|
|
100
|
+
* @private
|
|
101
|
+
*/
|
|
102
|
+
_isNegative(tokens: Token[]): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* A utility function to determine if a string consists of only space
|
|
105
|
+
* characters.
|
|
106
|
+
* @param {string} str A string to be tested
|
|
107
|
+
* @returns {boolean} true if the string is empty or consists of only spaces;
|
|
108
|
+
* false otherwise.
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
_isWhitespace(str: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Removes the beginning and trailing quotes from a string, unescapes any
|
|
114
|
+
* escaped quotes on its interior, and unescapes any escaped escape
|
|
115
|
+
* characters. Note that this function is not defensive; it assumes that the
|
|
116
|
+
* provided string is not empty, and that its first and last characters are
|
|
117
|
+
* actually quotes.
|
|
118
|
+
* @param {string} str A string whose first and last characters are quotes
|
|
119
|
+
* @returns {string} a string with the surrounding quotes stripped and escapes
|
|
120
|
+
* properly processed.
|
|
121
|
+
* @private
|
|
122
|
+
*/
|
|
123
|
+
_unquote(str: string): string;
|
|
124
|
+
_parseTemplateString(str: string): {
|
|
125
|
+
type: "static" | "interpolation";
|
|
126
|
+
value: string;
|
|
127
|
+
}[];
|
|
128
|
+
_unescapeTemplateString(str: string): string;
|
|
129
|
+
}
|
|
130
|
+
export default Lexer;
|