@oat-sa/expr-eval
Advanced tools
Comparing version 1.3.2 to 2.0.0
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.exprEval = factory()); | ||
}(this, (function () { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = global || self, factory(global.exprEval = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
@@ -12,6 +12,11 @@ var INUMBER = 'INUMBER'; | ||
var IVAR = 'IVAR'; | ||
var IVARNAME = 'IVARNAME'; | ||
var IFUNCOP = 'IFUNCOP'; | ||
var IFUNCALL = 'IFUNCALL'; | ||
var IFUNDEF = 'IFUNDEF'; | ||
var IEXPR = 'IEXPR'; | ||
var IEXPREVAL = 'IEXPREVAL'; | ||
var IMEMBER = 'IMEMBER'; | ||
var IENDSTATEMENT = 'IENDSTATEMENT'; | ||
var IARRAY = 'IARRAY'; | ||
@@ -30,2 +35,4 @@ function Instruction(type, value) { | ||
case IVAR: | ||
case IVARNAME: | ||
case IENDSTATEMENT: | ||
case IFUNCOP: | ||
@@ -35,2 +42,6 @@ return this.value; | ||
return 'CALL ' + this.value; | ||
case IFUNDEF: | ||
return 'DEF ' + this.value; | ||
case IARRAY: | ||
return 'ARRAY ' + this.value; | ||
case IMEMBER: | ||
@@ -63,4 +74,10 @@ return '.' + this.value; | ||
var type = item.type; | ||
if (type === INUMBER) { | ||
nstack.push(item); | ||
if (type === INUMBER || type === IVARNAME) { | ||
if (Array.isArray(item.value)) { | ||
nstack.push.apply(nstack, simplify(item.value.map(function (x) { | ||
return new Instruction(INUMBER, x); | ||
}).concat(new Instruction(IARRAY, item.value.length)), unaryOps, binaryOps, ternaryOps, values)); | ||
} else { | ||
nstack.push(item); | ||
} | ||
} else if (type === IVAR && values.hasOwnProperty(item.value)) { | ||
@@ -99,3 +116,9 @@ item = new Instruction(INUMBER, values[item.value]); | ||
nstack.push(new Instruction(INUMBER, n1.value[item.value])); | ||
} else { | ||
} /* else if (type === IARRAY && nstack.length >= item.value) { | ||
var length = item.value; | ||
while (length-- > 0) { | ||
newexpression.push(nstack.pop()); | ||
} | ||
newexpression.push(new Instruction(IARRAY, item.value)); | ||
} */ else { | ||
while (nstack.length > 0) { | ||
@@ -145,7 +168,14 @@ newexpression.push(nstack.shift()); | ||
var n1, n2, n3; | ||
var f; | ||
for (var i = 0; i < tokens.length; i++) { | ||
var f, args, argCount; | ||
if (isExpressionEvaluator(tokens)) { | ||
return resolveExpression(tokens, values); | ||
} | ||
var numTokens = tokens.length; | ||
for (var i = 0; i < numTokens; i++) { | ||
var item = tokens[i]; | ||
var type = item.type; | ||
if (type === INUMBER) { | ||
if (type === INUMBER || type === IVARNAME) { | ||
nstack.push(item.value); | ||
@@ -159,5 +189,8 @@ } else if (type === IOP2) { | ||
nstack.push(n1 ? true : !!evaluate(n2, expr, values)); | ||
} else if (item.value === '=') { | ||
f = expr.binaryOps[item.value]; | ||
nstack.push(f(n1, evaluate(n2, expr, values), values)); | ||
} else { | ||
f = expr.binaryOps[item.value]; | ||
nstack.push(f(n1, n2)); | ||
nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values))); | ||
} | ||
@@ -172,7 +205,12 @@ } else if (type === IOP3) { | ||
f = expr.ternaryOps[item.value]; | ||
nstack.push(f(n1, n2, n3)); | ||
nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values), resolveExpression(n3, values))); | ||
} | ||
} else if (type === IVAR) { | ||
if (/^__proto__|prototype|constructor$/.test(item.value)) { | ||
throw new Error('prototype access detected'); | ||
} | ||
if (item.value in expr.functions) { | ||
nstack.push(expr.functions[item.value]); | ||
} else if (item.value in expr.unaryOps && expr.parser.isOperatorEnabled(item.value)) { | ||
nstack.push(expr.unaryOps[item.value]); | ||
} else { | ||
@@ -189,3 +227,3 @@ var v = values[item.value]; | ||
f = expr.unaryOps[item.value]; | ||
nstack.push(f(n1)); | ||
nstack.push(f(resolveExpression(n1, values))); | ||
} else if (type === IFUNCOP) { | ||
@@ -201,6 +239,6 @@ n2 = nstack.pop(); | ||
} else if (type === IFUNCALL) { | ||
var argCount = item.value; | ||
var args = []; | ||
argCount = item.value; | ||
args = []; | ||
while (argCount-- > 0) { | ||
args.unshift(nstack.pop()); | ||
args.unshift(resolveExpression(nstack.pop(), values)); | ||
} | ||
@@ -213,7 +251,43 @@ f = nstack.pop(); | ||
} | ||
} else if (type === IFUNDEF) { | ||
// Create closure to keep references to arguments and expression | ||
nstack.push((function () { | ||
var n2 = nstack.pop(); | ||
var args = []; | ||
var argCount = item.value; | ||
while (argCount-- > 0) { | ||
args.unshift(nstack.pop()); | ||
} | ||
var n1 = nstack.pop(); | ||
var f = function () { | ||
var scope = Object.assign({}, values); | ||
for (var i = 0, len = args.length; i < len; i++) { | ||
scope[args[i]] = arguments[i]; | ||
} | ||
return evaluate(n2, expr, scope); | ||
}; | ||
// f.name = n1 | ||
Object.defineProperty(f, 'name', { | ||
value: n1, | ||
writable: false | ||
}); | ||
values[n1] = f; | ||
return f; | ||
})()); | ||
} else if (type === IEXPR) { | ||
nstack.push(item.value); | ||
nstack.push(createExpressionEvaluator(item, expr)); | ||
} else if (type === IEXPREVAL) { | ||
nstack.push(item); | ||
} else if (type === IMEMBER) { | ||
n1 = nstack.pop(); | ||
nstack.push(n1[item.value]); | ||
} else if (type === IENDSTATEMENT) { | ||
nstack.pop(); | ||
} else if (type === IARRAY) { | ||
argCount = item.value; | ||
args = []; | ||
while (argCount-- > 0) { | ||
args.unshift(nstack.pop()); | ||
} | ||
nstack.push(args); | ||
} else { | ||
@@ -226,9 +300,28 @@ throw new Error('invalid Expression'); | ||
} | ||
return nstack[0] === -0 ? 0: nstack[0]; | ||
// Explicitly return zero to avoid test issues caused by -0 | ||
return nstack[0] === 0 ? 0 : resolveExpression(nstack[0], values); | ||
} | ||
function createExpressionEvaluator(token, expr, values) { | ||
if (isExpressionEvaluator(token)) return token; | ||
return { | ||
type: IEXPREVAL, | ||
value: function (scope) { | ||
return evaluate(token.value, expr, scope); | ||
} | ||
}; | ||
} | ||
function isExpressionEvaluator(n) { | ||
return n && n.type === IEXPREVAL; | ||
} | ||
function resolveExpression(n, values) { | ||
return isExpressionEvaluator(n) ? n.value(values) : n; | ||
} | ||
function expressionToString(tokens, toJS) { | ||
var nstack = []; | ||
var n1, n2, n3; | ||
var f; | ||
var f, args, argCount; | ||
for (var i = 0; i < tokens.length; i++) { | ||
@@ -240,2 +333,4 @@ var item = tokens[i]; | ||
nstack.push('(' + item.value + ')'); | ||
} else if (Array.isArray(item.value)) { | ||
nstack.push('[' + item.value.map(escapeValue).join(', ') + ']'); | ||
} else { | ||
@@ -256,3 +351,3 @@ nstack.push(escapeValue(item.value)); | ||
} else if (f === '||') { | ||
nstack.push('(String(' + n1 + ') + String(' + n2 + '))'); | ||
nstack.push('(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }((' + n1 + '),(' + n2 + ')))'); | ||
} else if (f === '==') { | ||
@@ -262,2 +357,4 @@ nstack.push('(' + n1 + ' === ' + n2 + ')'); | ||
nstack.push('(' + n1 + ' !== ' + n2 + ')'); | ||
} else if (f === '[') { | ||
nstack.push(n1 + '[(' + n2 + ') | 0]'); | ||
} else { | ||
@@ -267,3 +364,7 @@ nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); | ||
} else { | ||
nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); | ||
if (f === '[') { | ||
nstack.push(n1 + '[' + n2 + ']'); | ||
} else { | ||
nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); | ||
} | ||
} | ||
@@ -280,3 +381,3 @@ } else if (type === IOP3) { | ||
} | ||
} else if (type === IVAR) { | ||
} else if (type === IVAR || type === IVARNAME) { | ||
nstack.push(item.value); | ||
@@ -302,4 +403,4 @@ } else if (type === IOP1) { | ||
} else if (type === IFUNCALL) { | ||
var argCount = item.value; | ||
var args = []; | ||
argCount = item.value; | ||
args = []; | ||
while (argCount-- > 0) { | ||
@@ -310,8 +411,28 @@ args.unshift(nstack.pop()); | ||
nstack.push(f + '(' + args.join(', ') + ')'); | ||
} else if (type === IFUNDEF) { | ||
n2 = nstack.pop(); | ||
argCount = item.value; | ||
args = []; | ||
while (argCount-- > 0) { | ||
args.unshift(nstack.pop()); | ||
} | ||
n1 = nstack.pop(); | ||
if (toJS) { | ||
nstack.push('(' + n1 + ' = function(' + args.join(', ') + ') { return ' + n2 + ' })'); | ||
} else { | ||
nstack.push('(' + n1 + '(' + args.join(', ') + ') = ' + n2 + ')'); | ||
} | ||
} else if (type === IMEMBER) { | ||
n1 = nstack.pop(); | ||
nstack.push(n1 + '.' + item.value); | ||
} else if (type === IARRAY) { | ||
argCount = item.value; | ||
args = []; | ||
while (argCount-- > 0) { | ||
args.unshift(nstack.pop()); | ||
} | ||
nstack.push('[' + args.join(', ') + ']'); | ||
} else if (type === IEXPR) { | ||
nstack.push('(' + expressionToString(item.value, toJS) + ')'); | ||
} else { | ||
} else if (type === IENDSTATEMENT) ; else { | ||
throw new Error('invalid Expression'); | ||
@@ -321,3 +442,7 @@ } | ||
if (nstack.length > 1) { | ||
throw new Error('invalid Expression (parity)'); | ||
if (toJS) { | ||
nstack = [ nstack.join(',') ]; | ||
} else { | ||
nstack = [ nstack.join(';') ]; | ||
} | ||
} | ||
@@ -350,3 +475,3 @@ return String(nstack[0]); | ||
var item = tokens[i]; | ||
if (item.type === IVAR) { | ||
if (item.type === IVAR || item.type === IVARNAME) { | ||
if (!withMembers && !contains(symbols, item.value)) { | ||
@@ -441,4 +566,6 @@ symbols.push(item.value); | ||
var TPAREN = 'TPAREN'; | ||
var TBRACKET = 'TBRACKET'; | ||
var TCOMMA = 'TCOMMA'; | ||
var TNAME = 'TNAME'; | ||
var TSEMICOLON = 'TSEMICOLON'; | ||
@@ -467,2 +594,3 @@ function Token(type, value, index) { | ||
this.options = parser.options; | ||
this.parser = parser; | ||
} | ||
@@ -496,3 +624,5 @@ | ||
this.isParen() || | ||
this.isBracket() || | ||
this.isComma() || | ||
this.isSemicolon() || | ||
this.isNamedOp() || | ||
@@ -539,2 +669,12 @@ this.isFuncOp() || | ||
TokenStream.prototype.isBracket = function () { | ||
var c = this.expression.charAt(this.pos); | ||
if ((c === '[' || c === ']') && this.isOperatorEnabled('[')) { | ||
this.current = this.newToken(TBRACKET, c); | ||
this.pos++; | ||
return true; | ||
} | ||
return false; | ||
}; | ||
TokenStream.prototype.isComma = function () { | ||
@@ -550,2 +690,12 @@ var c = this.expression.charAt(this.pos); | ||
TokenStream.prototype.isSemicolon = function () { | ||
var c = this.expression.charAt(this.pos); | ||
if (c === ';') { | ||
this.current = this.newToken(TSEMICOLON, ';'); | ||
this.pos++; | ||
return true; | ||
} | ||
return false; | ||
}; | ||
TokenStream.prototype.isConst = function () { | ||
@@ -870,3 +1020,3 @@ var startPos = this.pos; | ||
} else { | ||
return false; | ||
this.current = this.newToken(TOP, c); | ||
} | ||
@@ -893,38 +1043,4 @@ } else if (c === '!') { | ||
var optionNameMap = { | ||
'+': 'add', | ||
'-': 'subtract', | ||
'*': 'multiply', | ||
'/': 'divide', | ||
'%': 'remainder', | ||
'^': 'power', | ||
'!': 'factorial', | ||
'<': 'comparison', | ||
'>': 'comparison', | ||
'<=': 'comparison', | ||
'>=': 'comparison', | ||
'==': 'comparison', | ||
'!=': 'comparison', | ||
'||': 'concatenate', | ||
'and': 'logical', | ||
'or': 'logical', | ||
'not': 'logical', | ||
'?': 'conditional', | ||
':': 'conditional' | ||
}; | ||
function getOptionName(op) { | ||
return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op; | ||
} | ||
TokenStream.prototype.isOperatorEnabled = function (op) { | ||
var optionName = getOptionName(op); | ||
var operators = this.options.operators || {}; | ||
// in is a special case for now because it's disabled by default | ||
if (optionName === 'in') { | ||
return !!operators['in']; | ||
} | ||
return !(optionName in operators) || !!operators[optionName]; | ||
return this.parser.isOperatorEnabled(op); | ||
}; | ||
@@ -1009,3 +1125,8 @@ | ||
ParserState.prototype.parseAtom = function (instr) { | ||
if (this.accept(TNAME)) { | ||
var unaryOps = this.tokens.unaryOps; | ||
function isPrefixOperator(token) { | ||
return token.value in unaryOps; | ||
} | ||
if (this.accept(TNAME) || this.accept(TOP, isPrefixOperator)) { | ||
instr.push(new Instruction(IVAR, this.current.value)); | ||
@@ -1019,2 +1140,9 @@ } else if (this.accept(TNUMBER)) { | ||
this.expect(TPAREN, ')'); | ||
} else if (this.accept(TBRACKET, '[')) { | ||
if (this.accept(TBRACKET, ']')) { | ||
instr.push(new Instruction(IARRAY, 0)); | ||
} else { | ||
var argCount = this.parseArrayList(instr); | ||
instr.push(new Instruction(IARRAY, argCount)); | ||
} | ||
} else { | ||
@@ -1026,3 +1154,75 @@ throw new Error('unexpected ' + this.nextToken); | ||
ParserState.prototype.parseExpression = function (instr) { | ||
var exprInstr = []; | ||
if (this.parseUntilEndStatement(instr, exprInstr)) { | ||
return; | ||
} | ||
this.parseVariableAssignmentExpression(exprInstr); | ||
if (this.parseUntilEndStatement(instr, exprInstr)) { | ||
return; | ||
} | ||
this.pushExpression(instr, exprInstr); | ||
}; | ||
ParserState.prototype.pushExpression = function (instr, exprInstr) { | ||
for (var i = 0, len = exprInstr.length; i < len; i++) { | ||
instr.push(exprInstr[i]); | ||
} | ||
}; | ||
ParserState.prototype.parseUntilEndStatement = function (instr, exprInstr) { | ||
if (!this.accept(TSEMICOLON)) return false; | ||
if (this.nextToken && this.nextToken.type !== TEOF && !(this.nextToken.type === TPAREN && this.nextToken.value === ')')) { | ||
exprInstr.push(new Instruction(IENDSTATEMENT)); | ||
} | ||
if (this.nextToken.type !== TEOF) { | ||
this.parseExpression(exprInstr); | ||
} | ||
instr.push(new Instruction(IEXPR, exprInstr)); | ||
return true; | ||
}; | ||
ParserState.prototype.parseArrayList = function (instr) { | ||
var argCount = 0; | ||
while (!this.accept(TBRACKET, ']')) { | ||
this.parseExpression(instr); | ||
++argCount; | ||
while (this.accept(TCOMMA)) { | ||
this.parseExpression(instr); | ||
++argCount; | ||
} | ||
} | ||
return argCount; | ||
}; | ||
ParserState.prototype.parseVariableAssignmentExpression = function (instr) { | ||
this.parseConditionalExpression(instr); | ||
while (this.accept(TOP, '=')) { | ||
var varName = instr.pop(); | ||
var varValue = []; | ||
var lastInstrIndex = instr.length - 1; | ||
if (varName.type === IFUNCALL) { | ||
if (!this.tokens.isOperatorEnabled('()=')) { | ||
throw new Error('function definition is not permitted'); | ||
} | ||
for (var i = 0, len = varName.value + 1; i < len; i++) { | ||
var index = lastInstrIndex - i; | ||
if (instr[index].type === IVAR) { | ||
instr[index] = new Instruction(IVARNAME, instr[index].value); | ||
} | ||
} | ||
this.parseVariableAssignmentExpression(varValue); | ||
instr.push(new Instruction(IEXPR, varValue)); | ||
instr.push(new Instruction(IFUNDEF, varName.value)); | ||
continue; | ||
} | ||
if (varName.type !== IVAR && varName.type !== IMEMBER) { | ||
throw new Error('expected variable for assignment'); | ||
} | ||
this.parseVariableAssignmentExpression(varValue); | ||
instr.push(new Instruction(IVARNAME, varName.value)); | ||
instr.push(new Instruction(IEXPR, varValue)); | ||
instr.push(binaryInstruction('=')); | ||
} | ||
}; | ||
@@ -1105,10 +1305,17 @@ | ||
if (this.accept(TOP, isPrefixOperator)) { | ||
if ((this.current.value !== '-' && this.current.value !== '+' && this.nextToken.type === TPAREN && this.nextToken.value === '(')) { | ||
this.restore(); | ||
this.parseExponential(instr); | ||
} else { | ||
var op = this.current; | ||
this.parseFactor(instr); | ||
instr.push(unaryInstruction(op.value)); | ||
if (this.current.value !== '-' && this.current.value !== '+') { | ||
if (this.nextToken.type === TPAREN && this.nextToken.value === '(') { | ||
this.restore(); | ||
this.parseExponential(instr); | ||
return; | ||
} else if (this.nextToken.type === TSEMICOLON || this.nextToken.type === TCOMMA || this.nextToken.type === TEOF || (this.nextToken.type === TPAREN && this.nextToken.value === ')')) { | ||
this.restore(); | ||
this.parseAtom(instr); | ||
return; | ||
} | ||
} | ||
var op = this.current; | ||
this.parseFactor(instr); | ||
instr.push(unaryInstruction(op.value)); | ||
} else { | ||
@@ -1188,9 +1395,23 @@ this.parseExponential(instr); | ||
this.parseAtom(instr); | ||
while (this.accept(TOP, '.')) { | ||
if (!this.allowMemberAccess) { | ||
throw new Error('unexpected ".", member access is not permitted'); | ||
while (this.accept(TOP, '.') || this.accept(TBRACKET, '[')) { | ||
var op = this.current; | ||
if (op.value === '.') { | ||
if (!this.allowMemberAccess) { | ||
throw new Error('unexpected ".", member access is not permitted'); | ||
} | ||
this.expect(TNAME); | ||
instr.push(new Instruction(IMEMBER, this.current.value)); | ||
} else if (op.value === '[') { | ||
if (!this.tokens.isOperatorEnabled('[')) { | ||
throw new Error('unexpected "[]", arrays are disabled'); | ||
} | ||
this.parseExpression(instr); | ||
this.expect(TBRACKET, ']'); | ||
instr.push(binaryInstruction('[')); | ||
} else { | ||
throw new Error('unexpected symbol: ' + op.value); | ||
} | ||
this.expect(TNAME); | ||
instr.push(new Instruction(IMEMBER, this.current.value)); | ||
} | ||
@@ -1220,2 +1441,5 @@ }; | ||
function concat(a, b) { | ||
if (Array.isArray(a) && Array.isArray(b)) { | ||
return a.concat(b); | ||
} | ||
return '' + a + b; | ||
@@ -1384,3 +1608,6 @@ } | ||
function stringLength(s) { | ||
function stringOrArrayLength(s) { | ||
if (Array.isArray(s)) { | ||
return s.length; | ||
} | ||
return String(s).length; | ||
@@ -1440,2 +1667,110 @@ } | ||
function setVar(name, value, variables) { | ||
if (variables) variables[name] = value; | ||
return value; | ||
} | ||
function arrayIndex(array, index) { | ||
return array[index | 0]; | ||
} | ||
function max(array) { | ||
if (arguments.length === 1 && Array.isArray(array)) { | ||
return Math.max.apply(Math, array); | ||
} else { | ||
return Math.max.apply(Math, arguments); | ||
} | ||
} | ||
function min(array) { | ||
if (arguments.length === 1 && Array.isArray(array)) { | ||
return Math.min.apply(Math, array); | ||
} else { | ||
return Math.min.apply(Math, arguments); | ||
} | ||
} | ||
function arrayMap(f, a) { | ||
if (typeof f !== 'function') { | ||
throw new Error('First argument to map is not a function'); | ||
} | ||
if (!Array.isArray(a)) { | ||
throw new Error('Second argument to map is not an array'); | ||
} | ||
return a.map(function (x, i) { | ||
return f(x, i); | ||
}); | ||
} | ||
function arrayFold(f, init, a) { | ||
if (typeof f !== 'function') { | ||
throw new Error('First argument to fold is not a function'); | ||
} | ||
if (!Array.isArray(a)) { | ||
throw new Error('Second argument to fold is not an array'); | ||
} | ||
return a.reduce(function (acc, x, i) { | ||
return f(acc, x, i); | ||
}, init); | ||
} | ||
function arrayFilter(f, a) { | ||
if (typeof f !== 'function') { | ||
throw new Error('First argument to filter is not a function'); | ||
} | ||
if (!Array.isArray(a)) { | ||
throw new Error('Second argument to filter is not an array'); | ||
} | ||
return a.filter(function (x, i) { | ||
return f(x, i); | ||
}); | ||
} | ||
function stringOrArrayIndexOf(target, s) { | ||
if (!(Array.isArray(s) || typeof s === 'string')) { | ||
throw new Error('Second argument to indexOf is not a string or array'); | ||
} | ||
return s.indexOf(target); | ||
} | ||
function arrayJoin(sep, a) { | ||
if (!Array.isArray(a)) { | ||
throw new Error('Second argument to join is not an array'); | ||
} | ||
return a.join(sep); | ||
} | ||
function sign(x) { | ||
return ((x > 0) - (x < 0)) || +x; | ||
} | ||
var ONE_THIRD = 1/3; | ||
function cbrt(x) { | ||
return x < 0 ? -Math.pow(-x, ONE_THIRD) : Math.pow(x, ONE_THIRD); | ||
} | ||
function expm1(x) { | ||
return Math.exp(x) - 1; | ||
} | ||
function log1p(x) { | ||
return Math.log(1 + x); | ||
} | ||
function log2(x) { | ||
return Math.log(x) / Math.LN2; | ||
} | ||
function sum(array) { | ||
if (!Array.isArray(array)) { | ||
throw new Error('Sum argument is not an array'); | ||
} | ||
return array.reduce(function (total, value) { | ||
return total + Number(value); | ||
}, 0); | ||
} | ||
function Parser(options) { | ||
@@ -1457,6 +1792,10 @@ this.options = options || {}; | ||
sqrt: Math.sqrt, | ||
cbrt: Math.cbrt || cbrt, | ||
log: Math.log, | ||
log2: Math.log2 || log2, | ||
ln: Math.log, | ||
lg: Math.log10 || log10, | ||
log10: Math.log10 || log10, | ||
expm1: Math.expm1 || expm1, | ||
log1p: Math.log1p || log1p, | ||
abs: Math.abs, | ||
@@ -1471,4 +1810,5 @@ ceil: Math.ceil, | ||
not: not, | ||
length: stringLength, | ||
'!': factorial | ||
length: stringOrArrayLength, | ||
'!': factorial, | ||
sign: Math.sign || sign | ||
}; | ||
@@ -1492,3 +1832,5 @@ | ||
or: orOperator, | ||
'in': inOperator | ||
'in': inOperator, | ||
'=': setVar, | ||
'[': arrayIndex | ||
}; | ||
@@ -1503,4 +1845,4 @@ | ||
fac: factorial, | ||
min: Math.min, | ||
max: Math.max, | ||
min: min, | ||
max: max, | ||
hypot: Math.hypot || hypot, | ||
@@ -1512,3 +1854,9 @@ pyt: Math.hypot || hypot, // backward compat | ||
gamma: gamma, | ||
roundTo: roundTo | ||
roundTo: roundTo, | ||
map: arrayMap, | ||
fold: arrayFold, | ||
filter: arrayFilter, | ||
indexOf: stringOrArrayIndexOf, | ||
join: arrayJoin, | ||
sum: sum | ||
}; | ||
@@ -1552,2 +1900,38 @@ | ||
var optionNameMap = { | ||
'+': 'add', | ||
'-': 'subtract', | ||
'*': 'multiply', | ||
'/': 'divide', | ||
'%': 'remainder', | ||
'^': 'power', | ||
'!': 'factorial', | ||
'<': 'comparison', | ||
'>': 'comparison', | ||
'<=': 'comparison', | ||
'>=': 'comparison', | ||
'==': 'comparison', | ||
'!=': 'comparison', | ||
'||': 'concatenate', | ||
'and': 'logical', | ||
'or': 'logical', | ||
'not': 'logical', | ||
'?': 'conditional', | ||
':': 'conditional', | ||
'=': 'assignment', | ||
'[': 'array', | ||
'()=': 'fndef' | ||
}; | ||
function getOptionName(op) { | ||
return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op; | ||
} | ||
Parser.prototype.isOperatorEnabled = function (op) { | ||
var optionName = getOptionName(op); | ||
var operators = this.options.operators || {}; | ||
return !(optionName in operators) || !!operators[optionName]; | ||
}; | ||
/*! | ||
@@ -1564,2 +1948,3 @@ Based on ndef.parser, by Raphael Graf(r@undefined.ch) | ||
// Backwards compatibility | ||
var index = { | ||
@@ -1570,4 +1955,8 @@ Parser: Parser, | ||
return index; | ||
exports.Expression = Expression; | ||
exports.Parser = Parser; | ||
exports.default = index; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); |
@@ -1,1 +0,12 @@ | ||
!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";var t="INUMBER",e="IOP1",s="IOP2",r="IOP3",n="IVAR",i="IFUNCOP",o="IFUNCALL",p="IEXPR",a="IMEMBER";function h(t,e){this.type=t,this.value=void 0!==e&&null!==e?e:0}function u(t){return new h(e,t)}function c(t){return new h(s,t)}function l(t){return new h(r,t)}function f(i,h){for(var u,c,l,x,y=[],w=0;w<i.length;w++){var d=i[w],M=d.type;if(M===t)"number"==typeof d.value&&d.value<0?y.push("("+d.value+")"):y.push(v(d.value));else if(M===s)c=y.pop(),u=y.pop(),x=d.value,h?"^"===x?y.push("Math.pow("+u+", "+c+")"):"and"===x?y.push("(!!"+u+" && !!"+c+")"):"or"===x?y.push("(!!"+u+" || !!"+c+")"):"||"===x?y.push("(String("+u+") + String("+c+"))"):"=="===x?y.push("("+u+" === "+c+")"):"!="===x?y.push("("+u+" !== "+c+")"):y.push("("+u+" "+x+" "+c+")"):y.push("("+u+" "+x+" "+c+")");else if(M===r){if(l=y.pop(),c=y.pop(),u=y.pop(),"?"!==(x=d.value))throw new Error("invalid Expression");y.push("("+u+" ? "+c+" : "+l+")")}else if(M===n)y.push(d.value);else if(M===e)u=y.pop(),"-"===(x=d.value)||"+"===x?y.push("("+x+u+")"):h?"not"===x?y.push("(!"+u+")"):"!"===x?y.push("fac("+u+")"):y.push(x+"("+u+")"):"!"===x?y.push("("+u+"!)"):y.push("("+x+" "+u+")");else if(M===o){for(var g=d.value,E=[];g-- >0;)E.unshift(y.pop());x=y.pop(),y.push(x+"("+E.join(", ")+")")}else if(M===a)u=y.pop(),y.push(u+"."+d.value);else{if(M!==p)throw new Error("invalid Expression");y.push("("+f(d.value,h)+")")}}if(y.length>1)throw new Error("invalid Expression (parity)");return String(y[0])}function v(t){return"string"==typeof t?JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"):t}function x(t,e){for(var s=0;s<t.length;s++)if(t[s]===e)return!0;return!1}function y(t,e,s){for(var r=!!(s=s||{}).withMembers,i=null,o=0;o<t.length;o++){var h=t[o];h.type===n?r||x(e,h.value)?null!==i?(x(e,i)||e.push(i),i=h.value):i=h.value:e.push(h.value):h.type===a&&r&&null!==i?i+="."+h.value:h.type===p?y(h.value,e,s):null!==i&&(x(e,i)||e.push(i),i=null)}null===i||x(e,i)||e.push(i)}function w(t,e){this.tokens=t,this.parser=e,this.unaryOps=e.unaryOps,this.binaryOps=e.binaryOps,this.ternaryOps=e.ternaryOps,this.functions=e.functions}h.prototype.toString=function(){switch(this.type){case t:case e:case s:case r:case n:case i:return this.value;case o:return"CALL "+this.value;case a:return"."+this.value;default:return"Invalid Instruction"}},w.prototype.simplify=function(i){return i=i||{},new w(function i(o,u,c,l,f){for(var v,x,y,w,d=[],M=[],g=0;g<o.length;g++){var E=o[g],k=E.type;if(k===t)d.push(E);else if(k===n&&f.hasOwnProperty(E.value))E=new h(t,f[E.value]),d.push(E);else if(k===s&&d.length>1)x=d.pop(),v=d.pop(),w=c[E.value],E=new h(t,w(v.value,x.value)),d.push(E);else if(k===r&&d.length>2)y=d.pop(),x=d.pop(),v=d.pop(),"?"===E.value?d.push(v.value?x.value:y.value):(w=l[E.value],E=new h(t,w(v.value,x.value,y.value)),d.push(E));else if(k===e&&d.length>0)v=d.pop(),w=u[E.value],E=new h(t,w(v.value)),d.push(E);else if(k===p){for(;d.length>0;)M.push(d.shift());M.push(new h(p,i(E.value,u,c,l,f)))}else if(k===a&&d.length>0)v=d.pop(),d.push(new h(t,v.value[E.value]));else{for(;d.length>0;)M.push(d.shift());M.push(E)}}for(;d.length>0;)M.push(d.shift());return M}(this.tokens,this.unaryOps,this.binaryOps,this.ternaryOps,i),this.parser)},w.prototype.substitute=function(t,i){return i instanceof w||(i=this.parser.parse(String(i))),new w(function t(i,o,a){for(var f=[],v=0;v<i.length;v++){var x=i[v],y=x.type;if(y===n&&x.value===o)for(var w=0;w<a.tokens.length;w++){var d,M=a.tokens[w];d=M.type===e?u(M.value):M.type===s?c(M.value):M.type===r?l(M.value):new h(M.type,M.value),f.push(d)}else y===p?f.push(new h(p,t(x.value,o,a))):f.push(x)}return f}(this.tokens,t,i),this.parser)},w.prototype.evaluate=function(h){return h=h||{},function h(u,c,l){for(var f,v,x,y,w=[],d=0;d<u.length;d++){var M=u[d],g=M.type;if(g===t)w.push(M.value);else if(g===s)v=w.pop(),f=w.pop(),"and"===M.value?w.push(!!f&&!!h(v,c,l)):"or"===M.value?w.push(!!f||!!h(v,c,l)):(y=c.binaryOps[M.value],w.push(y(f,v)));else if(g===r)x=w.pop(),v=w.pop(),f=w.pop(),"?"===M.value?w.push(h(f?v:x,c,l)):(y=c.ternaryOps[M.value],w.push(y(f,v,x)));else if(g===n)if(M.value in c.functions)w.push(c.functions[M.value]);else{var E=l[M.value];if(void 0===E)throw new Error("undefined variable: "+M.value);w.push(E)}else if(g===e)f=w.pop(),y=c.unaryOps[M.value],w.push(y(f));else if(g===i){if(v=w.pop(),f=w.pop(),!(y=c.functions[M.value]).apply||!y.call)throw new Error(y+" is not a function");w.push(y.apply(void 0,[f,v]))}else if(g===o){for(var k=M.value,b=[];k-- >0;)b.unshift(w.pop());if(!(y=w.pop()).apply||!y.call)throw new Error(y+" is not a function");w.push(y.apply(void 0,b))}else if(g===p)w.push(M.value);else{if(g!==a)throw new Error("invalid Expression");f=w.pop(),w.push(f[M.value])}}if(w.length>1)throw new Error("invalid Expression (parity)");return-0===w[0]?0:w[0]}(this.tokens,this,h)},w.prototype.toString=function(){return f(this.tokens,!1)},w.prototype.symbols=function(t){t=t||{};var e=[];return y(this.tokens,e,t),e},w.prototype.variables=function(t){t=t||{};var e=[];y(this.tokens,e,t);var s=this.functions;return e.filter(function(t){return!(t in s)})},w.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 "+f(this.simplify(e).tokens,!0)+"; }");return function(){return r.apply(s,arguments)}};var d="TOP";function M(t,e,s){this.type=t,this.value=e,this.index=s}function g(t,e){this.pos=0,this.current=null,this.unaryOps=t.unaryOps,this.binaryOps=t.binaryOps,this.ternaryOps=t.ternaryOps,this.functions=t.functions,this.consts=t.consts,this.expression=e,this.savedPosition=0,this.savedCurrent=null,this.options=t.options}M.prototype.toString=function(){return this.type+": "+this.value},g.prototype.newToken=function(t,e,s){return new M(t,e,null!=s?s:this.pos)},g.prototype.save=function(){this.savedPosition=this.pos,this.savedCurrent=this.current},g.prototype.restore=function(){this.pos=this.savedPosition,this.current=this.savedCurrent},g.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.isFuncOp()||this.isConst()||this.isName()?this.current:void this.parseError('Unknown character "'+this.expression.charAt(this.pos)+'"')},g.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},g.prototype.isParen=function(){var t=this.expression.charAt(this.pos);return("("===t||")"===t)&&(this.current=this.newToken("TPAREN",t),this.pos++,!0)},g.prototype.isComma=function(){return","===this.expression.charAt(this.pos)&&(this.current=this.newToken("TCOMMA",","),this.pos++,!0)},g.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},g.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(d,r),this.pos+=r.length,!0}return!1},g.prototype.isFuncOp=function(){var t,e=this.expression.charAt(this.pos),s=this.pos+1,r=s;if("@"===e){for(;r<this.expression.length&&((e=this.expression.charAt(r)).toUpperCase()!==e.toLowerCase()||!(r===s||"_"!==e&&(e<"0"||e>"9")));r++);if(r>s&&(t=this.expression.substring(s,r))in this.functions)return this.current=this.newToken("TFUNCOP",t),this.pos=s+t.length,!0}return!1},g.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||"_"===r)){"_"===r&&(s=!0);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},g.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.pos>=this.expression.length));)e=this.expression.charAt(this.pos);return t};var E=/^[0-9a-f]{4}$/i;g.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);E.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},g.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)},g.prototype.isRadixInteger=function(){var t,e,s=this.pos;if(s>=this.expression.length-2||"0"!==this.expression.charAt(s))return!1;if(++s,"x"===this.expression.charAt(s))t=16,e=/^[0-9a-f]$/i,++s;else{if("b"!==this.expression.charAt(s))return!1;t=2,e=/^[01]$/i,++s}for(var r=!1,n=s;s<this.expression.length;){var i=this.expression.charAt(s);if(!e.test(i))break;s++,r=!0}return r&&(this.current=this.newToken("TNUMBER",parseInt(this.expression.substring(n,s),t)),this.pos=s),r},g.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 p=!0,a=!1;s<this.expression.length;){if(t=this.expression.charAt(s),!p||"+"!==t&&"-"!==t){if(!(t>="0"&&t<="9"))break;a=!0,p=!1}else p=!1;s++}a||(s=n)}return e?(this.current=this.newToken("TNUMBER",parseFloat(this.expression.substring(r,s))),this.pos=s):this.pos=n,e},g.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(d,e);else if("∙"===e||"•"===e)this.current=this.newToken(d,"*");else if(">"===e)"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(d,">="),this.pos++):this.current=this.newToken(d,">");else if("<"===e)"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(d,"<="),this.pos++):this.current=this.newToken(d,"<");else if("|"===e){if("|"!==this.expression.charAt(this.pos+1))return!1;this.current=this.newToken(d,"||"),this.pos++}else if("="===e){if("="!==this.expression.charAt(this.pos+1))return!1;this.current=this.newToken(d,"=="),this.pos++}else{if("!"!==e)return!1;"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(d,"!="),this.pos++):this.current=this.newToken(d,e)}return this.pos++,!!this.isOperatorEnabled(this.current.value)||(this.pos=t,!1)};var k={"+":"add","-":"subtract","*":"multiply","/":"divide","%":"remainder","^":"power","!":"factorial","<":"comparison",">":"comparison","<=":"comparison",">=":"comparison","==":"comparison","!=":"comparison","||":"concatenate",and:"logical",or:"logical",not:"logical","?":"conditional",":":"conditional"};function b(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}g.prototype.isOperatorEnabled=function(t){var e=function(t){return k.hasOwnProperty(t)?k[t]:t}(t),s=this.options.operators||{};return"in"===e?!!s.in:!(e in s&&!s[e])},g.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}},g.prototype.parseError=function(t){var e=this.getCoordinates();throw new Error("parse error ["+e.line+":"+e.column+"]: "+t)},b.prototype.next=function(){return this.current=this.nextToken,this.nextToken=this.tokens.next()},b.prototype.tokenMatches=function(t,e){return void 0===e||(Array.isArray(e)?x(e,t.value):"function"==typeof e?e(t):t.value===e)},b.prototype.save=function(){this.savedCurrent=this.current,this.savedNextToken=this.nextToken,this.tokens.save()},b.prototype.restore=function(){this.tokens.restore(),this.current=this.savedCurrent,this.nextToken=this.savedNextToken},b.prototype.accept=function(t,e){return!(this.nextToken.type!==t||!this.tokenMatches(this.nextToken,e))&&(this.next(),!0)},b.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))}},b.prototype.parseAtom=function(e){if(this.accept("TNAME"))e.push(new h(n,this.current.value));else if(this.accept("TNUMBER"))e.push(new h(t,this.current.value));else if(this.accept("TSTRING"))e.push(new h(t,this.current.value));else{if(!this.accept("TPAREN","("))throw new Error("unexpected "+this.nextToken);this.parseExpression(e),this.expect("TPAREN",")")}},b.prototype.parseExpression=function(t){this.parseConditionalExpression(t)},b.prototype.parseConditionalExpression=function(t){for(this.parseOrExpression(t);this.accept(d,"?");){var e=[],s=[];this.parseConditionalExpression(e),this.expect(d,":"),this.parseConditionalExpression(s),t.push(new h(p,e)),t.push(new h(p,s)),t.push(l("?"))}},b.prototype.parseOrExpression=function(t){for(this.parseAndExpression(t);this.accept(d,"or");){var e=[];this.parseAndExpression(e),t.push(new h(p,e)),t.push(c("or"))}},b.prototype.parseAndExpression=function(t){for(this.parseComparison(t);this.accept(d,"and");){var e=[];this.parseComparison(e),t.push(new h(p,e)),t.push(c("and"))}};var m=["==","!=","<","<=",">=",">","in"];b.prototype.parseComparison=function(t){for(this.parseAddSub(t);this.accept(d,m);){var e=this.current;this.parseAddSub(t),t.push(c(e.value))}};var O=["+","-","||"];b.prototype.parseAddSub=function(t){for(this.parseTerm(t);this.accept(d,O);){var e=this.current;this.parseTerm(t),t.push(c(e.value))}};var T=["*","/","%"];function A(t,e){return Number(t)+Number(e)}function C(t,e){return t-e}function N(t,e){return t*e}function P(t,e){return t/e}function F(t,e){return t%e}function I(t,e){return""+t+e}function S(t,e){return t===e}function R(t,e){return t!==e}function U(t,e){return t>e}function L(t,e){return t<e}function q(t,e){return t>=e}function B(t,e){return t<=e}function _(t,e){return Boolean(t&&e)}function $(t,e){return Boolean(t||e)}function G(t,e){return x(e,t)}function j(t){return(Math.exp(t)-Math.exp(-t))/2}function J(t){return(Math.exp(t)+Math.exp(-t))/2}function W(t){return t===1/0?1:t===-1/0?-1:(Math.exp(t)-Math.exp(-t))/(Math.exp(t)+Math.exp(-t))}function V(t){return t===-1/0?t:Math.log(t+Math.sqrt(t*t+1))}function X(t){return Math.log(t+Math.sqrt(t*t-1))}function z(t){return Math.log((1+t)/(1-t))/2}function D(t){return Math.log(t)*Math.LOG10E}function H(t){return-t}function K(t){return!t}function Q(t){return t<0?Math.ceil(t):Math.floor(t)}function Y(t){return Math.random()*(t||1)}function Z(t){return st(t+1)}b.prototype.parseTerm=function(t){for(this.parseFactor(t);this.accept(d,T);){var e=this.current;this.parseFactor(t),t.push(c(e.value))}},b.prototype.parseFactor=function(t){var e=this.tokens.unaryOps;if(this.save(),this.accept(d,function(t){return t.value in e}))if("-"!==this.current.value&&"+"!==this.current.value&&"TPAREN"===this.nextToken.type&&"("===this.nextToken.value)this.restore(),this.parseExponential(t);else{var s=this.current;this.parseFactor(t),t.push(u(s.value))}else this.parseExponential(t)},b.prototype.parseExponential=function(t){for(this.parsePostfixExpression(t);this.accept(d,"^");)this.parseFactor(t),t.push(c("^"))},b.prototype.parsePostfixExpression=function(t){for(this.parseFunctionOperator(t);this.accept(d,"!");)t.push(u("!"))},b.prototype.parseFunctionOperator=function(t){var e,s=this.tokens.functions;function r(t){return t.value in s}for(this.parseFunctionCall(t);this.accept("TFUNCOP",r);)e=this.current,this.parseFactor(t),t.push(new h(i,e.value))},b.prototype.parseFunctionCall=function(t){var e=this.tokens.unaryOps;if(this.accept(d,function(t){return t.value in e})){var s=this.current;this.parseAtom(t),t.push(u(s.value))}else for(this.parseMemberExpression(t);this.accept("TPAREN","(");)if(this.accept("TPAREN",")"))t.push(new h(o,0));else{var r=this.parseArgumentList(t);t.push(new h(o,r))}},b.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},b.prototype.parseMemberExpression=function(t){for(this.parseAtom(t);this.accept(d,".");){if(!this.allowMemberAccess)throw new Error('unexpected ".", member access is not permitted');this.expect("TNAME"),t.push(new h(a,this.current.value))}};var tt=4.7421875,et=[.9999999999999971,57.15623566586292,-59.59796035547549,14.136097974741746,-.4919138160976202,3399464998481189e-20,4652362892704858e-20,-9837447530487956e-20,.0001580887032249125,-.00021026444172410488,.00021743961811521265,-.0001643181065367639,8441822398385275e-20,-26190838401581408e-21,36899182659531625e-22];function st(t){var e,s;if(function(t){return isFinite(t)&&t===Math.round(t)}(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)*st(1-t));if(t>=171.35)return 1/0;if(t>85){var i=t*t,o=i*t,p=o*t,a=p*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*p)+163879/(209018880*a)+5246819/(75246796800*a*t))}--t,s=et[0];for(var h=1;h<et.length;++h)s+=et[h]/(t+h);return e=t+tt+.5,Math.sqrt(2*Math.PI)*Math.pow(e,t+.5)*Math.exp(-e)*s}function rt(t){return String(t).length}function nt(){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 it(t,e,s){return t?e:s}function ot(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=(t=Math.round(+(t[0]+"e"+(t[1]?+t[1]-e:-e)))).toString().split("e"))[0]+"e"+(t[1]?+t[1]+e:e))))}function pt(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||j,cosh:Math.cosh||J,tanh:Math.tanh||W,asinh:Math.asinh||V,acosh:Math.acosh||X,atanh:Math.atanh||z,sqrt:Math.sqrt,log:Math.log,ln:Math.log,lg:Math.log10||D,log10:Math.log10||D,abs:Math.abs,ceil:Math.ceil,floor:Math.floor,round:Math.round,trunc:Math.trunc||Q,"-":H,"+":Number,exp:Math.exp,not:K,length:rt,"!":Z},this.binaryOps={"+":A,"-":C,"*":N,"/":P,"%":F,"^":Math.pow,"||":I,"==":S,"!=":R,">":U,"<":L,">=":q,"<=":B,and:_,or:$,in:G},this.ternaryOps={"?":it},this.functions={random:Y,fac:Z,min:Math.min,max:Math.max,hypot:Math.hypot||nt,pyt:Math.hypot||nt,pow:Math.pow,atan2:Math.atan2,if:it,gamma:st,roundTo:ot},this.consts={E:Math.E,PI:Math.PI,true:!0,false:!1}}pt.prototype.parse=function(t){var e=[],s=new b(this,new g(this,t),{allowMemberAccess:this.options.allowMemberAccess});return s.parseExpression(e),s.expect("TEOF","EOF"),new w(e,this)},pt.prototype.evaluate=function(t,e){return this.parse(t).evaluate(e)};var at=new pt;return pt.parse=function(t){return at.parse(t)},pt.evaluate=function(t,e){return at.parse(t).evaluate(e)},{Parser:pt,Expression:w}}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).exprEval={})}(this,(function(t){"use strict";var e="INUMBER",r="IOP1",s="IOP2",n="IOP3",i="IVAR",o="IVARNAME",a="IFUNCOP",p="IFUNCALL",h="IFUNDEF",u="IEXPR",c="IEXPREVAL",f="IMEMBER",l="IENDSTATEMENT",v="IARRAY";function y(t,e){this.type=t,this.value=null!=e?e:0}function x(t){return new y(r,t)}function w(t){return new y(s,t)}function d(t){return new y(n,t)}function g(t,a,p,h,c){for(var l,x,w,d,E=[],M=[],m=0;m<t.length;m++){var A=t[m],b=A.type;if(b===e||b===o)Array.isArray(A.value)?E.push.apply(E,g(A.value.map((function(t){return new y(e,t)})).concat(new y(v,A.value.length)),a,p,h,c)):E.push(A);else if(b===i&&c.hasOwnProperty(A.value))A=new y(e,c[A.value]),E.push(A);else if(b===s&&E.length>1)x=E.pop(),l=E.pop(),d=p[A.value],A=new y(e,d(l.value,x.value)),E.push(A);else if(b===n&&E.length>2)w=E.pop(),x=E.pop(),l=E.pop(),"?"===A.value?E.push(l.value?x.value:w.value):(d=h[A.value],A=new y(e,d(l.value,x.value,w.value)),E.push(A));else if(b===r&&E.length>0)l=E.pop(),d=a[A.value],A=new y(e,d(l.value)),E.push(A);else if(b===u){for(;E.length>0;)M.push(E.shift());M.push(new y(u,g(A.value,a,p,h,c)))}else if(b===f&&E.length>0)l=E.pop(),E.push(new y(e,l.value[A.value]));else{for(;E.length>0;)M.push(E.shift());M.push(A)}}for(;E.length>0;)M.push(E.shift());return M}function E(t,e,o){for(var a=[],p=0;p<t.length;p++){var h=t[p],c=h.type;if(c===i&&h.value===e)for(var f=0;f<o.tokens.length;f++){var l,v=o.tokens[f];l=v.type===r?x(v.value):v.type===s?w(v.value):v.type===n?d(v.value):new y(v.type,v.value),a.push(l)}else c===u?a.push(new y(u,E(h.value,e,o))):a.push(h)}return a}function M(t,y,x){var w,d,g,E,k,O,T=[];if(A(t))return b(t,x);for(var C=t.length,N=0;N<C;N++){var S=t[N],I=S.type;if(I===e||I===o)T.push(S.value);else if(I===s)d=T.pop(),w=T.pop(),"and"===S.value?T.push(!!w&&!!M(d,y,x)):"or"===S.value?T.push(!!w||!!M(d,y,x)):"="===S.value?(E=y.binaryOps[S.value],T.push(E(w,M(d,y,x),x))):(E=y.binaryOps[S.value],T.push(E(b(w,x),b(d,x))));else if(I===n)g=T.pop(),d=T.pop(),w=T.pop(),"?"===S.value?T.push(M(w?d:g,y,x)):(E=y.ternaryOps[S.value],T.push(E(b(w,x),b(d,x),b(g,x))));else if(I===i){if(/^__proto__|prototype|constructor$/.test(S.value))throw new Error("prototype access detected");if(S.value in y.functions)T.push(y.functions[S.value]);else if(S.value in y.unaryOps&&y.parser.isOperatorEnabled(S.value))T.push(y.unaryOps[S.value]);else{var F=x[S.value];if(void 0===F)throw new Error("undefined variable: "+S.value);T.push(F)}}else if(I===r)w=T.pop(),E=y.unaryOps[S.value],T.push(E(b(w,x)));else if(I===a){if(d=T.pop(),w=T.pop(),!(E=y.functions[S.value]).apply||!E.call)throw new Error(E+" is not a function");T.push(E.apply(void 0,[w,d]))}else if(I===p){for(O=S.value,k=[];O-- >0;)k.unshift(b(T.pop(),x));if(!(E=T.pop()).apply||!E.call)throw new Error(E+" is not a function");T.push(E.apply(void 0,k))}else if(I===h)T.push(function(){for(var t=T.pop(),e=[],r=S.value;r-- >0;)e.unshift(T.pop());var s=T.pop(),n=function(){for(var r=Object.assign({},x),s=0,n=e.length;s<n;s++)r[e[s]]=arguments[s];return M(t,y,r)};return Object.defineProperty(n,"name",{value:s,writable:!1}),x[s]=n,n}());else if(I===u)T.push(m(S,y));else if(I===c)T.push(S);else if(I===f)w=T.pop(),T.push(w[S.value]);else if(I===l)T.pop();else{if(I!==v)throw new Error("invalid Expression");for(O=S.value,k=[];O-- >0;)k.unshift(T.pop());T.push(k)}}if(T.length>1)throw new Error("invalid Expression (parity)");return 0===T[0]?0:b(T[0],x)}function m(t,e,r){return A(t)?t:{type:c,value:function(r){return M(t.value,e,r)}}}function A(t){return t&&t.type===c}function b(t,e){return A(t)?t.value(e):t}function k(t,a){for(var c,y,x,w,d,g,E=[],M=0;M<t.length;M++){var m=t[M],A=m.type;if(A===e)"number"==typeof m.value&&m.value<0?E.push("("+m.value+")"):Array.isArray(m.value)?E.push("["+m.value.map(O).join(", ")+"]"):E.push(O(m.value));else if(A===s)y=E.pop(),c=E.pop(),w=m.value,a?"^"===w?E.push("Math.pow("+c+", "+y+")"):"and"===w?E.push("(!!"+c+" && !!"+y+")"):"or"===w?E.push("(!!"+c+" || !!"+y+")"):"||"===w?E.push("(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }(("+c+"),("+y+")))"):"=="===w?E.push("("+c+" === "+y+")"):"!="===w?E.push("("+c+" !== "+y+")"):"["===w?E.push(c+"[("+y+") | 0]"):E.push("("+c+" "+w+" "+y+")"):"["===w?E.push(c+"["+y+"]"):E.push("("+c+" "+w+" "+y+")");else if(A===n){if(x=E.pop(),y=E.pop(),c=E.pop(),"?"!==(w=m.value))throw new Error("invalid Expression");E.push("("+c+" ? "+y+" : "+x+")")}else if(A===i||A===o)E.push(m.value);else if(A===r)c=E.pop(),"-"===(w=m.value)||"+"===w?E.push("("+w+c+")"):a?"not"===w?E.push("(!"+c+")"):"!"===w?E.push("fac("+c+")"):E.push(w+"("+c+")"):"!"===w?E.push("("+c+"!)"):E.push("("+w+" "+c+")");else if(A===p){for(g=m.value,d=[];g-- >0;)d.unshift(E.pop());w=E.pop(),E.push(w+"("+d.join(", ")+")")}else if(A===h){for(y=E.pop(),g=m.value,d=[];g-- >0;)d.unshift(E.pop());c=E.pop(),a?E.push("("+c+" = function("+d.join(", ")+") { return "+y+" })"):E.push("("+c+"("+d.join(", ")+") = "+y+")")}else if(A===f)c=E.pop(),E.push(c+"."+m.value);else if(A===v){for(g=m.value,d=[];g-- >0;)d.unshift(E.pop());E.push("["+d.join(", ")+"]")}else if(A===u)E.push("("+k(m.value,a)+")");else if(A!==l)throw new Error("invalid Expression")}return E.length>1&&(E=a?[E.join(",")]:[E.join(";")]),String(E[0])}function O(t){return"string"==typeof t?JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"):t}function T(t,e){for(var r=0;r<t.length;r++)if(t[r]===e)return!0;return!1}function C(t,e,r){for(var s=!!(r=r||{}).withMembers,n=null,a=0;a<t.length;a++){var p=t[a];p.type===i||p.type===o?s||T(e,p.value)?null!==n?(T(e,n)||e.push(n),n=p.value):n=p.value:e.push(p.value):p.type===f&&s&&null!==n?n+="."+p.value:p.type===u?C(p.value,e,r):null!==n&&(T(e,n)||e.push(n),n=null)}null===n||T(e,n)||e.push(n)}function N(t,e){this.tokens=t,this.parser=e,this.unaryOps=e.unaryOps,this.binaryOps=e.binaryOps,this.ternaryOps=e.ternaryOps,this.functions=e.functions}y.prototype.toString=function(){switch(this.type){case e:case r:case s:case n:case i:case o:case l:case a:return this.value;case p:return"CALL "+this.value;case h:return"DEF "+this.value;case v:return"ARRAY "+this.value;case f:return"."+this.value;default:return"Invalid Instruction"}},N.prototype.simplify=function(t){return t=t||{},new N(g(this.tokens,this.unaryOps,this.binaryOps,this.ternaryOps,t),this.parser)},N.prototype.substitute=function(t,e){return e instanceof N||(e=this.parser.parse(String(e))),new N(E(this.tokens,t,e),this.parser)},N.prototype.evaluate=function(t){return t=t||{},M(this.tokens,this,t)},N.prototype.toString=function(){return k(this.tokens,!1)},N.prototype.symbols=function(t){t=t||{};var e=[];return C(this.tokens,e,t),e},N.prototype.variables=function(t){t=t||{};var e=[];C(this.tokens,e,t);var r=this.functions;return e.filter((function(t){return!(t in r)}))},N.prototype.toJSFunction=function(t,e){var r=this,s=new Function(t,"with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return "+k(this.simplify(e).tokens,!0)+"; }");return function(){return s.apply(r,arguments)}};var S="TEOF",I="TOP",F="TFUNCOP",P="TNUMBER",L="TSTRING",R="TPAREN",j="TBRACKET",U="TCOMMA",_="TNAME",q="TSEMICOLON";function B(t,e,r){this.type=t,this.value=e,this.index=r}function V(t,e){this.pos=0,this.current=null,this.unaryOps=t.unaryOps,this.binaryOps=t.binaryOps,this.ternaryOps=t.ternaryOps,this.functions=t.functions,this.consts=t.consts,this.expression=e,this.savedPosition=0,this.savedCurrent=null,this.options=t.options,this.parser=t}B.prototype.toString=function(){return this.type+": "+this.value},V.prototype.newToken=function(t,e,r){return new B(t,e,null!=r?r:this.pos)},V.prototype.save=function(){this.savedPosition=this.pos,this.savedCurrent=this.current},V.prototype.restore=function(){this.pos=this.savedPosition,this.current=this.savedCurrent},V.prototype.next=function(){return this.pos>=this.expression.length?this.newToken(S,"EOF"):this.isWhitespace()||this.isComment()?this.next():this.isRadixInteger()||this.isNumber()||this.isOperator()||this.isString()||this.isParen()||this.isBracket()||this.isComma()||this.isSemicolon()||this.isNamedOp()||this.isFuncOp()||this.isConst()||this.isName()?this.current:void this.parseError('Unknown character "'+this.expression.charAt(this.pos)+'"')},V.prototype.isString=function(){var t=!1,e=this.pos,r=this.expression.charAt(e);if("'"===r||'"'===r)for(var s=this.expression.indexOf(r,e+1);s>=0&&this.pos<this.expression.length;){if(this.pos=s+1,"\\"!==this.expression.charAt(s-1)){var n=this.expression.substring(e+1,s);this.current=this.newToken(L,this.unescape(n),e),t=!0;break}s=this.expression.indexOf(r,s+1)}return t},V.prototype.isParen=function(){var t=this.expression.charAt(this.pos);return("("===t||")"===t)&&(this.current=this.newToken(R,t),this.pos++,!0)},V.prototype.isBracket=function(){var t=this.expression.charAt(this.pos);return!("["!==t&&"]"!==t||!this.isOperatorEnabled("["))&&(this.current=this.newToken(j,t),this.pos++,!0)},V.prototype.isComma=function(){return","===this.expression.charAt(this.pos)&&(this.current=this.newToken(U,","),this.pos++,!0)},V.prototype.isSemicolon=function(){return";"===this.expression.charAt(this.pos)&&(this.current=this.newToken(q,";"),this.pos++,!0)},V.prototype.isConst=function(){for(var t=this.pos,e=t;e<this.expression.length;e++){var r=this.expression.charAt(e);if(r.toUpperCase()===r.toLowerCase()&&(e===this.pos||"_"!==r&&"."!==r&&(r<"0"||r>"9")))break}if(e>t){var s=this.expression.substring(t,e);if(s in this.consts)return this.current=this.newToken(P,this.consts[s]),this.pos+=s.length,!0}return!1},V.prototype.isNamedOp=function(){for(var t=this.pos,e=t;e<this.expression.length;e++){var r=this.expression.charAt(e);if(r.toUpperCase()===r.toLowerCase()&&(e===this.pos||"_"!==r&&(r<"0"||r>"9")))break}if(e>t){var s=this.expression.substring(t,e);if(this.isOperatorEnabled(s)&&(s in this.binaryOps||s in this.unaryOps||s in this.ternaryOps))return this.current=this.newToken(I,s),this.pos+=s.length,!0}return!1},V.prototype.isFuncOp=function(){var t,e=this.expression.charAt(this.pos),r=this.pos+1,s=r;if("@"===e){for(;s<this.expression.length&&((e=this.expression.charAt(s)).toUpperCase()!==e.toLowerCase()||!(s===r||"_"!==e&&(e<"0"||e>"9")));s++);if(s>r&&(t=this.expression.substring(r,s))in this.functions)return this.current=this.newToken(F,t),this.pos=r+t.length,!0}return!1},V.prototype.isName=function(){for(var t=this.pos,e=t,r=!1;e<this.expression.length;e++){var s=this.expression.charAt(e);if(s.toUpperCase()===s.toLowerCase()){if(e===this.pos&&("$"===s||"_"===s)){"_"===s&&(r=!0);continue}if(e===this.pos||!r||"_"!==s&&(s<"0"||s>"9"))break}else r=!0}if(r){var n=this.expression.substring(t,e);return this.current=this.newToken(_,n),this.pos+=n.length,!0}return!1},V.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.pos>=this.expression.length));)e=this.expression.charAt(this.pos);return t};var $=/^[0-9a-f]{4}$/i;function D(t,e,r){this.parser=t,this.tokens=e,this.current=null,this.nextToken=null,this.next(),this.savedCurrent=null,this.savedNextToken=null,this.allowMemberAccess=!1!==r.allowMemberAccess}V.prototype.unescape=function(t){var e=t.indexOf("\\");if(e<0)return t;for(var r=t.substring(0,e);e>=0;){var s=t.charAt(++e);switch(s){case"'":r+="'";break;case'"':r+='"';break;case"\\":r+="\\";break;case"/":r+="/";break;case"b":r+="\b";break;case"f":r+="\f";break;case"n":r+="\n";break;case"r":r+="\r";break;case"t":r+="\t";break;case"u":var n=t.substring(e+1,e+5);$.test(n)||this.parseError("Illegal escape sequence: \\u"+n),r+=String.fromCharCode(parseInt(n,16)),e+=4;break;default:throw this.parseError('Illegal escape sequence: "\\'+s+'"')}++e;var i=t.indexOf("\\",e);r+=t.substring(e,i<0?t.length:i),e=i}return r},V.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)},V.prototype.isRadixInteger=function(){var t,e,r=this.pos;if(r>=this.expression.length-2||"0"!==this.expression.charAt(r))return!1;if(++r,"x"===this.expression.charAt(r))t=16,e=/^[0-9a-f]$/i,++r;else{if("b"!==this.expression.charAt(r))return!1;t=2,e=/^[01]$/i,++r}for(var s=!1,n=r;r<this.expression.length;){var i=this.expression.charAt(r);if(!e.test(i))break;r++,s=!0}return s&&(this.current=this.newToken(P,parseInt(this.expression.substring(n,r),t)),this.pos=r),s},V.prototype.isNumber=function(){for(var t,e=!1,r=this.pos,s=r,n=r,i=!1,o=!1;r<this.expression.length&&((t=this.expression.charAt(r))>="0"&&t<="9"||!i&&"."===t);)"."===t?i=!0:o=!0,r++,e=o;if(e&&(n=r),"e"===t||"E"===t){r++;for(var a=!0,p=!1;r<this.expression.length;){if(t=this.expression.charAt(r),!a||"+"!==t&&"-"!==t){if(!(t>="0"&&t<="9"))break;p=!0,a=!1}else a=!1;r++}p||(r=n)}return e?(this.current=this.newToken(P,parseFloat(this.expression.substring(s,r))),this.pos=r):this.pos=n,e},V.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(I,e);else if("∙"===e||"•"===e)this.current=this.newToken(I,"*");else if(">"===e)"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(I,">="),this.pos++):this.current=this.newToken(I,">");else if("<"===e)"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(I,"<="),this.pos++):this.current=this.newToken(I,"<");else if("|"===e){if("|"!==this.expression.charAt(this.pos+1))return!1;this.current=this.newToken(I,"||"),this.pos++}else if("="===e)"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(I,"=="),this.pos++):this.current=this.newToken(I,e);else{if("!"!==e)return!1;"="===this.expression.charAt(this.pos+1)?(this.current=this.newToken(I,"!="),this.pos++):this.current=this.newToken(I,e)}return this.pos++,!!this.isOperatorEnabled(this.current.value)||(this.pos=t,!1)},V.prototype.isOperatorEnabled=function(t){return this.parser.isOperatorEnabled(t)},V.prototype.getCoordinates=function(){var t,e=0,r=-1;do{e++,t=this.pos-r,r=this.expression.indexOf("\n",r+1)}while(r>=0&&r<this.pos);return{line:e,column:t}},V.prototype.parseError=function(t){var e=this.getCoordinates();throw new Error("parse error ["+e.line+":"+e.column+"]: "+t)},D.prototype.next=function(){return this.current=this.nextToken,this.nextToken=this.tokens.next()},D.prototype.tokenMatches=function(t,e){return void 0===e||(Array.isArray(e)?T(e,t.value):"function"==typeof e?e(t):t.value===e)},D.prototype.save=function(){this.savedCurrent=this.current,this.savedNextToken=this.nextToken,this.tokens.save()},D.prototype.restore=function(){this.tokens.restore(),this.current=this.savedCurrent,this.nextToken=this.savedNextToken},D.prototype.accept=function(t,e){return!(this.nextToken.type!==t||!this.tokenMatches(this.nextToken,e))&&(this.next(),!0)},D.prototype.expect=function(t,e){if(!this.accept(t,e)){var r=this.tokens.getCoordinates();throw new Error("parse error ["+r.line+":"+r.column+"]: Expected "+(e||t))}},D.prototype.parseAtom=function(t){var r=this.tokens.unaryOps;if(this.accept(_)||this.accept(I,(function(t){return t.value in r})))t.push(new y(i,this.current.value));else if(this.accept(P))t.push(new y(e,this.current.value));else if(this.accept(L))t.push(new y(e,this.current.value));else if(this.accept(R,"("))this.parseExpression(t),this.expect(R,")");else{if(!this.accept(j,"["))throw new Error("unexpected "+this.nextToken);if(this.accept(j,"]"))t.push(new y(v,0));else{var s=this.parseArrayList(t);t.push(new y(v,s))}}},D.prototype.parseExpression=function(t){var e=[];this.parseUntilEndStatement(t,e)||(this.parseVariableAssignmentExpression(e),this.parseUntilEndStatement(t,e)||this.pushExpression(t,e))},D.prototype.pushExpression=function(t,e){for(var r=0,s=e.length;r<s;r++)t.push(e[r])},D.prototype.parseUntilEndStatement=function(t,e){return!!this.accept(q)&&(!this.nextToken||this.nextToken.type===S||this.nextToken.type===R&&")"===this.nextToken.value||e.push(new y(l)),this.nextToken.type!==S&&this.parseExpression(e),t.push(new y(u,e)),!0)},D.prototype.parseArrayList=function(t){for(var e=0;!this.accept(j,"]");)for(this.parseExpression(t),++e;this.accept(U);)this.parseExpression(t),++e;return e},D.prototype.parseVariableAssignmentExpression=function(t){for(this.parseConditionalExpression(t);this.accept(I,"=");){var e=t.pop(),r=[],s=t.length-1;if(e.type!==p){if(e.type!==i&&e.type!==f)throw new Error("expected variable for assignment");this.parseVariableAssignmentExpression(r),t.push(new y(o,e.value)),t.push(new y(u,r)),t.push(w("="))}else{if(!this.tokens.isOperatorEnabled("()="))throw new Error("function definition is not permitted");for(var n=0,a=e.value+1;n<a;n++){var c=s-n;t[c].type===i&&(t[c]=new y(o,t[c].value))}this.parseVariableAssignmentExpression(r),t.push(new y(u,r)),t.push(new y(h,e.value))}}},D.prototype.parseConditionalExpression=function(t){for(this.parseOrExpression(t);this.accept(I,"?");){var e=[],r=[];this.parseConditionalExpression(e),this.expect(I,":"),this.parseConditionalExpression(r),t.push(new y(u,e)),t.push(new y(u,r)),t.push(d("?"))}},D.prototype.parseOrExpression=function(t){for(this.parseAndExpression(t);this.accept(I,"or");){var e=[];this.parseAndExpression(e),t.push(new y(u,e)),t.push(w("or"))}},D.prototype.parseAndExpression=function(t){for(this.parseComparison(t);this.accept(I,"and");){var e=[];this.parseComparison(e),t.push(new y(u,e)),t.push(w("and"))}};var G=["==","!=","<","<=",">=",">","in"];D.prototype.parseComparison=function(t){for(this.parseAddSub(t);this.accept(I,G);){var e=this.current;this.parseAddSub(t),t.push(w(e.value))}};var J=["+","-","||"];D.prototype.parseAddSub=function(t){for(this.parseTerm(t);this.accept(I,J);){var e=this.current;this.parseTerm(t),t.push(w(e.value))}};var W=["*","/","%"];function X(t,e){return Number(t)+Number(e)}function Y(t,e){return t-e}function K(t,e){return t*e}function z(t,e){return t/e}function H(t,e){return t%e}function Q(t,e){return Array.isArray(t)&&Array.isArray(e)?t.concat(e):""+t+e}function Z(t,e){return t===e}function tt(t,e){return t!==e}function et(t,e){return t>e}function rt(t,e){return t<e}function st(t,e){return t>=e}function nt(t,e){return t<=e}function it(t,e){return Boolean(t&&e)}function ot(t,e){return Boolean(t||e)}function at(t,e){return T(e,t)}function pt(t){return(Math.exp(t)-Math.exp(-t))/2}function ht(t){return(Math.exp(t)+Math.exp(-t))/2}function ut(t){return t===1/0?1:t===-1/0?-1:(Math.exp(t)-Math.exp(-t))/(Math.exp(t)+Math.exp(-t))}function ct(t){return t===-1/0?t:Math.log(t+Math.sqrt(t*t+1))}function ft(t){return Math.log(t+Math.sqrt(t*t-1))}function lt(t){return Math.log((1+t)/(1-t))/2}function vt(t){return Math.log(t)*Math.LOG10E}function yt(t){return-t}function xt(t){return!t}function wt(t){return t<0?Math.ceil(t):Math.floor(t)}function dt(t){return Math.random()*(t||1)}function gt(t){return mt(t+1)}D.prototype.parseTerm=function(t){for(this.parseFactor(t);this.accept(I,W);){var e=this.current;this.parseFactor(t),t.push(w(e.value))}},D.prototype.parseFactor=function(t){var e=this.tokens.unaryOps;if(this.save(),this.accept(I,(function(t){return t.value in e}))){if("-"!==this.current.value&&"+"!==this.current.value){if(this.nextToken.type===R&&"("===this.nextToken.value)return this.restore(),void this.parseExponential(t);if(this.nextToken.type===q||this.nextToken.type===U||this.nextToken.type===S||this.nextToken.type===R&&")"===this.nextToken.value)return this.restore(),void this.parseAtom(t)}var r=this.current;this.parseFactor(t),t.push(x(r.value))}else this.parseExponential(t)},D.prototype.parseExponential=function(t){for(this.parsePostfixExpression(t);this.accept(I,"^");)this.parseFactor(t),t.push(w("^"))},D.prototype.parsePostfixExpression=function(t){for(this.parseFunctionOperator(t);this.accept(I,"!");)t.push(x("!"))},D.prototype.parseFunctionOperator=function(t){var e,r=this.tokens.functions;function s(t){return t.value in r}for(this.parseFunctionCall(t);this.accept(F,s);)e=this.current,this.parseFactor(t),t.push(new y(a,e.value))},D.prototype.parseFunctionCall=function(t){var e=this.tokens.unaryOps;if(this.accept(I,(function(t){return t.value in e}))){var r=this.current;this.parseAtom(t),t.push(x(r.value))}else for(this.parseMemberExpression(t);this.accept(R,"(");)if(this.accept(R,")"))t.push(new y(p,0));else{var s=this.parseArgumentList(t);t.push(new y(p,s))}},D.prototype.parseArgumentList=function(t){for(var e=0;!this.accept(R,")");)for(this.parseExpression(t),++e;this.accept(U);)this.parseExpression(t),++e;return e},D.prototype.parseMemberExpression=function(t){for(this.parseAtom(t);this.accept(I,".")||this.accept(j,"[");){var e=this.current;if("."===e.value){if(!this.allowMemberAccess)throw new Error('unexpected ".", member access is not permitted');this.expect(_),t.push(new y(f,this.current.value))}else{if("["!==e.value)throw new Error("unexpected symbol: "+e.value);if(!this.tokens.isOperatorEnabled("["))throw new Error('unexpected "[]", arrays are disabled');this.parseExpression(t),this.expect(j,"]"),t.push(w("["))}}};var Et=4.7421875,Mt=[.9999999999999971,57.15623566586292,-59.59796035547549,14.136097974741746,-.4919138160976202,3399464998481189e-20,4652362892704858e-20,-9837447530487956e-20,.0001580887032249125,-.00021026444172410488,.00021743961811521265,-.0001643181065367639,8441822398385275e-20,-26190838401581408e-21,36899182659531625e-22];function mt(t){var e,r;if(function(t){return isFinite(t)&&t===Math.round(t)}(t)){if(t<=0)return isFinite(t)?1/0:NaN;if(t>171)return 1/0;for(var s=t-2,n=t-1;s>1;)n*=s,s--;return 0===n&&(n=1),n}if(t<.5)return Math.PI/(Math.sin(Math.PI*t)*mt(1-t));if(t>=171.35)return 1/0;if(t>85){var i=t*t,o=i*t,a=o*t,p=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*p)+5246819/(75246796800*p*t))}--t,r=Mt[0];for(var h=1;h<Mt.length;++h)r+=Mt[h]/(t+h);return e=t+Et+.5,Math.sqrt(2*Math.PI)*Math.pow(e,t+.5)*Math.exp(-e)*r}function At(t){return Array.isArray(t)?t.length:String(t).length}function bt(){for(var t=0,e=0,r=0;r<arguments.length;r++){var s,n=Math.abs(arguments[r]);e<n?(t=t*(s=e/n)*s+1,e=n):t+=n>0?(s=n/e)*s:n}return e===1/0?1/0:e*Math.sqrt(t)}function kt(t,e,r){return t?e:r}function Ot(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=(t=Math.round(+(t[0]+"e"+(t[1]?+t[1]-e:-e)))).toString().split("e"))[0]+"e"+(t[1]?+t[1]+e:e))))}function Tt(t,e,r){return r&&(r[t]=e),e}function Ct(t,e){return t[0|e]}function Nt(t){return 1===arguments.length&&Array.isArray(t)?Math.max.apply(Math,t):Math.max.apply(Math,arguments)}function St(t){return 1===arguments.length&&Array.isArray(t)?Math.min.apply(Math,t):Math.min.apply(Math,arguments)}function It(t,e){if("function"!=typeof t)throw new Error("First argument to map is not a function");if(!Array.isArray(e))throw new Error("Second argument to map is not an array");return e.map((function(e,r){return t(e,r)}))}function Ft(t,e,r){if("function"!=typeof t)throw new Error("First argument to fold is not a function");if(!Array.isArray(r))throw new Error("Second argument to fold is not an array");return r.reduce((function(e,r,s){return t(e,r,s)}),e)}function Pt(t,e){if("function"!=typeof t)throw new Error("First argument to filter is not a function");if(!Array.isArray(e))throw new Error("Second argument to filter is not an array");return e.filter((function(e,r){return t(e,r)}))}function Lt(t,e){if(!Array.isArray(e)&&"string"!=typeof e)throw new Error("Second argument to indexOf is not a string or array");return e.indexOf(t)}function Rt(t,e){if(!Array.isArray(e))throw new Error("Second argument to join is not an array");return e.join(t)}function jt(t){return(t>0)-(t<0)||+t}var Ut=1/3;function _t(t){return t<0?-Math.pow(-t,Ut):Math.pow(t,Ut)}function qt(t){return Math.exp(t)-1}function Bt(t){return Math.log(1+t)}function Vt(t){return Math.log(t)/Math.LN2}function $t(t){if(!Array.isArray(t))throw new Error("Sum argument is not an array");return t.reduce((function(t,e){return t+Number(e)}),0)}function Dt(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||pt,cosh:Math.cosh||ht,tanh:Math.tanh||ut,asinh:Math.asinh||ct,acosh:Math.acosh||ft,atanh:Math.atanh||lt,sqrt:Math.sqrt,cbrt:Math.cbrt||_t,log:Math.log,log2:Math.log2||Vt,ln:Math.log,lg:Math.log10||vt,log10:Math.log10||vt,expm1:Math.expm1||qt,log1p:Math.log1p||Bt,abs:Math.abs,ceil:Math.ceil,floor:Math.floor,round:Math.round,trunc:Math.trunc||wt,"-":yt,"+":Number,exp:Math.exp,not:xt,length:At,"!":gt,sign:Math.sign||jt},this.binaryOps={"+":X,"-":Y,"*":K,"/":z,"%":H,"^":Math.pow,"||":Q,"==":Z,"!=":tt,">":et,"<":rt,">=":st,"<=":nt,and:it,or:ot,in:at,"=":Tt,"[":Ct},this.ternaryOps={"?":kt},this.functions={random:dt,fac:gt,min:St,max:Nt,hypot:Math.hypot||bt,pyt:Math.hypot||bt,pow:Math.pow,atan2:Math.atan2,if:kt,gamma:mt,roundTo:Ot,map:It,fold:Ft,filter:Pt,indexOf:Lt,join:Rt,sum:$t},this.consts={E:Math.E,PI:Math.PI,true:!0,false:!1}}Dt.prototype.parse=function(t){var e=[],r=new D(this,new V(this,t),{allowMemberAccess:this.options.allowMemberAccess});return r.parseExpression(e),r.expect(S,"EOF"),new N(e,this)},Dt.prototype.evaluate=function(t,e){return this.parse(t).evaluate(e)};var Gt=new Dt;Dt.parse=function(t){return Gt.parse(t)},Dt.evaluate=function(t,e){return Gt.parse(t).evaluate(e)};var Jt={"+":"add","-":"subtract","*":"multiply","/":"divide","%":"remainder","^":"power","!":"factorial","<":"comparison",">":"comparison","<=":"comparison",">=":"comparison","==":"comparison","!=":"comparison","||":"concatenate",and:"logical",or:"logical",not:"logical","?":"conditional",":":"conditional","=":"assignment","[":"array","()=":"fndef"};Dt.prototype.isOperatorEnabled=function(t){var e=function(t){return Jt.hasOwnProperty(t)?Jt[t]:t}(t),r=this.options.operators||{};return!(e in r)||!!r[e]}; | ||
/*! | ||
Based on ndef.parser, by Raphael Graf(r@undefined.ch) | ||
http://www.undefined.ch/mparser/index.html | ||
Ported to JavaScript and modified by Matthew Crumley (email@matthewcrumley.com, http://silentmatt.com/) | ||
You are free to use and modify this code in anyway you find useful. Please leave this comment in the code | ||
to acknowledge its original source. If you feel like it, I enjoy hearing about projects that use my code, | ||
but don't feel like you have to let me know or ask permission. | ||
*/ | ||
var Wt={Parser:Dt,Expression:N};t.Expression=N,t.Parser=Dt,t.default=Wt,Object.defineProperty(t,"__esModule",{value:!0})})); |
{ | ||
"name": "@oat-sa/expr-eval", | ||
"version": "1.3.2", | ||
"version": "2.0.0", | ||
"description": "Mathematical expression evaluator", | ||
"main": "dist/bundle.js", | ||
"module": "dist/index.mjs", | ||
"typings": "parser.d.ts", | ||
@@ -12,19 +13,20 @@ "directories": { | ||
"devDependencies": { | ||
"eslint": "^5.16.0", | ||
"eslint-config-semistandard": "^13.0.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint": "^6.3.0", | ||
"eslint-config-semistandard": "^15.0.0", | ||
"eslint-config-standard": "^13.0.1", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-node": "^8.0.1", | ||
"eslint-plugin-node": "^9.2.0", | ||
"eslint-plugin-promise": "^4.3.1", | ||
"eslint-plugin-standard": "^4.1.0", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^10.0.0", | ||
"rollup": "^0.63.5", | ||
"rollup-plugin-uglify": "^3.0.0" | ||
"nyc": "^14.1.1", | ||
"rollup": "^1.20.3", | ||
"rollup-plugin-terser": "^7.0.2" | ||
}, | ||
"scripts": { | ||
"test": "npm run build && mocha", | ||
"coverage": "npm run build && istanbul cover _mocha", | ||
"coverage": "npm run build && nyc --reporter=lcov --reporter=text-summary mocha", | ||
"lint": "eslint index.js src test rollup.config.js rollup-min.config.js", | ||
"build": "rollup -c rollup.config.js && rollup -c rollup-min.config.js", | ||
"watch": "rollup -c rollup.config.js -w", | ||
"build": "rollup -c rollup.config.js && rollup -c rollup-min.config.js && rollup -c rollup-esm.config.js", | ||
"prepublish": "npm run build" | ||
@@ -31,0 +33,0 @@ }, |
@@ -48,3 +48,13 @@ export type Value = number | ||
length?: boolean, | ||
in?: boolean | ||
in?: boolean, | ||
random?: boolean, | ||
min?: boolean, | ||
max?: boolean, | ||
assignment?: boolean, | ||
fndef?: boolean, | ||
cbrt?: boolean, | ||
expm1?: boolean, | ||
log1p?: boolean, | ||
sign?: boolean, | ||
log2?: boolean | ||
}; | ||
@@ -55,3 +65,5 @@ } | ||
constructor(options?: ParserOptions); | ||
unaryOps: any; | ||
functions: any; | ||
consts: any; | ||
parse(expression: string): Expression; | ||
@@ -69,3 +81,3 @@ evaluate(expression: string, values?: Value): number; | ||
variables(options?: { withMembers?: boolean }): string[]; | ||
toJSFunction(params: string, values?: Value): (...args: any[]) => number; | ||
toJSFunction(params: string | string[], values?: Value): (...args: any[]) => number; | ||
} |
150
README.md
@@ -26,7 +26,7 @@ JavaScript Expression Evaluator | ||
------------------------------------- | ||
```js | ||
const Parser = require('expr-eval').Parser; | ||
var Parser = require('expr-eval').Parser; | ||
var parser = new Parser(); | ||
var expr = parser.parse('2 * x + 1'); | ||
const parser = new Parser(); | ||
let expr = parser.parse('2 * x + 1'); | ||
console.log(expr.evaluate({ x: 3 })); // 7 | ||
@@ -36,3 +36,3 @@ | ||
Parser.evaluate('6 * x', { x: 7 }) // 42 | ||
``` | ||
Documentation | ||
@@ -57,4 +57,5 @@ ------------------------------------- | ||
- [Unary operators](#unary-operators) | ||
- [Array literals](#array-literals) | ||
- [Pre-defined functions](#pre-defined-functions) | ||
- [Custom functions](#custom-functions) | ||
- [Custom JavaScript functions](#custom-javascript-functions) | ||
- [Constants](#constants) | ||
@@ -74,4 +75,4 @@ | ||
For example, the following will create a `Parser` that does not allow comparison or logical operators, but does allow `in`: | ||
var parser = new Parser({ | ||
```js | ||
const parser = new Parser({ | ||
operators: { | ||
@@ -93,7 +94,8 @@ // These default to true, but are included to be explicit | ||
// The in operator is disabled by default in the current version | ||
'in': true | ||
// Disable 'in' and = operators | ||
'in': false, | ||
assignment: false | ||
} | ||
}); | ||
``` | ||
#### parse(expression: string) | ||
@@ -128,3 +130,3 @@ | ||
exception. | ||
```js | ||
js> expr = Parser.parse("2 ^ x"); | ||
@@ -134,3 +136,3 @@ (2^x) | ||
8 | ||
``` | ||
#### substitute(variable: string, expression: Expression | string | number) | ||
@@ -141,3 +143,3 @@ | ||
or number, it will be parsed into an `Expression`. | ||
```js | ||
js> expr = Parser.parse("2 * x + 1"); | ||
@@ -149,3 +151,3 @@ ((2*x)+1) | ||
25 | ||
``` | ||
#### simplify(variables: object) | ||
@@ -164,3 +166,3 @@ | ||
replaced with "8", resulting in `((8*x)+1)`. | ||
```js | ||
js> expr = Parser.parse("x * (y * atan(1))").simplify({ y: 4 }); | ||
@@ -170,7 +172,7 @@ (x*3.141592653589793) | ||
6.283185307179586 | ||
``` | ||
#### variables(options?: object) | ||
Get an array of the unbound variables in the expression. | ||
```js | ||
js> expr = Parser.parse("x * (y * atan(1))"); | ||
@@ -182,3 +184,3 @@ (x*(y*atan(1))) | ||
x | ||
``` | ||
By default, `variables` will return "top-level" objects, so for example, `Parser.parse(x.y.z).variables()` returns `['x']`. If you want to get the whole chain of object members, you can call it with `{ withMembers: true }`. So `Parser.parse(x.y.z).variables({ withMembers: true })` would return `['x.y.z']`. | ||
@@ -190,3 +192,3 @@ | ||
expression. | ||
```js | ||
js> expr = Parser.parse("min(x, y, z)"); | ||
@@ -198,3 +200,3 @@ (min(x, y, z)) | ||
min,x | ||
``` | ||
Like `variables`, `symbols` accepts an option argument `{ withMembers: true }` to include object members. | ||
@@ -215,3 +217,3 @@ | ||
simplified with variables bound to the supplied values. | ||
```js | ||
js> expr = Parser.parse("x + y + z"); | ||
@@ -227,3 +229,3 @@ ((x + y) + z) | ||
105 | ||
``` | ||
### Expression Syntax ### | ||
@@ -240,3 +242,3 @@ | ||
(...) | None | Grouping | ||
f(), x.y | Left | Function call, property access | ||
f(), x.y, a[i] | Left | Function call, property access, array indexing | ||
! | Left | Factorial | ||
@@ -246,18 +248,18 @@ ^ | Right | Exponentiation | ||
\*, /, % | Left | Multiplication, division, remainder | ||
+, -, \|\| | Left | Addition, subtraction, concatenation | ||
==, !=, >=, <=, >, <, in | Left | Equals, not equals, etc. "in" means "is the left operand included in the right array operand?" (disabled by default) | ||
+, -, \|\| | Left | Addition, subtraction, array/list concatenation | ||
==, !=, >=, <=, >, <, in | Left | Equals, not equals, etc. "in" means "is the left operand included in the right array operand?" | ||
and | Left | Logical AND | ||
or | Left | Logical OR | ||
x ? y : z | Right | Ternary conditional (if x then y else z) | ||
The `in` operator is disabled by default in the current version. To use it, | ||
construct a `Parser` instance with `operators.in` set to `true`. For example: | ||
var parser = new Parser({ | ||
= | Right | Variable assignment | ||
; | Left | Expression separator | ||
```js | ||
const parser = new Parser({ | ||
operators: { | ||
'in': true | ||
'in': true, | ||
'assignment': true | ||
} | ||
}); | ||
// Now parser supports 'x in array' expressions | ||
// Now parser supports 'x in array' and 'y = 2*x' expressions | ||
``` | ||
#### Unary operators | ||
@@ -280,3 +282,3 @@ | ||
x! | Factorial (x * (x-1) * (x-2) * … * 2 * 1). gamma(x + 1) for non-integers. | ||
abs x | Absolute value (magnatude) of x | ||
abs x | Absolute value (magnitude) of x | ||
acos x | Arc cosine of x (in radians) | ||
@@ -288,2 +290,3 @@ acosh x | Hyperbolic arc cosine of x (in radians) | ||
atanh x | Hyperbolic arc tangent of x (in radians) | ||
cbrt x | Cube root of x | ||
ceil x | Ceiling of x — the smallest integer that’s >= x | ||
@@ -293,9 +296,13 @@ cos x | Cosine of x (x is in radians) | ||
exp x | e^x (exponential/antilogarithm function with base e) | ||
expm1 x | e^x - 1 | ||
floor x | Floor of x — the largest integer that’s <= x | ||
length x | String length of x | ||
length x | String or array length of x | ||
ln x | Natural logarithm of x | ||
log x | Natural logarithm of x (synonym for ln, not base-10) | ||
log10 x | Base-10 logarithm of x | ||
log2 x | Base-2 logarithm of x | ||
log1p x | Natural logarithm of (1 + x) | ||
not x | Logical NOT operator | ||
round x | X, rounded to the nearest integer, using "gradeschool rounding" | ||
round x | X, rounded to the nearest integer, using "grade-school rounding" | ||
sign x | Sign of x (-1, 0, or 1 for negative, zero, or positive respectively) | ||
sin x | Sine of x (x is in radians) | ||
@@ -314,21 +321,42 @@ sinh x | Hyperbolic sine of x (x is in radians) | ||
Function | Description | ||
:----------- | :---------- | ||
random(n) | Get a random number in the range [0, n). If n is zero, or not provided, it defaults to 1. | ||
fac(n) | n! (factorial of n: "n * (n-1) * (n-2) * … * 2 * 1") Deprecated. Use the ! operator instead. | ||
min(a,b,…) | Get the smallest (minimum) number in the list | ||
max(a,b,…) | Get the largest (maximum) number in the list | ||
hypot(a,b) | Hypotenuse, i.e. the square root of the sum of squares of its arguments. | ||
pyt(a, b) | Alias for hypot | ||
pow(x, y) | Equivalent to x^y. For consistency with JavaScript's Math object. | ||
atan2(y, x) | Arc tangent of x/y. i.e. the angle between (0, 0) and (x, y) in radians. | ||
if(c, a, b) | Function form of c ? a : b | ||
roundTo(x, n) | Rounds x to n places after the decimal point. | ||
Function | Description | ||
:------------ | :---------- | ||
random(n) | Get a random number in the range [0, n). If n is zero, or not provided, it defaults to 1. | ||
fac(n) | n! (factorial of n: "n * (n-1) * (n-2) * … * 2 * 1") Deprecated. Use the ! operator instead. | ||
min(a,b,…) | Get the smallest (minimum) number in the list. | ||
max(a,b,…) | Get the largest (maximum) number in the list. | ||
hypot(a,b) | Hypotenuse, i.e. the square root of the sum of squares of its arguments. | ||
pyt(a, b) | Alias for hypot. | ||
pow(x, y) | Equivalent to x^y. For consistency with JavaScript's Math object. | ||
atan2(y, x) | Arc tangent of x/y. i.e. the angle between (0, 0) and (x, y) in radians. | ||
roundTo(x, n) | Rounds x to n places after the decimal point. | ||
map(f, a) | Array map: Pass each element of `a` the function `f`, and return an array of the results. | ||
fold(f, y, a) | Array fold: Fold/reduce array `a` into a single value, `y` by setting `y = f(y, x, index)` for each element `x` of the array. | ||
filter(f, a) | Array filter: Return an array containing only the values from `a` where `f(x, index)` is `true`. | ||
indexOf(x, a) | Return the first index of string or array `a` matching the value `x`, or `-1` if not found. | ||
join(sep, a) | Concatenate the elements of `a`, separated by `sep`. | ||
if(c, a, b) | Function form of c ? a : b. Note: This always evaluates both `a` and `b`, regardless of whether `c` is `true` or not. Use `c ? a : b` instead if there are side effects, or if evaluating the branches could be expensive. | ||
#### Custom functions | ||
#### Array literals | ||
Arrays can be created by including the elements inside square `[]` brackets, separated by commas. For example: | ||
[ 1, 2, 3, 2+2, 10/2, 3! ] | ||
#### Function definitions | ||
You can define functions using the syntax `name(params) = expression`. When it's evaluated, the name will be added to the passed in scope as a function. You can call it later in the expression, or make it available to other expressions by re-using the same scope object. Functions can support multiple parameters, separated by commas. | ||
Examples: | ||
```js | ||
square(x) = x*x | ||
add(a, b) = a + b | ||
factorial(x) = x < 2 ? 1 : x * factorial(x - 1) | ||
``` | ||
#### Custom JavaScript functions | ||
If you need additional functions that aren't supported out of the box, you can easily add them in your own code. Instances of the `Parser` class have a property called `functions` that's simply an object with all the functions that are in scope. You can add, replace, or delete any of the properties to customize what's available in the expressions. For example: | ||
```js | ||
const parser = new Parser(); | ||
var parser = new Parser(); | ||
// Add a new function | ||
@@ -338,9 +366,9 @@ parser.functions.customAddFunction = function (arg1, arg2) { | ||
}; | ||
// Remove the factorial function | ||
delete parser.functions.fac; | ||
parser.evaluate('customAddFunction(2, 4) == 6'); // true | ||
//parser.evaluate('fac(3)'); // This will fail | ||
``` | ||
#### Constants | ||
@@ -360,14 +388,14 @@ | ||
constants available to your expressions. For example: | ||
var parser = new Parser(); | ||
```js | ||
const parser = new Parser(); | ||
parser.consts.R = 1.234; | ||
console.log(parser.parse('A+B/R').toString()); // ((A + B) / 1.234) | ||
``` | ||
To disable the pre-defined constants, you can replace or delete `parser.consts`: | ||
var parser = new Parser(); | ||
```js | ||
const parser = new Parser(); | ||
parser.consts = {}; | ||
``` | ||
### Tests ### | ||
@@ -374,0 +402,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
151592
8
3616
382