691 lines
26 KiB
JavaScript
691 lines
26 KiB
JavaScript
/**
|
|
* @license
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2015 Matthew Crumley
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
! function (t, e) {
|
|
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : t.exprEval = e()
|
|
}(this, function () {
|
|
"use strict";
|
|
|
|
function t(t, e) {
|
|
this.type = t, this.value = void 0 !== e && null !== e ? e : 0
|
|
}
|
|
|
|
function e(e) {
|
|
return new t(Q, e)
|
|
}
|
|
|
|
function s(e) {
|
|
return new t(Y, e)
|
|
}
|
|
|
|
function r(e) {
|
|
return new t(Z, e)
|
|
}
|
|
|
|
function n(e, s, r, i, o) {
|
|
for (var a, h, p, u, c = [], l = [], f = 0; f < e.length; f++) {
|
|
var v = e[f], x = v.type;
|
|
if (x === K) c.push(v); else if (x === tt && o.hasOwnProperty(v.value)) v = new t(K, o[v.value]), c.push(v); else if (x === Y && c.length > 1) h = c.pop(), a = c.pop(), u = r[v.value], v = new t(K, u(a.value, h.value)), c.push(v); else if (x === Z && c.length > 2) p = c.pop(), h = c.pop(), a = c.pop(), "?" === v.value ? c.push(a.value ? h.value : p.value) : (u = i[v.value], v = new t(K, u(a.value, h.value, p.value)), c.push(v)); else if (x === Q && c.length > 0) a = c.pop(), u = s[v.value], v = new t(K, u(a.value)), c.push(v); else if (x === st) {
|
|
for (; c.length > 0;) l.push(c.shift());
|
|
l.push(new t(st, n(v.value, s, r, i, o)))
|
|
} else if (x === rt && c.length > 0) a = c.pop(), c.push(new t(K, a.value[v.value])); else {
|
|
for (; c.length > 0;) l.push(c.shift());
|
|
l.push(v)
|
|
}
|
|
}
|
|
for (; c.length > 0;) l.push(c.shift());
|
|
return l
|
|
}
|
|
|
|
function i(n, o, a) {
|
|
for (var h = [], p = 0; p < n.length; p++) {
|
|
var u = n[p], c = u.type;
|
|
if (c === tt && u.value === o) for (var l = 0; l < a.tokens.length; l++) {
|
|
var f, v = a.tokens[l];
|
|
f = v.type === Q ? e(v.value) : v.type === Y ? s(v.value) : v.type === Z ? r(v.value) : new t(v.type, v.value), h.push(f)
|
|
} else c === st ? h.push(new t(st, i(u.value, o, a))) : h.push(u)
|
|
}
|
|
return h
|
|
}
|
|
|
|
function o(t, e, s) {
|
|
for (var r, n, i, a, h = [], p = 0; p < t.length; p++) {
|
|
var u = t[p], c = u.type;
|
|
if (c === K) h.push(u.value); else if (c === Y) n = h.pop(), r = h.pop(), a = e.binaryOps[u.value], h.push(a(r, n)); else if (c === Z) i = h.pop(), n = h.pop(), r = h.pop(), "?" === u.value ? h.push(o(r ? n : i, e, s)) : (a = e.ternaryOps[u.value], h.push(a(r, n, i))); else if (c === tt) if (u.value in e.functions) h.push(e.functions[u.value]); else {
|
|
var l = s[u.value];
|
|
if (void 0 === l) throw new Error("undefined variable: " + u.value);
|
|
h.push(l)
|
|
} else if (c === Q) r = h.pop(), a = e.unaryOps[u.value], h.push(a(r)); else if (c === et) {
|
|
for (var f = u.value, v = []; f-- > 0;) v.unshift(h.pop());
|
|
if ( ! (a = h.pop()).apply || ! a.call) throw new Error(a + " is not a function");
|
|
h.push(a.apply(void 0, v))
|
|
} else if (c === st) h.push(u.value); else {
|
|
if (c !== rt) throw new Error("invalid Expression");
|
|
r = h.pop(), h.push(r[u.value])
|
|
}
|
|
}
|
|
if (h.length > 1) throw new Error("invalid Expression (parity)");
|
|
return h[0]
|
|
}
|
|
|
|
function a(t, e) {
|
|
for (var s, r, n, i, o = [], p = 0; p < t.length; p++) {
|
|
var u = t[p], c = u.type;
|
|
if (c === K) "number" == typeof u.value && u.value < 0 ? o.push("(" + u.value + ")") : o.push(h(u.value)); else if (c === Y) r = o.pop(), s = o.pop(), i = u.value, e ? "^" === i ? o.push("Math.pow(" + s + ", " + r + ")") : "and" === i ? o.push("(!!" + s + " && !!" + r + ")") : "or" === i ? o.push("(!!" + s + " || !!" + r + ")") : "||" === i ? o.push("(String(" + s + ") + String(" + r + "))") : "==" === i ? o.push("(" + s + " === " + r + ")") : "!=" === i ? o.push("(" + s + " !== " + r + ")") : o.push("(" + s + " " + i + " " + r + ")") : o.push("(" + s + " " + i + " " + r + ")"); else if (c === Z) {
|
|
if (n = o.pop(), r = o.pop(), s = o.pop(), "?" !== (i = u.value)) throw new Error("invalid Expression");
|
|
o.push("(" + s + " ? " + r + " : " + n + ")")
|
|
} else if (c === tt) o.push(u.value); else if (c === Q) s = o.pop(), "-" === (i = u.value) || "+" === i ? o.push("(" + i + s + ")") : e ? "not" === i ? o.push("(!" + s + ")") : "!" === i ? o.push("fac(" + s + ")") : o.push(i + "(" + s + ")") : "!" === i ? o.push("(" + s + "!)") : o.push("(" + i + " " + s + ")"); else if (c === et) {
|
|
for (var l = u.value, f = []; l-- > 0;) f.unshift(o.pop());
|
|
i = o.pop(), o.push(i + "(" + f.join(", ") + ")")
|
|
} else if (c === rt) s = o.pop(), o.push(s + "." + u.value); else {
|
|
if (c !== st) throw new Error("invalid Expression");
|
|
o.push("(" + a(u.value, e) + ")")
|
|
}
|
|
}
|
|
if (o.length > 1) throw new Error("invalid Expression (parity)");
|
|
return String(o[0])
|
|
}
|
|
|
|
function h(t) {
|
|
return "string" == typeof t ? JSON.stringify(t).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029") : t
|
|
}
|
|
|
|
function p(t, e) {
|
|
for (var s = 0; s < t.length; s++) if (t[s] === e) return ! 0;
|
|
return ! 1
|
|
}
|
|
|
|
function u(t, e, s) {
|
|
for (var r = !! (s = s || {}).withMembers, n = null, i = 0; i < t.length; i++) {
|
|
var o = t[i];
|
|
o.type !== tt || p(e, o.value) ? o.type === rt && r && null !== n ? n += "." + o.value : o.type === st ? u(o.value, e, s) : null !== n && (p(e, n) || e.push(n), n = null) : r ? null !== n ? (p(e, n) || e.push(n), n = o.value) : n = o.value : e.push(o.value)
|
|
}
|
|
null === n || p(e, n) || e.push(n)
|
|
}
|
|
|
|
function c(t, e) {
|
|
this.tokens = t, this.parser = e, this.unaryOps = e.unaryOps, this.binaryOps = e.binaryOps, this.ternaryOps = e.ternaryOps, this.functions = e.functions
|
|
}
|
|
|
|
function l(t, e, s) {
|
|
this.type = t, this.value = e, this.index = s
|
|
}
|
|
|
|
function f(t, e) {
|
|
this.pos = 0, this.current = null, this.unaryOps = t.unaryOps, this.binaryOps = t.binaryOps, this.ternaryOps = t.ternaryOps, this.consts = t.consts, this.expression = e, this.savedPosition = 0, this.savedCurrent = null, this.options = t.options
|
|
}
|
|
|
|
function v(t) {
|
|
return ot.hasOwnProperty(t) ? ot[t] : t
|
|
}
|
|
|
|
function x(t, e, s) {
|
|
this.parser = t, this.tokens = e, this.current = null, this.nextToken = null, this.next(), this.savedCurrent = null, this.savedNextToken = null, this.allowMemberAccess = ! 1 !== s.allowMemberAccess
|
|
}
|
|
|
|
function y(t, e) {
|
|
return Number(t) + Number(e)
|
|
}
|
|
|
|
function w(t, e) {
|
|
return t - e
|
|
}
|
|
|
|
function d(t, e) {
|
|
return t * e
|
|
}
|
|
|
|
function M(t, e) {
|
|
return t / e
|
|
}
|
|
|
|
function g(t, e) {
|
|
return t % e
|
|
}
|
|
|
|
function E(t, e) {
|
|
return "" + t + e
|
|
}
|
|
|
|
function k(t, e) {
|
|
return t === e
|
|
}
|
|
|
|
function b(t, e) {
|
|
return t !== e
|
|
}
|
|
|
|
function m(t, e) {
|
|
return t > e
|
|
}
|
|
|
|
function T(t, e) {
|
|
return t < e
|
|
}
|
|
|
|
function A(t, e) {
|
|
return t >= e
|
|
}
|
|
|
|
function O(t, e) {
|
|
return t <= e
|
|
}
|
|
|
|
function N(t, e) {
|
|
return Boolean(t && e)
|
|
}
|
|
|
|
function C(t, e) {
|
|
return Boolean(t || e)
|
|
}
|
|
|
|
function P(t, e) {
|
|
return p(e, t)
|
|
}
|
|
|
|
function I(t) {
|
|
return (Math.exp(t) - Math.exp(-t)) / 2
|
|
}
|
|
|
|
function S(t) {
|
|
return (Math.exp(t) + Math.exp(-t)) / 2
|
|
}
|
|
|
|
function R(t) {
|
|
return t === 1 / 0 ? 1 : t === -1 / 0 ? -1 : (Math.exp(t) - Math.exp(-t)) / (Math.exp(t) + Math.exp(-t))
|
|
}
|
|
|
|
function F(t) {
|
|
return t === -1 / 0 ? t : Math.log(t + Math.sqrt(t * t + 1))
|
|
}
|
|
|
|
function L(t) {
|
|
return Math.log(t + Math.sqrt(t * t - 1))
|
|
}
|
|
|
|
function U(t) {
|
|
return Math.log((1 + t) / (1 - t)) / 2
|
|
}
|
|
|
|
function q(t) {
|
|
return Math.log(t) * Math.LOG10E
|
|
}
|
|
|
|
function B(t) {
|
|
return -t
|
|
}
|
|
|
|
function $(t) {
|
|
return ! t
|
|
}
|
|
|
|
function G(t) {
|
|
return t < 0 ? Math.ceil(t) : Math.floor(t)
|
|
}
|
|
|
|
function _(t) {
|
|
return Math.random() * (t || 1)
|
|
}
|
|
|
|
function j(t) {
|
|
return W(t + 1)
|
|
}
|
|
|
|
function J(t) {
|
|
return isFinite(t) && t === Math.round(t)
|
|
}
|
|
|
|
function W(t) {
|
|
var e, s;
|
|
if (J(t)) {
|
|
if (t <= 0) return isFinite(t) ? 1 / 0 : NaN;
|
|
if (t > 171) return 1 / 0;
|
|
for (var r = t - 2, n = t - 1; r > 1;) n *= r, r--;
|
|
return 0 === n && (n = 1), n
|
|
}
|
|
if (t < .5) return Math.PI / (Math.sin(Math.PI * t) * W(1 - t));
|
|
if (t >= 171.35) return 1 / 0;
|
|
if (t > 85) {
|
|
var i = t * t, o = i * t, a = o * t, h = a * t;
|
|
return Math.sqrt(2 * Math.PI / t) * Math.pow(t / Math.E, t) * (1 + 1 / (12 * t) + 1 / (288 * i) - 139 / (51840 * o) - 571 / (2488320 * a) + 163879 / (209018880 * h) + 5246819 / (75246796800 * h * t))
|
|
}
|
|
--t, s = ct[0];
|
|
for (var p = 1; p < ct.length; ++p) s += ct[p] / (t + p);
|
|
return e = t + ut + .5, Math.sqrt(2 * Math.PI) * Math.pow(e, t + .5) * Math.exp(-e) * s
|
|
}
|
|
|
|
function V(t) {
|
|
return String(t).length
|
|
}
|
|
|
|
function X() {
|
|
for (var t = 0, e = 0, s = 0; s < arguments.length; s++) {
|
|
var r, n = Math.abs(arguments[s]);
|
|
e < n ? (t = t * (r = e / n) * r + 1, e = n) : t += n > 0 ? (r = n / e) * r : n
|
|
}
|
|
return e === 1 / 0 ? 1 / 0 : e * Math.sqrt(t)
|
|
}
|
|
|
|
function z(t, e, s) {
|
|
return t ? e : s
|
|
}
|
|
|
|
function D(t, e) {
|
|
return void 0 === e || 0 == +e ? Math.round(t) : (t = +t, e = -+e, isNaN(t) || "number" != typeof e || e % 1 != 0 ? NaN : (t = t.toString().split("e"), t = Math.round(+(t[0] + "e" + (t[1] ? +t[1] - e : -e))), +((t = t.toString().split("e"))[0] + "e" + (t[1] ? +t[1] + e : e))))
|
|
}
|
|
|
|
function H(t) {
|
|
this.options = t || {}, this.unaryOps = {
|
|
sin: Math.sin,
|
|
cos: Math.cos,
|
|
tan: Math.tan,
|
|
asin: Math.asin,
|
|
acos: Math.acos,
|
|
atan: Math.atan,
|
|
sinh: Math.sinh || I,
|
|
cosh: Math.cosh || S,
|
|
tanh: Math.tanh || R,
|
|
asinh: Math.asinh || F,
|
|
acosh: Math.acosh || L,
|
|
atanh: Math.atanh || U,
|
|
sqrt: Math.sqrt,
|
|
log: Math.log,
|
|
ln: Math.log,
|
|
lg: Math.log10 || q,
|
|
log10: Math.log10 || q,
|
|
abs: Math.abs,
|
|
ceil: Math.ceil,
|
|
floor: Math.floor,
|
|
round: Math.round,
|
|
trunc: Math.trunc || G,
|
|
"-": B,
|
|
"+": Number,
|
|
exp: Math.exp,
|
|
not: $,
|
|
length: V,
|
|
"!": j
|
|
}, this.binaryOps = {
|
|
"+": y,
|
|
"-": w,
|
|
"*": d,
|
|
"/": M,
|
|
"%": g,
|
|
"^": Math.pow,
|
|
"||": E,
|
|
"==": k,
|
|
"!=": b,
|
|
">": m,
|
|
"<": T,
|
|
">=": A,
|
|
"<=": O,
|
|
and: N,
|
|
or: C,
|
|
in: P
|
|
}, this.ternaryOps = {"?": z}, this.functions = {
|
|
random: _,
|
|
fac: j,
|
|
min: Math.min,
|
|
max: Math.max,
|
|
hypot: Math.hypot || X,
|
|
pyt: Math.hypot || X,
|
|
pow: Math.pow,
|
|
atan2: Math.atan2,
|
|
if: z,
|
|
gamma: W,
|
|
roundTo: D
|
|
}, this.consts = {E: Math.E, PI: Math.PI, true: ! 0, false: ! 1}
|
|
}
|
|
|
|
var K = "INUMBER", Q = "IOP1", Y = "IOP2", Z = "IOP3", tt = "IVAR", et = "IFUNCALL", st = "IEXPR", rt = "IMEMBER";
|
|
t.prototype.toString = function () {
|
|
switch (this.type) {
|
|
case K:
|
|
case Q:
|
|
case Y:
|
|
case Z:
|
|
case tt:
|
|
return this.value;
|
|
case et:
|
|
return "CALL " + this.value;
|
|
case rt:
|
|
return "." + this.value;
|
|
default:
|
|
return "Invalid Instruction"
|
|
}
|
|
}, c.prototype.simplify = function (t) {
|
|
return t = t || {}, new c(n(this.tokens, this.unaryOps, this.binaryOps, this.ternaryOps, t), this.parser)
|
|
}, c.prototype.substitute = function (t, e) {
|
|
return e instanceof c || (e = this.parser.parse(String(e))), new c(i(this.tokens, t, e), this.parser)
|
|
}, c.prototype.evaluate = function (t) {
|
|
return t = t || {}, o(this.tokens, this, t)
|
|
}, c.prototype.toString = function () {
|
|
return a(this.tokens, ! 1)
|
|
}, c.prototype.symbols = function (t) {
|
|
t = t || {};
|
|
var e = [];
|
|
return u(this.tokens, e, t), e
|
|
}, c.prototype.variables = function (t) {
|
|
t = t || {};
|
|
var e = [];
|
|
u(this.tokens, e, t);
|
|
var s = this.functions;
|
|
return e.filter(function (t) {
|
|
return ! (t in s)
|
|
})
|
|
}, c.prototype.toJSFunction = function (t, e) {
|
|
var s = this,
|
|
r = new Function(t, "with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return " + a(this.simplify(e).tokens, ! 0) + "; }");
|
|
return function () {
|
|
return r.apply(s, arguments)
|
|
}
|
|
};
|
|
var nt = "TOP";
|
|
l.prototype.toString = function () {
|
|
return this.type + ": " + this.value
|
|
}, f.prototype.newToken = function (t, e, s) {
|
|
return new l(t, e, null != s ? s : this.pos)
|
|
}, f.prototype.save = function () {
|
|
this.savedPosition = this.pos, this.savedCurrent = this.current
|
|
}, f.prototype.restore = function () {
|
|
this.pos = this.savedPosition, this.current = this.savedCurrent
|
|
}, f.prototype.next = function () {
|
|
return this.pos >= this.expression.length ? this.newToken("TEOF", "EOF") : this.isWhitespace() || this.isComment() ? this.next() : this.isRadixInteger() || this.isNumber() || this.isOperator() || this.isString() || this.isParen() || this.isComma() || this.isNamedOp() || this.isConst() || this.isName() ? this.current : void this.parseError('Unknown character "' + this.expression.charAt(this.pos) + '"')
|
|
}, f.prototype.isString = function () {
|
|
var t = ! 1, e = this.pos, s = this.expression.charAt(e);
|
|
if ("'" === s || '"' === s) for (var r = this.expression.indexOf(s, e + 1); r >= 0 && this.pos < this.expression.length;) {
|
|
if (this.pos = r + 1, "\\" !== this.expression.charAt(r - 1)) {
|
|
var n = this.expression.substring(e + 1, r);
|
|
this.current = this.newToken("TSTRING", this.unescape(n), e), t = ! 0;
|
|
break
|
|
}
|
|
r = this.expression.indexOf(s, r + 1)
|
|
}
|
|
return t
|
|
}, f.prototype.isParen = function () {
|
|
var t = this.expression.charAt(this.pos);
|
|
return ("(" === t || ")" === t) && (this.current = this.newToken("TPAREN", t), this.pos++, ! 0)
|
|
}, f.prototype.isComma = function () {
|
|
return "," === this.expression.charAt(this.pos) && (this.current = this.newToken("TCOMMA", ","), this.pos++, ! 0)
|
|
}, f.prototype.isConst = function () {
|
|
for (var t = this.pos, e = t; e < this.expression.length; e++) {
|
|
var s = this.expression.charAt(e);
|
|
if (s.toUpperCase() === s.toLowerCase() && (e === this.pos || "_" !== s && "." !== s && (s < "0" || s > "9"))) break
|
|
}
|
|
if (e > t) {
|
|
var r = this.expression.substring(t, e);
|
|
if (r in this.consts) return this.current = this.newToken("TNUMBER", this.consts[r]), this.pos += r.length, ! 0
|
|
}
|
|
return ! 1
|
|
}, f.prototype.isNamedOp = function () {
|
|
for (var t = this.pos, e = t; e < this.expression.length; e++) {
|
|
var s = this.expression.charAt(e);
|
|
if (s.toUpperCase() === s.toLowerCase() && (e === this.pos || "_" !== s && (s < "0" || s > "9"))) break
|
|
}
|
|
if (e > t) {
|
|
var r = this.expression.substring(t, e);
|
|
if (this.isOperatorEnabled(r) && (r in this.binaryOps || r in this.unaryOps || r in this.ternaryOps)) return this.current = this.newToken(nt, r), this.pos += r.length, ! 0
|
|
}
|
|
return ! 1
|
|
}, f.prototype.isName = function () {
|
|
for (var t = this.pos, e = t, s = ! 1; e < this.expression.length; e++) {
|
|
var r = this.expression.charAt(e);
|
|
if (r.toUpperCase() === r.toLowerCase()) {
|
|
if (e === this.pos && "$" === r) continue;
|
|
if (e === this.pos || ! s || "_" !== r && (r < "0" || r > "9")) break
|
|
} else s = ! 0
|
|
}
|
|
if (s) {
|
|
var n = this.expression.substring(t, e);
|
|
return this.current = this.newToken("TNAME", n), this.pos += n.length, ! 0
|
|
}
|
|
return ! 1
|
|
}, f.prototype.isWhitespace = function () {
|
|
for (var t = ! 1, e = this.expression.charAt(this.pos); ! (" " !== e && "\t" !== e && "\n" !== e && "\r" !== e || (t = ! 0, ++this.pos >= this.expression.length));) e = this.expression.charAt(this.pos);
|
|
return t
|
|
};
|
|
var it = /^[0-9a-f]{4}$/i;
|
|
f.prototype.unescape = function (t) {
|
|
var e = t.indexOf("\\");
|
|
if (e < 0) return t;
|
|
for (var s = t.substring(0, e); e >= 0;) {
|
|
var r = t.charAt(++e);
|
|
switch (r) {
|
|
case"'":
|
|
s += "'";
|
|
break;
|
|
case'"':
|
|
s += '"';
|
|
break;
|
|
case"\\":
|
|
s += "\\";
|
|
break;
|
|
case"/":
|
|
s += "/";
|
|
break;
|
|
case"b":
|
|
s += "\b";
|
|
break;
|
|
case"f":
|
|
s += "\f";
|
|
break;
|
|
case"n":
|
|
s += "\n";
|
|
break;
|
|
case"r":
|
|
s += "\r";
|
|
break;
|
|
case"t":
|
|
s += "\t";
|
|
break;
|
|
case"u":
|
|
var n = t.substring(e + 1, e + 5);
|
|
it.test(n) || this.parseError("Illegal escape sequence: \\u" + n), s += String.fromCharCode(parseInt(n, 16)), e += 4;
|
|
break;
|
|
default:
|
|
throw this.parseError('Illegal escape sequence: "\\' + r + '"')
|
|
}
|
|
++e;
|
|
var i = t.indexOf("\\", e);
|
|
s += t.substring(e, i < 0 ? t.length : i), e = i
|
|
}
|
|
return s
|
|
}, f.prototype.isComment = function () {
|
|
return "/" === this.expression.charAt(this.pos) && "*" === this.expression.charAt(this.pos + 1) && (this.pos = this.expression.indexOf("*/", this.pos) + 2, 1 === this.pos && (this.pos = this.expression.length), ! 0)
|
|
}, f.prototype.isRadixInteger = function () {
|
|
var t = this.pos;
|
|
if (t >= this.expression.length - 2 || "0" !== this.expression.charAt(t)) return ! 1;
|
|
++t;
|
|
var e, s;
|
|
if ("x" === this.expression.charAt(t)) e = 16, s = /^[0-9a-f]$/i, ++t; else {
|
|
if ("b" !== this.expression.charAt(t)) return ! 1;
|
|
e = 2, s = /^[01]$/i, ++t
|
|
}
|
|
for (var r = ! 1, n = t; t < this.expression.length;) {
|
|
var i = this.expression.charAt(t);
|
|
if ( ! s.test(i)) break;
|
|
t++, r = ! 0
|
|
}
|
|
return r && (this.current = this.newToken("TNUMBER", parseInt(this.expression.substring(n, t), e)), this.pos = t), r
|
|
}, f.prototype.isNumber = function () {
|
|
for (var t, e = ! 1, s = this.pos, r = s, n = s, i = ! 1, o = ! 1; s < this.expression.length && ((t = this.expression.charAt(s)) >= "0" && t <= "9" || ! i && "." === t);) "." === t ? i = ! 0 : o = ! 0, s++, e = o;
|
|
if (e && (n = s), "e" === t || "E" === t) {
|
|
s++;
|
|
for (var a = ! 0, h = ! 1; s < this.expression.length;) {
|
|
if (t = this.expression.charAt(s), ! a || "+" !== t && "-" !== t) {
|
|
if ( ! (t >= "0" && t <= "9")) break;
|
|
h = ! 0, a = ! 1
|
|
} else a = ! 1;
|
|
s++
|
|
}
|
|
h || (s = n)
|
|
}
|
|
return e ? (this.current = this.newToken("TNUMBER", parseFloat(this.expression.substring(r, s))), this.pos = s) : this.pos = n, e
|
|
}, f.prototype.isOperator = function () {
|
|
var t = this.pos, e = this.expression.charAt(this.pos);
|
|
if ("+" === e || "-" === e || "*" === e || "/" === e || "%" === e || "^" === e || "?" === e || ":" === e || "." === e) this.current = this.newToken(nt, e); else if ("∙" === e || "•" === e) this.current = this.newToken(nt, "*"); else if (">" === e) "=" === this.expression.charAt(this.pos + 1) ? (this.current = this.newToken(nt, ">="), this.pos++) : this.current = this.newToken(nt, ">"); else if ("<" === e) "=" === this.expression.charAt(this.pos + 1) ? (this.current = this.newToken(nt, "<="), this.pos++) : this.current = this.newToken(nt, "<"); else if ("|" === e) {
|
|
if ("|" !== this.expression.charAt(this.pos + 1)) return ! 1;
|
|
this.current = this.newToken(nt, "||"), this.pos++
|
|
} else if ("=" === e) {
|
|
if ("=" !== this.expression.charAt(this.pos + 1)) return ! 1;
|
|
this.current = this.newToken(nt, "=="), this.pos++
|
|
} else {
|
|
if ("!" !== e) return ! 1;
|
|
"=" === this.expression.charAt(this.pos + 1) ? (this.current = this.newToken(nt, "!="), this.pos++) : this.current = this.newToken(nt, e)
|
|
}
|
|
return this.pos++, !! this.isOperatorEnabled(this.current.value) || (this.pos = t, ! 1)
|
|
};
|
|
var ot = {
|
|
"+": "add",
|
|
"-": "subtract",
|
|
"*": "multiply",
|
|
"/": "divide",
|
|
"%": "remainder",
|
|
"^": "power",
|
|
"!": "factorial",
|
|
"<": "comparison",
|
|
">": "comparison",
|
|
"<=": "comparison",
|
|
">=": "comparison",
|
|
"==": "comparison",
|
|
"!=": "comparison",
|
|
"||": "concatenate",
|
|
and: "logical",
|
|
or: "logical",
|
|
not: "logical",
|
|
"?": "conditional",
|
|
":": "conditional"
|
|
};
|
|
f.prototype.isOperatorEnabled = function (t) {
|
|
var e = v(t), s = this.options.operators || {};
|
|
return "in" === e ? !! s.in : ! (e in s && ! s[e])
|
|
}, f.prototype.getCoordinates = function () {
|
|
var t, e = 0, s = -1;
|
|
do {
|
|
e++, t = this.pos - s, s = this.expression.indexOf("\n", s + 1)
|
|
} while (s >= 0 && s < this.pos);
|
|
return {line: e, column: t}
|
|
}, f.prototype.parseError = function (t) {
|
|
var e = this.getCoordinates();
|
|
throw new Error("parse error [" + e.line + ":" + e.column + "]: " + t)
|
|
}, x.prototype.next = function () {
|
|
return this.current = this.nextToken, this.nextToken = this.tokens.next()
|
|
}, x.prototype.tokenMatches = function (t, e) {
|
|
return void 0 === e || (Array.isArray(e) ? p(e, t.value) : "function" == typeof e ? e(t) : t.value === e)
|
|
}, x.prototype.save = function () {
|
|
this.savedCurrent = this.current, this.savedNextToken = this.nextToken, this.tokens.save()
|
|
}, x.prototype.restore = function () {
|
|
this.tokens.restore(), this.current = this.savedCurrent, this.nextToken = this.savedNextToken
|
|
}, x.prototype.accept = function (t, e) {
|
|
return ! (this.nextToken.type !== t || ! this.tokenMatches(this.nextToken, e)) && (this.next(), ! 0)
|
|
}, x.prototype.expect = function (t, e) {
|
|
if ( ! this.accept(t, e)) {
|
|
var s = this.tokens.getCoordinates();
|
|
throw new Error("parse error [" + s.line + ":" + s.column + "]: Expected " + (e || t))
|
|
}
|
|
}, x.prototype.parseAtom = function (e) {
|
|
if (this.accept("TNAME")) e.push(new t(tt, this.current.value)); else if (this.accept("TNUMBER")) e.push(new t(K, this.current.value)); else if (this.accept("TSTRING")) e.push(new t(K, this.current.value)); else {
|
|
if ( ! this.accept("TPAREN", "(")) throw new Error("unexpected " + this.nextToken);
|
|
this.parseExpression(e), this.expect("TPAREN", ")")
|
|
}
|
|
}, x.prototype.parseExpression = function (t) {
|
|
this.parseConditionalExpression(t)
|
|
}, x.prototype.parseConditionalExpression = function (e) {
|
|
for (this.parseOrExpression(e); this.accept(nt, "?");) {
|
|
var s = [], n = [];
|
|
this.parseConditionalExpression(s), this.expect(nt, ":"), this.parseConditionalExpression(n), e.push(new t(st, s)), e.push(new t(st, n)), e.push(r("?"))
|
|
}
|
|
}, x.prototype.parseOrExpression = function (t) {
|
|
for (this.parseAndExpression(t); this.accept(nt, "or");) this.parseAndExpression(t), t.push(s("or"))
|
|
}, x.prototype.parseAndExpression = function (t) {
|
|
for (this.parseComparison(t); this.accept(nt, "and");) this.parseComparison(t), t.push(s("and"))
|
|
};
|
|
var at = ["==", "!=", "<", "<=", ">=", ">", "in"];
|
|
x.prototype.parseComparison = function (t) {
|
|
for (this.parseAddSub(t); this.accept(nt, at);) {
|
|
var e = this.current;
|
|
this.parseAddSub(t), t.push(s(e.value))
|
|
}
|
|
};
|
|
var ht = ["+", "-", "||"];
|
|
x.prototype.parseAddSub = function (t) {
|
|
for (this.parseTerm(t); this.accept(nt, ht);) {
|
|
var e = this.current;
|
|
this.parseTerm(t), t.push(s(e.value))
|
|
}
|
|
};
|
|
var pt = ["*", "/", "%"];
|
|
x.prototype.parseTerm = function (t) {
|
|
for (this.parseFactor(t); this.accept(nt, pt);) {
|
|
var e = this.current;
|
|
this.parseFactor(t), t.push(s(e.value))
|
|
}
|
|
}, x.prototype.parseFactor = function (t) {
|
|
var s = this.tokens.unaryOps;
|
|
if (this.save(), this.accept(nt, function (t) {
|
|
return t.value in s
|
|
})) if ("-" !== this.current.value && "+" !== this.current.value && "TPAREN" === this.nextToken.type && "(" === this.nextToken.value) this.restore(), this.parseExponential(t); else {
|
|
var r = this.current;
|
|
this.parseFactor(t), t.push(e(r.value))
|
|
} else this.parseExponential(t)
|
|
}, x.prototype.parseExponential = function (t) {
|
|
for (this.parsePostfixExpression(t); this.accept(nt, "^");) this.parseFactor(t), t.push(s("^"))
|
|
}, x.prototype.parsePostfixExpression = function (t) {
|
|
for (this.parseFunctionCall(t); this.accept(nt, "!");) t.push(e("!"))
|
|
}, x.prototype.parseFunctionCall = function (s) {
|
|
var r = this.tokens.unaryOps;
|
|
if (this.accept(nt, function (t) {
|
|
return t.value in r
|
|
})) {
|
|
var n = this.current;
|
|
this.parseAtom(s), s.push(e(n.value))
|
|
} else for (this.parseMemberExpression(s); this.accept("TPAREN", "(");) if (this.accept("TPAREN", ")")) s.push(new t(et, 0)); else {
|
|
var i = this.parseArgumentList(s);
|
|
s.push(new t(et, i))
|
|
}
|
|
}, x.prototype.parseArgumentList = function (t) {
|
|
for (var e = 0; ! this.accept("TPAREN", ")");) for (this.parseExpression(t), ++e; this.accept("TCOMMA");) this.parseExpression(t), ++e;
|
|
return e
|
|
}, x.prototype.parseMemberExpression = function (e) {
|
|
for (this.parseAtom(e); this.accept(nt, ".");) {
|
|
if ( ! this.allowMemberAccess) throw new Error('unexpected ".", member access is not permitted');
|
|
this.expect("TNAME"), e.push(new t(rt, this.current.value))
|
|
}
|
|
};
|
|
var ut = 4.7421875,
|
|
ct = [.9999999999999971, 57.15623566586292, -59.59796035547549, 14.136097974741746, -.4919138160976202, 3399464998481189e-20, 4652362892704858e-20, -9837447530487956e-20, .0001580887032249125, -.00021026444172410488, .00021743961811521265, -.0001643181065367639, 8441822398385275e-20, -26190838401581408e-21, 36899182659531625e-22];
|
|
H.prototype.parse = function (t) {
|
|
var e = [], s = new x(this, new f(this, t), {allowMemberAccess: this.options.allowMemberAccess});
|
|
return s.parseExpression(e), s.expect("TEOF", "EOF"), new c(e, this)
|
|
}, H.prototype.evaluate = function (t, e) {
|
|
return this.parse(t).evaluate(e)
|
|
};
|
|
var lt = new H;
|
|
return H.parse = function (t) {
|
|
return lt.parse(t)
|
|
}, H.evaluate = function (t, e) {
|
|
return lt.parse(t).evaluate(e)
|
|
}, {Parser: H, Expression: c}
|
|
});
|