@revisium/formula 0.8.0 → 0.10.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.
Files changed (75) hide show
  1. package/dist/__tests__/array-context.spec.d.ts +2 -0
  2. package/dist/__tests__/array-context.spec.d.ts.map +1 -0
  3. package/dist/__tests__/dependency-graph.spec.d.ts +2 -0
  4. package/dist/__tests__/dependency-graph.spec.d.ts.map +1 -0
  5. package/dist/__tests__/evaluate-complex.spec.d.ts +2 -0
  6. package/dist/__tests__/evaluate-complex.spec.d.ts.map +1 -0
  7. package/dist/__tests__/parse-formula.spec.d.ts +2 -0
  8. package/dist/__tests__/parse-formula.spec.d.ts.map +1 -0
  9. package/dist/__tests__/parser.spec.d.ts +2 -0
  10. package/dist/__tests__/parser.spec.d.ts.map +1 -0
  11. package/dist/__tests__/replace-dependencies.spec.d.ts +2 -0
  12. package/dist/__tests__/replace-dependencies.spec.d.ts.map +1 -0
  13. package/dist/__tests__/serialize-ast.spec.d.ts +2 -0
  14. package/dist/__tests__/serialize-ast.spec.d.ts.map +1 -0
  15. package/dist/__tests__/validate-syntax.spec.d.ts +2 -0
  16. package/dist/__tests__/validate-syntax.spec.d.ts.map +1 -0
  17. package/dist/dependency-graph.d.ts +17 -0
  18. package/dist/dependency-graph.d.ts.map +1 -0
  19. package/dist/editor/index.cjs +4 -19
  20. package/dist/editor/index.d.ts +8 -1
  21. package/dist/editor/index.d.ts.map +1 -0
  22. package/dist/editor/index.mjs +3 -0
  23. package/dist/formula-spec.cjs +831 -535
  24. package/dist/formula-spec.cjs.map +1 -1
  25. package/dist/formula-spec.d.ts +10 -5
  26. package/dist/formula-spec.d.ts.map +1 -0
  27. package/dist/formula-spec.mjs +1062 -0
  28. package/dist/formula-spec.mjs.map +1 -0
  29. package/dist/index.cjs +121 -131
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.ts +10 -25
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.mjs +130 -0
  34. package/dist/index.mjs.map +1 -0
  35. package/dist/ohm/core/parser.d.ts +30 -0
  36. package/dist/ohm/core/parser.d.ts.map +1 -0
  37. package/dist/ohm/core/replace-dependencies.d.ts +3 -0
  38. package/dist/ohm/core/replace-dependencies.d.ts.map +1 -0
  39. package/dist/ohm/core/serialize-ast.d.ts +3 -0
  40. package/dist/ohm/core/serialize-ast.d.ts.map +1 -0
  41. package/dist/ohm/core/types.d.ts +78 -0
  42. package/dist/ohm/core/types.d.ts.map +1 -0
  43. package/dist/ohm/grammar/index.d.ts +3 -0
  44. package/dist/ohm/grammar/index.d.ts.map +1 -0
  45. package/dist/ohm/index.d.ts +8 -0
  46. package/dist/ohm/index.d.ts.map +1 -0
  47. package/dist/ohm/semantics/index.d.ts +2 -0
  48. package/dist/ohm/semantics/index.d.ts.map +1 -0
  49. package/dist/parse-formula.d.ts +9 -0
  50. package/dist/parse-formula.d.ts.map +1 -0
  51. package/dist/types.d.ts +52 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/validate-syntax-Dttxs0ku.mjs +1426 -0
  54. package/dist/validate-syntax-Dttxs0ku.mjs.map +1 -0
  55. package/dist/validate-syntax-q3bM-DaM.cjs +1507 -0
  56. package/dist/validate-syntax-q3bM-DaM.cjs.map +1 -0
  57. package/dist/validate-syntax.d.ts +9 -0
  58. package/dist/validate-syntax.d.ts.map +1 -0
  59. package/package.json +12 -11
  60. package/dist/chunk-4FIOGFOL.cjs +0 -1512
  61. package/dist/chunk-4FIOGFOL.cjs.map +0 -1
  62. package/dist/chunk-RMAHNB4D.js +0 -1482
  63. package/dist/chunk-RMAHNB4D.js.map +0 -1
  64. package/dist/editor/index.cjs.map +0 -1
  65. package/dist/editor/index.d.cts +0 -1
  66. package/dist/editor/index.js +0 -3
  67. package/dist/editor/index.js.map +0 -1
  68. package/dist/formula-spec.d.cts +0 -68
  69. package/dist/formula-spec.js +0 -765
  70. package/dist/formula-spec.js.map +0 -1
  71. package/dist/index-CPsOPCQ6.d.cts +0 -166
  72. package/dist/index-CPsOPCQ6.d.ts +0 -166
  73. package/dist/index.d.cts +0 -25
  74. package/dist/index.js +0 -111
  75. package/dist/index.js.map +0 -1
@@ -1,1512 +0,0 @@
1
- 'use strict';
2
-
3
- var ohm = require('ohm-js');
4
-
5
- function _interopNamespace(e) {
6
- if (e && e.__esModule) return e;
7
- var n = Object.create(null);
8
- if (e) {
9
- Object.keys(e).forEach(function (k) {
10
- if (k !== 'default') {
11
- var d = Object.getOwnPropertyDescriptor(e, k);
12
- Object.defineProperty(n, k, d.get ? d : {
13
- enumerable: true,
14
- get: function () { return e[k]; }
15
- });
16
- }
17
- });
18
- }
19
- n.default = e;
20
- return Object.freeze(n);
21
- }
22
-
23
- var ohm__namespace = /*#__PURE__*/_interopNamespace(ohm);
24
-
25
- // src/ohm/grammar/index.ts
26
- var grammarText = String.raw`Formula {
27
- Expression = Ternary
28
-
29
- // Ternary: condition ? then : else
30
- Ternary
31
- = LogicalOr "?" Ternary ":" Ternary -- ternary
32
- | LogicalOr
33
-
34
- // Logical OR: a || b
35
- LogicalOr
36
- = LogicalOr "||" LogicalAnd -- or
37
- | LogicalAnd
38
-
39
- // Logical AND: a && b
40
- LogicalAnd
41
- = LogicalAnd "&&" Equality -- and
42
- | Equality
43
-
44
- // Equality: a == b, a != b
45
- Equality
46
- = Equality "==" Comparison -- eq
47
- | Equality "!=" Comparison -- neq
48
- | Comparison
49
-
50
- // Comparison: a > b, a < b, a >= b, a <= b
51
- Comparison
52
- = Comparison ">=" Additive -- gte
53
- | Comparison "<=" Additive -- lte
54
- | Comparison ">" Additive -- gt
55
- | Comparison "<" Additive -- lt
56
- | Additive
57
-
58
- // Additive: a + b, a - b
59
- Additive
60
- = Additive "+" Multiplicative -- plus
61
- | Additive "-" Multiplicative -- minus
62
- | Multiplicative
63
-
64
- // Multiplicative: a * b, a / b, a % b
65
- Multiplicative
66
- = Multiplicative "*" Unary -- times
67
- | Multiplicative "/" Unary -- div
68
- | Multiplicative "%" Unary -- mod
69
- | Unary
70
-
71
- // Unary: -a, !a
72
- Unary
73
- = "-" Unary -- neg
74
- | "!" Unary -- not
75
- | Postfix
76
-
77
- // Postfix: function calls, property access, array access
78
- Postfix
79
- = Postfix "(" Arguments? ")" -- call
80
- | Postfix "." identifier -- property
81
- | Postfix "[" Expression "]" -- index
82
- | Postfix "[" "*" "]" -- wildcard
83
- | Primary
84
-
85
- // Arguments for function calls
86
- Arguments
87
- = Expression ("," Expression)*
88
-
89
- // Primary expressions
90
- Primary
91
- = "(" Expression ")" -- paren
92
- | "[" string "]" -- bracketedField
93
- | number
94
- | string
95
- | boolean
96
- | null
97
- | rootPath
98
- | relativePath
99
- | contextToken
100
- | identifier
101
-
102
- // Literals
103
- number
104
- = "-"? digit+ "." digit+ -- float
105
- | "-"? digit+ -- int
106
-
107
- string
108
- = "\"" doubleStringChar* "\""
109
- | "'" singleStringChar* "'"
110
-
111
- doubleStringChar
112
- = ~("\"" | "\\") any -- regular
113
- | "\\" any -- escape
114
-
115
- singleStringChar
116
- = ~("'" | "\\") any -- regular
117
- | "\\" any -- escape
118
-
119
- boolean
120
- = "true" ~identifierPart -- true
121
- | "false" ~identifierPart -- false
122
-
123
- null = "null" ~identifierPart
124
-
125
- // Identifiers and paths
126
- identifier = ~reserved identifierStart identifierPart*
127
-
128
- identifierStart = letter | "_"
129
- identifierPart = letter | digit | "_"
130
-
131
- // Special paths
132
- rootPath = "/" identifierPart+
133
-
134
- relativePathPrefix = ".." "/"
135
- relativePath = relativePathPrefix+ identifierPart+
136
-
137
- contextToken
138
- = "@" identifierPart+ -- at
139
- | "#" identifierPart+ -- hash
140
-
141
- // Reserved words (cannot be used as identifiers)
142
- reserved
143
- = ("true" | "false" | "null") ~identifierPart
144
-
145
- // Whitespace (implicit, Ohm handles automatically)
146
- }`;
147
- var grammar2 = ohm__namespace.grammar(grammarText);
148
-
149
- // src/ohm/semantics/index.ts
150
- function isSafePropertyName(name) {
151
- return name !== "__proto__";
152
- }
153
- function childrenToAST(children) {
154
- return children.filter((c) => "toAST" in c).map((c) => c.toAST());
155
- }
156
- function childrenDependencies(children) {
157
- return children.filter((c) => "dependencies" in c).flatMap((c) => c.dependencies());
158
- }
159
- function childrenFeatures(children) {
160
- return children.filter((c) => "features" in c).flatMap((c) => c.features());
161
- }
162
- var semantics = grammar2.createSemantics();
163
- semantics.addOperation("toAST", {
164
- Expression(e) {
165
- return e.toAST();
166
- },
167
- Ternary_ternary(cond, _q, cons, _c, alt) {
168
- return {
169
- type: "TernaryOp",
170
- condition: cond.toAST(),
171
- consequent: cons.toAST(),
172
- alternate: alt.toAST()
173
- };
174
- },
175
- Ternary(e) {
176
- return e.toAST();
177
- },
178
- LogicalOr_or(left, _op, right) {
179
- return {
180
- type: "BinaryOp",
181
- op: "||",
182
- left: left.toAST(),
183
- right: right.toAST()
184
- };
185
- },
186
- LogicalOr(e) {
187
- return e.toAST();
188
- },
189
- LogicalAnd_and(left, _op, right) {
190
- return {
191
- type: "BinaryOp",
192
- op: "&&",
193
- left: left.toAST(),
194
- right: right.toAST()
195
- };
196
- },
197
- LogicalAnd(e) {
198
- return e.toAST();
199
- },
200
- Equality_eq(left, _op, right) {
201
- return {
202
- type: "BinaryOp",
203
- op: "==",
204
- left: left.toAST(),
205
- right: right.toAST()
206
- };
207
- },
208
- Equality_neq(left, _op, right) {
209
- return {
210
- type: "BinaryOp",
211
- op: "!=",
212
- left: left.toAST(),
213
- right: right.toAST()
214
- };
215
- },
216
- Equality(e) {
217
- return e.toAST();
218
- },
219
- Comparison_gte(left, _op, right) {
220
- return {
221
- type: "BinaryOp",
222
- op: ">=",
223
- left: left.toAST(),
224
- right: right.toAST()
225
- };
226
- },
227
- Comparison_lte(left, _op, right) {
228
- return {
229
- type: "BinaryOp",
230
- op: "<=",
231
- left: left.toAST(),
232
- right: right.toAST()
233
- };
234
- },
235
- Comparison_gt(left, _op, right) {
236
- return {
237
- type: "BinaryOp",
238
- op: ">",
239
- left: left.toAST(),
240
- right: right.toAST()
241
- };
242
- },
243
- Comparison_lt(left, _op, right) {
244
- return {
245
- type: "BinaryOp",
246
- op: "<",
247
- left: left.toAST(),
248
- right: right.toAST()
249
- };
250
- },
251
- Comparison(e) {
252
- return e.toAST();
253
- },
254
- Additive_plus(left, _op, right) {
255
- return {
256
- type: "BinaryOp",
257
- op: "+",
258
- left: left.toAST(),
259
- right: right.toAST()
260
- };
261
- },
262
- Additive_minus(left, _op, right) {
263
- return {
264
- type: "BinaryOp",
265
- op: "-",
266
- left: left.toAST(),
267
- right: right.toAST()
268
- };
269
- },
270
- Additive(e) {
271
- return e.toAST();
272
- },
273
- Multiplicative_times(left, _op, right) {
274
- return {
275
- type: "BinaryOp",
276
- op: "*",
277
- left: left.toAST(),
278
- right: right.toAST()
279
- };
280
- },
281
- Multiplicative_div(left, _op, right) {
282
- return {
283
- type: "BinaryOp",
284
- op: "/",
285
- left: left.toAST(),
286
- right: right.toAST()
287
- };
288
- },
289
- Multiplicative_mod(left, _op, right) {
290
- return {
291
- type: "BinaryOp",
292
- op: "%",
293
- left: left.toAST(),
294
- right: right.toAST()
295
- };
296
- },
297
- Multiplicative(e) {
298
- return e.toAST();
299
- },
300
- Unary_neg(_op, expr) {
301
- return { type: "UnaryOp", op: "-", argument: expr.toAST() };
302
- },
303
- Unary_not(_op, expr) {
304
- return { type: "UnaryOp", op: "!", argument: expr.toAST() };
305
- },
306
- Unary(e) {
307
- return e.toAST();
308
- },
309
- Postfix_call(callee, _lp, args, _rp) {
310
- const firstArg = args.children[0];
311
- const argList = firstArg ? firstArg.toAST() : [];
312
- return {
313
- type: "CallExpression",
314
- callee: callee.toAST(),
315
- arguments: Array.isArray(argList) ? argList : [argList]
316
- };
317
- },
318
- Postfix_property(obj, _dot, prop) {
319
- return {
320
- type: "MemberExpression",
321
- object: obj.toAST(),
322
- property: prop.sourceString
323
- };
324
- },
325
- Postfix_index(obj, _lb, index, _rb) {
326
- const indexAST = index.toAST();
327
- if (indexAST.type === "StringLiteral") {
328
- return {
329
- type: "BracketedMemberExpression",
330
- object: obj.toAST(),
331
- property: indexAST.value
332
- };
333
- }
334
- return {
335
- type: "IndexExpression",
336
- object: obj.toAST(),
337
- index: indexAST
338
- };
339
- },
340
- Postfix_wildcard(obj, _lb, _star, _rb) {
341
- return {
342
- type: "WildcardExpression",
343
- object: obj.toAST()
344
- };
345
- },
346
- Postfix(e) {
347
- return e.toAST();
348
- },
349
- // Returns an array of arguments, not a single ASTNode
350
- // @ts-expect-error - intentionally returns array for function arguments
351
- Arguments(first, _comma, rest) {
352
- return [first.toAST(), ...rest.children.map((c) => c.toAST())];
353
- },
354
- Primary_paren(_lp, expr, _rp) {
355
- return expr.toAST();
356
- },
357
- Primary_bracketedField(_lb, str, _rb) {
358
- const strAST = str.toAST();
359
- return { type: "BracketedIdentifier", name: strAST.value };
360
- },
361
- Primary(e) {
362
- return e.toAST();
363
- },
364
- number_float(_neg, _int, _dot, _frac) {
365
- return {
366
- type: "NumberLiteral",
367
- value: Number.parseFloat(this.sourceString)
368
- };
369
- },
370
- number_int(_neg, _digits) {
371
- return {
372
- type: "NumberLiteral",
373
- value: Number.parseInt(this.sourceString, 10)
374
- };
375
- },
376
- string(_open, chars, _close) {
377
- const raw = chars.sourceString;
378
- return { type: "StringLiteral", value: raw.replaceAll(/\\(.)/g, "$1") };
379
- },
380
- boolean_true(_) {
381
- return { type: "BooleanLiteral", value: true };
382
- },
383
- boolean_false(_) {
384
- return { type: "BooleanLiteral", value: false };
385
- },
386
- null(_) {
387
- return { type: "NullLiteral" };
388
- },
389
- identifier(_start, _rest) {
390
- return { type: "Identifier", name: this.sourceString };
391
- },
392
- rootPath(_slash, _path) {
393
- return { type: "RootPath", path: this.sourceString };
394
- },
395
- relativePath(_dotSlashes, _parts) {
396
- return { type: "RelativePath", path: this.sourceString };
397
- },
398
- contextToken_at(_at, _name) {
399
- return { type: "ContextToken", name: this.sourceString };
400
- },
401
- contextToken_hash(_hash, _name) {
402
- return { type: "ContextToken", name: this.sourceString };
403
- },
404
- // @ts-expect-error - _iter returns array for iteration nodes
405
- _iter(...children) {
406
- return childrenToAST(children);
407
- },
408
- _terminal() {
409
- return { type: "Identifier", name: this.sourceString };
410
- }
411
- });
412
- semantics.addOperation("dependencies", {
413
- identifier(_start, _rest) {
414
- return [this.sourceString];
415
- },
416
- Primary_bracketedField(_lb, _str, _rb) {
417
- return [this.sourceString];
418
- },
419
- rootPath(_slash, _path) {
420
- return [this.sourceString];
421
- },
422
- relativePath(_dotSlashes, _parts) {
423
- return [this.sourceString];
424
- },
425
- contextToken_at(_at, _name) {
426
- return [];
427
- },
428
- contextToken_hash(_hash, _name) {
429
- return [];
430
- },
431
- Postfix_property(obj, _dot, prop) {
432
- const objDeps = obj.dependencies();
433
- if (objDeps.length === 1) {
434
- return [`${objDeps[0]}.${prop.sourceString}`];
435
- }
436
- return objDeps;
437
- },
438
- Postfix_index(obj, _lb, index, _rb) {
439
- const objDeps = obj.dependencies();
440
- const indexNode = index.toAST();
441
- if (indexNode.type === "StringLiteral") {
442
- const strValue = indexNode.value;
443
- const quote = this.sourceString.includes('"') ? '"' : "'";
444
- if (objDeps.length === 1) {
445
- return [`${objDeps[0]}[${quote}${strValue}${quote}]`];
446
- }
447
- return objDeps;
448
- }
449
- const getNumericIndex2 = (node) => {
450
- if (node.type === "NumberLiteral") {
451
- return node.value;
452
- }
453
- if (node.type === "UnaryOp" && node.op === "-" && node.argument.type === "NumberLiteral") {
454
- return -node.argument.value;
455
- }
456
- return null;
457
- };
458
- const numericIndex = getNumericIndex2(indexNode);
459
- if (objDeps.length === 1 && numericIndex !== null) {
460
- return [`${objDeps[0]}[${numericIndex}]`];
461
- }
462
- return [...objDeps, ...index.dependencies()];
463
- },
464
- Postfix_wildcard(obj, _lb, _star, _rb) {
465
- const objDeps = obj.dependencies();
466
- if (objDeps.length === 1) {
467
- return [`${objDeps[0]}[*]`];
468
- }
469
- return objDeps;
470
- },
471
- Postfix_call(callee, _lp, args, _rp) {
472
- const calleeDeps = callee.dependencies();
473
- const calleeAST = callee.toAST();
474
- const argDeps = childrenDependencies(args.children);
475
- if (calleeAST.type === "Identifier") {
476
- return argDeps;
477
- }
478
- return [...calleeDeps, ...argDeps];
479
- },
480
- number_float(_neg, _int, _dot, _frac) {
481
- return [];
482
- },
483
- number_int(_neg, _digits) {
484
- return [];
485
- },
486
- string(_open, _chars, _close) {
487
- return [];
488
- },
489
- boolean_true(_) {
490
- return [];
491
- },
492
- boolean_false(_) {
493
- return [];
494
- },
495
- null(_) {
496
- return [];
497
- },
498
- _nonterminal(...children) {
499
- return childrenDependencies(children);
500
- },
501
- _iter(...children) {
502
- return childrenDependencies(children);
503
- },
504
- _terminal() {
505
- return [];
506
- }
507
- });
508
- var ARRAY_FUNCTIONS = /* @__PURE__ */ new Set([
509
- "sum",
510
- "avg",
511
- "count",
512
- "first",
513
- "last",
514
- "join",
515
- "includes"
516
- ]);
517
- semantics.addOperation("features", {
518
- Primary_bracketedField(_lb, _str, _rb) {
519
- return ["bracket_notation"];
520
- },
521
- rootPath(_slash, _path) {
522
- const path = this.sourceString;
523
- const features = ["root_path"];
524
- if (path.includes(".")) {
525
- features.push("nested_path");
526
- }
527
- return features;
528
- },
529
- relativePath(_dotSlashes, _parts) {
530
- const path = this.sourceString;
531
- const features = ["relative_path"];
532
- const withoutPrefix = path.replace(/^(\.\.\/)+/, "");
533
- if (withoutPrefix.includes(".")) {
534
- features.push("nested_path");
535
- }
536
- return features;
537
- },
538
- contextToken_at(_at, _name) {
539
- return ["context_token"];
540
- },
541
- contextToken_hash(_hash, _name) {
542
- return ["context_token"];
543
- },
544
- Postfix_property(obj, _dot, _prop) {
545
- const objFeatures = obj.features();
546
- return [...objFeatures, "nested_path"];
547
- },
548
- Postfix_index(obj, _lb, index, _rb) {
549
- const objFeatures = obj.features();
550
- const indexFeatures = index.features();
551
- const indexNode = index.toAST();
552
- if (indexNode.type === "StringLiteral") {
553
- return [...objFeatures, ...indexFeatures, "bracket_notation"];
554
- }
555
- return [...objFeatures, ...indexFeatures, "array_index"];
556
- },
557
- Postfix_wildcard(obj, _lb, _star, _rb) {
558
- const objFeatures = obj.features();
559
- return [...objFeatures, "array_wildcard"];
560
- },
561
- Postfix_call(callee, _lp, args, _rp) {
562
- const calleeAST = callee.toAST();
563
- const argFeatures = childrenFeatures(args.children);
564
- if (calleeAST.type === "Identifier" && ARRAY_FUNCTIONS.has(calleeAST.name.toLowerCase())) {
565
- return [...argFeatures, "array_function"];
566
- }
567
- return argFeatures;
568
- },
569
- _nonterminal(...children) {
570
- return childrenFeatures(children);
571
- },
572
- _iter(...children) {
573
- return childrenFeatures(children);
574
- },
575
- _terminal() {
576
- return [];
577
- }
578
- });
579
- var BUILTINS = {
580
- // Logical
581
- and: (a, b) => Boolean(a) && Boolean(b),
582
- or: (a, b) => Boolean(a) || Boolean(b),
583
- not: (a) => !a,
584
- // String
585
- concat: (...args) => args.map(String).join(""),
586
- upper: (s) => String(s).toUpperCase(),
587
- lower: (s) => String(s).toLowerCase(),
588
- trim: (s) => String(s).trim(),
589
- left: (s, n) => String(s).slice(0, Math.max(0, Math.floor(Number(n)))),
590
- right: (s, n) => {
591
- const str = String(s);
592
- const count = Math.max(0, Math.floor(Number(n)));
593
- return count === 0 ? "" : str.slice(-count);
594
- },
595
- replace: (s, search, repl) => String(s).replace(String(search), String(repl)),
596
- tostring: String,
597
- length: (s) => {
598
- if (Array.isArray(s)) return s.length;
599
- if (typeof s === "string") return s.length;
600
- if (s !== null && typeof s === "object") return Object.keys(s).length;
601
- return String(s).length;
602
- },
603
- contains: (s, search) => String(s).includes(String(search)),
604
- startswith: (s, search) => String(s).startsWith(String(search)),
605
- endswith: (s, search) => String(s).endsWith(String(search)),
606
- join: (arr, sep) => {
607
- if (!Array.isArray(arr)) return "";
608
- if (sep === void 0 || sep === null) return arr.join(",");
609
- if (typeof sep !== "string" && typeof sep !== "number") {
610
- return arr.join(",");
611
- }
612
- return arr.join(String(sep));
613
- },
614
- // Numeric
615
- tonumber: Number,
616
- toboolean: Boolean,
617
- isnull: (v) => v === null || v === void 0,
618
- coalesce: (...args) => args.find((v) => v !== null && v !== void 0) ?? null,
619
- round: (n, dec) => {
620
- const factor = 10 ** (dec === void 0 ? 0 : Number(dec));
621
- return Math.round(Number(n) * factor) / factor;
622
- },
623
- floor: (n) => Math.floor(Number(n)),
624
- ceil: (n) => Math.ceil(Number(n)),
625
- abs: (n) => Math.abs(Number(n)),
626
- sqrt: (n) => Math.sqrt(Number(n)),
627
- pow: (base, exp) => Math.pow(Number(base), Number(exp)),
628
- min: (...args) => args.length === 0 ? Number.NaN : Math.min(...args.map(Number)),
629
- max: (...args) => args.length === 0 ? Number.NaN : Math.max(...args.map(Number)),
630
- log: (n) => Math.log(Number(n)),
631
- log10: (n) => Math.log10(Number(n)),
632
- exp: (n) => Math.exp(Number(n)),
633
- sign: (n) => Math.sign(Number(n)),
634
- // Array
635
- sum: (arr) => Array.isArray(arr) ? arr.reduce((a, b) => a + Number(b), 0) : 0,
636
- avg: (arr) => Array.isArray(arr) && arr.length > 0 ? arr.reduce((a, b) => a + Number(b), 0) / arr.length : 0,
637
- count: (arr) => Array.isArray(arr) ? arr.length : 0,
638
- first: (arr) => Array.isArray(arr) ? arr[0] : void 0,
639
- last: (arr) => Array.isArray(arr) ? arr.at(-1) : void 0,
640
- includes: (arr, val) => Array.isArray(arr) ? arr.includes(val) : false,
641
- // Conditional
642
- if: (cond, ifTrue, ifFalse) => cond ? ifTrue : ifFalse
643
- };
644
- function getByPath(obj, path) {
645
- const parts = path.split(".");
646
- let current = obj;
647
- for (const part of parts) {
648
- if (current === null || current === void 0) return void 0;
649
- current = current[part];
650
- }
651
- return current;
652
- }
653
- semantics.addOperation("eval(ctx)", {
654
- Expression(e) {
655
- return e.eval(this.args.ctx);
656
- },
657
- Ternary_ternary(cond, _q, cons, _c, alt) {
658
- return cond.eval(this.args.ctx) ? cons.eval(this.args.ctx) : alt.eval(this.args.ctx);
659
- },
660
- Ternary(e) {
661
- return e.eval(this.args.ctx);
662
- },
663
- LogicalOr_or(left, _op, right) {
664
- return left.eval(this.args.ctx) || right.eval(this.args.ctx);
665
- },
666
- LogicalOr(e) {
667
- return e.eval(this.args.ctx);
668
- },
669
- LogicalAnd_and(left, _op, right) {
670
- return left.eval(this.args.ctx) && right.eval(this.args.ctx);
671
- },
672
- LogicalAnd(e) {
673
- return e.eval(this.args.ctx);
674
- },
675
- Equality_eq(left, _op, right) {
676
- return left.eval(this.args.ctx) == right.eval(this.args.ctx);
677
- },
678
- Equality_neq(left, _op, right) {
679
- return left.eval(this.args.ctx) != right.eval(this.args.ctx);
680
- },
681
- Equality(e) {
682
- return e.eval(this.args.ctx);
683
- },
684
- Comparison_gte(left, _op, right) {
685
- return left.eval(this.args.ctx) >= right.eval(this.args.ctx);
686
- },
687
- Comparison_lte(left, _op, right) {
688
- return left.eval(this.args.ctx) <= right.eval(this.args.ctx);
689
- },
690
- Comparison_gt(left, _op, right) {
691
- return left.eval(this.args.ctx) > right.eval(this.args.ctx);
692
- },
693
- Comparison_lt(left, _op, right) {
694
- return left.eval(this.args.ctx) < right.eval(this.args.ctx);
695
- },
696
- Comparison(e) {
697
- return e.eval(this.args.ctx);
698
- },
699
- Additive_plus(left, _op, right) {
700
- const l = left.eval(this.args.ctx);
701
- const r = right.eval(this.args.ctx);
702
- if (typeof l === "string" || typeof r === "string") {
703
- return String(l) + String(r);
704
- }
705
- return l + r;
706
- },
707
- Additive_minus(left, _op, right) {
708
- return left.eval(this.args.ctx) - right.eval(this.args.ctx);
709
- },
710
- Additive(e) {
711
- return e.eval(this.args.ctx);
712
- },
713
- Multiplicative_times(left, _op, right) {
714
- return left.eval(this.args.ctx) * right.eval(this.args.ctx);
715
- },
716
- Multiplicative_div(left, _op, right) {
717
- return left.eval(this.args.ctx) / right.eval(this.args.ctx);
718
- },
719
- Multiplicative_mod(left, _op, right) {
720
- return left.eval(this.args.ctx) % right.eval(this.args.ctx);
721
- },
722
- Multiplicative(e) {
723
- return e.eval(this.args.ctx);
724
- },
725
- Unary_neg(_op, expr) {
726
- return -expr.eval(this.args.ctx);
727
- },
728
- Unary_not(_op, expr) {
729
- return !expr.eval(this.args.ctx);
730
- },
731
- Unary(e) {
732
- return e.eval(this.args.ctx);
733
- },
734
- Postfix_call(callee, _lp, args, _rp) {
735
- const calleeAST = callee.toAST();
736
- const getArgValues = () => {
737
- const argsNode = args.children[0];
738
- if (!argsNode) {
739
- return [];
740
- }
741
- return argsNode.eval(this.args.ctx);
742
- };
743
- if (calleeAST.type === "Identifier") {
744
- const fnName = calleeAST.name.toLowerCase();
745
- const builtinFn = BUILTINS[fnName];
746
- if (builtinFn) {
747
- return builtinFn(...getArgValues());
748
- }
749
- }
750
- const fn = callee.eval(this.args.ctx);
751
- if (typeof fn === "function") {
752
- return fn(...getArgValues());
753
- }
754
- const calleeName = calleeAST.type === "Identifier" ? calleeAST.name : "expression";
755
- throw new Error(`'${calleeName}' is not a function`);
756
- },
757
- Postfix_property(obj, _dot, prop) {
758
- const objVal = obj.eval(this.args.ctx);
759
- return objVal?.[prop.sourceString];
760
- },
761
- Postfix_index(obj, _lb, index, _rb) {
762
- const objVal = obj.eval(this.args.ctx);
763
- const idx = index.eval(this.args.ctx);
764
- if (typeof idx === "string") {
765
- if (!isSafePropertyName(idx)) {
766
- return void 0;
767
- }
768
- return objVal?.[idx];
769
- }
770
- const numIdx = idx;
771
- if (numIdx < 0) {
772
- return objVal?.[objVal.length + numIdx];
773
- }
774
- return objVal?.[numIdx];
775
- },
776
- Postfix_wildcard(obj, _lb, _star, _rb) {
777
- return obj.eval(this.args.ctx);
778
- },
779
- Postfix(e) {
780
- return e.eval(this.args.ctx);
781
- },
782
- Arguments(first, _comma, rest) {
783
- return [
784
- first.eval(this.args.ctx),
785
- ...rest.children.map((c) => c.eval(this.args.ctx))
786
- ];
787
- },
788
- Primary_paren(_lp, expr, _rp) {
789
- return expr.eval(this.args.ctx);
790
- },
791
- Primary_bracketedField(_lb, str, _rb) {
792
- const fieldName = str.eval(this.args.ctx);
793
- if (!isSafePropertyName(fieldName)) {
794
- return void 0;
795
- }
796
- return this.args.ctx[fieldName];
797
- },
798
- Primary(e) {
799
- return e.eval(this.args.ctx);
800
- },
801
- number_float(_neg, _int, _dot, _frac) {
802
- return Number.parseFloat(this.sourceString);
803
- },
804
- number_int(_neg, _digits) {
805
- return Number.parseInt(this.sourceString, 10);
806
- },
807
- string(_open, chars, _close) {
808
- return chars.sourceString.replaceAll(/\\(.)/g, "$1");
809
- },
810
- boolean_true(_) {
811
- return true;
812
- },
813
- boolean_false(_) {
814
- return false;
815
- },
816
- null(_) {
817
- return null;
818
- },
819
- identifier(_start, _rest) {
820
- const name = this.sourceString;
821
- return this.args.ctx[name];
822
- },
823
- rootPath(_slash, _path) {
824
- const fullPath = this.sourceString;
825
- if (fullPath in this.args.ctx) {
826
- return this.args.ctx[fullPath];
827
- }
828
- const parts = fullPath.slice(1).split(".");
829
- const firstPart = parts[0];
830
- if (!firstPart) return void 0;
831
- const rootKey = "/" + firstPart;
832
- let value = this.args.ctx[rootKey];
833
- for (let i = 1; i < parts.length; i++) {
834
- if (value === null || value === void 0) return void 0;
835
- const part = parts[i];
836
- if (!part) continue;
837
- value = value[part];
838
- }
839
- return value;
840
- },
841
- relativePath(_dotSlashes, _parts) {
842
- const fullPath = this.sourceString;
843
- if (fullPath in this.args.ctx) {
844
- return this.args.ctx[fullPath];
845
- }
846
- const path = fullPath.replace(/^(\.\.\/)+/, "");
847
- return getByPath(this.args.ctx, path);
848
- },
849
- contextToken_at(_at, _name) {
850
- return this.args.ctx[this.sourceString];
851
- },
852
- contextToken_hash(_hash, _name) {
853
- return this.args.ctx[this.sourceString];
854
- },
855
- _nonterminal(...children) {
856
- const ctx = this.args.ctx;
857
- for (const child of children) {
858
- if ("eval" in child) {
859
- return child.eval(ctx);
860
- }
861
- }
862
- return void 0;
863
- },
864
- _iter(...children) {
865
- return children.map((c) => c.eval(this.args.ctx));
866
- },
867
- _terminal() {
868
- return void 0;
869
- }
870
- });
871
-
872
- // src/ohm/core/parser.ts
873
- function parseFormula(expression) {
874
- const trimmed = expression.trim();
875
- if (!trimmed) {
876
- throw new Error("Empty expression");
877
- }
878
- const matchResult = grammar2.match(trimmed);
879
- if (matchResult.failed()) {
880
- throw new Error(matchResult.message ?? "Parse error");
881
- }
882
- const adapter = semantics(matchResult);
883
- const ast = adapter.toAST();
884
- const dependencies = [...new Set(adapter.dependencies())];
885
- const allFeatures = adapter.features();
886
- const features = [...new Set(allFeatures)];
887
- const minVersion = features.length > 0 ? "1.1" : "1.0";
888
- return { ast, dependencies, features, minVersion };
889
- }
890
- function validateSyntax(expression) {
891
- const trimmed = expression.trim();
892
- if (!trimmed) {
893
- return { isValid: false, error: "Empty expression" };
894
- }
895
- const matchResult = grammar2.match(trimmed);
896
- if (matchResult.failed()) {
897
- const pos = matchResult.getRightmostFailurePosition?.();
898
- return {
899
- isValid: false,
900
- error: matchResult.message ?? "Parse error",
901
- position: pos
902
- };
903
- }
904
- return { isValid: true };
905
- }
906
- function evaluate(expression, context) {
907
- const trimmed = expression.trim();
908
- if (!trimmed) {
909
- throw new Error("Empty expression");
910
- }
911
- const matchResult = grammar2.match(trimmed);
912
- if (matchResult.failed()) {
913
- throw new Error(matchResult.message ?? "Parse error");
914
- }
915
- const safeContext = {};
916
- for (const [key, value] of Object.entries(context)) {
917
- if (typeof value !== "function") {
918
- safeContext[key] = value;
919
- }
920
- }
921
- return semantics(matchResult).eval(safeContext);
922
- }
923
- function parseCurrentPath(currentPath) {
924
- const segments = [];
925
- let current = "";
926
- let inBracket = false;
927
- for (const char of currentPath) {
928
- if (char === "[") {
929
- inBracket = true;
930
- current += char;
931
- } else if (char === "]") {
932
- inBracket = false;
933
- current += char;
934
- } else if (char === "." && !inBracket) {
935
- if (current) {
936
- segments.push(current);
937
- current = "";
938
- }
939
- } else {
940
- current += char;
941
- }
942
- }
943
- if (current) {
944
- segments.push(current);
945
- }
946
- return segments;
947
- }
948
- function getValueByPath(data, path) {
949
- const segments = parseCurrentPath(path);
950
- let current = data;
951
- for (const segment of segments) {
952
- if (current === null || current === void 0) {
953
- return void 0;
954
- }
955
- if (typeof current !== "object") {
956
- return void 0;
957
- }
958
- const bracketMatch = /^([^[]+)\[(\d+)\]$/.exec(segment);
959
- if (bracketMatch?.[1] && bracketMatch[2]) {
960
- const fieldName = bracketMatch[1];
961
- const index = Number.parseInt(bracketMatch[2], 10);
962
- const arr = current[fieldName];
963
- if (!Array.isArray(arr)) {
964
- return void 0;
965
- }
966
- current = arr[index];
967
- } else {
968
- current = current[segment];
969
- }
970
- }
971
- return current;
972
- }
973
- function extractRootField(fieldPath) {
974
- const dotIndex = fieldPath.indexOf(".");
975
- const bracketIndex = fieldPath.indexOf("[");
976
- if (dotIndex === -1 && bracketIndex === -1) {
977
- return fieldPath;
978
- }
979
- if (dotIndex === -1) {
980
- return fieldPath.slice(0, bracketIndex);
981
- }
982
- if (bracketIndex === -1) {
983
- return fieldPath.slice(0, dotIndex);
984
- }
985
- return fieldPath.slice(0, Math.min(dotIndex, bracketIndex));
986
- }
987
- function countParentLevels(path) {
988
- let count = 0;
989
- let remaining = path;
990
- while (remaining.startsWith("../")) {
991
- count++;
992
- remaining = remaining.slice(3);
993
- }
994
- return count;
995
- }
996
- function getPathAfterParents(path) {
997
- return path.replace(/^(\.\.\/)+/, "");
998
- }
999
- function resolveRelativePath(rootData, currentPath, relativePath) {
1000
- const parentLevels = countParentLevels(relativePath);
1001
- const fieldPath = getPathAfterParents(relativePath);
1002
- if (!currentPath) {
1003
- return getValueByPath(rootData, fieldPath);
1004
- }
1005
- const pathSegments = parseCurrentPath(currentPath);
1006
- const targetLevel = pathSegments.length - parentLevels;
1007
- if (targetLevel <= 0) {
1008
- return getValueByPath(rootData, fieldPath);
1009
- }
1010
- const basePath = pathSegments.slice(0, targetLevel).join(".");
1011
- const fullPath = basePath ? `${basePath}.${fieldPath}` : fieldPath;
1012
- return getValueByPath(rootData, fullPath);
1013
- }
1014
- function extractRelativeBase(relativePath) {
1015
- const pathAfterParents = getPathAfterParents(relativePath);
1016
- const baseField = extractRootField(pathAfterParents);
1017
- const prefix = relativePath.slice(
1018
- 0,
1019
- relativePath.length - pathAfterParents.length
1020
- );
1021
- return prefix + baseField;
1022
- }
1023
- function buildPathReferences(rootData, dependencies, currentPath) {
1024
- const refs = {};
1025
- for (const dep of dependencies) {
1026
- if (dep.startsWith("/")) {
1027
- const fieldPath = dep.slice(1);
1028
- const rootField = extractRootField(fieldPath);
1029
- const contextKey = "/" + rootField;
1030
- if (!(contextKey in refs)) {
1031
- refs[contextKey] = getValueByPath(rootData, rootField);
1032
- }
1033
- } else if (dep.startsWith("../")) {
1034
- const contextKey = extractRelativeBase(dep);
1035
- if (!(contextKey in refs)) {
1036
- refs[contextKey] = resolveRelativePath(
1037
- rootData,
1038
- currentPath,
1039
- contextKey
1040
- );
1041
- }
1042
- }
1043
- }
1044
- return refs;
1045
- }
1046
- function evaluateWithContext(expression, options) {
1047
- const { rootData, itemData, currentPath } = options;
1048
- const trimmed = expression.trim();
1049
- if (!trimmed) {
1050
- throw new Error("Empty expression");
1051
- }
1052
- const parsed = parseFormula(trimmed);
1053
- const pathRefs = buildPathReferences(
1054
- rootData,
1055
- parsed.dependencies,
1056
- currentPath
1057
- );
1058
- const context = {
1059
- ...rootData,
1060
- ...itemData,
1061
- ...pathRefs
1062
- };
1063
- return evaluate(trimmed, context);
1064
- }
1065
- var ARITHMETIC_OPS = /* @__PURE__ */ new Set(["+", "-", "*", "/", "%"]);
1066
- var COMPARISON_OPS = /* @__PURE__ */ new Set(["<", ">", "<=", ">=", "==", "!="]);
1067
- var LOGICAL_OPS = /* @__PURE__ */ new Set(["&&", "||", "!"]);
1068
- var NUMERIC_FUNCTIONS = /* @__PURE__ */ new Set([
1069
- "round",
1070
- "floor",
1071
- "ceil",
1072
- "abs",
1073
- "sqrt",
1074
- "pow",
1075
- "min",
1076
- "max",
1077
- "log",
1078
- "log10",
1079
- "exp",
1080
- "sign",
1081
- "sum",
1082
- "avg",
1083
- "count",
1084
- "tonumber",
1085
- "length"
1086
- ]);
1087
- var STRING_FUNCTIONS = /* @__PURE__ */ new Set([
1088
- "concat",
1089
- "upper",
1090
- "lower",
1091
- "trim",
1092
- "left",
1093
- "right",
1094
- "replace",
1095
- "tostring",
1096
- "join"
1097
- ]);
1098
- var BOOLEAN_FUNCTIONS = /* @__PURE__ */ new Set([
1099
- "and",
1100
- "or",
1101
- "not",
1102
- "contains",
1103
- "startswith",
1104
- "endswith",
1105
- "isnull",
1106
- "toboolean",
1107
- "includes"
1108
- ]);
1109
- function getFieldType(path, fieldTypes) {
1110
- const rootField = path.split(".")[0]?.split("[")[0] || path;
1111
- const schemaType = fieldTypes[rootField];
1112
- if (schemaType === "number") return "number";
1113
- if (schemaType === "string") return "string";
1114
- if (schemaType === "boolean") return "boolean";
1115
- return "unknown";
1116
- }
1117
- function inferLiteralType(node) {
1118
- switch (node.type) {
1119
- case "NumberLiteral":
1120
- return "number";
1121
- case "BooleanLiteral":
1122
- return "boolean";
1123
- case "StringLiteral":
1124
- return "string";
1125
- case "NullLiteral":
1126
- return "unknown";
1127
- default:
1128
- return null;
1129
- }
1130
- }
1131
- function inferBinaryOpType(node, fieldTypes) {
1132
- const { op } = node;
1133
- if (op === "+") {
1134
- const leftType = inferTypeFromAST(node.left, fieldTypes);
1135
- const rightType = inferTypeFromAST(node.right, fieldTypes);
1136
- if (leftType === "string" || rightType === "string") return "string";
1137
- if (leftType === "unknown" || rightType === "unknown") return "unknown";
1138
- return "number";
1139
- }
1140
- if (ARITHMETIC_OPS.has(op)) return "number";
1141
- if (COMPARISON_OPS.has(op)) return "boolean";
1142
- if (LOGICAL_OPS.has(op)) return "boolean";
1143
- return "unknown";
1144
- }
1145
- function inferCallExpressionType(node, fieldTypes) {
1146
- const funcName = node.callee.type === "Identifier" ? node.callee.name.toLowerCase() : "";
1147
- if (NUMERIC_FUNCTIONS.has(funcName)) return "number";
1148
- if (STRING_FUNCTIONS.has(funcName)) return "string";
1149
- if (BOOLEAN_FUNCTIONS.has(funcName)) return "boolean";
1150
- if (funcName === "if" && node.arguments.length >= 3) {
1151
- const thenArg = node.arguments[1];
1152
- const elseArg = node.arguments[2];
1153
- if (thenArg && elseArg) {
1154
- const thenType = inferTypeFromAST(thenArg, fieldTypes);
1155
- const elseType = inferTypeFromAST(elseArg, fieldTypes);
1156
- if (thenType === elseType) return thenType;
1157
- }
1158
- }
1159
- return "unknown";
1160
- }
1161
- function inferTypeFromAST(node, fieldTypes) {
1162
- const literalType = inferLiteralType(node);
1163
- if (literalType !== null) return literalType;
1164
- switch (node.type) {
1165
- case "Identifier":
1166
- return getFieldType(node.name, fieldTypes);
1167
- case "RootPath":
1168
- case "RelativePath":
1169
- case "ContextToken":
1170
- case "IndexExpression":
1171
- case "WildcardExpression":
1172
- return "unknown";
1173
- case "MemberExpression": {
1174
- const objectType = inferTypeFromAST(node.object, fieldTypes);
1175
- if (objectType !== "unknown") return objectType;
1176
- if (node.object.type === "Identifier") {
1177
- return getFieldType(`${node.object.name}.${node.property}`, fieldTypes);
1178
- }
1179
- return "unknown";
1180
- }
1181
- case "BinaryOp":
1182
- return inferBinaryOpType(node, fieldTypes);
1183
- case "UnaryOp": {
1184
- if (node.op === "-") return "number";
1185
- if (node.op === "!") return "boolean";
1186
- return "unknown";
1187
- }
1188
- case "TernaryOp": {
1189
- const thenType = inferTypeFromAST(node.consequent, fieldTypes);
1190
- const elseType = inferTypeFromAST(node.alternate, fieldTypes);
1191
- return thenType === elseType ? thenType : "unknown";
1192
- }
1193
- case "CallExpression":
1194
- return inferCallExpressionType(node, fieldTypes);
1195
- default:
1196
- return "unknown";
1197
- }
1198
- }
1199
- function inferFormulaType(expression, fieldTypes = {}) {
1200
- const trimmed = expression.trim();
1201
- if (!trimmed) {
1202
- return "unknown";
1203
- }
1204
- try {
1205
- const { ast } = parseFormula(trimmed);
1206
- return inferTypeFromAST(ast, fieldTypes);
1207
- } catch {
1208
- return "unknown";
1209
- }
1210
- }
1211
-
1212
- // src/ohm/core/serialize-ast.ts
1213
- function escapeDoubleQuoted(value) {
1214
- let result = "";
1215
- for (const char of value) {
1216
- switch (char) {
1217
- case "\\":
1218
- result += String.raw`\\`;
1219
- break;
1220
- case '"':
1221
- result += String.raw`\"`;
1222
- break;
1223
- case "\n":
1224
- result += String.raw`\n`;
1225
- break;
1226
- case "\r":
1227
- result += String.raw`\r`;
1228
- break;
1229
- case " ":
1230
- result += String.raw`\t`;
1231
- break;
1232
- default:
1233
- result += char;
1234
- }
1235
- }
1236
- return result;
1237
- }
1238
- var PRECEDENCE = {
1239
- "||": 1,
1240
- "&&": 2,
1241
- "==": 3,
1242
- "!=": 3,
1243
- ">": 4,
1244
- "<": 4,
1245
- ">=": 4,
1246
- "<=": 4,
1247
- "+": 5,
1248
- "-": 5,
1249
- "*": 6,
1250
- "/": 6,
1251
- "%": 6
1252
- };
1253
- function serializeBinaryOp(node) {
1254
- const prec = PRECEDENCE[node.op] ?? 0;
1255
- const wrapLeft = (child) => {
1256
- const s = serializeNode(child);
1257
- if (child.type === "BinaryOp") {
1258
- const childPrec = PRECEDENCE[child.op] ?? 0;
1259
- if (childPrec < prec) {
1260
- return `(${s})`;
1261
- }
1262
- }
1263
- if (child.type === "TernaryOp") {
1264
- return `(${s})`;
1265
- }
1266
- return s;
1267
- };
1268
- const wrapRight = (child) => {
1269
- const s = serializeNode(child);
1270
- if (child.type === "BinaryOp") {
1271
- const childPrec = PRECEDENCE[child.op] ?? 0;
1272
- if (childPrec <= prec) {
1273
- return `(${s})`;
1274
- }
1275
- }
1276
- if (child.type === "TernaryOp") {
1277
- return `(${s})`;
1278
- }
1279
- return s;
1280
- };
1281
- return `${wrapLeft(node.left)} ${node.op} ${wrapRight(node.right)}`;
1282
- }
1283
- function serializeNode(node) {
1284
- switch (node.type) {
1285
- case "NumberLiteral":
1286
- return String(node.value);
1287
- case "StringLiteral":
1288
- return `"${escapeDoubleQuoted(node.value)}"`;
1289
- case "BooleanLiteral":
1290
- return String(node.value);
1291
- case "NullLiteral":
1292
- return "null";
1293
- case "Identifier":
1294
- return node.name;
1295
- case "BracketedIdentifier":
1296
- return `["${escapeDoubleQuoted(node.name)}"]`;
1297
- case "RootPath":
1298
- return node.path;
1299
- case "RelativePath":
1300
- return node.path;
1301
- case "ContextToken":
1302
- return node.name;
1303
- case "BinaryOp":
1304
- return serializeBinaryOp(node);
1305
- case "UnaryOp":
1306
- return `${node.op}${serializeUnaryArgument(node)}`;
1307
- case "TernaryOp":
1308
- return `${serializeTernaryCondition(node.condition)} ? ${serializeNode(node.consequent)} : ${serializeNode(node.alternate)}`;
1309
- case "CallExpression":
1310
- return `${serializeNode(node.callee)}(${node.arguments.map(serializeNode).join(", ")})`;
1311
- case "MemberExpression":
1312
- return `${serializePostfixObject(node.object)}.${node.property}`;
1313
- case "BracketedMemberExpression":
1314
- return `${serializePostfixObject(node.object)}["${escapeDoubleQuoted(node.property)}"]`;
1315
- case "IndexExpression":
1316
- return `${serializePostfixObject(node.object)}[${serializeNode(node.index)}]`;
1317
- case "WildcardExpression":
1318
- return `${serializePostfixObject(node.object)}[*]`;
1319
- }
1320
- }
1321
- function serializeUnaryArgument(node) {
1322
- const s = serializeNode(node.argument);
1323
- if (node.argument.type === "BinaryOp" || node.argument.type === "TernaryOp") {
1324
- return `(${s})`;
1325
- }
1326
- return s;
1327
- }
1328
- function serializeTernaryCondition(node) {
1329
- const s = serializeNode(node);
1330
- if (node.type === "TernaryOp") {
1331
- return `(${s})`;
1332
- }
1333
- return s;
1334
- }
1335
- function serializePostfixObject(node) {
1336
- const s = serializeNode(node);
1337
- if (node.type === "BinaryOp" || node.type === "TernaryOp" || node.type === "UnaryOp") {
1338
- return `(${s})`;
1339
- }
1340
- return s;
1341
- }
1342
- function serializeAst(ast) {
1343
- return serializeNode(ast);
1344
- }
1345
-
1346
- // src/ohm/core/replace-dependencies.ts
1347
- function collectDependencyPath(node) {
1348
- switch (node.type) {
1349
- case "Identifier":
1350
- return node.name;
1351
- case "BracketedIdentifier":
1352
- return `["${node.name}"]`;
1353
- case "RootPath":
1354
- return node.path;
1355
- case "RelativePath":
1356
- return node.path;
1357
- case "MemberExpression": {
1358
- const objPath = collectDependencyPath(node.object);
1359
- if (objPath === null) {
1360
- return null;
1361
- }
1362
- return `${objPath}.${node.property}`;
1363
- }
1364
- case "BracketedMemberExpression": {
1365
- const objPath = collectDependencyPath(node.object);
1366
- if (objPath === null) {
1367
- return null;
1368
- }
1369
- const quote = '"';
1370
- return `${objPath}[${quote}${node.property}${quote}]`;
1371
- }
1372
- case "IndexExpression": {
1373
- const objPath = collectDependencyPath(node.object);
1374
- if (objPath === null) {
1375
- return null;
1376
- }
1377
- const numericIndex = getNumericIndex(node.index);
1378
- if (numericIndex !== null) {
1379
- return `${objPath}[${numericIndex}]`;
1380
- }
1381
- return null;
1382
- }
1383
- case "WildcardExpression": {
1384
- const objPath = collectDependencyPath(node.object);
1385
- if (objPath === null) {
1386
- return null;
1387
- }
1388
- return `${objPath}[*]`;
1389
- }
1390
- default:
1391
- return null;
1392
- }
1393
- }
1394
- function getNumericIndex(node) {
1395
- if (node.type === "NumberLiteral") {
1396
- return node.value;
1397
- }
1398
- if (node.type === "UnaryOp" && node.op === "-" && node.argument.type === "NumberLiteral") {
1399
- return -node.argument.value;
1400
- }
1401
- return null;
1402
- }
1403
- function findMatch(node, replacements) {
1404
- const fullPath = collectDependencyPath(node);
1405
- if (fullPath !== null) {
1406
- const value = replacements[fullPath];
1407
- if (value !== void 0) {
1408
- return value;
1409
- }
1410
- }
1411
- return null;
1412
- }
1413
- function pathToAst(path) {
1414
- const { ast } = parseFormula(path);
1415
- return ast;
1416
- }
1417
- function replaceNode(node, replacements) {
1418
- const replacement = findMatch(node, replacements);
1419
- if (replacement !== null) {
1420
- return pathToAst(replacement);
1421
- }
1422
- switch (node.type) {
1423
- case "NumberLiteral":
1424
- case "StringLiteral":
1425
- case "BooleanLiteral":
1426
- case "NullLiteral":
1427
- case "Identifier":
1428
- case "BracketedIdentifier":
1429
- case "RootPath":
1430
- case "RelativePath":
1431
- case "ContextToken":
1432
- return node;
1433
- case "BinaryOp":
1434
- return {
1435
- ...node,
1436
- left: replaceNode(node.left, replacements),
1437
- right: replaceNode(node.right, replacements)
1438
- };
1439
- case "UnaryOp":
1440
- return {
1441
- ...node,
1442
- argument: replaceNode(node.argument, replacements)
1443
- };
1444
- case "TernaryOp":
1445
- return {
1446
- ...node,
1447
- condition: replaceNode(node.condition, replacements),
1448
- consequent: replaceNode(node.consequent, replacements),
1449
- alternate: replaceNode(node.alternate, replacements)
1450
- };
1451
- case "CallExpression": {
1452
- const isSimpleFunctionCall = node.callee.type === "Identifier";
1453
- return {
1454
- ...node,
1455
- callee: isSimpleFunctionCall ? node.callee : replaceNode(node.callee, replacements),
1456
- arguments: node.arguments.map((arg) => replaceNode(arg, replacements))
1457
- };
1458
- }
1459
- case "MemberExpression":
1460
- case "BracketedMemberExpression":
1461
- case "WildcardExpression":
1462
- return {
1463
- ...node,
1464
- object: replaceNode(node.object, replacements)
1465
- };
1466
- case "IndexExpression":
1467
- return {
1468
- ...node,
1469
- object: replaceNode(node.object, replacements),
1470
- index: replaceNode(node.index, replacements)
1471
- };
1472
- }
1473
- }
1474
- function replaceDependencies(ast, replacements) {
1475
- return replaceNode(ast, replacements);
1476
- }
1477
-
1478
- // src/parse-formula.ts
1479
- function parseExpression(expression) {
1480
- const result = parseFormula(expression);
1481
- return {
1482
- expression,
1483
- dependencies: result.dependencies,
1484
- minVersion: result.minVersion,
1485
- features: result.features
1486
- };
1487
- }
1488
-
1489
- // src/validate-syntax.ts
1490
- function validateFormulaSyntax(expression) {
1491
- const result = validateSyntax(expression);
1492
- if (result.isValid) {
1493
- return { isValid: true };
1494
- }
1495
- return {
1496
- isValid: false,
1497
- error: result.error,
1498
- position: result.position
1499
- };
1500
- }
1501
-
1502
- exports.evaluate = evaluate;
1503
- exports.evaluateWithContext = evaluateWithContext;
1504
- exports.inferFormulaType = inferFormulaType;
1505
- exports.parseExpression = parseExpression;
1506
- exports.parseFormula = parseFormula;
1507
- exports.replaceDependencies = replaceDependencies;
1508
- exports.serializeAst = serializeAst;
1509
- exports.validateFormulaSyntax = validateFormulaSyntax;
1510
- exports.validateSyntax = validateSyntax;
1511
- //# sourceMappingURL=chunk-4FIOGFOL.cjs.map
1512
- //# sourceMappingURL=chunk-4FIOGFOL.cjs.map