lightview 2.3.4 → 2.3.5

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/lightview-all.js CHANGED
@@ -2371,7 +2371,7 @@
2371
2371
  const resolveTemplate = (node, context2) => {
2372
2372
  if (typeof node === "string") {
2373
2373
  if (node.startsWith("=")) {
2374
- const res = resolveExpression(node, context2);
2374
+ const res = resolveExpression$1(node, context2);
2375
2375
  const final = res instanceof LazyValue ? res.resolve(context2) : res;
2376
2376
  return unwrapSignal(final);
2377
2377
  }
@@ -2427,7 +2427,7 @@
2427
2427
  } else if (globalMode && !arg.startsWith("=") && !arg.startsWith("./")) {
2428
2428
  nestedExpr = `=/${arg}`;
2429
2429
  }
2430
- const val = resolveExpression(nestedExpr, context);
2430
+ const val = resolveExpression$1(nestedExpr, context);
2431
2431
  if (val instanceof LazyValue) {
2432
2432
  return { value: val, isLazy: true };
2433
2433
  }
@@ -2906,7 +2906,7 @@
2906
2906
  const ast = parser.parseExpression(0);
2907
2907
  return evaluateAST(ast, context);
2908
2908
  };
2909
- const resolveExpression = (expr, context) => {
2909
+ const resolveExpression$1 = (expr, context) => {
2910
2910
  var _a2, _b2;
2911
2911
  if (typeof expr !== "string") return expr;
2912
2912
  if (hasOperatorSyntax(expr)) {
@@ -2993,7 +2993,7 @@
2993
2993
  const parseExpression = (expr, context) => {
2994
2994
  const LV = getLV();
2995
2995
  if (!LV || typeof expr !== "string") return expr;
2996
- return LV.computed(() => resolveExpression(expr, context));
2996
+ return LV.computed(() => resolveExpression$1(expr, context));
2997
2997
  };
2998
2998
  const parseCDOMC = (input) => {
2999
2999
  let i = 0;
@@ -3284,6 +3284,32 @@
3284
3284
  while (j < len2 && /\s/.test(input[j])) j++;
3285
3285
  if (input[j] === ":") {
3286
3286
  result += `"${word}"`;
3287
+ } else if (input[j] === "(") {
3288
+ let expr = word;
3289
+ i = j;
3290
+ let parenDepth = 0;
3291
+ let inQuote = null;
3292
+ while (i < len2) {
3293
+ const c = input[i];
3294
+ if (inQuote) {
3295
+ if (c === inQuote && input[i - 1] !== "\\") inQuote = null;
3296
+ } else if (c === '"' || c === "'") {
3297
+ inQuote = c;
3298
+ } else {
3299
+ if (c === "(") parenDepth++;
3300
+ else if (c === ")") {
3301
+ parenDepth--;
3302
+ if (parenDepth === 0) {
3303
+ expr += c;
3304
+ i++;
3305
+ break;
3306
+ }
3307
+ }
3308
+ }
3309
+ expr += c;
3310
+ i++;
3311
+ }
3312
+ result += JSON.stringify("=" + expr);
3287
3313
  } else {
3288
3314
  if (word === "true" || word === "false" || word === "null") {
3289
3315
  result += word;
@@ -3315,7 +3341,7 @@
3315
3341
  throw e;
3316
3342
  }
3317
3343
  };
3318
- const add = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
3344
+ const add$1 = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
3319
3345
  const subtract = (a, b) => Number(a) - Number(b);
3320
3346
  const multiply = (...args) => args.reduce((a, b) => Number(a) * Number(b), 1);
3321
3347
  const divide = (a, b) => Number(a) / Number(b);
@@ -3323,12 +3349,14 @@
3323
3349
  const ceil = (val) => Math.ceil(val);
3324
3350
  const floor = (val) => Math.floor(val);
3325
3351
  const abs = (val) => Math.abs(val);
3326
- const mod = (a, b) => a % b;
3352
+ const mod$1 = (a, b) => a % b;
3327
3353
  const pow = (a, b) => Math.pow(a, b);
3328
3354
  const sqrt = (val) => Math.sqrt(val);
3355
+ const negate = (val) => -Number(val);
3356
+ const toPercent = (val) => Number(val) / 100;
3329
3357
  const registerMathHelpers = (register) => {
3330
- register("+", add);
3331
- register("add", add);
3358
+ register("+", add$1);
3359
+ register("add", add$1);
3332
3360
  register("-", subtract);
3333
3361
  register("sub", subtract);
3334
3362
  register("*", multiply);
@@ -3339,11 +3367,13 @@
3339
3367
  register("ceil", ceil);
3340
3368
  register("floor", floor);
3341
3369
  register("abs", abs);
3342
- register("mod", mod);
3370
+ register("mod", mod$1);
3343
3371
  register("pow", pow);
3344
3372
  register("sqrt", sqrt);
3373
+ register("negate", negate);
3374
+ register("toPercent", toPercent);
3345
3375
  };
3346
- const ifHelper = (condition, thenVal, elseVal) => condition ? thenVal : elseVal;
3376
+ const ifHelper = (condition2, thenVal, elseVal) => condition2 ? thenVal : elseVal;
3347
3377
  const andHelper = (...args) => args.every(Boolean);
3348
3378
  const orHelper = (...args) => args.some(Boolean);
3349
3379
  const notHelper = (val) => !val;
@@ -3367,7 +3397,7 @@
3367
3397
  const items = args.slice(0, -1);
3368
3398
  return items.join(separator);
3369
3399
  };
3370
- const concat = (...args) => args.join("");
3400
+ const concat$1 = (...args) => args.join("");
3371
3401
  const upper = (s) => String(s).toUpperCase();
3372
3402
  const lower = (s) => String(s).toLowerCase();
3373
3403
  const trim = (s) => String(s).trim();
@@ -3381,13 +3411,13 @@
3381
3411
  const titleCase = (s) => {
3382
3412
  return String(s).toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3383
3413
  };
3384
- const contains$1 = (s, search) => String(s).includes(search);
3414
+ const contains$2 = (s, search) => String(s).includes(search);
3385
3415
  const startsWith = (s, prefix) => String(s).startsWith(prefix);
3386
3416
  const endsWith = (s, suffix) => String(s).endsWith(suffix);
3387
3417
  const defaultHelper = (val, fallback) => val !== void 0 && val !== null ? val : fallback;
3388
3418
  const registerStringHelpers = (register) => {
3389
3419
  register("join", join$1);
3390
- register("concat", concat);
3420
+ register("concat", concat$1);
3391
3421
  register("upper", upper);
3392
3422
  register("lower", lower);
3393
3423
  register("trim", trim);
@@ -3396,7 +3426,7 @@
3396
3426
  register("split", split);
3397
3427
  register("capitalize", capitalize);
3398
3428
  register("titleCase", titleCase);
3399
- register("contains", contains$1);
3429
+ register("contains", contains$2);
3400
3430
  register("startsWith", startsWith);
3401
3431
  register("endsWith", endsWith);
3402
3432
  register("default", defaultHelper);
@@ -3469,7 +3499,7 @@
3469
3499
  const lte = (a, b) => a <= b;
3470
3500
  const neq = (a, b) => a !== b;
3471
3501
  const between = (val, min2, max2) => val >= min2 && val <= max2;
3472
- const contains = (arr, val) => Array.isArray(arr) && arr.includes(val);
3502
+ const contains$1 = (arr, val) => Array.isArray(arr) && arr.includes(val);
3473
3503
  const registerCompareHelpers = (register) => {
3474
3504
  register("gt", gt);
3475
3505
  register(">", gt);
@@ -3482,7 +3512,7 @@
3482
3512
  register("neq", neq);
3483
3513
  register("!=", neq);
3484
3514
  register("between", between);
3485
- register("in", contains);
3515
+ register("in", contains$1);
3486
3516
  };
3487
3517
  const sumIf = (arr, predicate) => {
3488
3518
  if (!Array.isArray(arr)) return 0;
@@ -3573,16 +3603,35 @@
3573
3603
  };
3574
3604
  const index = (arr, idx) => Array.isArray(arr) ? arr[idx] : void 0;
3575
3605
  const match = (val, arr) => Array.isArray(arr) ? arr.indexOf(val) : -1;
3606
+ const pathRef = (path, context) => {
3607
+ if (path && typeof path === "object" && "value" in path) {
3608
+ return unwrapSignal(path.value);
3609
+ }
3610
+ if (typeof path === "string") {
3611
+ const normalized = path.startsWith("=") ? path : "=" + path;
3612
+ const resolved = resolvePath(normalized, context);
3613
+ const value = unwrapSignal(resolved);
3614
+ if (typeof value === "number") return value;
3615
+ if (typeof value === "string" && value !== "" && !isNaN(parseFloat(value)) && isFinite(Number(value))) {
3616
+ return parseFloat(value);
3617
+ }
3618
+ return value;
3619
+ }
3620
+ return unwrapSignal(path);
3621
+ };
3576
3622
  const registerLookupHelpers = (register) => {
3577
3623
  register("lookup", lookup);
3578
3624
  register("vlookup", vlookup);
3579
3625
  register("index", index);
3580
3626
  register("match", match);
3627
+ register("$", pathRef, { pathAware: true });
3628
+ register("val", pathRef, { pathAware: true });
3629
+ register("indirect", pathRef, { pathAware: true });
3581
3630
  };
3582
3631
  const sum = (...args) => args.reduce((a, b) => a + (Number(b) || 0), 0);
3583
3632
  const avg = (...args) => args.length === 0 ? 0 : sum(...args) / args.length;
3584
- const min = (...args) => Math.min(...args);
3585
- const max = (...args) => Math.max(...args);
3633
+ const min$1 = (...args) => Math.min(...args);
3634
+ const max$1 = (...args) => Math.max(...args);
3586
3635
  const median = (...args) => {
3587
3636
  if (args.length === 0) return 0;
3588
3637
  const sorted = [...args].sort((a, b) => a - b);
@@ -3604,8 +3653,8 @@
3604
3653
  const registerStatsHelpers = (register) => {
3605
3654
  register("sum", sum);
3606
3655
  register("avg", avg);
3607
- register("min", min);
3608
- register("max", max);
3656
+ register("min", min$1);
3657
+ register("max", max$1);
3609
3658
  register("median", median);
3610
3659
  register("stdev", stdev);
3611
3660
  register("var", variance);
@@ -3720,6 +3769,1657 @@
3720
3769
  const registerNetworkHelpers = (register) => {
3721
3770
  register("fetch", fetchHelper);
3722
3771
  };
3772
+ var INUMBER = "INUMBER";
3773
+ var IOP1 = "IOP1";
3774
+ var IOP2 = "IOP2";
3775
+ var IOP3 = "IOP3";
3776
+ var IVAR = "IVAR";
3777
+ var IVARNAME = "IVARNAME";
3778
+ var IFUNCALL = "IFUNCALL";
3779
+ var IFUNDEF = "IFUNDEF";
3780
+ var IEXPR = "IEXPR";
3781
+ var IEXPREVAL = "IEXPREVAL";
3782
+ var IMEMBER = "IMEMBER";
3783
+ var IENDSTATEMENT = "IENDSTATEMENT";
3784
+ var IARRAY = "IARRAY";
3785
+ function Instruction(type, value) {
3786
+ this.type = type;
3787
+ this.value = value !== void 0 && value !== null ? value : 0;
3788
+ }
3789
+ Instruction.prototype.toString = function() {
3790
+ switch (this.type) {
3791
+ case INUMBER:
3792
+ case IOP1:
3793
+ case IOP2:
3794
+ case IOP3:
3795
+ case IVAR:
3796
+ case IVARNAME:
3797
+ case IENDSTATEMENT:
3798
+ return this.value;
3799
+ case IFUNCALL:
3800
+ return "CALL " + this.value;
3801
+ case IFUNDEF:
3802
+ return "DEF " + this.value;
3803
+ case IARRAY:
3804
+ return "ARRAY " + this.value;
3805
+ case IMEMBER:
3806
+ return "." + this.value;
3807
+ default:
3808
+ return "Invalid Instruction";
3809
+ }
3810
+ };
3811
+ function unaryInstruction(value) {
3812
+ return new Instruction(IOP1, value);
3813
+ }
3814
+ function binaryInstruction(value) {
3815
+ return new Instruction(IOP2, value);
3816
+ }
3817
+ function ternaryInstruction(value) {
3818
+ return new Instruction(IOP3, value);
3819
+ }
3820
+ function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) {
3821
+ var nstack = [];
3822
+ var newexpression = [];
3823
+ var n1, n2, n3;
3824
+ var f;
3825
+ for (var i = 0; i < tokens.length; i++) {
3826
+ var item = tokens[i];
3827
+ var type = item.type;
3828
+ if (type === INUMBER || type === IVARNAME) {
3829
+ if (Array.isArray(item.value)) {
3830
+ nstack.push.apply(nstack, simplify(item.value.map(function(x) {
3831
+ return new Instruction(INUMBER, x);
3832
+ }).concat(new Instruction(IARRAY, item.value.length)), unaryOps, binaryOps, ternaryOps, values));
3833
+ } else {
3834
+ nstack.push(item);
3835
+ }
3836
+ } else if (type === IVAR && values.hasOwnProperty(item.value)) {
3837
+ item = new Instruction(INUMBER, values[item.value]);
3838
+ nstack.push(item);
3839
+ } else if (type === IOP2 && nstack.length > 1) {
3840
+ n2 = nstack.pop();
3841
+ n1 = nstack.pop();
3842
+ f = binaryOps[item.value];
3843
+ item = new Instruction(INUMBER, f(n1.value, n2.value));
3844
+ nstack.push(item);
3845
+ } else if (type === IOP3 && nstack.length > 2) {
3846
+ n3 = nstack.pop();
3847
+ n2 = nstack.pop();
3848
+ n1 = nstack.pop();
3849
+ if (item.value === "?") {
3850
+ nstack.push(n1.value ? n2.value : n3.value);
3851
+ } else {
3852
+ f = ternaryOps[item.value];
3853
+ item = new Instruction(INUMBER, f(n1.value, n2.value, n3.value));
3854
+ nstack.push(item);
3855
+ }
3856
+ } else if (type === IOP1 && nstack.length > 0) {
3857
+ n1 = nstack.pop();
3858
+ f = unaryOps[item.value];
3859
+ item = new Instruction(INUMBER, f(n1.value));
3860
+ nstack.push(item);
3861
+ } else if (type === IEXPR) {
3862
+ while (nstack.length > 0) {
3863
+ newexpression.push(nstack.shift());
3864
+ }
3865
+ newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values)));
3866
+ } else if (type === IMEMBER && nstack.length > 0) {
3867
+ n1 = nstack.pop();
3868
+ nstack.push(new Instruction(INUMBER, n1.value[item.value]));
3869
+ } else {
3870
+ while (nstack.length > 0) {
3871
+ newexpression.push(nstack.shift());
3872
+ }
3873
+ newexpression.push(item);
3874
+ }
3875
+ }
3876
+ while (nstack.length > 0) {
3877
+ newexpression.push(nstack.shift());
3878
+ }
3879
+ return newexpression;
3880
+ }
3881
+ function substitute(tokens, variable, expr) {
3882
+ var newexpression = [];
3883
+ for (var i = 0; i < tokens.length; i++) {
3884
+ var item = tokens[i];
3885
+ var type = item.type;
3886
+ if (type === IVAR && item.value === variable) {
3887
+ for (var j = 0; j < expr.tokens.length; j++) {
3888
+ var expritem = expr.tokens[j];
3889
+ var replitem;
3890
+ if (expritem.type === IOP1) {
3891
+ replitem = unaryInstruction(expritem.value);
3892
+ } else if (expritem.type === IOP2) {
3893
+ replitem = binaryInstruction(expritem.value);
3894
+ } else if (expritem.type === IOP3) {
3895
+ replitem = ternaryInstruction(expritem.value);
3896
+ } else {
3897
+ replitem = new Instruction(expritem.type, expritem.value);
3898
+ }
3899
+ newexpression.push(replitem);
3900
+ }
3901
+ } else if (type === IEXPR) {
3902
+ newexpression.push(new Instruction(IEXPR, substitute(item.value, variable, expr)));
3903
+ } else {
3904
+ newexpression.push(item);
3905
+ }
3906
+ }
3907
+ return newexpression;
3908
+ }
3909
+ function evaluate(tokens, expr, values) {
3910
+ var nstack = [];
3911
+ var n1, n2, n3;
3912
+ var f, args, argCount;
3913
+ if (isExpressionEvaluator(tokens)) {
3914
+ return resolveExpression(tokens, values);
3915
+ }
3916
+ var numTokens = tokens.length;
3917
+ for (var i = 0; i < numTokens; i++) {
3918
+ var item = tokens[i];
3919
+ var type = item.type;
3920
+ if (type === INUMBER || type === IVARNAME) {
3921
+ nstack.push(item.value);
3922
+ } else if (type === IOP2) {
3923
+ n2 = nstack.pop();
3924
+ n1 = nstack.pop();
3925
+ if (item.value === "and") {
3926
+ nstack.push(n1 ? !!evaluate(n2, expr, values) : false);
3927
+ } else if (item.value === "or") {
3928
+ nstack.push(n1 ? true : !!evaluate(n2, expr, values));
3929
+ } else if (item.value === "=") {
3930
+ f = expr.binaryOps[item.value];
3931
+ nstack.push(f(n1, evaluate(n2, expr, values), values));
3932
+ } else {
3933
+ f = expr.binaryOps[item.value];
3934
+ nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values)));
3935
+ }
3936
+ } else if (type === IOP3) {
3937
+ n3 = nstack.pop();
3938
+ n2 = nstack.pop();
3939
+ n1 = nstack.pop();
3940
+ if (item.value === "?") {
3941
+ nstack.push(evaluate(n1 ? n2 : n3, expr, values));
3942
+ } else {
3943
+ f = expr.ternaryOps[item.value];
3944
+ nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values), resolveExpression(n3, values)));
3945
+ }
3946
+ } else if (type === IVAR) {
3947
+ if (item.value in expr.functions) {
3948
+ nstack.push(expr.functions[item.value]);
3949
+ } else if (item.value in expr.unaryOps && expr.parser.isOperatorEnabled(item.value)) {
3950
+ nstack.push(expr.unaryOps[item.value]);
3951
+ } else {
3952
+ var v = values[item.value];
3953
+ if (v !== void 0) {
3954
+ nstack.push(v);
3955
+ } else {
3956
+ throw new Error("undefined variable: " + item.value);
3957
+ }
3958
+ }
3959
+ } else if (type === IOP1) {
3960
+ n1 = nstack.pop();
3961
+ f = expr.unaryOps[item.value];
3962
+ nstack.push(f(resolveExpression(n1, values)));
3963
+ } else if (type === IFUNCALL) {
3964
+ argCount = item.value;
3965
+ args = [];
3966
+ while (argCount-- > 0) {
3967
+ args.unshift(resolveExpression(nstack.pop(), values));
3968
+ }
3969
+ f = nstack.pop();
3970
+ if (f.apply && f.call) {
3971
+ nstack.push(f.apply(void 0, args));
3972
+ } else {
3973
+ throw new Error(f + " is not a function");
3974
+ }
3975
+ } else if (type === IFUNDEF) {
3976
+ nstack.push(function() {
3977
+ var n22 = nstack.pop();
3978
+ var args2 = [];
3979
+ var argCount2 = item.value;
3980
+ while (argCount2-- > 0) {
3981
+ args2.unshift(nstack.pop());
3982
+ }
3983
+ var n12 = nstack.pop();
3984
+ var f2 = function() {
3985
+ var scope = Object.assign({}, values);
3986
+ for (var i2 = 0, len2 = args2.length; i2 < len2; i2++) {
3987
+ scope[args2[i2]] = arguments[i2];
3988
+ }
3989
+ return evaluate(n22, expr, scope);
3990
+ };
3991
+ Object.defineProperty(f2, "name", {
3992
+ value: n12,
3993
+ writable: false
3994
+ });
3995
+ values[n12] = f2;
3996
+ return f2;
3997
+ }());
3998
+ } else if (type === IEXPR) {
3999
+ nstack.push(createExpressionEvaluator(item, expr));
4000
+ } else if (type === IEXPREVAL) {
4001
+ nstack.push(item);
4002
+ } else if (type === IMEMBER) {
4003
+ n1 = nstack.pop();
4004
+ nstack.push(n1[item.value]);
4005
+ } else if (type === IENDSTATEMENT) {
4006
+ nstack.pop();
4007
+ } else if (type === IARRAY) {
4008
+ argCount = item.value;
4009
+ args = [];
4010
+ while (argCount-- > 0) {
4011
+ args.unshift(nstack.pop());
4012
+ }
4013
+ nstack.push(args);
4014
+ } else {
4015
+ throw new Error("invalid Expression");
4016
+ }
4017
+ }
4018
+ if (nstack.length > 1) {
4019
+ throw new Error("invalid Expression (parity)");
4020
+ }
4021
+ return nstack[0] === 0 ? 0 : resolveExpression(nstack[0], values);
4022
+ }
4023
+ function createExpressionEvaluator(token, expr, values) {
4024
+ if (isExpressionEvaluator(token)) return token;
4025
+ return {
4026
+ type: IEXPREVAL,
4027
+ value: function(scope) {
4028
+ return evaluate(token.value, expr, scope);
4029
+ }
4030
+ };
4031
+ }
4032
+ function isExpressionEvaluator(n) {
4033
+ return n && n.type === IEXPREVAL;
4034
+ }
4035
+ function resolveExpression(n, values) {
4036
+ return isExpressionEvaluator(n) ? n.value(values) : n;
4037
+ }
4038
+ function expressionToString(tokens, toJS) {
4039
+ var nstack = [];
4040
+ var n1, n2, n3;
4041
+ var f, args, argCount;
4042
+ for (var i = 0; i < tokens.length; i++) {
4043
+ var item = tokens[i];
4044
+ var type = item.type;
4045
+ if (type === INUMBER) {
4046
+ if (typeof item.value === "number" && item.value < 0) {
4047
+ nstack.push("(" + item.value + ")");
4048
+ } else if (Array.isArray(item.value)) {
4049
+ nstack.push("[" + item.value.map(escapeValue).join(", ") + "]");
4050
+ } else {
4051
+ nstack.push(escapeValue(item.value));
4052
+ }
4053
+ } else if (type === IOP2) {
4054
+ n2 = nstack.pop();
4055
+ n1 = nstack.pop();
4056
+ f = item.value;
4057
+ if (toJS) {
4058
+ if (f === "^") {
4059
+ nstack.push("Math.pow(" + n1 + ", " + n2 + ")");
4060
+ } else if (f === "and") {
4061
+ nstack.push("(!!" + n1 + " && !!" + n2 + ")");
4062
+ } else if (f === "or") {
4063
+ nstack.push("(!!" + n1 + " || !!" + n2 + ")");
4064
+ } else if (f === "||") {
4065
+ nstack.push("(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }((" + n1 + "),(" + n2 + ")))");
4066
+ } else if (f === "==") {
4067
+ nstack.push("(" + n1 + " === " + n2 + ")");
4068
+ } else if (f === "!=") {
4069
+ nstack.push("(" + n1 + " !== " + n2 + ")");
4070
+ } else if (f === "[") {
4071
+ nstack.push(n1 + "[(" + n2 + ") | 0]");
4072
+ } else {
4073
+ nstack.push("(" + n1 + " " + f + " " + n2 + ")");
4074
+ }
4075
+ } else {
4076
+ if (f === "[") {
4077
+ nstack.push(n1 + "[" + n2 + "]");
4078
+ } else {
4079
+ nstack.push("(" + n1 + " " + f + " " + n2 + ")");
4080
+ }
4081
+ }
4082
+ } else if (type === IOP3) {
4083
+ n3 = nstack.pop();
4084
+ n2 = nstack.pop();
4085
+ n1 = nstack.pop();
4086
+ f = item.value;
4087
+ if (f === "?") {
4088
+ nstack.push("(" + n1 + " ? " + n2 + " : " + n3 + ")");
4089
+ } else {
4090
+ throw new Error("invalid Expression");
4091
+ }
4092
+ } else if (type === IVAR || type === IVARNAME) {
4093
+ nstack.push(item.value);
4094
+ } else if (type === IOP1) {
4095
+ n1 = nstack.pop();
4096
+ f = item.value;
4097
+ if (f === "-" || f === "+") {
4098
+ nstack.push("(" + f + n1 + ")");
4099
+ } else if (toJS) {
4100
+ if (f === "not") {
4101
+ nstack.push("(!" + n1 + ")");
4102
+ } else if (f === "!") {
4103
+ nstack.push("fac(" + n1 + ")");
4104
+ } else {
4105
+ nstack.push(f + "(" + n1 + ")");
4106
+ }
4107
+ } else if (f === "!") {
4108
+ nstack.push("(" + n1 + "!)");
4109
+ } else {
4110
+ nstack.push("(" + f + " " + n1 + ")");
4111
+ }
4112
+ } else if (type === IFUNCALL) {
4113
+ argCount = item.value;
4114
+ args = [];
4115
+ while (argCount-- > 0) {
4116
+ args.unshift(nstack.pop());
4117
+ }
4118
+ f = nstack.pop();
4119
+ nstack.push(f + "(" + args.join(", ") + ")");
4120
+ } else if (type === IFUNDEF) {
4121
+ n2 = nstack.pop();
4122
+ argCount = item.value;
4123
+ args = [];
4124
+ while (argCount-- > 0) {
4125
+ args.unshift(nstack.pop());
4126
+ }
4127
+ n1 = nstack.pop();
4128
+ if (toJS) {
4129
+ nstack.push("(" + n1 + " = function(" + args.join(", ") + ") { return " + n2 + " })");
4130
+ } else {
4131
+ nstack.push("(" + n1 + "(" + args.join(", ") + ") = " + n2 + ")");
4132
+ }
4133
+ } else if (type === IMEMBER) {
4134
+ n1 = nstack.pop();
4135
+ nstack.push(n1 + "." + item.value);
4136
+ } else if (type === IARRAY) {
4137
+ argCount = item.value;
4138
+ args = [];
4139
+ while (argCount-- > 0) {
4140
+ args.unshift(nstack.pop());
4141
+ }
4142
+ nstack.push("[" + args.join(", ") + "]");
4143
+ } else if (type === IEXPR) {
4144
+ nstack.push("(" + expressionToString(item.value, toJS) + ")");
4145
+ } else if (type === IENDSTATEMENT) ;
4146
+ else {
4147
+ throw new Error("invalid Expression");
4148
+ }
4149
+ }
4150
+ if (nstack.length > 1) {
4151
+ if (toJS) {
4152
+ nstack = [nstack.join(",")];
4153
+ } else {
4154
+ nstack = [nstack.join(";")];
4155
+ }
4156
+ }
4157
+ return String(nstack[0]);
4158
+ }
4159
+ function escapeValue(v) {
4160
+ if (typeof v === "string") {
4161
+ return JSON.stringify(v).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
4162
+ }
4163
+ return v;
4164
+ }
4165
+ function contains(array, obj) {
4166
+ for (var i = 0; i < array.length; i++) {
4167
+ if (array[i] === obj) {
4168
+ return true;
4169
+ }
4170
+ }
4171
+ return false;
4172
+ }
4173
+ function getSymbols(tokens, symbols, options) {
4174
+ options = options || {};
4175
+ var withMembers = !!options.withMembers;
4176
+ var prevVar = null;
4177
+ for (var i = 0; i < tokens.length; i++) {
4178
+ var item = tokens[i];
4179
+ if (item.type === IVAR || item.type === IVARNAME) {
4180
+ if (!withMembers && !contains(symbols, item.value)) {
4181
+ symbols.push(item.value);
4182
+ } else if (prevVar !== null) {
4183
+ if (!contains(symbols, prevVar)) {
4184
+ symbols.push(prevVar);
4185
+ }
4186
+ prevVar = item.value;
4187
+ } else {
4188
+ prevVar = item.value;
4189
+ }
4190
+ } else if (item.type === IMEMBER && withMembers && prevVar !== null) {
4191
+ prevVar += "." + item.value;
4192
+ } else if (item.type === IEXPR) {
4193
+ getSymbols(item.value, symbols, options);
4194
+ } else if (prevVar !== null) {
4195
+ if (!contains(symbols, prevVar)) {
4196
+ symbols.push(prevVar);
4197
+ }
4198
+ prevVar = null;
4199
+ }
4200
+ }
4201
+ if (prevVar !== null && !contains(symbols, prevVar)) {
4202
+ symbols.push(prevVar);
4203
+ }
4204
+ }
4205
+ function Expression(tokens, parser) {
4206
+ this.tokens = tokens;
4207
+ this.parser = parser;
4208
+ this.unaryOps = parser.unaryOps;
4209
+ this.binaryOps = parser.binaryOps;
4210
+ this.ternaryOps = parser.ternaryOps;
4211
+ this.functions = parser.functions;
4212
+ }
4213
+ Expression.prototype.simplify = function(values) {
4214
+ values = values || {};
4215
+ return new Expression(simplify(this.tokens, this.unaryOps, this.binaryOps, this.ternaryOps, values), this.parser);
4216
+ };
4217
+ Expression.prototype.substitute = function(variable, expr) {
4218
+ if (!(expr instanceof Expression)) {
4219
+ expr = this.parser.parse(String(expr));
4220
+ }
4221
+ return new Expression(substitute(this.tokens, variable, expr), this.parser);
4222
+ };
4223
+ Expression.prototype.evaluate = function(values) {
4224
+ values = values || {};
4225
+ return evaluate(this.tokens, this, values);
4226
+ };
4227
+ Expression.prototype.toString = function() {
4228
+ return expressionToString(this.tokens, false);
4229
+ };
4230
+ Expression.prototype.symbols = function(options) {
4231
+ options = options || {};
4232
+ var vars = [];
4233
+ getSymbols(this.tokens, vars, options);
4234
+ return vars;
4235
+ };
4236
+ Expression.prototype.variables = function(options) {
4237
+ options = options || {};
4238
+ var vars = [];
4239
+ getSymbols(this.tokens, vars, options);
4240
+ var functions = this.functions;
4241
+ return vars.filter(function(name) {
4242
+ return !(name in functions);
4243
+ });
4244
+ };
4245
+ Expression.prototype.toJSFunction = function(param, variables) {
4246
+ var expr = this;
4247
+ var f = new Function(param, "with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return " + expressionToString(this.simplify(variables).tokens, true) + "; }");
4248
+ return function() {
4249
+ return f.apply(expr, arguments);
4250
+ };
4251
+ };
4252
+ var TEOF = "TEOF";
4253
+ var TOP = "TOP";
4254
+ var TNUMBER = "TNUMBER";
4255
+ var TSTRING = "TSTRING";
4256
+ var TPAREN = "TPAREN";
4257
+ var TBRACKET = "TBRACKET";
4258
+ var TCOMMA = "TCOMMA";
4259
+ var TNAME = "TNAME";
4260
+ var TSEMICOLON = "TSEMICOLON";
4261
+ function Token(type, value, index2) {
4262
+ this.type = type;
4263
+ this.value = value;
4264
+ this.index = index2;
4265
+ }
4266
+ Token.prototype.toString = function() {
4267
+ return this.type + ": " + this.value;
4268
+ };
4269
+ function TokenStream(parser, expression) {
4270
+ this.pos = 0;
4271
+ this.current = null;
4272
+ this.unaryOps = parser.unaryOps;
4273
+ this.binaryOps = parser.binaryOps;
4274
+ this.ternaryOps = parser.ternaryOps;
4275
+ this.consts = parser.consts;
4276
+ this.expression = expression;
4277
+ this.savedPosition = 0;
4278
+ this.savedCurrent = null;
4279
+ this.options = parser.options;
4280
+ this.parser = parser;
4281
+ }
4282
+ TokenStream.prototype.newToken = function(type, value, pos) {
4283
+ return new Token(type, value, pos != null ? pos : this.pos);
4284
+ };
4285
+ TokenStream.prototype.save = function() {
4286
+ this.savedPosition = this.pos;
4287
+ this.savedCurrent = this.current;
4288
+ };
4289
+ TokenStream.prototype.restore = function() {
4290
+ this.pos = this.savedPosition;
4291
+ this.current = this.savedCurrent;
4292
+ };
4293
+ TokenStream.prototype.next = function() {
4294
+ if (this.pos >= this.expression.length) {
4295
+ return this.newToken(TEOF, "EOF");
4296
+ }
4297
+ if (this.isWhitespace() || this.isComment()) {
4298
+ return this.next();
4299
+ } else if (this.isRadixInteger() || this.isNumber() || this.isOperator() || this.isString() || this.isParen() || this.isBracket() || this.isComma() || this.isSemicolon() || this.isNamedOp() || this.isConst() || this.isName()) {
4300
+ return this.current;
4301
+ } else {
4302
+ this.parseError('Unknown character "' + this.expression.charAt(this.pos) + '"');
4303
+ }
4304
+ };
4305
+ TokenStream.prototype.isString = function() {
4306
+ var r = false;
4307
+ var startPos = this.pos;
4308
+ var quote = this.expression.charAt(startPos);
4309
+ if (quote === "'" || quote === '"') {
4310
+ var index2 = this.expression.indexOf(quote, startPos + 1);
4311
+ while (index2 >= 0 && this.pos < this.expression.length) {
4312
+ this.pos = index2 + 1;
4313
+ if (this.expression.charAt(index2 - 1) !== "\\") {
4314
+ var rawString = this.expression.substring(startPos + 1, index2);
4315
+ this.current = this.newToken(TSTRING, this.unescape(rawString), startPos);
4316
+ r = true;
4317
+ break;
4318
+ }
4319
+ index2 = this.expression.indexOf(quote, index2 + 1);
4320
+ }
4321
+ }
4322
+ return r;
4323
+ };
4324
+ TokenStream.prototype.isParen = function() {
4325
+ var c = this.expression.charAt(this.pos);
4326
+ if (c === "(" || c === ")") {
4327
+ this.current = this.newToken(TPAREN, c);
4328
+ this.pos++;
4329
+ return true;
4330
+ }
4331
+ return false;
4332
+ };
4333
+ TokenStream.prototype.isBracket = function() {
4334
+ var c = this.expression.charAt(this.pos);
4335
+ if ((c === "[" || c === "]") && this.isOperatorEnabled("[")) {
4336
+ this.current = this.newToken(TBRACKET, c);
4337
+ this.pos++;
4338
+ return true;
4339
+ }
4340
+ return false;
4341
+ };
4342
+ TokenStream.prototype.isComma = function() {
4343
+ var c = this.expression.charAt(this.pos);
4344
+ if (c === ",") {
4345
+ this.current = this.newToken(TCOMMA, ",");
4346
+ this.pos++;
4347
+ return true;
4348
+ }
4349
+ return false;
4350
+ };
4351
+ TokenStream.prototype.isSemicolon = function() {
4352
+ var c = this.expression.charAt(this.pos);
4353
+ if (c === ";") {
4354
+ this.current = this.newToken(TSEMICOLON, ";");
4355
+ this.pos++;
4356
+ return true;
4357
+ }
4358
+ return false;
4359
+ };
4360
+ TokenStream.prototype.isConst = function() {
4361
+ var startPos = this.pos;
4362
+ var i = startPos;
4363
+ for (; i < this.expression.length; i++) {
4364
+ var c = this.expression.charAt(i);
4365
+ if (c.toUpperCase() === c.toLowerCase()) {
4366
+ if (i === this.pos || c !== "_" && c !== "." && (c < "0" || c > "9")) {
4367
+ break;
4368
+ }
4369
+ }
4370
+ }
4371
+ if (i > startPos) {
4372
+ var str = this.expression.substring(startPos, i);
4373
+ if (str in this.consts) {
4374
+ this.current = this.newToken(TNUMBER, this.consts[str]);
4375
+ this.pos += str.length;
4376
+ return true;
4377
+ }
4378
+ }
4379
+ return false;
4380
+ };
4381
+ TokenStream.prototype.isNamedOp = function() {
4382
+ var startPos = this.pos;
4383
+ var i = startPos;
4384
+ for (; i < this.expression.length; i++) {
4385
+ var c = this.expression.charAt(i);
4386
+ if (c.toUpperCase() === c.toLowerCase()) {
4387
+ if (i === this.pos || c !== "_" && (c < "0" || c > "9")) {
4388
+ break;
4389
+ }
4390
+ }
4391
+ }
4392
+ if (i > startPos) {
4393
+ var str = this.expression.substring(startPos, i);
4394
+ if (this.isOperatorEnabled(str) && (str in this.binaryOps || str in this.unaryOps || str in this.ternaryOps)) {
4395
+ this.current = this.newToken(TOP, str);
4396
+ this.pos += str.length;
4397
+ return true;
4398
+ }
4399
+ }
4400
+ return false;
4401
+ };
4402
+ TokenStream.prototype.isName = function() {
4403
+ var startPos = this.pos;
4404
+ var i = startPos;
4405
+ var hasLetter = false;
4406
+ for (; i < this.expression.length; i++) {
4407
+ var c = this.expression.charAt(i);
4408
+ if (c.toUpperCase() === c.toLowerCase()) {
4409
+ if (i === this.pos && (c === "$" || c === "_")) {
4410
+ if (c === "_") {
4411
+ hasLetter = true;
4412
+ }
4413
+ continue;
4414
+ } else if (i === this.pos || !hasLetter || c !== "_" && (c < "0" || c > "9")) {
4415
+ break;
4416
+ }
4417
+ } else {
4418
+ hasLetter = true;
4419
+ }
4420
+ }
4421
+ if (hasLetter) {
4422
+ var str = this.expression.substring(startPos, i);
4423
+ this.current = this.newToken(TNAME, str);
4424
+ this.pos += str.length;
4425
+ return true;
4426
+ }
4427
+ return false;
4428
+ };
4429
+ TokenStream.prototype.isWhitespace = function() {
4430
+ var r = false;
4431
+ var c = this.expression.charAt(this.pos);
4432
+ while (c === " " || c === " " || c === "\n" || c === "\r") {
4433
+ r = true;
4434
+ this.pos++;
4435
+ if (this.pos >= this.expression.length) {
4436
+ break;
4437
+ }
4438
+ c = this.expression.charAt(this.pos);
4439
+ }
4440
+ return r;
4441
+ };
4442
+ var codePointPattern = /^[0-9a-f]{4}$/i;
4443
+ TokenStream.prototype.unescape = function(v) {
4444
+ var index2 = v.indexOf("\\");
4445
+ if (index2 < 0) {
4446
+ return v;
4447
+ }
4448
+ var buffer = v.substring(0, index2);
4449
+ while (index2 >= 0) {
4450
+ var c = v.charAt(++index2);
4451
+ switch (c) {
4452
+ case "'":
4453
+ buffer += "'";
4454
+ break;
4455
+ case '"':
4456
+ buffer += '"';
4457
+ break;
4458
+ case "\\":
4459
+ buffer += "\\";
4460
+ break;
4461
+ case "/":
4462
+ buffer += "/";
4463
+ break;
4464
+ case "b":
4465
+ buffer += "\b";
4466
+ break;
4467
+ case "f":
4468
+ buffer += "\f";
4469
+ break;
4470
+ case "n":
4471
+ buffer += "\n";
4472
+ break;
4473
+ case "r":
4474
+ buffer += "\r";
4475
+ break;
4476
+ case "t":
4477
+ buffer += " ";
4478
+ break;
4479
+ case "u":
4480
+ var codePoint = v.substring(index2 + 1, index2 + 5);
4481
+ if (!codePointPattern.test(codePoint)) {
4482
+ this.parseError("Illegal escape sequence: \\u" + codePoint);
4483
+ }
4484
+ buffer += String.fromCharCode(parseInt(codePoint, 16));
4485
+ index2 += 4;
4486
+ break;
4487
+ default:
4488
+ throw this.parseError('Illegal escape sequence: "\\' + c + '"');
4489
+ }
4490
+ ++index2;
4491
+ var backslash = v.indexOf("\\", index2);
4492
+ buffer += v.substring(index2, backslash < 0 ? v.length : backslash);
4493
+ index2 = backslash;
4494
+ }
4495
+ return buffer;
4496
+ };
4497
+ TokenStream.prototype.isComment = function() {
4498
+ var c = this.expression.charAt(this.pos);
4499
+ if (c === "/" && this.expression.charAt(this.pos + 1) === "*") {
4500
+ this.pos = this.expression.indexOf("*/", this.pos) + 2;
4501
+ if (this.pos === 1) {
4502
+ this.pos = this.expression.length;
4503
+ }
4504
+ return true;
4505
+ }
4506
+ return false;
4507
+ };
4508
+ TokenStream.prototype.isRadixInteger = function() {
4509
+ var pos = this.pos;
4510
+ if (pos >= this.expression.length - 2 || this.expression.charAt(pos) !== "0") {
4511
+ return false;
4512
+ }
4513
+ ++pos;
4514
+ var radix;
4515
+ var validDigit;
4516
+ if (this.expression.charAt(pos) === "x") {
4517
+ radix = 16;
4518
+ validDigit = /^[0-9a-f]$/i;
4519
+ ++pos;
4520
+ } else if (this.expression.charAt(pos) === "b") {
4521
+ radix = 2;
4522
+ validDigit = /^[01]$/i;
4523
+ ++pos;
4524
+ } else {
4525
+ return false;
4526
+ }
4527
+ var valid = false;
4528
+ var startPos = pos;
4529
+ while (pos < this.expression.length) {
4530
+ var c = this.expression.charAt(pos);
4531
+ if (validDigit.test(c)) {
4532
+ pos++;
4533
+ valid = true;
4534
+ } else {
4535
+ break;
4536
+ }
4537
+ }
4538
+ if (valid) {
4539
+ this.current = this.newToken(TNUMBER, parseInt(this.expression.substring(startPos, pos), radix));
4540
+ this.pos = pos;
4541
+ }
4542
+ return valid;
4543
+ };
4544
+ TokenStream.prototype.isNumber = function() {
4545
+ var valid = false;
4546
+ var pos = this.pos;
4547
+ var startPos = pos;
4548
+ var resetPos = pos;
4549
+ var foundDot = false;
4550
+ var foundDigits = false;
4551
+ var c;
4552
+ while (pos < this.expression.length) {
4553
+ c = this.expression.charAt(pos);
4554
+ if (c >= "0" && c <= "9" || !foundDot && c === ".") {
4555
+ if (c === ".") {
4556
+ foundDot = true;
4557
+ } else {
4558
+ foundDigits = true;
4559
+ }
4560
+ pos++;
4561
+ valid = foundDigits;
4562
+ } else {
4563
+ break;
4564
+ }
4565
+ }
4566
+ if (valid) {
4567
+ resetPos = pos;
4568
+ }
4569
+ if (c === "e" || c === "E") {
4570
+ pos++;
4571
+ var acceptSign = true;
4572
+ var validExponent = false;
4573
+ while (pos < this.expression.length) {
4574
+ c = this.expression.charAt(pos);
4575
+ if (acceptSign && (c === "+" || c === "-")) {
4576
+ acceptSign = false;
4577
+ } else if (c >= "0" && c <= "9") {
4578
+ validExponent = true;
4579
+ acceptSign = false;
4580
+ } else {
4581
+ break;
4582
+ }
4583
+ pos++;
4584
+ }
4585
+ if (!validExponent) {
4586
+ pos = resetPos;
4587
+ }
4588
+ }
4589
+ if (valid) {
4590
+ this.current = this.newToken(TNUMBER, parseFloat(this.expression.substring(startPos, pos)));
4591
+ this.pos = pos;
4592
+ } else {
4593
+ this.pos = resetPos;
4594
+ }
4595
+ return valid;
4596
+ };
4597
+ TokenStream.prototype.isOperator = function() {
4598
+ var startPos = this.pos;
4599
+ var c = this.expression.charAt(this.pos);
4600
+ if (c === "+" || c === "-" || c === "*" || c === "/" || c === "%" || c === "^" || c === "?" || c === ":" || c === ".") {
4601
+ this.current = this.newToken(TOP, c);
4602
+ } else if (c === "∙" || c === "•") {
4603
+ this.current = this.newToken(TOP, "*");
4604
+ } else if (c === ">") {
4605
+ if (this.expression.charAt(this.pos + 1) === "=") {
4606
+ this.current = this.newToken(TOP, ">=");
4607
+ this.pos++;
4608
+ } else {
4609
+ this.current = this.newToken(TOP, ">");
4610
+ }
4611
+ } else if (c === "<") {
4612
+ if (this.expression.charAt(this.pos + 1) === "=") {
4613
+ this.current = this.newToken(TOP, "<=");
4614
+ this.pos++;
4615
+ } else {
4616
+ this.current = this.newToken(TOP, "<");
4617
+ }
4618
+ } else if (c === "|") {
4619
+ if (this.expression.charAt(this.pos + 1) === "|") {
4620
+ this.current = this.newToken(TOP, "||");
4621
+ this.pos++;
4622
+ } else {
4623
+ return false;
4624
+ }
4625
+ } else if (c === "=") {
4626
+ if (this.expression.charAt(this.pos + 1) === "=") {
4627
+ this.current = this.newToken(TOP, "==");
4628
+ this.pos++;
4629
+ } else {
4630
+ this.current = this.newToken(TOP, c);
4631
+ }
4632
+ } else if (c === "!") {
4633
+ if (this.expression.charAt(this.pos + 1) === "=") {
4634
+ this.current = this.newToken(TOP, "!=");
4635
+ this.pos++;
4636
+ } else {
4637
+ this.current = this.newToken(TOP, c);
4638
+ }
4639
+ } else {
4640
+ return false;
4641
+ }
4642
+ this.pos++;
4643
+ if (this.isOperatorEnabled(this.current.value)) {
4644
+ return true;
4645
+ } else {
4646
+ this.pos = startPos;
4647
+ return false;
4648
+ }
4649
+ };
4650
+ TokenStream.prototype.isOperatorEnabled = function(op) {
4651
+ return this.parser.isOperatorEnabled(op);
4652
+ };
4653
+ TokenStream.prototype.getCoordinates = function() {
4654
+ var line = 0;
4655
+ var column;
4656
+ var newline = -1;
4657
+ do {
4658
+ line++;
4659
+ column = this.pos - newline;
4660
+ newline = this.expression.indexOf("\n", newline + 1);
4661
+ } while (newline >= 0 && newline < this.pos);
4662
+ return {
4663
+ line,
4664
+ column
4665
+ };
4666
+ };
4667
+ TokenStream.prototype.parseError = function(msg) {
4668
+ var coords = this.getCoordinates();
4669
+ throw new Error("parse error [" + coords.line + ":" + coords.column + "]: " + msg);
4670
+ };
4671
+ function ParserState(parser, tokenStream, options) {
4672
+ this.parser = parser;
4673
+ this.tokens = tokenStream;
4674
+ this.current = null;
4675
+ this.nextToken = null;
4676
+ this.next();
4677
+ this.savedCurrent = null;
4678
+ this.savedNextToken = null;
4679
+ this.allowMemberAccess = options.allowMemberAccess !== false;
4680
+ }
4681
+ ParserState.prototype.next = function() {
4682
+ this.current = this.nextToken;
4683
+ return this.nextToken = this.tokens.next();
4684
+ };
4685
+ ParserState.prototype.tokenMatches = function(token, value) {
4686
+ if (typeof value === "undefined") {
4687
+ return true;
4688
+ } else if (Array.isArray(value)) {
4689
+ return contains(value, token.value);
4690
+ } else if (typeof value === "function") {
4691
+ return value(token);
4692
+ } else {
4693
+ return token.value === value;
4694
+ }
4695
+ };
4696
+ ParserState.prototype.save = function() {
4697
+ this.savedCurrent = this.current;
4698
+ this.savedNextToken = this.nextToken;
4699
+ this.tokens.save();
4700
+ };
4701
+ ParserState.prototype.restore = function() {
4702
+ this.tokens.restore();
4703
+ this.current = this.savedCurrent;
4704
+ this.nextToken = this.savedNextToken;
4705
+ };
4706
+ ParserState.prototype.accept = function(type, value) {
4707
+ if (this.nextToken.type === type && this.tokenMatches(this.nextToken, value)) {
4708
+ this.next();
4709
+ return true;
4710
+ }
4711
+ return false;
4712
+ };
4713
+ ParserState.prototype.expect = function(type, value) {
4714
+ if (!this.accept(type, value)) {
4715
+ var coords = this.tokens.getCoordinates();
4716
+ throw new Error("parse error [" + coords.line + ":" + coords.column + "]: Expected " + (value || type));
4717
+ }
4718
+ };
4719
+ ParserState.prototype.parseAtom = function(instr) {
4720
+ var unaryOps = this.tokens.unaryOps;
4721
+ function isPrefixOperator(token) {
4722
+ return token.value in unaryOps;
4723
+ }
4724
+ if (this.accept(TNAME) || this.accept(TOP, isPrefixOperator)) {
4725
+ instr.push(new Instruction(IVAR, this.current.value));
4726
+ } else if (this.accept(TNUMBER)) {
4727
+ instr.push(new Instruction(INUMBER, this.current.value));
4728
+ } else if (this.accept(TSTRING)) {
4729
+ instr.push(new Instruction(INUMBER, this.current.value));
4730
+ } else if (this.accept(TPAREN, "(")) {
4731
+ this.parseExpression(instr);
4732
+ this.expect(TPAREN, ")");
4733
+ } else if (this.accept(TBRACKET, "[")) {
4734
+ if (this.accept(TBRACKET, "]")) {
4735
+ instr.push(new Instruction(IARRAY, 0));
4736
+ } else {
4737
+ var argCount = this.parseArrayList(instr);
4738
+ instr.push(new Instruction(IARRAY, argCount));
4739
+ }
4740
+ } else {
4741
+ throw new Error("unexpected " + this.nextToken);
4742
+ }
4743
+ };
4744
+ ParserState.prototype.parseExpression = function(instr) {
4745
+ var exprInstr = [];
4746
+ if (this.parseUntilEndStatement(instr, exprInstr)) {
4747
+ return;
4748
+ }
4749
+ this.parseVariableAssignmentExpression(exprInstr);
4750
+ if (this.parseUntilEndStatement(instr, exprInstr)) {
4751
+ return;
4752
+ }
4753
+ this.pushExpression(instr, exprInstr);
4754
+ };
4755
+ ParserState.prototype.pushExpression = function(instr, exprInstr) {
4756
+ for (var i = 0, len2 = exprInstr.length; i < len2; i++) {
4757
+ instr.push(exprInstr[i]);
4758
+ }
4759
+ };
4760
+ ParserState.prototype.parseUntilEndStatement = function(instr, exprInstr) {
4761
+ if (!this.accept(TSEMICOLON)) return false;
4762
+ if (this.nextToken && this.nextToken.type !== TEOF && !(this.nextToken.type === TPAREN && this.nextToken.value === ")")) {
4763
+ exprInstr.push(new Instruction(IENDSTATEMENT));
4764
+ }
4765
+ if (this.nextToken.type !== TEOF) {
4766
+ this.parseExpression(exprInstr);
4767
+ }
4768
+ instr.push(new Instruction(IEXPR, exprInstr));
4769
+ return true;
4770
+ };
4771
+ ParserState.prototype.parseArrayList = function(instr) {
4772
+ var argCount = 0;
4773
+ while (!this.accept(TBRACKET, "]")) {
4774
+ this.parseExpression(instr);
4775
+ ++argCount;
4776
+ while (this.accept(TCOMMA)) {
4777
+ this.parseExpression(instr);
4778
+ ++argCount;
4779
+ }
4780
+ }
4781
+ return argCount;
4782
+ };
4783
+ ParserState.prototype.parseVariableAssignmentExpression = function(instr) {
4784
+ this.parseConditionalExpression(instr);
4785
+ while (this.accept(TOP, "=")) {
4786
+ var varName = instr.pop();
4787
+ var varValue = [];
4788
+ var lastInstrIndex = instr.length - 1;
4789
+ if (varName.type === IFUNCALL) {
4790
+ if (!this.tokens.isOperatorEnabled("()=")) {
4791
+ throw new Error("function definition is not permitted");
4792
+ }
4793
+ for (var i = 0, len2 = varName.value + 1; i < len2; i++) {
4794
+ var index2 = lastInstrIndex - i;
4795
+ if (instr[index2].type === IVAR) {
4796
+ instr[index2] = new Instruction(IVARNAME, instr[index2].value);
4797
+ }
4798
+ }
4799
+ this.parseVariableAssignmentExpression(varValue);
4800
+ instr.push(new Instruction(IEXPR, varValue));
4801
+ instr.push(new Instruction(IFUNDEF, varName.value));
4802
+ continue;
4803
+ }
4804
+ if (varName.type !== IVAR && varName.type !== IMEMBER) {
4805
+ throw new Error("expected variable for assignment");
4806
+ }
4807
+ this.parseVariableAssignmentExpression(varValue);
4808
+ instr.push(new Instruction(IVARNAME, varName.value));
4809
+ instr.push(new Instruction(IEXPR, varValue));
4810
+ instr.push(binaryInstruction("="));
4811
+ }
4812
+ };
4813
+ ParserState.prototype.parseConditionalExpression = function(instr) {
4814
+ this.parseOrExpression(instr);
4815
+ while (this.accept(TOP, "?")) {
4816
+ var trueBranch = [];
4817
+ var falseBranch = [];
4818
+ this.parseConditionalExpression(trueBranch);
4819
+ this.expect(TOP, ":");
4820
+ this.parseConditionalExpression(falseBranch);
4821
+ instr.push(new Instruction(IEXPR, trueBranch));
4822
+ instr.push(new Instruction(IEXPR, falseBranch));
4823
+ instr.push(ternaryInstruction("?"));
4824
+ }
4825
+ };
4826
+ ParserState.prototype.parseOrExpression = function(instr) {
4827
+ this.parseAndExpression(instr);
4828
+ while (this.accept(TOP, "or")) {
4829
+ var falseBranch = [];
4830
+ this.parseAndExpression(falseBranch);
4831
+ instr.push(new Instruction(IEXPR, falseBranch));
4832
+ instr.push(binaryInstruction("or"));
4833
+ }
4834
+ };
4835
+ ParserState.prototype.parseAndExpression = function(instr) {
4836
+ this.parseComparison(instr);
4837
+ while (this.accept(TOP, "and")) {
4838
+ var trueBranch = [];
4839
+ this.parseComparison(trueBranch);
4840
+ instr.push(new Instruction(IEXPR, trueBranch));
4841
+ instr.push(binaryInstruction("and"));
4842
+ }
4843
+ };
4844
+ var COMPARISON_OPERATORS = ["==", "!=", "<", "<=", ">=", ">", "in"];
4845
+ ParserState.prototype.parseComparison = function(instr) {
4846
+ this.parseAddSub(instr);
4847
+ while (this.accept(TOP, COMPARISON_OPERATORS)) {
4848
+ var op = this.current;
4849
+ this.parseAddSub(instr);
4850
+ instr.push(binaryInstruction(op.value));
4851
+ }
4852
+ };
4853
+ var ADD_SUB_OPERATORS = ["+", "-", "||"];
4854
+ ParserState.prototype.parseAddSub = function(instr) {
4855
+ this.parseTerm(instr);
4856
+ while (this.accept(TOP, ADD_SUB_OPERATORS)) {
4857
+ var op = this.current;
4858
+ this.parseTerm(instr);
4859
+ instr.push(binaryInstruction(op.value));
4860
+ }
4861
+ };
4862
+ var TERM_OPERATORS = ["*", "/", "%"];
4863
+ ParserState.prototype.parseTerm = function(instr) {
4864
+ this.parseFactor(instr);
4865
+ while (this.accept(TOP, TERM_OPERATORS)) {
4866
+ var op = this.current;
4867
+ this.parseFactor(instr);
4868
+ instr.push(binaryInstruction(op.value));
4869
+ }
4870
+ };
4871
+ ParserState.prototype.parseFactor = function(instr) {
4872
+ var unaryOps = this.tokens.unaryOps;
4873
+ function isPrefixOperator(token) {
4874
+ return token.value in unaryOps;
4875
+ }
4876
+ this.save();
4877
+ if (this.accept(TOP, isPrefixOperator)) {
4878
+ if (this.current.value !== "-" && this.current.value !== "+") {
4879
+ if (this.nextToken.type === TPAREN && this.nextToken.value === "(") {
4880
+ this.restore();
4881
+ this.parseExponential(instr);
4882
+ return;
4883
+ } else if (this.nextToken.type === TSEMICOLON || this.nextToken.type === TCOMMA || this.nextToken.type === TEOF || this.nextToken.type === TPAREN && this.nextToken.value === ")") {
4884
+ this.restore();
4885
+ this.parseAtom(instr);
4886
+ return;
4887
+ }
4888
+ }
4889
+ var op = this.current;
4890
+ this.parseFactor(instr);
4891
+ instr.push(unaryInstruction(op.value));
4892
+ } else {
4893
+ this.parseExponential(instr);
4894
+ }
4895
+ };
4896
+ ParserState.prototype.parseExponential = function(instr) {
4897
+ this.parsePostfixExpression(instr);
4898
+ while (this.accept(TOP, "^")) {
4899
+ this.parseFactor(instr);
4900
+ instr.push(binaryInstruction("^"));
4901
+ }
4902
+ };
4903
+ ParserState.prototype.parsePostfixExpression = function(instr) {
4904
+ this.parseFunctionCall(instr);
4905
+ while (this.accept(TOP, "!")) {
4906
+ instr.push(unaryInstruction("!"));
4907
+ }
4908
+ };
4909
+ ParserState.prototype.parseFunctionCall = function(instr) {
4910
+ var unaryOps = this.tokens.unaryOps;
4911
+ function isPrefixOperator(token) {
4912
+ return token.value in unaryOps;
4913
+ }
4914
+ if (this.accept(TOP, isPrefixOperator)) {
4915
+ var op = this.current;
4916
+ this.parseAtom(instr);
4917
+ instr.push(unaryInstruction(op.value));
4918
+ } else {
4919
+ this.parseMemberExpression(instr);
4920
+ while (this.accept(TPAREN, "(")) {
4921
+ if (this.accept(TPAREN, ")")) {
4922
+ instr.push(new Instruction(IFUNCALL, 0));
4923
+ } else {
4924
+ var argCount = this.parseArgumentList(instr);
4925
+ instr.push(new Instruction(IFUNCALL, argCount));
4926
+ }
4927
+ }
4928
+ }
4929
+ };
4930
+ ParserState.prototype.parseArgumentList = function(instr) {
4931
+ var argCount = 0;
4932
+ while (!this.accept(TPAREN, ")")) {
4933
+ this.parseExpression(instr);
4934
+ ++argCount;
4935
+ while (this.accept(TCOMMA)) {
4936
+ this.parseExpression(instr);
4937
+ ++argCount;
4938
+ }
4939
+ }
4940
+ return argCount;
4941
+ };
4942
+ ParserState.prototype.parseMemberExpression = function(instr) {
4943
+ this.parseAtom(instr);
4944
+ while (this.accept(TOP, ".") || this.accept(TBRACKET, "[")) {
4945
+ var op = this.current;
4946
+ if (op.value === ".") {
4947
+ if (!this.allowMemberAccess) {
4948
+ throw new Error('unexpected ".", member access is not permitted');
4949
+ }
4950
+ this.expect(TNAME);
4951
+ instr.push(new Instruction(IMEMBER, this.current.value));
4952
+ } else if (op.value === "[") {
4953
+ if (!this.tokens.isOperatorEnabled("[")) {
4954
+ throw new Error('unexpected "[]", arrays are disabled');
4955
+ }
4956
+ this.parseExpression(instr);
4957
+ this.expect(TBRACKET, "]");
4958
+ instr.push(binaryInstruction("["));
4959
+ } else {
4960
+ throw new Error("unexpected symbol: " + op.value);
4961
+ }
4962
+ }
4963
+ };
4964
+ function add(a, b) {
4965
+ return Number(a) + Number(b);
4966
+ }
4967
+ function sub(a, b) {
4968
+ return a - b;
4969
+ }
4970
+ function mul(a, b) {
4971
+ return a * b;
4972
+ }
4973
+ function div(a, b) {
4974
+ return a / b;
4975
+ }
4976
+ function mod(a, b) {
4977
+ return a % b;
4978
+ }
4979
+ function concat(a, b) {
4980
+ if (Array.isArray(a) && Array.isArray(b)) {
4981
+ return a.concat(b);
4982
+ }
4983
+ return "" + a + b;
4984
+ }
4985
+ function equal(a, b) {
4986
+ return a === b;
4987
+ }
4988
+ function notEqual(a, b) {
4989
+ return a !== b;
4990
+ }
4991
+ function greaterThan(a, b) {
4992
+ return a > b;
4993
+ }
4994
+ function lessThan(a, b) {
4995
+ return a < b;
4996
+ }
4997
+ function greaterThanEqual(a, b) {
4998
+ return a >= b;
4999
+ }
5000
+ function lessThanEqual(a, b) {
5001
+ return a <= b;
5002
+ }
5003
+ function andOperator(a, b) {
5004
+ return Boolean(a && b);
5005
+ }
5006
+ function orOperator(a, b) {
5007
+ return Boolean(a || b);
5008
+ }
5009
+ function inOperator(a, b) {
5010
+ return contains(b, a);
5011
+ }
5012
+ function sinh(a) {
5013
+ return (Math.exp(a) - Math.exp(-a)) / 2;
5014
+ }
5015
+ function cosh(a) {
5016
+ return (Math.exp(a) + Math.exp(-a)) / 2;
5017
+ }
5018
+ function tanh(a) {
5019
+ if (a === Infinity) return 1;
5020
+ if (a === -Infinity) return -1;
5021
+ return (Math.exp(a) - Math.exp(-a)) / (Math.exp(a) + Math.exp(-a));
5022
+ }
5023
+ function asinh(a) {
5024
+ if (a === -Infinity) return a;
5025
+ return Math.log(a + Math.sqrt(a * a + 1));
5026
+ }
5027
+ function acosh(a) {
5028
+ return Math.log(a + Math.sqrt(a * a - 1));
5029
+ }
5030
+ function atanh(a) {
5031
+ return Math.log((1 + a) / (1 - a)) / 2;
5032
+ }
5033
+ function log10(a) {
5034
+ return Math.log(a) * Math.LOG10E;
5035
+ }
5036
+ function neg(a) {
5037
+ return -a;
5038
+ }
5039
+ function not(a) {
5040
+ return !a;
5041
+ }
5042
+ function trunc(a) {
5043
+ return a < 0 ? Math.ceil(a) : Math.floor(a);
5044
+ }
5045
+ function random(a) {
5046
+ return Math.random() * (a || 1);
5047
+ }
5048
+ function factorial(a) {
5049
+ return gamma(a + 1);
5050
+ }
5051
+ function isInteger(value) {
5052
+ return isFinite(value) && value === Math.round(value);
5053
+ }
5054
+ var GAMMA_G = 4.7421875;
5055
+ var GAMMA_P = [
5056
+ 0.9999999999999971,
5057
+ 57.15623566586292,
5058
+ -59.59796035547549,
5059
+ 14.136097974741746,
5060
+ -0.4919138160976202,
5061
+ 3399464998481189e-20,
5062
+ 4652362892704858e-20,
5063
+ -9837447530487956e-20,
5064
+ 1580887032249125e-19,
5065
+ -21026444172410488e-20,
5066
+ 21743961811521265e-20,
5067
+ -1643181065367639e-19,
5068
+ 8441822398385275e-20,
5069
+ -26190838401581408e-21,
5070
+ 36899182659531625e-22
5071
+ ];
5072
+ function gamma(n) {
5073
+ var t, x;
5074
+ if (isInteger(n)) {
5075
+ if (n <= 0) {
5076
+ return isFinite(n) ? Infinity : NaN;
5077
+ }
5078
+ if (n > 171) {
5079
+ return Infinity;
5080
+ }
5081
+ var value = n - 2;
5082
+ var res = n - 1;
5083
+ while (value > 1) {
5084
+ res *= value;
5085
+ value--;
5086
+ }
5087
+ if (res === 0) {
5088
+ res = 1;
5089
+ }
5090
+ return res;
5091
+ }
5092
+ if (n < 0.5) {
5093
+ return Math.PI / (Math.sin(Math.PI * n) * gamma(1 - n));
5094
+ }
5095
+ if (n >= 171.35) {
5096
+ return Infinity;
5097
+ }
5098
+ if (n > 85) {
5099
+ var twoN = n * n;
5100
+ var threeN = twoN * n;
5101
+ var fourN = threeN * n;
5102
+ var fiveN = fourN * n;
5103
+ return Math.sqrt(2 * Math.PI / n) * Math.pow(n / Math.E, n) * (1 + 1 / (12 * n) + 1 / (288 * twoN) - 139 / (51840 * threeN) - 571 / (2488320 * fourN) + 163879 / (209018880 * fiveN) + 5246819 / (75246796800 * fiveN * n));
5104
+ }
5105
+ --n;
5106
+ x = GAMMA_P[0];
5107
+ for (var i = 1; i < GAMMA_P.length; ++i) {
5108
+ x += GAMMA_P[i] / (n + i);
5109
+ }
5110
+ t = n + GAMMA_G + 0.5;
5111
+ return Math.sqrt(2 * Math.PI) * Math.pow(t, n + 0.5) * Math.exp(-t) * x;
5112
+ }
5113
+ function stringOrArrayLength(s) {
5114
+ if (Array.isArray(s)) {
5115
+ return s.length;
5116
+ }
5117
+ return String(s).length;
5118
+ }
5119
+ function hypot() {
5120
+ var sum2 = 0;
5121
+ var larg = 0;
5122
+ for (var i = 0; i < arguments.length; i++) {
5123
+ var arg = Math.abs(arguments[i]);
5124
+ var div2;
5125
+ if (larg < arg) {
5126
+ div2 = larg / arg;
5127
+ sum2 = sum2 * div2 * div2 + 1;
5128
+ larg = arg;
5129
+ } else if (arg > 0) {
5130
+ div2 = arg / larg;
5131
+ sum2 += div2 * div2;
5132
+ } else {
5133
+ sum2 += arg;
5134
+ }
5135
+ }
5136
+ return larg === Infinity ? Infinity : larg * Math.sqrt(sum2);
5137
+ }
5138
+ function condition(cond, yep, nope) {
5139
+ return cond ? yep : nope;
5140
+ }
5141
+ function roundTo(value, exp) {
5142
+ if (typeof exp === "undefined" || +exp === 0) {
5143
+ return Math.round(value);
5144
+ }
5145
+ value = +value;
5146
+ exp = -+exp;
5147
+ if (isNaN(value) || !(typeof exp === "number" && exp % 1 === 0)) {
5148
+ return NaN;
5149
+ }
5150
+ value = value.toString().split("e");
5151
+ value = Math.round(+(value[0] + "e" + (value[1] ? +value[1] - exp : -exp)));
5152
+ value = value.toString().split("e");
5153
+ return +(value[0] + "e" + (value[1] ? +value[1] + exp : exp));
5154
+ }
5155
+ function setVar(name, value, variables) {
5156
+ if (variables) variables[name] = value;
5157
+ return value;
5158
+ }
5159
+ function arrayIndex(array, index2) {
5160
+ return array[index2 | 0];
5161
+ }
5162
+ function max(array) {
5163
+ if (arguments.length === 1 && Array.isArray(array)) {
5164
+ return Math.max.apply(Math, array);
5165
+ } else {
5166
+ return Math.max.apply(Math, arguments);
5167
+ }
5168
+ }
5169
+ function min(array) {
5170
+ if (arguments.length === 1 && Array.isArray(array)) {
5171
+ return Math.min.apply(Math, array);
5172
+ } else {
5173
+ return Math.min.apply(Math, arguments);
5174
+ }
5175
+ }
5176
+ function arrayMap(f, a) {
5177
+ if (typeof f !== "function") {
5178
+ throw new Error("First argument to map is not a function");
5179
+ }
5180
+ if (!Array.isArray(a)) {
5181
+ throw new Error("Second argument to map is not an array");
5182
+ }
5183
+ return a.map(function(x, i) {
5184
+ return f(x, i);
5185
+ });
5186
+ }
5187
+ function arrayFold(f, init, a) {
5188
+ if (typeof f !== "function") {
5189
+ throw new Error("First argument to fold is not a function");
5190
+ }
5191
+ if (!Array.isArray(a)) {
5192
+ throw new Error("Second argument to fold is not an array");
5193
+ }
5194
+ return a.reduce(function(acc, x, i) {
5195
+ return f(acc, x, i);
5196
+ }, init);
5197
+ }
5198
+ function arrayFilter(f, a) {
5199
+ if (typeof f !== "function") {
5200
+ throw new Error("First argument to filter is not a function");
5201
+ }
5202
+ if (!Array.isArray(a)) {
5203
+ throw new Error("Second argument to filter is not an array");
5204
+ }
5205
+ return a.filter(function(x, i) {
5206
+ return f(x, i);
5207
+ });
5208
+ }
5209
+ function stringOrArrayIndexOf(target, s) {
5210
+ if (!(Array.isArray(s) || typeof s === "string")) {
5211
+ throw new Error("Second argument to indexOf is not a string or array");
5212
+ }
5213
+ return s.indexOf(target);
5214
+ }
5215
+ function arrayJoin(sep, a) {
5216
+ if (!Array.isArray(a)) {
5217
+ throw new Error("Second argument to join is not an array");
5218
+ }
5219
+ return a.join(sep);
5220
+ }
5221
+ function sign(x) {
5222
+ return (x > 0) - (x < 0) || +x;
5223
+ }
5224
+ var ONE_THIRD = 1 / 3;
5225
+ function cbrt(x) {
5226
+ return x < 0 ? -Math.pow(-x, ONE_THIRD) : Math.pow(x, ONE_THIRD);
5227
+ }
5228
+ function expm1(x) {
5229
+ return Math.exp(x) - 1;
5230
+ }
5231
+ function log1p(x) {
5232
+ return Math.log(1 + x);
5233
+ }
5234
+ function log2(x) {
5235
+ return Math.log(x) / Math.LN2;
5236
+ }
5237
+ function Parser(options) {
5238
+ this.options = options || {};
5239
+ this.unaryOps = {
5240
+ sin: Math.sin,
5241
+ cos: Math.cos,
5242
+ tan: Math.tan,
5243
+ asin: Math.asin,
5244
+ acos: Math.acos,
5245
+ atan: Math.atan,
5246
+ sinh: Math.sinh || sinh,
5247
+ cosh: Math.cosh || cosh,
5248
+ tanh: Math.tanh || tanh,
5249
+ asinh: Math.asinh || asinh,
5250
+ acosh: Math.acosh || acosh,
5251
+ atanh: Math.atanh || atanh,
5252
+ sqrt: Math.sqrt,
5253
+ cbrt: Math.cbrt || cbrt,
5254
+ log: Math.log,
5255
+ log2: Math.log2 || log2,
5256
+ ln: Math.log,
5257
+ lg: Math.log10 || log10,
5258
+ log10: Math.log10 || log10,
5259
+ expm1: Math.expm1 || expm1,
5260
+ log1p: Math.log1p || log1p,
5261
+ abs: Math.abs,
5262
+ ceil: Math.ceil,
5263
+ floor: Math.floor,
5264
+ round: Math.round,
5265
+ trunc: Math.trunc || trunc,
5266
+ "-": neg,
5267
+ "+": Number,
5268
+ exp: Math.exp,
5269
+ not,
5270
+ length: stringOrArrayLength,
5271
+ "!": factorial,
5272
+ sign: Math.sign || sign
5273
+ };
5274
+ this.binaryOps = {
5275
+ "+": add,
5276
+ "-": sub,
5277
+ "*": mul,
5278
+ "/": div,
5279
+ "%": mod,
5280
+ "^": Math.pow,
5281
+ "||": concat,
5282
+ "==": equal,
5283
+ "!=": notEqual,
5284
+ ">": greaterThan,
5285
+ "<": lessThan,
5286
+ ">=": greaterThanEqual,
5287
+ "<=": lessThanEqual,
5288
+ and: andOperator,
5289
+ or: orOperator,
5290
+ "in": inOperator,
5291
+ "=": setVar,
5292
+ "[": arrayIndex
5293
+ };
5294
+ this.ternaryOps = {
5295
+ "?": condition
5296
+ };
5297
+ this.functions = {
5298
+ random,
5299
+ fac: factorial,
5300
+ min,
5301
+ max,
5302
+ hypot: Math.hypot || hypot,
5303
+ pyt: Math.hypot || hypot,
5304
+ // backward compat
5305
+ pow: Math.pow,
5306
+ atan2: Math.atan2,
5307
+ "if": condition,
5308
+ gamma,
5309
+ roundTo,
5310
+ map: arrayMap,
5311
+ fold: arrayFold,
5312
+ filter: arrayFilter,
5313
+ indexOf: stringOrArrayIndexOf,
5314
+ join: arrayJoin
5315
+ };
5316
+ this.consts = {
5317
+ E: Math.E,
5318
+ PI: Math.PI,
5319
+ "true": true,
5320
+ "false": false
5321
+ };
5322
+ }
5323
+ Parser.prototype.parse = function(expr) {
5324
+ var instr = [];
5325
+ var parserState = new ParserState(
5326
+ this,
5327
+ new TokenStream(this, expr),
5328
+ { allowMemberAccess: this.options.allowMemberAccess }
5329
+ );
5330
+ parserState.parseExpression(instr);
5331
+ parserState.expect(TEOF, "EOF");
5332
+ return new Expression(instr, this);
5333
+ };
5334
+ Parser.prototype.evaluate = function(expr, variables) {
5335
+ return this.parse(expr).evaluate(variables);
5336
+ };
5337
+ var sharedParser = new Parser();
5338
+ Parser.parse = function(expr) {
5339
+ return sharedParser.parse(expr);
5340
+ };
5341
+ Parser.evaluate = function(expr, variables) {
5342
+ return sharedParser.parse(expr).evaluate(variables);
5343
+ };
5344
+ var optionNameMap = {
5345
+ "+": "add",
5346
+ "-": "subtract",
5347
+ "*": "multiply",
5348
+ "/": "divide",
5349
+ "%": "remainder",
5350
+ "^": "power",
5351
+ "!": "factorial",
5352
+ "<": "comparison",
5353
+ ">": "comparison",
5354
+ "<=": "comparison",
5355
+ ">=": "comparison",
5356
+ "==": "comparison",
5357
+ "!=": "comparison",
5358
+ "||": "concatenate",
5359
+ "and": "logical",
5360
+ "or": "logical",
5361
+ "not": "logical",
5362
+ "?": "conditional",
5363
+ ":": "conditional",
5364
+ "=": "assignment",
5365
+ "[": "array",
5366
+ "()=": "fndef"
5367
+ };
5368
+ function getOptionName(op) {
5369
+ return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op;
5370
+ }
5371
+ Parser.prototype.isOperatorEnabled = function(op) {
5372
+ var optionName = getOptionName(op);
5373
+ var operators2 = this.options.operators || {};
5374
+ return !(optionName in operators2) || !!operators2[optionName];
5375
+ };
5376
+ const calc = (expression, context) => {
5377
+ if (typeof expression !== "string") {
5378
+ return expression;
5379
+ }
5380
+ let processedExpression = expression;
5381
+ try {
5382
+ const pathResolver = (path) => {
5383
+ let currentPath = path;
5384
+ let value;
5385
+ let depth = 0;
5386
+ while (typeof currentPath === "string" && (currentPath.startsWith("/") || currentPath.startsWith("=/")) && depth < 5) {
5387
+ const normalizedPath = currentPath.startsWith("/") ? "=" + currentPath : currentPath;
5388
+ const resolved = resolvePath(normalizedPath, context);
5389
+ value = unwrapSignal(resolved);
5390
+ if (typeof value === "string" && (value.startsWith("/") || value.startsWith("=/")) && value !== currentPath) {
5391
+ currentPath = value;
5392
+ depth++;
5393
+ } else {
5394
+ break;
5395
+ }
5396
+ }
5397
+ if (typeof value === "number") return value;
5398
+ if (typeof value === "string") {
5399
+ const num = parseFloat(value);
5400
+ if (!isNaN(num) && isFinite(Number(value))) return num;
5401
+ return value === "" ? 0 : `"${value.replace(/"/g, '\\"')}"`;
5402
+ }
5403
+ return value === void 0 || value === null ? 0 : value;
5404
+ };
5405
+ const pathRegex = /\$\(\s*['"](.*?)['"]\s*\)/g;
5406
+ processedExpression = expression.replace(pathRegex, (match2, path) => {
5407
+ const val = pathResolver(path);
5408
+ return val;
5409
+ });
5410
+ const parser = new Parser();
5411
+ const parsed = parser.parse(processedExpression);
5412
+ return parsed.evaluate();
5413
+ } catch (error) {
5414
+ console.error("JPRX calc error:", error.message);
5415
+ console.error("Original expression:", expression);
5416
+ console.error("Processed expression:", processedExpression);
5417
+ return NaN;
5418
+ }
5419
+ };
5420
+ const registerCalcHelpers = (register) => {
5421
+ register("calc", calc, { pathAware: true });
5422
+ };
3723
5423
  registerMathHelpers(registerHelper);
3724
5424
  registerLogicHelpers(registerHelper);
3725
5425
  registerStringHelpers(registerHelper);
@@ -3732,6 +5432,7 @@
3732
5432
  registerStatsHelpers(registerHelper);
3733
5433
  registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
3734
5434
  registerNetworkHelpers(registerHelper);
5435
+ registerCalcHelpers(registerHelper);
3735
5436
  registerHelper("move", (selector, location = "beforeend") => {
3736
5437
  return {
3737
5438
  isLazy: true,
@@ -3865,8 +5566,8 @@
3865
5566
  const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
3866
5567
  const target = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
3867
5568
  const context = getContext(target, isEvent ? eventOrNode : null);
3868
- const result = resolveExpression(expr, context);
3869
- if (result && typeof result === "object" && result.isLazy) return result.resolve(eventOrNode);
5569
+ const result = resolveExpression$1(expr, context);
5570
+ if (result && typeof result === "object" && result.isLazy) return result.resolve(context);
3870
5571
  return result;
3871
5572
  };
3872
5573
  const hydrate = (node, parent = null) => {
@@ -3952,7 +5653,7 @@
3952
5653
  parseExpression,
3953
5654
  resolvePath,
3954
5655
  resolvePathAsContext,
3955
- resolveExpression,
5656
+ resolveExpression: resolveExpression$1,
3956
5657
  parseCDOMC,
3957
5658
  parseJPRX,
3958
5659
  unwrapSignal,