@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.
Files changed (89) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSE.txt +19 -0
  3. package/README.md +216 -0
  4. package/dist/Expression.d.ts +38 -0
  5. package/dist/Expression.js +75 -0
  6. package/dist/Expression.js.map +1 -0
  7. package/dist/Jexl.d.ts +148 -0
  8. package/dist/Jexl.js +208 -0
  9. package/dist/Jexl.js.map +1 -0
  10. package/dist/Lexer.d.ts +130 -0
  11. package/dist/Lexer.js +321 -0
  12. package/dist/Lexer.js.map +1 -0
  13. package/dist/PromiseSync.d.ts +13 -0
  14. package/dist/PromiseSync.js +80 -0
  15. package/dist/PromiseSync.js.map +1 -0
  16. package/dist/evaluator/Evaluator.d.ts +92 -0
  17. package/dist/evaluator/Evaluator.js +153 -0
  18. package/dist/evaluator/Evaluator.js.map +1 -0
  19. package/dist/evaluator/handlers.d.ts +111 -0
  20. package/dist/evaluator/handlers.js +216 -0
  21. package/dist/evaluator/handlers.js.map +1 -0
  22. package/dist/grammar.d.ts +25 -0
  23. package/dist/grammar.js +179 -0
  24. package/dist/grammar.js.map +1 -0
  25. package/dist/index.d.ts +5 -0
  26. package/dist/index.js +20 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/package.json +1 -0
  29. package/dist/parser/Parser.d.ts +112 -0
  30. package/dist/parser/Parser.js +233 -0
  31. package/dist/parser/Parser.js.map +1 -0
  32. package/dist/parser/handlers.d.ts +112 -0
  33. package/dist/parser/handlers.js +302 -0
  34. package/dist/parser/handlers.js.map +1 -0
  35. package/dist/parser/states.d.ts +47 -0
  36. package/dist/parser/states.js +195 -0
  37. package/dist/parser/states.js.map +1 -0
  38. package/dist/types.d.ts +77 -0
  39. package/dist/types.js +7 -0
  40. package/dist/types.js.map +1 -0
  41. package/esm/Expression.d.ts +38 -0
  42. package/esm/Expression.js +70 -0
  43. package/esm/Expression.js.map +1 -0
  44. package/esm/Jexl.d.ts +148 -0
  45. package/esm/Jexl.js +202 -0
  46. package/esm/Jexl.js.map +1 -0
  47. package/esm/Lexer.d.ts +130 -0
  48. package/esm/Lexer.js +319 -0
  49. package/esm/Lexer.js.map +1 -0
  50. package/esm/PromiseSync.d.ts +13 -0
  51. package/esm/PromiseSync.js +78 -0
  52. package/esm/PromiseSync.js.map +1 -0
  53. package/esm/evaluator/Evaluator.d.ts +92 -0
  54. package/esm/evaluator/Evaluator.js +118 -0
  55. package/esm/evaluator/Evaluator.js.map +1 -0
  56. package/esm/evaluator/handlers.d.ts +111 -0
  57. package/esm/evaluator/handlers.js +202 -0
  58. package/esm/evaluator/handlers.js.map +1 -0
  59. package/esm/grammar.d.ts +25 -0
  60. package/esm/grammar.js +175 -0
  61. package/esm/grammar.js.map +1 -0
  62. package/esm/index.d.ts +5 -0
  63. package/esm/index.js +9 -0
  64. package/esm/index.js.map +1 -0
  65. package/esm/parser/Parser.d.ts +112 -0
  66. package/esm/parser/Parser.js +198 -0
  67. package/esm/parser/Parser.js.map +1 -0
  68. package/esm/parser/handlers.d.ts +112 -0
  69. package/esm/parser/handlers.js +280 -0
  70. package/esm/parser/handlers.js.map +1 -0
  71. package/esm/parser/states.d.ts +47 -0
  72. package/esm/parser/states.js +159 -0
  73. package/esm/parser/states.js.map +1 -0
  74. package/esm/types.d.ts +77 -0
  75. package/esm/types.js +6 -0
  76. package/esm/types.js.map +1 -0
  77. package/package.json +67 -0
  78. package/src/Expression.ts +95 -0
  79. package/src/Jexl.ts +232 -0
  80. package/src/Lexer.ts +344 -0
  81. package/src/PromiseSync.ts +86 -0
  82. package/src/evaluator/Evaluator.ts +153 -0
  83. package/src/evaluator/handlers.ts +226 -0
  84. package/src/grammar.ts +200 -0
  85. package/src/index.ts +10 -0
  86. package/src/parser/Parser.ts +235 -0
  87. package/src/parser/handlers.ts +309 -0
  88. package/src/parser/states.ts +177 -0
  89. 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
@@ -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;