Spaces:
Build error
Build error
| JavaScript Expression Evaluator | |
| =============================== | |
| [](https://www.npmjs.com/package/expr-eval) | |
| [](https://cdnjs.com/libraries/expr-eval) | |
| [](https://travis-ci.org/silentmatt/expr-eval) | |
| Description | |
| ------------------------------------- | |
| Parses and evaluates mathematical expressions. It's a safer and more | |
| math-oriented alternative to using JavaScript’s `eval` function for mathematical | |
| expressions. | |
| It has built-in support for common math operators and functions. Additionally, | |
| you can add your own JavaScript functions. Expressions can be evaluated | |
| directly, or compiled into native JavaScript functions. | |
| Installation | |
| ------------------------------------- | |
| npm install expr-eval | |
| Basic Usage | |
| ------------------------------------- | |
| var Parser = require('expr-eval').Parser; | |
| var parser = new Parser(); | |
| var expr = parser.parse('2 * x + 1'); | |
| console.log(expr.evaluate({ x: 3 })); // 7 | |
| // or | |
| Parser.evaluate('6 * x', { x: 7 }) // 42 | |
| Documentation | |
| ------------------------------------- | |
| * [Parser](#parser) | |
| - [Parser()](#parser-1) | |
| - [parse(expression: string)](#parseexpression-string) | |
| - [Parser.parse(expression: string)](#parserparseexpression-string) | |
| - [Parser.evaluate(expression: string, variables?: object)](#parserevaluateexpression-string-variables-object) | |
| * [Expression](#expression) | |
| - [evaluate(variables?: object)](#evaluatevariables-object) | |
| - [substitute(variable: string, expression: Expression | string | number)](#substitutevariable-string-expression-expression--string--number) | |
| - [simplify(variables: object)](#simplifyvariables-object) | |
| - [variables(options?: object)](#variablesoptions-object) | |
| - [symbols(options?: object)](#symbolsoptions-object) | |
| - [toString()](#tostring) | |
| - [toJSFunction(parameters: array | string, variables?: object)](#tojsfunctionparameters-array--string-variables-object) | |
| * [Expression Syntax](#expression-syntax) | |
| - [Operator Precedence](#operator-precedence) | |
| - [Unary operators](#unary-operators) | |
| - [Array literals](#array-literals) | |
| - [Pre-defined functions](#pre-defined-functions) | |
| - [Custom JavaScript functions](#custom-javascript-functions) | |
| - [Constants](#constants) | |
| ### Parser ### | |
| Parser is the main class in the library. It has as single `parse` method, and | |
| "static" methods for parsing and evaluating expressions. | |
| #### Parser() | |
| Constructs a new `Parser` instance. | |
| The constructor takes an optional `options` parameter that allows you to enable or disable operators. | |
| For example, the following will create a `Parser` that does not allow comparison or logical operators, but does allow `in`: | |
| var parser = new Parser({ | |
| operators: { | |
| // These default to true, but are included to be explicit | |
| add: true, | |
| concatenate: true, | |
| conditional: true, | |
| divide: true, | |
| factorial: true, | |
| multiply: true, | |
| power: true, | |
| remainder: true, | |
| subtract: true, | |
| // Disable and, or, not, <, ==, !=, etc. | |
| logical: false, | |
| comparison: false, | |
| // Disable 'in' and = operators | |
| 'in': false, | |
| assignment: false | |
| } | |
| }); | |
| #### parse(expression: string) | |
| Convert a mathematical expression into an `Expression` object. | |
| #### Parser.parse(expression: string) | |
| Static equivalent of `new Parser().parse(expression)`. | |
| #### Parser.evaluate(expression: string, variables?: object) | |
| Parse and immediately evaluate an expression using the values and functions from | |
| the `variables` object. | |
| Parser.evaluate(expr, vars) is equivalent to calling | |
| Parser.parse(expr).evaluate(vars). | |
| ### Expression ### | |
| `Parser.parse(str)` returns an `Expression` object. `Expression`s are similar to | |
| JavaScript functions, i.e. they can be "called" with variables bound to | |
| passed-in values. In fact, they can even be converted into JavaScript | |
| functions. | |
| #### evaluate(variables?: object) | |
| Evaluate the expression, with variables bound to the values in {variables}. Each | |
| variable in the expression is bound to the corresponding member of the | |
| `variables` object. If there are unbound variables, `evaluate` will throw an | |
| exception. | |
| js> expr = Parser.parse("2 ^ x"); | |
| (2^x) | |
| js> expr.evaluate({ x: 3 }); | |
| 8 | |
| #### substitute(variable: string, expression: Expression | string | number) | |
| Create a new `Expression` with the specified variable replaced with another | |
| expression. This is similar to function composition. If `expression` is a string | |
| or number, it will be parsed into an `Expression`. | |
| js> expr = Parser.parse("2 * x + 1"); | |
| ((2*x)+1) | |
| js> expr.substitute("x", "4 * x"); | |
| ((2*(4*x))+1) | |
| js> expr2.evaluate({ x: 3 }); | |
| 25 | |
| #### simplify(variables: object) | |
| Simplify constant sub-expressions and replace variable references with literal | |
| values. This is basically a partial evaluation, that does as much of the | |
| calculation as it can with the provided variables. Function calls are not | |
| evaluated (except the built-in operator functions), since they may not be | |
| deterministic. | |
| Simplify is pretty simple. For example, it doesn’t know that addition and | |
| multiplication are associative, so `((2*(4*x))+1)` from the previous example | |
| cannot be simplified unless you provide a value for x. `2*4*x+1` can however, | |
| because it’s parsed as `(((2*4)*x)+1)`, so the `(2*4)` sub-expression will be | |
| replaced with "8", resulting in `((8*x)+1)`. | |
| js> expr = Parser.parse("x * (y * atan(1))").simplify({ y: 4 }); | |
| (x*3.141592653589793) | |
| js> expr.evaluate({ x: 2 }); | |
| 6.283185307179586 | |
| #### variables(options?: object) | |
| Get an array of the unbound variables in the expression. | |
| js> expr = Parser.parse("x * (y * atan(1))"); | |
| (x*(y*atan(1))) | |
| js> expr.variables(); | |
| x,y | |
| js> expr.simplify({ y: 4 }).variables(); | |
| 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']`. | |
| #### symbols(options?: object) | |
| Get an array of variables, including any built-in functions used in the | |
| expression. | |
| js> expr = Parser.parse("min(x, y, z)"); | |
| (min(x, y, z)) | |
| js> expr.symbols(); | |
| min,x,y,z | |
| js> expr.simplify({ y: 4, z: 5 }).symbols(); | |
| min,x | |
| Like `variables`, `symbols` accepts an option argument `{ withMembers: true }` to include object members. | |
| #### toString() | |
| Convert the expression to a string. `toString()` surrounds every sub-expression | |
| with parentheses (except literal values, variables, and function calls), so | |
| it’s useful for debugging precedence errors. | |
| #### toJSFunction(parameters: array | string, variables?: object) | |
| Convert an `Expression` object into a callable JavaScript function. `parameters` | |
| is an array of parameter names, or a string, with the names separated by commas. | |
| If the optional `variables` argument is provided, the expression will be | |
| simplified with variables bound to the supplied values. | |
| js> expr = Parser.parse("x + y + z"); | |
| ((x + y) + z) | |
| js> f = expr.toJSFunction("x,y,z"); | |
| [Function] // function (x, y, z) { return x + y + z; }; | |
| js> f(1, 2, 3) | |
| 6 | |
| js> f = expr.toJSFunction("y,z", { x: 100 }); | |
| [Function] // function (y, z) { return 100 + y + z; }; | |
| js> f(2, 3) | |
| 105 | |
| ### Expression Syntax ### | |
| The parser accepts a pretty basic grammar. It's similar to normal JavaScript | |
| expressions, but is more math-oriented. For example, the `^` operator is | |
| exponentiation, not xor. | |
| #### Operator Precedence | |
| Operator | Associativity | Description | |
| :----------------------- | :------------ | :---------- | |
| (...) | None | Grouping | |
| f(), x.y, a[i] | Left | Function call, property access, array indexing | |
| ! | Left | Factorial | |
| ^ | Right | Exponentiation | |
| +, -, not, sqrt, etc. | Right | Unary prefix operators (see below for the full list) | |
| \*, /, % | Left | Multiplication, division, remainder | |
| +, -, \|\| | 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) | |
| = | Right | Variable assignment | |
| ; | Left | Expression separator | |
| var parser = new Parser({ | |
| operators: { | |
| 'in': true, | |
| 'assignment': true | |
| } | |
| }); | |
| // Now parser supports 'x in array' and 'y = 2*x' expressions | |
| #### Unary operators | |
| The parser has several built-in "functions" that are actually unary operators. | |
| The primary difference between these and functions are that they can only accept | |
| exactly one argument, and parentheses are optional. With parentheses, they have | |
| the same precedence as function calls, but without parentheses, they keep their | |
| normal precedence (just below `^`). For example, `sin(x)^2` is equivalent to | |
| `(sin x)^2`, and `sin x^2` is equivalent to `sin(x^2)`. | |
| The unary `+` and `-` operators are an exception, and always have their normal | |
| precedence. | |
| Operator | Description | |
| :------- | :---------- | |
| -x | Negation | |
| +x | Unary plus. This converts it's operand to a number, but has no other effect. | |
| x! | Factorial (x * (x-1) * (x-2) * … * 2 * 1). gamma(x + 1) for non-integers. | |
| abs x | Absolute value (magnitude) of x | |
| acos x | Arc cosine of x (in radians) | |
| acosh x | Hyperbolic arc cosine of x (in radians) | |
| asin x | Arc sine of x (in radians) | |
| asinh x | Hyperbolic arc sine of x (in radians) | |
| atan x | Arc tangent 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 | |
| cos x | Cosine of x (x is in radians) | |
| cosh x | Hyperbolic 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 | |
| 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 "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) | |
| sinh x | Hyperbolic sine of x (x is in radians) | |
| sqrt x | Square root of x. Result is NaN (Not a Number) if x is negative. | |
| tan x | Tangent of x (x is in radians) | |
| tanh x | Hyperbolic tangent of x (x is in radians) | |
| trunc x | Integral part of a X, looks like floor(x) unless for negative number | |
| #### Pre-defined functions | |
| Besides the "operator" functions, there are several pre-defined functions. You | |
| can provide your own, by binding variables to normal JavaScript functions. | |
| These are not evaluated by simplify. | |
| 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. | |
| #### 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: | |
| 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: | |
| var parser = new Parser(); | |
| // Add a new function | |
| parser.functions.customAddFunction = function (arg1, arg2) { | |
| return 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 | |
| The parser also includes a number of pre-defined constants that can be used in expressions. These are shown | |
| in the table below: | |
| Constant | Description | |
| :----------- | :---------- | |
| E | The value of `Math.E` from your JavaScript runtime | |
| PI | The value of `Math.PI` from your JavaScript runtime | |
| true | Logical `true` value | |
| false | Logical `false` value | |
| Pre-defined constants are stored in `parser.consts`. You can make changes to this property to customise the | |
| constants available to your expressions. For example: | |
| var 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(); | |
| parser.consts = {}; | |
| ### Tests ### | |
| 1. `cd` to the project directory | |
| 2. Install development dependencies: `npm install` | |
| 3. Run the tests: `npm test` | |