Comparing version 2.0.4 to 2.1.1
@@ -201,4 +201,5 @@ "use strict"; | ||
if (token.type === _Token2.default.TYPE_COMMAND) { | ||
var fnName = token.value.substr(1).toLowerCase(); | ||
token.value = this.constants[fnName]; | ||
token.value = token.value.substr(1).toLowerCase(); | ||
token.name = token.value; // Save name of function for debugging later | ||
token.value = this.constants[token.name]; | ||
} | ||
@@ -224,15 +225,37 @@ } | ||
value: function replaceConstants() { | ||
for (var i in this.tokens) { | ||
var token = this.tokens[i]; | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
if (token.type === _Token2.default.TYPE_SYMBOL) { | ||
// Symbols will need to be looked up during the evaluation phase. | ||
// If the symbol refers to things defined in either Math or | ||
// the locals, compile them, to prevent slow lookups later. | ||
if (typeof this.constants[token.value] === "function") { | ||
this.tokens[i] = new _Token2.default(_Token2.default.TYPE_FUNCTION, this.constants[token.value]); | ||
} else if (typeof this.constants[token.value] === "number") { | ||
this.tokens[i] = new _Token2.default(_Token2.default.TYPE_NUMBER, this.constants[token.value]); | ||
try { | ||
for (var _iterator3 = this.tokens[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var token = _step3.value; | ||
if (token.type === _Token2.default.TYPE_SYMBOL) { | ||
// Symbols will need to be looked up during the evaluation phase. | ||
// If the symbol refers to things defined in either Math or | ||
// the locals, compile them, to prevent slow lookups later. | ||
if (typeof this.constants[token.value] === "function") { | ||
token.type = _Token2.default.TYPE_FUNCTION; | ||
token.name = token.value; // Save name of function for debugging later | ||
token.value = this.constants[token.value]; | ||
} else if (typeof this.constants[token.value] === "number") { | ||
token.type = _Token2.default.TYPE_NUMBER; | ||
token.value = token.fn = this.constants[token.value]; | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3.return) { | ||
_iterator3.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
} | ||
@@ -239,0 +262,0 @@ } |
@@ -25,2 +25,3 @@ "use strict"; | ||
this.value = value; | ||
this.name = null; // Used in function and command nodes to retain the fn name when minified | ||
this.children = []; | ||
@@ -156,3 +157,3 @@ } | ||
value: function toString() { | ||
var val = typeof this.value === "function" ? this.value.name : this.value; | ||
var val = typeof this.value === "function" ? this.name : this.value; | ||
return this.children.length + " " + this.type + " [" + val + "]"; | ||
@@ -159,0 +160,0 @@ } |
@@ -188,4 +188,5 @@ "use strict"; | ||
node = new _Node2.default(_Node2.default.TYPE_FUNCTION, cmdToken.value); | ||
node.name = cmdToken.name; | ||
for (var i = 0; i < _arities2.default[cmdToken.value.name]; i++) { | ||
for (var i = 0; i < _arities2.default[cmdToken.name]; i++) { | ||
node.addChild(this.val()); | ||
@@ -195,2 +196,3 @@ } | ||
node = new _Node2.default(_Node2.default.TYPE_FUNCTION, this.prevToken.value); | ||
node.name = this.prevToken.name; | ||
@@ -197,0 +199,0 @@ // Multi-param functions require parens and have commas |
@@ -24,2 +24,3 @@ "use strict"; | ||
this.value = value; | ||
this.name = null; // Used in function and command tokens to retain the fn name when minified | ||
} | ||
@@ -39,6 +40,5 @@ | ||
// Does the value contain a function? If so, print a human-readable name. | ||
var value = typeof this.value === "function" ? this.value.name : this.value; | ||
var val = typeof this.value === "function" ? this.name : this.value; | ||
return this.type + "[" + value + "]"; | ||
return this.type + "[" + val + "]"; | ||
} | ||
@@ -66,3 +66,3 @@ }]); | ||
[Token.TYPE_RPAREN, /(\)|]|}|\\right\)|\\right])/], // Match ), ], }, \right), \right] | ||
[Token.TYPE_PLUS, /\+/], [Token.TYPE_MINUS, /-/], [Token.TYPE_TIMES, /\*/], [Token.TYPE_DIVIDE, /\//], [Token.TYPE_COMMAND, /\\[A-Za-z]+/], [Token.TYPE_SYMBOL, /[A-Za-z][A-Za-z0-9]*/], [Token.TYPE_WHITESPACE, /\s+/], // Whitespace | ||
[Token.TYPE_PLUS, /\+/], [Token.TYPE_MINUS, /-/], [Token.TYPE_TIMES, /\*/], [Token.TYPE_DIVIDE, /\//], [Token.TYPE_COMMAND, /\\[A-Za-z]+/], [Token.TYPE_SYMBOL, /[A-Za-z_][A-Za-z_0-9]*/], [Token.TYPE_WHITESPACE, /\s+/], // Whitespace | ||
[Token.TYPE_ABS, /\|/], [Token.TYPE_BANG, /!/], [Token.TYPE_COMMA, /,/], [Token.TYPE_POWER, /\^/], [Token.TYPE_NUMBER, /\d+(\.\d+)?/]]); | ||
@@ -69,0 +69,0 @@ exports.default = Token; |
{ | ||
"name": "evaluatex", | ||
"version": "2.0.4", | ||
"version": "2.1.1", | ||
"description": "An ASCII and LaTeX math parser and evaluator", | ||
@@ -11,3 +11,3 @@ "main": "index.js", | ||
"scripts": { | ||
"build": "babel -d dist src", | ||
"build": "babel -d dist src && webpack dist/minifier.js -o dist/evaluatex.min.js", | ||
"test": "mocha --require babel-register" | ||
@@ -25,3 +25,5 @@ }, | ||
"chai": "^4.1.2", | ||
"mocha": "^5.1.1" | ||
"mocha": "^5.1.1", | ||
"webpack": "^4.6.0", | ||
"webpack-cli": "^2.1.2" | ||
}, | ||
@@ -28,0 +30,0 @@ "dependencies": {}, |
173
README.md
@@ -48,173 +48,2 @@ Evaluatex | ||
------------------ | ||
Evaluatex compiles a string into a Javascript function that you can invoke anytime. It's like calling `eval()`, but without the [evil](http://linterrors.com/js/eval-is-evil). | ||
```javascript | ||
const fn = evaluatex("1 + 2 * 3 ^ 4") | ||
fn() | ||
// 163 | ||
``` | ||
A one-liner: | ||
```javascript | ||
const result = evaluatex("1 + 2 * 3 ^ 4")() | ||
// result = 163 | ||
``` | ||
Evaluatex returns a function because you can then invoke it multiple times with different variables. | ||
```javascript | ||
fn2 = evaluatex("1 + magic") | ||
fn2({ magic: 3 }) | ||
// 4 | ||
fn2({ magic: 99 }) | ||
// 100 | ||
``` | ||
### Evaluatex is a calculator | ||
Evaluatex supports all of the features you should expect from a simple calculator, including order of operations. Exponents use the `^` operator. | ||
```javascript | ||
evaluatex("1 + 2 * 3 ^ 4")() | ||
// 163 | ||
``` | ||
You can use named values in expressions that are visible to the expression only. This avoids the need for `eval`. See the *Constants and variables* section for more. | ||
```javascript | ||
evaluatex("1 + a / b", { a: 3, b: 4 })() | ||
// 1.75 | ||
``` | ||
Implicit multiplication with brackets or variables is not a problem. | ||
```javascript | ||
evaluatex("4a(1 + b)", { a: 3, b: 4 })() | ||
// 60 | ||
``` | ||
You have full access to Javascript's `Math` object, including all functions and constants. | ||
```javascript | ||
evaluatex("sin(0.5PI) + magic", { magic: 3 })() | ||
// 4 | ||
``` | ||
You can omit brackets from simple functions, but be careful with implicit multiplication. | ||
```javascript | ||
evaluatex("sin 2PI")() // Interpreted as sin(2) * PI | ||
// 2.8566 | ||
evaluatex("sin PI^2")() // Interpreted as sin(PI^2) | ||
// -0.43 | ||
``` | ||
> There is no universally-accepted standard for treating coefficients inside paren-less functions. Whenever in doubt, use parentheses. | ||
## Custom functions | ||
You can even define custom functions. | ||
```javascript | ||
evaluatex("incr(4)", { incr: function(x) { return x + 1; } })() | ||
// 5 | ||
``` | ||
Multi-argument functions work just as well, but you need to include parentheses. | ||
```javascript | ||
evaluatex("hypot(3, 4)")() | ||
// 5 | ||
evaluatex("min(5, 4, 3, 2, 1)")() | ||
// 1 | ||
``` | ||
There's even functions built right in to Evaluatex to help with logs, roots, and trig: | ||
```javascript | ||
evaluatex("logn(81, 3)")() | ||
// 4 | ||
evaluatex("rootn(8, 3)")() | ||
// 2 | ||
evaluatex("csc(0.25PI)")() | ||
// 1.414 | ||
``` | ||
Absolute values work like a charm... | ||
```javascript | ||
evaluatex("|5 - 20|")() | ||
// 15 | ||
``` | ||
...as do factorials, which round to the nearest integer before performing the calculation: | ||
```javascript | ||
evaluatex("3.6!")() | ||
// 24 | ||
``` | ||
### Constants and variables | ||
You can refer to symbols, such as `x`, in a math expression. These symbols can be **constant** or **variable**. | ||
**Constants** are specified in the call to `evaluatex()` as the second parameter. Their values are compiled by Evaluatex into the resultant equation. Use constants if you know that they won't change between invocations. Constants may be numeric values or functions. | ||
```javascript | ||
const fn = evaluatex("100 + x + incr(1)", { x: 5, incr: x => x + 1 }); | ||
fn(); | ||
// 107 | ||
``` | ||
**Variables** are specified in the output function. Their values can be changed between invocations. If you compile an expression with a variable, you *must* give a value for that variable, otherwise Evaluatex will complain. Variables may only be numeric values, and not functions. | ||
```javascript | ||
const fn = evaluatex("100 + x"); | ||
fn({ x: 5 }); // 105 | ||
fn({ x: 6 }); // 106 | ||
``` | ||
You can combine constants and variables. Do note that constants have priority over variables - if you define a constant, you can't change it without re-compiling the equation. | ||
```javascript | ||
const fn = evaluatex("x + y", { x: 100 }); | ||
fn({ y: 5 }); // 105 | ||
fn({ x: 0, y: 6 }); // 106 | ||
``` | ||
### Constants and variables: performance notes | ||
Using a variable requires looking up the variable every time that it is used. This is a little slow. If a variable doesn't change, prefer constants. | ||
If you use a constant and need to change it, you need to call `evaluatex()` again to re-compile the math expression. This is **really** slow. If there's a chance that a constant may change (e.g. user input), prefer variables. | ||
LaTeX-specific behaviour | ||
------------------------ | ||
Turn on LaTeX idiosyncrasies with `{ latex: true }` in the third parameter: | ||
```javascript | ||
evaluatex("x^24", { x: 2 }, { latex: true })() | ||
// 16 | ||
``` | ||
The previous example is evaluated as x^(2) * 4, since LaTeX often takes only the first digit of a number for such operations. Use curly braces (`{` and `}`) to fix that: | ||
```javascript | ||
evaluatex("x^{24}", { x: 2 }, { latex: true })() | ||
// 16777216 | ||
``` | ||
If you try to use parens or square brackets, Evaluatex will complain. | ||
```javascript | ||
evaluatex("x^(24)", { x: 2 }, { latex: true }) | ||
Error! | ||
``` | ||
LaTeX thinks that the above expression means `x^'(' * 24)`, which is clearly bogus syntax. When in doubt, always use braces. | ||
One more example: | ||
```javascript | ||
evaluatex("\\frac 123") // Interpreted as (1/2) * 3 | ||
1.5 | ||
``` | ||
A complete manual is available on the [project page](https://arthanzel.github.io/evaluatex). |
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
55967
15
893
8
48