@jbrowse/jexl 3.0.2 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/dist/Expression.d.ts +19 -7
- package/dist/Expression.js +32 -11
- package/dist/Expression.js.map +1 -1
- package/dist/Jexl.d.ts +13 -12
- package/dist/Jexl.js +31 -30
- package/dist/Jexl.js.map +1 -1
- package/dist/Lexer.d.ts +9 -9
- package/dist/Lexer.js +61 -24
- package/dist/Lexer.js.map +1 -1
- package/dist/evaluator/Evaluator.d.ts +20 -34
- package/dist/evaluator/Evaluator.js +19 -64
- package/dist/evaluator/Evaluator.js.map +1 -1
- package/dist/evaluator/compile.d.ts +27 -0
- package/dist/evaluator/compile.js +279 -0
- package/dist/evaluator/compile.js.map +1 -0
- package/dist/grammar.d.ts +29 -9
- package/dist/grammar.js +23 -7
- package/dist/grammar.js.map +1 -1
- package/dist/parser/Parser.d.ts +7 -8
- package/dist/parser/Parser.js +46 -14
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/handlers.d.ts +8 -8
- package/dist/parser/handlers.js +84 -51
- package/dist/parser/handlers.js.map +1 -1
- package/dist/parser/states.d.ts +2 -2
- package/dist/parser/states.js +19 -40
- package/dist/parser/states.js.map +1 -1
- package/dist/types.d.ts +18 -7
- package/esm/Expression.d.ts +19 -7
- package/esm/Expression.js +32 -11
- package/esm/Expression.js.map +1 -1
- package/esm/Jexl.d.ts +13 -12
- package/esm/Jexl.js +31 -30
- package/esm/Jexl.js.map +1 -1
- package/esm/Lexer.d.ts +9 -9
- package/esm/Lexer.js +61 -24
- package/esm/Lexer.js.map +1 -1
- package/esm/evaluator/Evaluator.d.ts +20 -34
- package/esm/evaluator/Evaluator.js +19 -31
- package/esm/evaluator/Evaluator.js.map +1 -1
- package/esm/evaluator/compile.d.ts +27 -0
- package/esm/evaluator/compile.js +276 -0
- package/esm/evaluator/compile.js.map +1 -0
- package/esm/grammar.d.ts +29 -9
- package/esm/grammar.js +22 -7
- package/esm/grammar.js.map +1 -1
- package/esm/parser/Parser.d.ts +7 -8
- package/esm/parser/Parser.js +46 -14
- package/esm/parser/Parser.js.map +1 -1
- package/esm/parser/handlers.d.ts +8 -8
- package/esm/parser/handlers.js +81 -50
- package/esm/parser/handlers.js.map +1 -1
- package/esm/parser/states.d.ts +2 -2
- package/esm/parser/states.js +19 -40
- package/esm/parser/states.js.map +1 -1
- package/esm/types.d.ts +18 -7
- package/package.json +25 -28
- package/src/Expression.ts +31 -17
- package/src/Jexl.ts +59 -21
- package/src/Lexer.ts +63 -33
- package/src/evaluator/Evaluator.ts +27 -44
- package/src/evaluator/compile.ts +317 -0
- package/src/grammar.ts +69 -21
- package/src/parser/Parser.ts +50 -28
- package/src/parser/handlers.ts +122 -76
- package/src/parser/states.ts +22 -42
- package/src/types.ts +22 -7
- package/CHANGELOG.md +0 -249
- package/dist/evaluator/handlers.d.ts +0 -112
- package/dist/evaluator/handlers.js +0 -208
- package/dist/evaluator/handlers.js.map +0 -1
- package/esm/evaluator/handlers.d.ts +0 -112
- package/esm/evaluator/handlers.js +0 -194
- package/esm/evaluator/handlers.js.map +0 -1
- package/src/evaluator/handlers.ts +0 -212
package/dist/parser/Parser.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type Lexer from '../Lexer.ts';
|
|
2
|
+
import type { Grammar } from '../grammar.ts';
|
|
2
3
|
import type { AstNode, Token } from '../types.ts';
|
|
3
|
-
interface Grammar {
|
|
4
|
-
elements: Record<string, any>;
|
|
5
|
-
}
|
|
6
4
|
/**
|
|
7
5
|
* The Parser is a state machine that converts tokens from the {@link Lexer}
|
|
8
6
|
* into an Abstract Syntax Tree (AST), capable of being evaluated in any
|
|
@@ -27,7 +25,7 @@ declare class Parser {
|
|
|
27
25
|
_tree: AstNode | null;
|
|
28
26
|
_exprStr: string;
|
|
29
27
|
_relative: boolean;
|
|
30
|
-
_stopMap: Record<string,
|
|
28
|
+
_stopMap: Record<string, string>;
|
|
31
29
|
_cursor?: AstNode | null;
|
|
32
30
|
_subParser?: Parser;
|
|
33
31
|
_parentStop?: boolean;
|
|
@@ -35,7 +33,7 @@ declare class Parser {
|
|
|
35
33
|
_nextIdentRelative?: boolean;
|
|
36
34
|
_curObjKey?: string;
|
|
37
35
|
_sequenceExpressions?: AstNode[];
|
|
38
|
-
constructor(grammar: Grammar, lexer: Lexer, prefix?: string, stopMap?: Record<string,
|
|
36
|
+
constructor(grammar: Grammar, lexer: Lexer, prefix?: string, stopMap?: Record<string, string>);
|
|
39
37
|
/**
|
|
40
38
|
* Processes a new token into the AST and manages the transitions of the state
|
|
41
39
|
* machine.
|
|
@@ -46,7 +44,7 @@ declare class Parser {
|
|
|
46
44
|
* @returns {boolean|*} the stopState value if this parser encountered a token
|
|
47
45
|
* in the stopState mapb false if tokens can continue.
|
|
48
46
|
*/
|
|
49
|
-
addToken(token: Token):
|
|
47
|
+
addToken(token: Token): string | false;
|
|
50
48
|
/**
|
|
51
49
|
* Processes an array of tokens iteratively through the {@link #addToken}
|
|
52
50
|
* function.
|
|
@@ -62,7 +60,7 @@ declare class Parser {
|
|
|
62
60
|
* @throws {Error} if the parser is not in a state where it's legal to end
|
|
63
61
|
* the expression, indicating that the expression is incomplete
|
|
64
62
|
*/
|
|
65
|
-
complete():
|
|
63
|
+
complete(): AstNode | null;
|
|
66
64
|
/**
|
|
67
65
|
* Indicates whether the expression tree contains a relative path identifier.
|
|
68
66
|
* @returns {boolean} true if a relative identifier exists false otherwise.
|
|
@@ -105,8 +103,9 @@ declare class Parser {
|
|
|
105
103
|
* Prepares the Parser to accept a subexpression by (re)instantiating the
|
|
106
104
|
* subParser.
|
|
107
105
|
* @param {string} [exprStr] The expression string to prefix to the new Parser
|
|
106
|
+
* @returns {Parser} the new subParser, also stored on this instance
|
|
108
107
|
* @private
|
|
109
108
|
*/
|
|
110
|
-
_startSubExpression(exprStr?: string):
|
|
109
|
+
_startSubExpression(exprStr?: string): Parser;
|
|
111
110
|
}
|
|
112
111
|
export default Parser;
|
package/dist/parser/Parser.js
CHANGED
|
@@ -39,6 +39,21 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
const handlers = __importStar(require("./handlers.js"));
|
|
41
41
|
const states_ts_1 = require("./states.js");
|
|
42
|
+
/**
|
|
43
|
+
* The handler to run for a token type when the state it appears in doesn't
|
|
44
|
+
* name one of its own. Token types absent here — the brackets, parens and
|
|
45
|
+
* separators — carry no behavior beyond the state transition the state machine
|
|
46
|
+
* gives them.
|
|
47
|
+
*/
|
|
48
|
+
const tokenHandlers = {
|
|
49
|
+
binaryOp: handlers.binaryOp,
|
|
50
|
+
dot: handlers.dot,
|
|
51
|
+
identifier: handlers.identifier,
|
|
52
|
+
literal: handlers.literal,
|
|
53
|
+
semicolon: handlers.semicolon,
|
|
54
|
+
templateString: handlers.templateString,
|
|
55
|
+
unaryOp: handlers.unaryOp
|
|
56
|
+
};
|
|
42
57
|
/**
|
|
43
58
|
* The Parser is a state machine that converts tokens from the {@link Lexer}
|
|
44
59
|
* into an Abstract Syntax Tree (AST), capable of being evaluated in any
|
|
@@ -57,6 +72,20 @@ const states_ts_1 = require("./states.js");
|
|
|
57
72
|
* instead of boolean false.
|
|
58
73
|
*/
|
|
59
74
|
class Parser {
|
|
75
|
+
_grammar;
|
|
76
|
+
_lexer;
|
|
77
|
+
_state;
|
|
78
|
+
_tree;
|
|
79
|
+
_exprStr;
|
|
80
|
+
_relative;
|
|
81
|
+
_stopMap;
|
|
82
|
+
_cursor;
|
|
83
|
+
_subParser;
|
|
84
|
+
_parentStop;
|
|
85
|
+
_nextIdentEncapsulate;
|
|
86
|
+
_nextIdentRelative;
|
|
87
|
+
_curObjKey;
|
|
88
|
+
_sequenceExpressions;
|
|
60
89
|
constructor(grammar, lexer, prefix, stopMap) {
|
|
61
90
|
this._grammar = grammar;
|
|
62
91
|
this._lexer = lexer;
|
|
@@ -84,10 +113,8 @@ class Parser {
|
|
|
84
113
|
const startExpr = this._exprStr;
|
|
85
114
|
this._exprStr += token.raw;
|
|
86
115
|
if (state.subHandler) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
const stopState = this._subParser.addToken(token);
|
|
116
|
+
const subParser = this._subParser ?? this._startSubExpression(startExpr);
|
|
117
|
+
const stopState = subParser.addToken(token);
|
|
91
118
|
if (stopState) {
|
|
92
119
|
this._endSubExpression();
|
|
93
120
|
if (stopState === '_semicolon') {
|
|
@@ -106,13 +133,10 @@ class Parser {
|
|
|
106
133
|
}
|
|
107
134
|
else if (state.tokenTypes?.[token.type]) {
|
|
108
135
|
const typeOpts = state.tokenTypes[token.type];
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (handleFunc) {
|
|
114
|
-
handleFunc.call(this, token);
|
|
115
|
-
}
|
|
136
|
+
// the state's own handler wins over the token type's default one, and a
|
|
137
|
+
// token type with neither only drives the transition below
|
|
138
|
+
const handleFunc = typeOpts.handler ?? tokenHandlers[token.type];
|
|
139
|
+
handleFunc?.call(this, token);
|
|
116
140
|
if (typeOpts.toState) {
|
|
117
141
|
this._state = typeOpts.toState;
|
|
118
142
|
}
|
|
@@ -132,7 +156,9 @@ class Parser {
|
|
|
132
156
|
* the {@link Lexer#tokenize} function.
|
|
133
157
|
*/
|
|
134
158
|
addTokens(tokens) {
|
|
135
|
-
|
|
159
|
+
for (const token of tokens) {
|
|
160
|
+
this.addToken(token);
|
|
161
|
+
}
|
|
136
162
|
}
|
|
137
163
|
/**
|
|
138
164
|
* Marks this Parser instance as completed and retrieves the full AST.
|
|
@@ -143,7 +169,12 @@ class Parser {
|
|
|
143
169
|
* the expression, indicating that the expression is incomplete
|
|
144
170
|
*/
|
|
145
171
|
complete() {
|
|
146
|
-
|
|
172
|
+
// `_subParser` counts as unfinished business alongside `_cursor`: a group
|
|
173
|
+
// that opened before anything was placed in the tree, as in "(1", leaves
|
|
174
|
+
// the cursor null, and testing the cursor alone let the missing ")" pass
|
|
175
|
+
// silently and evaluate as if it were closed.
|
|
176
|
+
if ((this._cursor || this._subParser) &&
|
|
177
|
+
!states_ts_1.states[this._state].completable) {
|
|
147
178
|
throw new Error(`Unexpected end of expression: ${this._exprStr}`);
|
|
148
179
|
}
|
|
149
180
|
if (this._subParser) {
|
|
@@ -191,7 +222,6 @@ class Parser {
|
|
|
191
222
|
this._tree = node;
|
|
192
223
|
}
|
|
193
224
|
else {
|
|
194
|
-
;
|
|
195
225
|
this._cursor.right = node;
|
|
196
226
|
this._setParent(node, this._cursor);
|
|
197
227
|
}
|
|
@@ -228,6 +258,7 @@ class Parser {
|
|
|
228
258
|
* Prepares the Parser to accept a subexpression by (re)instantiating the
|
|
229
259
|
* subParser.
|
|
230
260
|
* @param {string} [exprStr] The expression string to prefix to the new Parser
|
|
261
|
+
* @returns {Parser} the new subParser, also stored on this instance
|
|
231
262
|
* @private
|
|
232
263
|
*/
|
|
233
264
|
_startSubExpression(exprStr) {
|
|
@@ -240,6 +271,7 @@ class Parser {
|
|
|
240
271
|
endStates = { ...endStates, semicolon: '_semicolon' };
|
|
241
272
|
}
|
|
242
273
|
this._subParser = new Parser(this._grammar, this._lexer, exprStr, endStates);
|
|
274
|
+
return this._subParser;
|
|
243
275
|
}
|
|
244
276
|
}
|
|
245
277
|
exports.default = Parser;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../src/parser/Parser.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,wDAAyC;AACzC,2CAAoC;
|
|
1
|
+
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../src/parser/Parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import Parser from './Parser.ts';
|
|
1
2
|
import type { AstNode, Token } from '../types.ts';
|
|
2
|
-
import type Parser from './Parser.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Handles a subexpression that's used to define a transform argument's value.
|
|
5
5
|
* @param {{type: <string>}} ast The subexpression tree
|
|
@@ -36,7 +36,13 @@ export declare function filter(this: Parser, ast: AstNode | null): void;
|
|
|
36
36
|
/**
|
|
37
37
|
* Handles identifier tokens when used to indicate the name of a function to
|
|
38
38
|
* be called.
|
|
39
|
-
*
|
|
39
|
+
*
|
|
40
|
+
* A call written against a value, `a.b(x)`, becomes `b(a, x)`: jexl functions
|
|
41
|
+
* live in one global pool and have no receiver, so the value the name was read
|
|
42
|
+
* from is passed as the first argument instead. Every function in the pool is
|
|
43
|
+
* already written that way — `get(feature, key)`, `split(str, sep)` — which is
|
|
44
|
+
* what makes the two spellings equivalent. Previously the receiver was simply
|
|
45
|
+
* dropped, so `refName.split(' ')` quietly called `split(' ')`.
|
|
40
46
|
*/
|
|
41
47
|
export declare function functionCall(this: Parser): void;
|
|
42
48
|
/**
|
|
@@ -94,12 +100,6 @@ export declare function ternaryMid(this: Parser, ast: AstNode | null): void;
|
|
|
94
100
|
* test element.
|
|
95
101
|
*/
|
|
96
102
|
export declare function ternaryStart(this: Parser): void;
|
|
97
|
-
/**
|
|
98
|
-
* Handles identifier tokens when used to indicate the name of a transform to
|
|
99
|
-
* be applied.
|
|
100
|
-
* @param {{type: <string>}} token A token object
|
|
101
|
-
*/
|
|
102
|
-
export declare function transform(this: Parser, token: Token): void;
|
|
103
103
|
/**
|
|
104
104
|
* Handles token of type 'unaryOp', indicating that the operation has only
|
|
105
105
|
* one input: a right side.
|
package/dist/parser/handlers.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* Jexl
|
|
4
4
|
* Copyright 2020 Tom Shawver
|
|
5
5
|
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
6
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
10
|
exports.argVal = argVal;
|
|
8
11
|
exports.arrayStart = arrayStart;
|
|
@@ -21,9 +24,12 @@ exports.subExpression = subExpression;
|
|
|
21
24
|
exports.ternaryEnd = ternaryEnd;
|
|
22
25
|
exports.ternaryMid = ternaryMid;
|
|
23
26
|
exports.ternaryStart = ternaryStart;
|
|
24
|
-
exports.transform = transform;
|
|
25
27
|
exports.unaryOp = unaryOp;
|
|
26
28
|
exports.semicolon = semicolon;
|
|
29
|
+
const grammar_ts_1 = require("../grammar.js");
|
|
30
|
+
// circular with Parser.ts, which is fine: the binding is only read from inside
|
|
31
|
+
// a handler, long after both modules have finished evaluating
|
|
32
|
+
const Parser_ts_1 = __importDefault(require("./Parser.js"));
|
|
27
33
|
/**
|
|
28
34
|
* Handles a subexpression that's used to define a transform argument's value.
|
|
29
35
|
* @param {{type: <string>}} ast The subexpression tree
|
|
@@ -39,10 +45,11 @@ function argVal(ast) {
|
|
|
39
45
|
* initialized with an empty array.
|
|
40
46
|
*/
|
|
41
47
|
function arrayStart() {
|
|
42
|
-
|
|
48
|
+
const node = {
|
|
43
49
|
type: 'ArrayLiteral',
|
|
44
50
|
value: []
|
|
45
|
-
}
|
|
51
|
+
};
|
|
52
|
+
this._placeAtCursor(node);
|
|
46
53
|
}
|
|
47
54
|
/**
|
|
48
55
|
* Handles a subexpression representing an element of an array literal.
|
|
@@ -61,7 +68,10 @@ function arrayVal(ast) {
|
|
|
61
68
|
*/
|
|
62
69
|
function binaryOp(token) {
|
|
63
70
|
if (token.value === '=') {
|
|
64
|
-
|
|
71
|
+
// `from` marks a member access such as `a.b`; only a bare name can be
|
|
72
|
+
// assigned to, since the Evaluator writes straight into the context
|
|
73
|
+
if (this._cursor?.type !== 'Identifier' ||
|
|
74
|
+
this._cursor.from) {
|
|
65
75
|
throw new Error('Left side of assignment must be a variable name');
|
|
66
76
|
}
|
|
67
77
|
const node = {
|
|
@@ -73,17 +83,23 @@ function binaryOp(token) {
|
|
|
73
83
|
this._placeAtCursor(node);
|
|
74
84
|
return;
|
|
75
85
|
}
|
|
76
|
-
const
|
|
86
|
+
const tokenValue = token.value;
|
|
87
|
+
const precedence = (0, grammar_ts_1.precedenceOf)(this._grammar.elements[tokenValue]);
|
|
77
88
|
let parent = this._cursor?._parent;
|
|
78
|
-
while (parent
|
|
79
|
-
parent
|
|
80
|
-
|
|
89
|
+
while (parent) {
|
|
90
|
+
const parentExpr = parent;
|
|
91
|
+
if (!parentExpr.operator) {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if ((0, grammar_ts_1.precedenceOf)(this._grammar.elements[parentExpr.operator]) < precedence) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
81
97
|
this._cursor = parent;
|
|
82
98
|
parent = parent._parent;
|
|
83
99
|
}
|
|
84
100
|
const node = {
|
|
85
101
|
type: 'BinaryExpression',
|
|
86
|
-
operator:
|
|
102
|
+
operator: tokenValue,
|
|
87
103
|
left: this._cursor
|
|
88
104
|
};
|
|
89
105
|
this._setParent(this._cursor, node);
|
|
@@ -96,13 +112,15 @@ function binaryOp(token) {
|
|
|
96
112
|
* AST.
|
|
97
113
|
*/
|
|
98
114
|
function dot() {
|
|
99
|
-
const
|
|
115
|
+
const cursor = this._cursor;
|
|
116
|
+
// the dot continues an identifier chain unless the cursor is an operator
|
|
117
|
+
// still waiting on its right-hand side, in which case it opens a relative
|
|
118
|
+
// path instead — as in the leading dot of `list[.price > 5]`
|
|
100
119
|
this._nextIdentEncapsulate =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(
|
|
104
|
-
|
|
105
|
-
this._nextIdentRelative = !this._cursor || !this._nextIdentEncapsulate;
|
|
120
|
+
!!cursor &&
|
|
121
|
+
cursor.type !== 'UnaryExpression' &&
|
|
122
|
+
(cursor.type !== 'BinaryExpression' || !!cursor.right);
|
|
123
|
+
this._nextIdentRelative = !this._nextIdentEncapsulate;
|
|
106
124
|
if (this._nextIdentRelative) {
|
|
107
125
|
this._relative = true;
|
|
108
126
|
}
|
|
@@ -113,25 +131,40 @@ function dot() {
|
|
|
113
131
|
* @param {{type: <string>}} ast The subexpression tree
|
|
114
132
|
*/
|
|
115
133
|
function filter(ast) {
|
|
116
|
-
|
|
134
|
+
const node = {
|
|
117
135
|
type: 'FilterExpression',
|
|
118
136
|
expr: ast,
|
|
119
137
|
relative: this._subParser.isRelative(),
|
|
120
138
|
subject: this._cursor
|
|
121
|
-
}
|
|
139
|
+
};
|
|
140
|
+
this._placeBeforeCursor(node);
|
|
122
141
|
}
|
|
123
142
|
/**
|
|
124
143
|
* Handles identifier tokens when used to indicate the name of a function to
|
|
125
144
|
* be called.
|
|
126
|
-
*
|
|
145
|
+
*
|
|
146
|
+
* A call written against a value, `a.b(x)`, becomes `b(a, x)`: jexl functions
|
|
147
|
+
* live in one global pool and have no receiver, so the value the name was read
|
|
148
|
+
* from is passed as the first argument instead. Every function in the pool is
|
|
149
|
+
* already written that way — `get(feature, key)`, `split(str, sep)` — which is
|
|
150
|
+
* what makes the two spellings equivalent. Previously the receiver was simply
|
|
151
|
+
* dropped, so `refName.split(' ')` quietly called `split(' ')`.
|
|
127
152
|
*/
|
|
128
153
|
function functionCall() {
|
|
129
|
-
this.
|
|
154
|
+
const cursor = this._cursor;
|
|
155
|
+
if (cursor?.type !== 'Identifier') {
|
|
156
|
+
// reached by `a[expr]()`, whose subject is a filter rather than a name;
|
|
157
|
+
// there is nothing to look up in the function pool
|
|
158
|
+
throw new Error(`Functions must be called by name: ${this._exprStr}`);
|
|
159
|
+
}
|
|
160
|
+
const { from } = cursor;
|
|
161
|
+
const node = {
|
|
130
162
|
type: 'FunctionCall',
|
|
131
|
-
name:
|
|
132
|
-
args: [],
|
|
163
|
+
name: cursor.value,
|
|
164
|
+
args: from ? [from] : [],
|
|
133
165
|
pool: 'functions'
|
|
134
|
-
}
|
|
166
|
+
};
|
|
167
|
+
this._placeBeforeCursor(node);
|
|
135
168
|
}
|
|
136
169
|
/**
|
|
137
170
|
* Handles identifier tokens by adding them as a new node in the AST.
|
|
@@ -161,10 +194,11 @@ function identifier(token) {
|
|
|
161
194
|
* @param {{type: <string>}} token A token object
|
|
162
195
|
*/
|
|
163
196
|
function literal(token) {
|
|
164
|
-
|
|
197
|
+
const node = {
|
|
165
198
|
type: 'Literal',
|
|
166
199
|
value: token.value
|
|
167
|
-
}
|
|
200
|
+
};
|
|
201
|
+
this._placeAtCursor(node);
|
|
168
202
|
}
|
|
169
203
|
/**
|
|
170
204
|
* Handles template string tokens by parsing their interpolation expressions
|
|
@@ -173,7 +207,8 @@ function literal(token) {
|
|
|
173
207
|
*/
|
|
174
208
|
function templateString(token) {
|
|
175
209
|
const parts = [];
|
|
176
|
-
|
|
210
|
+
const tokenParts = Array.isArray(token.value) ? token.value : [];
|
|
211
|
+
for (const part of tokenParts) {
|
|
177
212
|
if (part.type === 'static') {
|
|
178
213
|
parts.push({
|
|
179
214
|
type: 'static',
|
|
@@ -182,7 +217,7 @@ function templateString(token) {
|
|
|
182
217
|
}
|
|
183
218
|
else {
|
|
184
219
|
const subTokens = this._lexer.tokenize(part.value);
|
|
185
|
-
const subParser = new
|
|
220
|
+
const subParser = new Parser_ts_1.default(this._grammar, this._lexer);
|
|
186
221
|
subParser.addTokens(subTokens);
|
|
187
222
|
const subAst = subParser.complete();
|
|
188
223
|
if (!subAst) {
|
|
@@ -194,10 +229,11 @@ function templateString(token) {
|
|
|
194
229
|
});
|
|
195
230
|
}
|
|
196
231
|
}
|
|
197
|
-
|
|
232
|
+
const node = {
|
|
198
233
|
type: 'TemplateLiteral',
|
|
199
|
-
parts
|
|
200
|
-
}
|
|
234
|
+
parts
|
|
235
|
+
};
|
|
236
|
+
this._placeAtCursor(node);
|
|
201
237
|
}
|
|
202
238
|
/**
|
|
203
239
|
* Queues a new object literal key to be written once a value is collected.
|
|
@@ -211,10 +247,11 @@ function objKey(token) {
|
|
|
211
247
|
* initialized with an empty object.
|
|
212
248
|
*/
|
|
213
249
|
function objStart() {
|
|
214
|
-
|
|
250
|
+
const node = {
|
|
215
251
|
type: 'ObjectLiteral',
|
|
216
252
|
value: {}
|
|
217
|
-
}
|
|
253
|
+
};
|
|
254
|
+
this._placeAtCursor(node);
|
|
218
255
|
}
|
|
219
256
|
/**
|
|
220
257
|
* Handles an object value by adding its AST to the queued key on the object
|
|
@@ -222,8 +259,15 @@ function objStart() {
|
|
|
222
259
|
* @param {{type: <string>}} ast The subexpression tree
|
|
223
260
|
*/
|
|
224
261
|
function objVal(ast) {
|
|
225
|
-
|
|
226
|
-
|
|
262
|
+
// defined rather than assigned so that the key "__proto__" becomes an
|
|
263
|
+
// ordinary entry of the node's key map instead of re-pointing its prototype,
|
|
264
|
+
// which dropped the entry before the Evaluator ever saw it
|
|
265
|
+
Object.defineProperty(this._cursor.value, this._curObjKey, {
|
|
266
|
+
value: ast,
|
|
267
|
+
writable: true,
|
|
268
|
+
enumerable: true,
|
|
269
|
+
configurable: true
|
|
270
|
+
});
|
|
227
271
|
}
|
|
228
272
|
/**
|
|
229
273
|
* Handles traditional subexpressions, delineated with the groupStart and
|
|
@@ -239,7 +283,7 @@ function subExpression(ast) {
|
|
|
239
283
|
*/
|
|
240
284
|
function ternaryEnd(ast) {
|
|
241
285
|
;
|
|
242
|
-
this._cursor.alternate = ast;
|
|
286
|
+
this._cursor.alternate = ast ?? undefined;
|
|
243
287
|
}
|
|
244
288
|
/**
|
|
245
289
|
* Handles a completed consequent subexpression of a ternary operator.
|
|
@@ -247,7 +291,7 @@ function ternaryEnd(ast) {
|
|
|
247
291
|
*/
|
|
248
292
|
function ternaryMid(ast) {
|
|
249
293
|
;
|
|
250
|
-
this._cursor.consequent = ast;
|
|
294
|
+
this._cursor.consequent = ast ?? undefined;
|
|
251
295
|
}
|
|
252
296
|
/**
|
|
253
297
|
* Handles the start of a new ternary expression by encapsulating the entire
|
|
@@ -255,35 +299,24 @@ function ternaryMid(ast) {
|
|
|
255
299
|
* test element.
|
|
256
300
|
*/
|
|
257
301
|
function ternaryStart() {
|
|
258
|
-
|
|
302
|
+
const node = {
|
|
259
303
|
type: 'ConditionalExpression',
|
|
260
304
|
test: this._tree
|
|
261
305
|
};
|
|
306
|
+
this._tree = node;
|
|
262
307
|
this._cursor = this._tree;
|
|
263
308
|
}
|
|
264
|
-
/**
|
|
265
|
-
* Handles identifier tokens when used to indicate the name of a transform to
|
|
266
|
-
* be applied.
|
|
267
|
-
* @param {{type: <string>}} token A token object
|
|
268
|
-
*/
|
|
269
|
-
function transform(token) {
|
|
270
|
-
this._placeBeforeCursor({
|
|
271
|
-
type: 'FunctionCall',
|
|
272
|
-
name: token.value,
|
|
273
|
-
args: [this._cursor],
|
|
274
|
-
pool: 'transforms'
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
309
|
/**
|
|
278
310
|
* Handles token of type 'unaryOp', indicating that the operation has only
|
|
279
311
|
* one input: a right side.
|
|
280
312
|
* @param {{type: <string>}} token A token object
|
|
281
313
|
*/
|
|
282
314
|
function unaryOp(token) {
|
|
283
|
-
|
|
315
|
+
const node = {
|
|
284
316
|
type: 'UnaryExpression',
|
|
285
317
|
operator: token.value
|
|
286
|
-
}
|
|
318
|
+
};
|
|
319
|
+
this._placeAtCursor(node);
|
|
287
320
|
}
|
|
288
321
|
/**
|
|
289
322
|
* Handles semicolon separator between expressions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/parser/handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/parser/states.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { AstNode } from '../types.ts';
|
|
1
|
+
import type { AstNode, Token } from '../types.ts';
|
|
2
2
|
import type Parser from './Parser.ts';
|
|
3
3
|
interface TokenTypeOptions {
|
|
4
4
|
toState?: string;
|
|
5
|
-
handler?: (this: Parser,
|
|
5
|
+
handler?: (this: Parser, token: Token) => void;
|
|
6
6
|
}
|
|
7
7
|
interface StateDefinition {
|
|
8
8
|
tokenTypes?: Record<string, TokenTypeOptions>;
|
package/dist/parser/states.js
CHANGED
|
@@ -39,6 +39,19 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
exports.states = void 0;
|
|
41
41
|
const h = __importStar(require("./handlers.js"));
|
|
42
|
+
/**
|
|
43
|
+
* The tokens that may follow a finished operand: an operator to combine it
|
|
44
|
+
* with, a dot or subscript to keep drilling into it, a question mark opening a
|
|
45
|
+
* ternary, or a semicolon ending the statement. Shared by every state that
|
|
46
|
+
* sits on a complete value, which is also why each of them is completable.
|
|
47
|
+
*/
|
|
48
|
+
const afterOperand = {
|
|
49
|
+
binaryOp: { toState: 'expectOperand' },
|
|
50
|
+
dot: { toState: 'traverse' },
|
|
51
|
+
openBracket: { toState: 'filter' },
|
|
52
|
+
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
53
|
+
semicolon: { handler: h.semicolon }
|
|
54
|
+
};
|
|
42
55
|
/**
|
|
43
56
|
* A mapping of all states in the finite state machine to a set of instructions
|
|
44
57
|
* for handling or transitioning into other states. Each state can be handled
|
|
@@ -85,21 +98,9 @@ exports.states = {
|
|
|
85
98
|
}
|
|
86
99
|
},
|
|
87
100
|
expectBinOp: {
|
|
88
|
-
tokenTypes:
|
|
89
|
-
binaryOp: { toState: 'expectOperand' },
|
|
90
|
-
pipe: { toState: 'expectTransform' },
|
|
91
|
-
dot: { toState: 'traverse' },
|
|
92
|
-
openBracket: { toState: 'filter' },
|
|
93
|
-
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
94
|
-
semicolon: { handler: h.semicolon }
|
|
95
|
-
},
|
|
101
|
+
tokenTypes: afterOperand,
|
|
96
102
|
completable: true
|
|
97
103
|
},
|
|
98
|
-
expectTransform: {
|
|
99
|
-
tokenTypes: {
|
|
100
|
-
identifier: { toState: 'postTransform', handler: h.transform }
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
104
|
expectObjKey: {
|
|
104
105
|
tokenTypes: {
|
|
105
106
|
literal: { toState: 'expectKeyValSep', handler: h.objKey },
|
|
@@ -112,38 +113,16 @@ exports.states = {
|
|
|
112
113
|
colon: { toState: 'objVal' }
|
|
113
114
|
}
|
|
114
115
|
},
|
|
115
|
-
postTransform: {
|
|
116
|
-
tokenTypes: {
|
|
117
|
-
openParen: { toState: 'argVal' },
|
|
118
|
-
binaryOp: { toState: 'expectOperand' },
|
|
119
|
-
dot: { toState: 'traverse' },
|
|
120
|
-
openBracket: { toState: 'filter' },
|
|
121
|
-
pipe: { toState: 'expectTransform' },
|
|
122
|
-
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
123
|
-
semicolon: { handler: h.semicolon }
|
|
124
|
-
},
|
|
125
|
-
completable: true
|
|
126
|
-
},
|
|
127
116
|
postArgs: {
|
|
128
|
-
tokenTypes:
|
|
129
|
-
binaryOp: { toState: 'expectOperand' },
|
|
130
|
-
dot: { toState: 'traverse' },
|
|
131
|
-
openBracket: { toState: 'filter' },
|
|
132
|
-
pipe: { toState: 'expectTransform' },
|
|
133
|
-
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
134
|
-
semicolon: { handler: h.semicolon }
|
|
135
|
-
},
|
|
117
|
+
tokenTypes: afterOperand,
|
|
136
118
|
completable: true
|
|
137
119
|
},
|
|
138
120
|
identifier: {
|
|
139
121
|
tokenTypes: {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
openParen: { toState: 'argVal', handler: h.functionCall }
|
|
144
|
-
pipe: { toState: 'expectTransform' },
|
|
145
|
-
question: { toState: 'ternaryMid', handler: h.ternaryStart },
|
|
146
|
-
semicolon: { handler: h.semicolon }
|
|
122
|
+
...afterOperand,
|
|
123
|
+
// a name is the only operand that can be followed by an argument list,
|
|
124
|
+
// since a function is called by name rather than evaluated as a value
|
|
125
|
+
openParen: { toState: 'argVal', handler: h.functionCall }
|
|
147
126
|
},
|
|
148
127
|
completable: true
|
|
149
128
|
},
|