@swaggerexpert/jsonpath 2.4.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,30 @@
1
1
  import { utilities, identifiers } from 'apg-lite';
2
2
  import JSONPathParseError from "../../errors/JSONPathParseError.mjs";
3
- const cst = ruleName => {
3
+ const cst = nodeType => {
4
4
  return (state, chars, phraseIndex, phraseLength, data) => {
5
+ var _data$options, _data$options2;
5
6
  if (!(typeof data === 'object' && data !== null && !Array.isArray(data))) {
6
7
  throw new JSONPathParseError("parser's user data must be an object");
7
8
  }
8
9
 
9
10
  // drop the empty nodes
10
- if (phraseLength === 0) return;
11
+ if ((_data$options = data.options) !== null && _data$options !== void 0 && _data$options.optimize && phraseLength === 0 && (_data$options2 = data.options) !== null && _data$options2 !== void 0 && (_data$options2 = _data$options2.droppableTypes) !== null && _data$options2 !== void 0 && _data$options2.includes(nodeType)) {
12
+ return;
13
+ }
11
14
  if (state === identifiers.SEM_PRE) {
12
15
  const node = {
13
- type: ruleName,
16
+ type: nodeType,
14
17
  text: utilities.charsToString(chars, phraseIndex, phraseLength),
15
18
  start: phraseIndex,
16
19
  length: phraseLength,
17
20
  children: []
18
21
  };
19
22
  if (data.stack.length > 0) {
20
- var _data$options, _data$options2;
23
+ var _data$options3, _data$options4;
21
24
  const parent = data.stack[data.stack.length - 1];
22
25
  const prevSibling = parent.children[parent.children.length - 1];
23
26
  const isTextNodeWithinTextNode = parent.type === 'text' && node.type === 'text';
24
- const shouldCollapse = ((_data$options = data.options) === null || _data$options === void 0 ? void 0 : _data$options.optimize) && ((_data$options2 = data.options) === null || _data$options2 === void 0 || (_data$options2 = _data$options2.collapsibleTypes) === null || _data$options2 === void 0 ? void 0 : _data$options2.includes(node.type)) && (prevSibling === null || prevSibling === void 0 ? void 0 : prevSibling.type) === node.type;
27
+ const shouldCollapse = ((_data$options3 = data.options) === null || _data$options3 === void 0 ? void 0 : _data$options3.optimize) && ((_data$options4 = data.options) === null || _data$options4 === void 0 || (_data$options4 = _data$options4.collapsibleTypes) === null || _data$options4 === void 0 ? void 0 : _data$options4.includes(node.type)) && (prevSibling === null || prevSibling === void 0 ? void 0 : prevSibling.type) === node.type;
25
28
  if (shouldCollapse) {
26
29
  prevSibling.text += node.text;
27
30
  prevSibling.length += node.length;
@@ -1,19 +1,18 @@
1
1
  import { Parser, Stats, Trace } from 'apg-lite';
2
2
  import Grammar from "../grammar.mjs";
3
- import CSTTranslator from "./translators/CSTTranslator.mjs";
3
+ import ASTTranslator from "./translators/ASTTranslator/index.mjs";
4
4
  import JSONPathParseError from "../errors/JSONPathParseError.mjs";
5
5
  const grammar = new Grammar();
6
6
  const parse = (jsonPath, {
7
7
  normalized = false,
8
8
  stats = false,
9
9
  trace = false,
10
- translator = new CSTTranslator()
10
+ translator = new ASTTranslator()
11
11
  } = {}) => {
12
12
  if (typeof jsonPath !== 'string') {
13
13
  throw new TypeError('JSONPath must be a string');
14
14
  }
15
15
  try {
16
- var _parser$ast;
17
16
  const parser = new Parser();
18
17
  if (translator) parser.ast = translator;
19
18
  if (stats) parser.stats = new Stats();
@@ -22,7 +21,7 @@ const parse = (jsonPath, {
22
21
  const result = parser.parse(grammar, startRule, jsonPath);
23
22
  return {
24
23
  result,
25
- tree: result.success ? (_parser$ast = parser.ast) === null || _parser$ast === void 0 ? void 0 : _parser$ast.getTree() : undefined,
24
+ tree: result.success && translator ? parser.ast.getTree() : undefined,
26
25
  stats: parser.stats,
27
26
  trace: parser.trace
28
27
  };
@@ -0,0 +1,9 @@
1
+ export const decodeString = str => {
2
+ return JSON.parse(`"${str.replace(/"/g, '\\"')}"`);
3
+ };
4
+ export const decodeInteger = str => {
5
+ return parseInt(str, 10);
6
+ };
7
+ export const decodeJSONValue = str => {
8
+ return JSON.parse(str);
9
+ };
@@ -0,0 +1,9 @@
1
+ import CSTOptimizedTranslator from "../CSTOptimizedTranslator.mjs";
2
+ import { transformCSTtoAST, default as transformers } from "./transformers.mjs";
3
+ class ASTTranslator extends CSTOptimizedTranslator {
4
+ getTree() {
5
+ const cst = super.getTree();
6
+ return transformCSTtoAST(cst.root, transformers);
7
+ }
8
+ }
9
+ export default ASTTranslator;
@@ -0,0 +1,404 @@
1
+ import JSONPathParseError from "../../../errors/JSONPathParseError.mjs";
2
+ import { decodeString, decodeInteger, decodeJSONValue } from "./decoders.mjs";
3
+ export const transformCSTtoAST = (node, transformerMap, ctx = {
4
+ parent: null,
5
+ path: []
6
+ }) => {
7
+ const transformer = transformerMap[node.type];
8
+ if (!transformer) {
9
+ throw new JSONPathParseError(`No transformer for CST node type: ${node.type}`);
10
+ }
11
+ const nextCtx = {
12
+ parent: node,
13
+ path: [...ctx.path, node]
14
+ };
15
+ return transformer(node, nextCtx);
16
+ };
17
+ const transformers = {
18
+ /**
19
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.1.1
20
+ */
21
+ ['jsonpath-query'](node, ctx) {
22
+ const segments = node.children.find(c => c.type === 'segments');
23
+ return {
24
+ type: 'JsonPathQuery',
25
+ segments: segments ? segments.children.filter(({
26
+ type
27
+ }) => type === 'segment').map(segNode => transformCSTtoAST(segNode, transformers, ctx)) : []
28
+ };
29
+ },
30
+ /**
31
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.5
32
+ */
33
+ segment(node, ctx) {
34
+ const child = node.children.find(({
35
+ type
36
+ }) => ['child-segment', 'descendant-segment'].includes(type));
37
+ return transformCSTtoAST(child, transformers, ctx);
38
+ },
39
+ /**
40
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3
41
+ */
42
+ selector(node, ctx) {
43
+ const child = node.children.find(({
44
+ type
45
+ }) => ['name-selector', 'wildcard-selector', 'slice-selector', 'index-selector', 'filter-selector'].includes(type));
46
+ return transformCSTtoAST(child, transformers, ctx);
47
+ },
48
+ /**
49
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3.1.1
50
+ */
51
+ ['name-selector'](node, ctx) {
52
+ const stringLiteralCSTNode = node.children.find(({
53
+ type
54
+ }) => type === 'string-literal');
55
+ const stringLiteralASTNode = transformCSTtoAST(stringLiteralCSTNode, transformers, ctx);
56
+ return {
57
+ type: 'NameSelector',
58
+ value: stringLiteralASTNode.value,
59
+ format: stringLiteralASTNode.format
60
+ };
61
+ },
62
+ ['string-literal'](node) {
63
+ const isSingleQuoted = node.children.find(({
64
+ type,
65
+ text
66
+ }) => type === 'text' && text === "'");
67
+ const quoted = node.children.find(({
68
+ type
69
+ }) => ['double-quoted', 'single-quoted'].includes(type));
70
+ return {
71
+ type: 'StringLiteral',
72
+ value: quoted ? decodeString(quoted.text) : '',
73
+ format: isSingleQuoted ? 'single-quoted' : 'double-quoted'
74
+ };
75
+ },
76
+ /**
77
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3.2.1
78
+ */
79
+ ['wildcard-selector']() {
80
+ return {
81
+ type: 'WildcardSelector'
82
+ };
83
+ },
84
+ /**
85
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3.3.1
86
+ */
87
+ ['index-selector'](node) {
88
+ return {
89
+ type: 'IndexSelector',
90
+ value: decodeInteger(node.text)
91
+ };
92
+ },
93
+ /**
94
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3.4.1
95
+ */
96
+ ['slice-selector'](node) {
97
+ const start = node.children.find(({
98
+ type
99
+ }) => type === 'start');
100
+ const end = node.children.find(({
101
+ type
102
+ }) => type === 'end');
103
+ const step = node.children.find(({
104
+ type
105
+ }) => type === 'step');
106
+ return {
107
+ type: 'SliceSelector',
108
+ start: start ? decodeInteger(start.text) : null,
109
+ end: end ? decodeInteger(end.text) : null,
110
+ step: step ? decodeInteger(step.text) : null
111
+ };
112
+ },
113
+ /**
114
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.3.5.1
115
+ */
116
+ ['filter-selector'](node, ctx) {
117
+ const child = node.children.find(({
118
+ type
119
+ }) => type === 'logical-expr');
120
+ return {
121
+ type: 'FilterSelector',
122
+ expression: transformCSTtoAST(child, transformers, ctx)
123
+ };
124
+ },
125
+ ['logical-expr'](node, ctx) {
126
+ const child = node.children.find(({
127
+ type
128
+ }) => type === 'logical-or-expr');
129
+ return transformCSTtoAST(child, transformers, ctx);
130
+ },
131
+ ['logical-or-expr'](node, ctx) {
132
+ const logicalAndExprs = node.children.filter(({
133
+ type
134
+ }) => type === 'logical-and-expr');
135
+ if (logicalAndExprs.length === 1) {
136
+ return transformCSTtoAST(logicalAndExprs[0], transformers, ctx);
137
+ }
138
+
139
+ // fold left for left-associativity
140
+ let left = transformCSTtoAST(logicalAndExprs[0], transformers, ctx);
141
+ for (let i = 1; i < logicalAndExprs.length; i += 1) {
142
+ const right = transformCSTtoAST(logicalAndExprs[i], transformers, ctx);
143
+ left = {
144
+ type: 'LogicalOrExpr',
145
+ left,
146
+ right
147
+ };
148
+ }
149
+ },
150
+ ['logical-and-expr'](node, ctx) {
151
+ const basicExprs = node.children.filter(({
152
+ type
153
+ }) => type === 'basic-expr');
154
+ if (basicExprs.length === 1) {
155
+ return transformCSTtoAST(basicExprs[0], transformers, ctx);
156
+ }
157
+ let left = transformCSTtoAST(basicExprs[0], transformers, ctx);
158
+ for (let i = 1; i < basicExprs.length; i += 1) {
159
+ const right = transformCSTtoAST(basicExprs[i], transformers, ctx);
160
+ left = {
161
+ type: 'LogicalAndExpr',
162
+ left,
163
+ right
164
+ };
165
+ }
166
+ return left;
167
+ },
168
+ ['basic-expr'](node, ctx) {
169
+ const child = node.children.find(({
170
+ type
171
+ }) => ['paren-expr', 'comparison-expr', 'test-expr'].includes(type));
172
+ return transformCSTtoAST(child, transformers, ctx);
173
+ },
174
+ ['paren-expr'](node, ctx) {
175
+ const isNegated = node.children.some(child => child.type === 'logical-not-op');
176
+ const logicalExprCSTNode = node.children.find(child => child.type === 'logical-expr');
177
+ const logicalExpressionASTNode = transformCSTtoAST(logicalExprCSTNode, transformers, ctx);
178
+ if (isNegated) {
179
+ return {
180
+ type: 'LogicalNotExpr',
181
+ expression: logicalExpressionASTNode
182
+ };
183
+ }
184
+ return logicalExpressionASTNode;
185
+ },
186
+ ['test-expr'](node, ctx) {
187
+ const isNegated = node.children.some(({
188
+ type
189
+ }) => type === 'logical-not-op');
190
+ const expression = node.children.find(({
191
+ type
192
+ }) => ['filter-query', 'function-expr'].includes(type));
193
+ const testExpr = {
194
+ type: 'TestExpr',
195
+ expression: transformCSTtoAST(expression, transformers, ctx)
196
+ };
197
+ return isNegated ? {
198
+ type: 'LogicalNotExpr',
199
+ expression: testExpr
200
+ } : testExpr;
201
+ },
202
+ ['filter-query'](node, ctx) {
203
+ const child = node.children.find(({
204
+ type
205
+ }) => ['rel-query', 'jsonpath-query'].includes(type));
206
+ return {
207
+ type: 'FilterQuery',
208
+ query: transformCSTtoAST(child, transformers, ctx)
209
+ };
210
+ },
211
+ ['rel-query'](node, ctx) {
212
+ const segments = node.children.find(c => c.type === 'segments');
213
+ return {
214
+ type: 'RelQuery',
215
+ segments: segments ? segments.children.filter(n => n.type === 'segment').map(segNode => transformCSTtoAST(segNode, transformers, ctx)) : []
216
+ };
217
+ },
218
+ ['comparison-expr'](node, ctx) {
219
+ const children = node.children.filter(({
220
+ type
221
+ }) => ['comparable', 'comparison-op'].includes(type));
222
+ const [left, op, right] = children;
223
+ return {
224
+ type: 'ComparisonExpr',
225
+ left: transformCSTtoAST(left, transformers, ctx),
226
+ op: op.text,
227
+ right: transformCSTtoAST(right, transformers, ctx)
228
+ };
229
+ },
230
+ ['literal'](node, ctx) {
231
+ const child = node.children.find(({
232
+ type
233
+ }) => ['number', 'string-literal', 'true', 'false', 'null'].includes(type));
234
+ if (child.type === 'string-literal') {
235
+ const stringLiteralASTNode = transformCSTtoAST(child, transformers, ctx);
236
+ return {
237
+ type: 'Literal',
238
+ value: stringLiteralASTNode.value
239
+ };
240
+ }
241
+ return {
242
+ type: 'Literal',
243
+ value: decodeJSONValue(child.text)
244
+ };
245
+ },
246
+ ['comparable'](node, ctx) {
247
+ const child = node.children.find(({
248
+ type
249
+ }) => ['singular-query', 'function-expr', 'literal'].includes(type));
250
+ return transformCSTtoAST(child, transformers, ctx);
251
+ },
252
+ ['singular-query'](node, ctx) {
253
+ const child = node.children.find(({
254
+ type
255
+ }) => ['rel-singular-query', 'abs-singular-query'].includes(type));
256
+ return transformCSTtoAST(child, transformers, ctx);
257
+ },
258
+ ['rel-singular-query'](node, ctx) {
259
+ const segmentsNode = node.children.find(({
260
+ type
261
+ }) => type === 'singular-query-segments');
262
+ const segments = segmentsNode ? segmentsNode.children.filter(({
263
+ type
264
+ }) => ['name-segment', 'index-segment'].includes(type)).map(segNode => ({
265
+ type: 'SingularQuerySegment',
266
+ selector: transformCSTtoAST(segNode, transformers, ctx)
267
+ })) : [];
268
+ return {
269
+ type: 'RelSingularQuery',
270
+ segments
271
+ };
272
+ },
273
+ ['abs-singular-query'](node, ctx) {
274
+ const segmentsNode = node.children.find(({
275
+ type
276
+ }) => type === 'singular-query-segments');
277
+ const segments = segmentsNode ? segmentsNode.children.filter(({
278
+ type
279
+ }) => ['name-segment', 'index-segment'].includes(type)).map(segNode => ({
280
+ type: 'SingularQuerySegment',
281
+ selector: transformCSTtoAST(segNode, transformers, ctx)
282
+ })) : [];
283
+ return {
284
+ type: 'AbsSingularQuery',
285
+ segments
286
+ };
287
+ },
288
+ ['name-segment'](node, ctx) {
289
+ const child = node.children.find(({
290
+ type
291
+ }) => ['name-selector', 'member-name-shorthand'].includes(type));
292
+ return transformCSTtoAST(child, transformers, ctx);
293
+ },
294
+ ['index-segment'](node, ctx) {
295
+ const child = node.children.find(({
296
+ type
297
+ }) => type === 'index-selector');
298
+ return transformCSTtoAST(child, transformers, ctx);
299
+ },
300
+ /**
301
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.4
302
+ */
303
+ ['function-expr'](node, ctx) {
304
+ const name = node.children.find(({
305
+ type
306
+ }) => type === 'function-name');
307
+ const args = node.children.filter(({
308
+ type
309
+ }) => type === 'function-argument');
310
+ return {
311
+ type: 'FunctionExpr',
312
+ name: name.text,
313
+ arguments: args.map(arg => transformCSTtoAST(arg, transformers, ctx))
314
+ };
315
+ },
316
+ ['function-argument'](node, ctx) {
317
+ const child = node.children.find(({
318
+ type
319
+ }) => ['logical-expr', 'function-expr', 'filter-query', 'literal'].includes(type));
320
+ return transformCSTtoAST(child, transformers, ctx);
321
+ },
322
+ /**
323
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.5.1.1
324
+ */
325
+ ['child-segment'](node, ctx) {
326
+ const child = node.children.find(({
327
+ type
328
+ }) => ['bracketed-selection', 'wildcard-selector', 'member-name-shorthand'].includes(type));
329
+ return {
330
+ type: 'ChildSegment',
331
+ selector: transformCSTtoAST(child, transformers, ctx)
332
+ };
333
+ },
334
+ ['bracketed-selection'](node, ctx) {
335
+ return {
336
+ type: 'BracketedSelection',
337
+ selectors: node.children.filter(({
338
+ type
339
+ }) => type === 'selector').map(selectorNode => transformCSTtoAST(selectorNode, transformers, ctx))
340
+ };
341
+ },
342
+ ['member-name-shorthand'](node) {
343
+ return {
344
+ type: 'NameSelector',
345
+ value: node.text,
346
+ format: 'shorthand'
347
+ };
348
+ },
349
+ /**
350
+ * https://www.rfc-editor.org/rfc/rfc9535#section-2.5.2.1
351
+ */
352
+ ['descendant-segment'](node, ctx) {
353
+ const child = node.children.find(({
354
+ type
355
+ }) => ['bracketed-selection', 'wildcard-selector', 'member-name-shorthand'].includes(type));
356
+ return {
357
+ type: 'DescendantSegment',
358
+ selector: transformCSTtoAST(child, transformers, ctx)
359
+ };
360
+ },
361
+ /**
362
+ * https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
363
+ */
364
+ ['normalized-path'](node, ctx) {
365
+ return {
366
+ type: 'JsonPathQuery',
367
+ segments: node.children.filter(({
368
+ type
369
+ }) => type === 'normal-index-segment').map(segNode => transformCSTtoAST(segNode, transformers, ctx))
370
+ };
371
+ },
372
+ ['normal-index-segment'](node, ctx) {
373
+ const child = node.children.find(({
374
+ type
375
+ }) => type === 'normal-selector');
376
+ return {
377
+ type: 'ChildSegment',
378
+ selector: transformCSTtoAST(child, transformers, ctx)
379
+ };
380
+ },
381
+ ['normal-selector'](node, ctx) {
382
+ const child = node.children.find(({
383
+ type
384
+ }) => ['normal-name-selector', 'normal-index-selector'].includes(type));
385
+ return transformCSTtoAST(child, transformers, ctx);
386
+ },
387
+ ['normal-name-selector'](node) {
388
+ const child = node.children.find(({
389
+ type
390
+ }) => type === 'normal-single-quoted');
391
+ return {
392
+ type: 'NameSelector',
393
+ value: child ? decodeString(child.text) : '',
394
+ format: 'single-quoted'
395
+ };
396
+ },
397
+ ['normal-index-selector'](node) {
398
+ return {
399
+ type: 'IndexSelector',
400
+ value: decodeInteger(node.text)
401
+ };
402
+ }
403
+ };
404
+ export default transformers;
@@ -1,18 +1,24 @@
1
1
  import CSTTranslator from "./CSTTranslator.mjs";
2
2
  class CSTOptimizedTranslator extends CSTTranslator {
3
3
  collapsibleTypes = ['single-quoted', 'double-quoted', 'normal-single-quoted'];
4
+ droppableTypes = ['text', 'segments', 'singular-query-segments'];
4
5
  constructor({
5
- collapsibleTypes
6
+ collapsibleTypes,
7
+ droppableTypes
6
8
  } = {}) {
7
9
  super();
8
10
  if (Array.isArray(collapsibleTypes)) {
9
11
  this.collapsibleTypes = collapsibleTypes;
10
12
  }
13
+ if (Array.isArray(droppableTypes)) {
14
+ this.droppableTypes = droppableTypes;
15
+ }
11
16
  }
12
17
  getTree() {
13
18
  const options = {
14
19
  optimize: true,
15
- collapsibleTypes: this.collapsibleTypes
20
+ collapsibleTypes: this.collapsibleTypes,
21
+ droppableTypes: this.droppableTypes
16
22
  };
17
23
  const data = {
18
24
  stack: [],
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.4.1",
6
+ "version": "3.0.0",
7
7
  "description": "RCF 9535 implementation of JSONPath",
8
8
  "main": "./cjs/index.cjs",
9
9
  "types": "./types/index.d.ts",
package/types/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export declare class XMLTranslator implements Translator<XMLTree> {
24
24
  getTree(): XMLTree;
25
25
  }
26
26
 
27
- export interface ParseResult<TTree = unknown> {
27
+ export interface ParseResult<TTree = ASTTree> {
28
28
  readonly result: {
29
29
  readonly success: boolean;
30
30
  readonly state: number;
@@ -54,6 +54,159 @@ export interface CSTTree {
54
54
 
55
55
  export type XMLTree = string;
56
56
 
57
+ /* AST Tree start */
58
+ export interface ASTTree {
59
+ readonly root: JSONPathQueryASTNode;
60
+ }
61
+ export interface ASTNode {
62
+ readonly type:
63
+ | 'JSONPathQuery'
64
+ | 'NameSelector'
65
+ | 'WildcardSelector'
66
+ | 'IndexSelector'
67
+ | 'SliceSelector'
68
+ | 'FilterSelector'
69
+ | 'LogicalOrExpr'
70
+ | 'LogicalAndExpr'
71
+ | 'LogicalNotExpr'
72
+ | 'TestExpr'
73
+ | 'FilterQuery'
74
+ | 'RelQuery'
75
+ | 'ComparisonExpr'
76
+ | 'Literal'
77
+ | 'RelSingularQuery'
78
+ | 'AbsSingularQuery'
79
+ | 'FunctionExpr'
80
+ | 'ChildSegment'
81
+ | 'DescendantSegment'
82
+ | 'BracketedSelection';
83
+ }
84
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.1.1
85
+ export interface JSONPathQueryASTNode extends ASTNode {
86
+ readonly type: 'JSONPathQuery';
87
+ segments: SegmentASTNode[];
88
+ }
89
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.3.1.1
90
+ export interface NameSelectorASTNode extends ASTNode {
91
+ type: 'NameSelector';
92
+ value: string;
93
+ format: 'single-quoted' | 'double-quoted' | 'shorthand';
94
+ }
95
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.3.2.1
96
+ export interface WildcardSelectorASTNode extends ASTNode {
97
+ type: 'WildcardSelector';
98
+ }
99
+ // https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
100
+ export interface IndexSelectorASTNode extends ASTNode {
101
+ type: 'IndexSelector';
102
+ value: number;
103
+ }
104
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.3.4.1
105
+ export interface SliceSelectorASTNode extends ASTNode {
106
+ type: 'SliceSelector';
107
+ start: number | null;
108
+ end: number | null ;
109
+ step: number | null;
110
+ }
111
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.3.5.1
112
+ export interface FilterSelectorASTNode extends ASTNode {
113
+ type: 'FilterSelector';
114
+ expression: LogicalExprASTNode;
115
+ }
116
+ export interface LogicalOrExprASTNode extends ASTNode {
117
+ type: 'LogicalOrExpr';
118
+ left: LogicalExprASTNode;
119
+ right: LogicalExprASTNode;
120
+ }
121
+ export interface LogicalAndExprASTNode extends ASTNode {
122
+ type: 'LogicalAndExpr';
123
+ left: LogicalExprASTNode;
124
+ right: LogicalExprASTNode;
125
+ }
126
+ export interface LogicalNotExprASTNode extends ASTNode {
127
+ type: 'LogicalNotExpr';
128
+ expression: LogicalExprASTNode;
129
+ }
130
+ export interface TestExprASTNode extends ASTNode {
131
+ type: 'TestExpr';
132
+ expression: FilterQueryASTNode | FunctionExprASTNode;
133
+ }
134
+ export interface FilterQueryASTNode extends ASTNode {
135
+ type: 'FilterQuery';
136
+ query: RelQueryASTNode | JSONPathQueryASTNode;
137
+ }
138
+ export interface RelQueryASTNode extends ASTNode {
139
+ type: 'RelQuery';
140
+ segments: SegmentASTNode[];
141
+ }
142
+ export interface ComparisonExprASTNode extends ASTNode {
143
+ type: 'ComparisonExpr';
144
+ left: ComparableASTNode;
145
+ operator: '==' | '!=' | '<=' | '>=' | '<' | '>';
146
+ right: ComparableASTNode;
147
+ }
148
+ export interface LiteralASTNode extends ASTNode {
149
+ type: 'Literal';
150
+ value: string | number | boolean | null;
151
+ }
152
+ export interface RelSingularQueryASTNode extends ASTNode {
153
+ type: 'RelSingularQuery';
154
+ segments: SingularQuerySegmentASTNode[];
155
+ }
156
+ export interface AbsSingularQueryASTNode extends ASTNode {
157
+ type: 'AbsSingularQuery';
158
+ segments: SingularQuerySegmentASTNode[];
159
+ }
160
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.4
161
+ export interface FunctionExprASTNode extends ASTNode {
162
+ type: 'FunctionExpr';
163
+ name: string;
164
+ arguments: FunctionArgumentASTNode[];
165
+ }
166
+ // https://www.rfc-editor.org/rfc/rfc9535#section-2.5.1.1
167
+ export interface ChildSegmentASTNode extends ASTNode {
168
+ type: 'ChildSegment';
169
+ selector: BracketedSelectionASTNode | WildcardSelectorASTNode | NameSelectorASTNode;
170
+ }
171
+ export interface BracketedSelectionASTNode extends ASTNode {
172
+ type: 'BracketedSelection';
173
+ selectors: SelectorASTNode[];
174
+ }
175
+ export interface DescendantSegmentASTNode extends ASTNode {
176
+ type: 'DescendantSegment';
177
+ selector: BracketedSelectionASTNode | WildcardSelectorASTNode | NameSelectorASTNode;
178
+ }
179
+ // union types
180
+ export type SelectorASTNode =
181
+ | NameSelectorASTNode
182
+ | WildcardSelectorASTNode
183
+ | SliceSelectorASTNode
184
+ | IndexSelectorASTNode
185
+ | FilterQueryASTNode;
186
+ export type LogicalExprASTNode =
187
+ | LogicalOrExprASTNode
188
+ | LogicalAndExprASTNode
189
+ | LogicalNotExprASTNode
190
+ | TestExprASTNode
191
+ | ComparisonExprASTNode;
192
+ export type ComparableASTNode =
193
+ | RelSingularQueryASTNode
194
+ | AbsSingularQueryASTNode
195
+ | FunctionExprASTNode
196
+ | LiteralASTNode;
197
+ export type SegmentASTNode =
198
+ | ChildSegmentASTNode
199
+ | DescendantSegmentASTNode;
200
+ export type FunctionArgumentASTNode =
201
+ | LogicalExprASTNode
202
+ | FilterQueryASTNode
203
+ | FunctionExprASTNode
204
+ | LiteralASTNode;
205
+ export type SingularQuerySegmentASTNode =
206
+ | NameSelectorASTNode
207
+ | IndexSelectorASTNode;
208
+ /* AST Tree end */
209
+
57
210
  export interface Stats {
58
211
  displayStats(): string;
59
212
  displayHits(): string;