Giter VIP home page Giter VIP logo

expr-eval's Introduction

JavaScript Expression Evaluator

npm CDNJS version Build Status

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

    const Parser = require('expr-eval').Parser;

    const parser = new Parser();
    let expr = parser.parse('2 * x + 1');
    console.log(expr.evaluate({ x: 3 })); // 7

    // or
    Parser.evaluate('6 * x', { x: 7 }) // 42

Documentation

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:

    const 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. Expressions 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
    const 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 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 "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:

    const 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:

    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:

    const parser = new Parser();
    parser.consts = {};

Tests

  1. cd to the project directory
  2. Install development dependencies: npm install
  3. Run the tests: npm test

expr-eval's People

Contributors

akumzy avatar antonburger avatar ashkulz avatar connor4312 avatar domoritz avatar dupski avatar eliot-akira avatar epicfaace avatar escopecz avatar extend1994 avatar gillardo avatar gk4m avatar greenkeeper[bot] avatar itangalo avatar j2l4e avatar lucifer63 avatar marwahaha avatar mattyclarkson avatar mikelitton avatar pyrou avatar regular avatar rreusser avatar sdegutis avatar silentmatt avatar simonschick avatar stlsmiths avatar w0den avatar weberhofer avatar yoshino-s avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

expr-eval's Issues

License

What is the license for the expression evaluator.

I'm assuming it is MIT. Is that correct?

Ternary Operator not always parsable

Hi Matt,

I have checked the latest parser... unfortunately the parser cannot parse arbitrary combinations of ternary operators.

Sampe:
var exp = Parser.parse(' a == 1 ? b == 2 ? 3 : 4 : 5'); -> fails, because when the parser reaches the second question mark, it expected a colon.
var exp = Parser.parse(' a == 1 ? (b == 2 ? 3 : 4 ) : 5'); -> works, because the parser sees the brackets tying the nested condition together.

Nevertheless, while the first expression is hard to read, it's still correct from a mathematical point of view.

Note: var exp = Parser.parse(' a == 1 ? 5 : b == 2 ? 3 : 4'); works again, since it reads the colon after the question mark as "expected".

max(1, 2, min(3, 4))

I had problem with functions defined like in the subject.

Script generates unneeded brackets when comma is used.
Produced code is: max( (1, 2), min(3,4) ) ) and this does not produce desired result.

Problem i identified was on line 248: nstack.push("(" + n1 + f + n2 + ")");

I changed to:

if( f == ','){
nstack.push( n1 + f + n2 );
}else{
nstack.push("(" + n1 + f + n2 + ")");
}

Add support for variable assignment

Right now "variables" are really constants that are evaluated at evaluation time, instead of parse time. I should consider adding an assignment operator (probably either = or :=).

Some considerations:

  • There's no concept of "statements" so it's somewhat questionable if there's a real use case for this.
    • But maybe a statement/expression separator could be added (like the , operator in JavaScript), to allow expressions like x = random(); x * x which would only be possible now by evaluating x ahead of time and passing it in as an argument.
  • Currently, expression evaluation is essentially side-effect free (with the minor exception of random, which updates the current PRNG state).
  • Support could be made opt-in with the new options argument.

Rename module

js-expression-eval is a really long name, so we should change it to something shorter like exp-eval or expr-eval.

An in-range update of eslint-plugin-standard is breaking the build 🚨

Version 2.2.0 of eslint-plugin-standard just got published.

Branch Build failing 🚨
Dependency eslint-plugin-standard
Current Version 2.1.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As eslint-plugin-standard is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Commits

The new version differs by 3 commits .

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

ReadMe is expected

The library needs a read-me file which can point out the expression mechanism and its usage.

Add seedable random number generator

Right now, the random() function is just the built-in Math.random() from the environment. It might be useful to use a deterministic, seedable generator.

Some thought needs to go into how to the implementation since currently, expressions are essentially stateless. Potential options are:

  • Store the current rng state as a property of the expression and maybe provide a seedrandom() function to update it.

  • Pass in and update the seed using a special property in the variables object. Maybe with an invalid variable name so it doesn't conflict with normal variables.

Either way, it's probably useful to be able to share rng state between expressions, so it should be stored in its own object, and should allow for being set explicitly.

Functions are returned among variables()

I tried different functions, and noticed that this doesn't work :

pow(2, 4)

neither does

min(2, 5)

By looking a little further, it looks like "pow" or "min" are seen as a variables when calling variables().

Am I missing something ?

Operators taking precedence even within variable names

It seems that the parser is giving precedence to operators found within variable names, which feels like a bug. For example, the following will fail to parse because it is matching or within the variable name:

   Parser.evaluate('org > 5', { org: 10 })

It feels like the parser should be observing word boundaries, or maybe that variables should be parsed out before operators?

Error when a variable whose name starts with E or PI

if a variable is defined with the names in upper-case and the names start with E or PI prefixes like ERGONOMIC or PITTSBURGH, the parser confuses them with the constants Math.E and Math.PI and throws the next error: unexpected variable.

`!true` and `!false`

Hi

Should !true return false, and !false return true?
I noticed in the tests that there is a not keyword which does exactly this, but the ! doesn't seem to work.
E.g.,

    // Fails
    it('!true', function () {
      expect(parser.evaluate('!true')).to.equal(false);
    });

    // Fails
    it('!false', function () {
      expect(parser.evaluate('!false')).to.equal(true);
    });

    // Works
    it('not true', function () {
      expect(parser.evaluate('not true')).to.equal(false);
    });

    // Works
    it('not false', function () {
      expect(parser.evaluate('not false')).to.equal(true);
    });

Scientific notation

Hi. Is there a way to work with scientific notation?

> Parser.evaluate("5.5e+5")
Error: parse error [column 4]: unexpected variable

Feat: percent support

Like 50 + 10%.

Strange cases:
50 + 10% - 5 — it can't be treated as 10 % -5, right?)
50 + 10% + 5 — if you going to get mod — you avoid using plus sign, right?.

As far as I see other operators after a percent sign could be treated as a syntax error.

p.s. Probably it could be nice to see some units support like 5cm, but it's another story.

Support for Conditional (ternary) Operator

Support for the conditional operator would be really great. Currently I added an if-function which accepts the condition and two values... but using <expression> ? <if-true> : <if-false> would feel much more natural.

Since this is a ternary operator and the parser can only handle unary and binary operators at the moment, this might be not that easy.

indexOf polyfill overwrites native implementation

The polyfill introduced by PR #3 overwrites the native implementation of indexof in all browsers.

Due to the fact this polyfill is suboptimal, this has severe performance issues in larger applications. Please consider removing it (as indexOf is supported in all major browsers and from IE9 onwards) or fix the check to only overwrite the indexOf function if it really isn't present.

Conditionally restrict available operators

I'm using this project in a project used for training math (and some other things).

It would be useful for me to be able to restrict which operators the parser accepts – in particular it would be useful if I could make the parser accept "5/6" as an expression, but not (say) "1/2+1/3".

(I've tried to fiddle with ops2 to conditionally unset some operators, but so far without success.)

Add parenthesis around negative numbers

It would be awesome if the toString() function would add parenthesis around negative numbers.

Currently:
Parser.parse("1 + b").simplify({b : -7}).toString(); // 1+-7

Would like:
Parser.parse("1 + b").simplify({b : -7}).toString(); // 1+(-7)

I have basically no idea of how to make the code do this, though.

Bug at line 213

There is a bug at line 213 when evaluating "-(x+6)(x+3)(x+3)(x-3)(x-6)/200" for x = -10. I don't know the code well enough to find it. Something about "-4 is not a function"

An in-range update of eslint is breaking the build 🚨

Version 3.16.0 of eslint just got published.

Branch Build failing 🚨
Dependency eslint
Current Version 3.15.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As eslint is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Release Notes v3.16.0
  • d89d0b4 Update: fix quotes false negative for string literals as template tags (#8107) (Teddy Katz)
  • 21be366 Chore: Ensuring eslint:recommended rules are sorted. (#8106) (Kevin Partington)
  • 360dbe4 Update: Improve error message when extend config missing (fixes #6115) (#8100) (alberto)
  • f62a724 Chore: use updated token iterator methods (#8103) (Kai Cataldo)
  • daf6f26 Fix: check output in RuleTester when errors is a number (fixes #7640) (#8097) (alberto)
  • cfb65c5 Update: make no-lone-blocks report blocks in switch cases (fixes #8047) (#8062) (Teddy Katz)
  • 290fb1f Update: Add includeComments to getTokenByRangeStart (fixes #8068) (#8069) (Kai Cataldo)
  • ff066dc Chore: Incorrect source code test text (#8096) (Jack Ford)
  • 14d146d Docs: Clarify --ext only works with directories (fixes #7939) (#8095) (alberto)
  • 013a454 Docs: Add TSC meeting quorum requirement (#8086) (Kevin Partington)
  • 7516303 Fix: sourceCode.getTokenAfter shouldn't skip tokens after comments (#8055) (Toru Nagashima)
  • c53e034 Fix: unicode-bom fixer insert BOM in appropriate location (fixes #8083) (#8084) (pantosha)
  • 55ac302 Chore: fix the timing to define rules for tests (#8082) (Toru Nagashima)
  • c7e64f3 Upgrade: mock-fs (#8070) (Toru Nagashima)
  • acc3301 Update: handle uncommon linebreaks consistently in rules (fixes #7949) (#8049) (Teddy Katz)
  • 591b74a Chore: enable operator-linebreak on ESLint codebase (#8064) (Teddy Katz)
  • 6445d2a Docs: Add documentation for /* exported */ (fixes #7998) (#8065) (Lee Yi Min)
  • fcc38db Chore: simplify and improve performance for autofix (#8035) (Toru Nagashima)
  • b04fde7 Chore: improve performance of SourceCode constructor (#8054) (Teddy Katz)
  • 90fd555 Update: improve null detection in eqeqeq for ES6 regexes (fixes #8020) (#8042) (Teddy Katz)
  • 16248e2 Fix: no-extra-boolean-cast incorrect Boolean() autofixing (fixes #7977) (#8037) (Jonathan Wilsson)
  • 834f45d Update: rewrite TokenStore (fixes #7810) (#7936) (Toru Nagashima)
  • 329dcdc Chore: unify checks for statement list parents (#8048) (Teddy Katz)
  • c596690 Docs: Clarify generator-star-spacing config example (fixes #8027) (#8034) (Hòa Trần)
  • a11d4a6 Docs: fix a typo in shareable configs documentation (#8036) (Dan Homola)
  • 1e3d4c6 Update: add fixer for no-unused-labels (#7841) (Teddy Katz)
  • f47fb98 Update: ensure semi-spacing checks import/export declarations (#8033) (Teddy Katz)
  • e228d56 Update: no-undefined handles properties/classes/modules (fixes #7964) (#7966) (Kevin Partington)
  • 7bc92d9 Chore: fix invalid test cases (#8030) (Toru Nagashima)
Commits

The new version differs by 31 commits .

  • 3c26a59 3.16.0
  • 5bdb960 Build: package.json and changelog update for 3.16.0
  • d89d0b4 Update: fix quotes false negative for string literals as template tags (#8107)
  • 21be366 Chore: Ensuring eslint:recommended rules are sorted. (#8106)
  • 360dbe4 Update: Improve error message when extend config missing (fixes #6115) (#8100)
  • f62a724 Chore: use updated token iterator methods (#8103)
  • daf6f26 Fix: check output in RuleTester when errors is a number (fixes #7640) (#8097)
  • cfb65c5 Update: make no-lone-blocks report blocks in switch cases (fixes #8047) (#8062)
  • 290fb1f Update: Add includeComments to getTokenByRangeStart (fixes #8068) (#8069)
  • ff066dc Chore: Incorrect source code test text (#8096)
  • 14d146d Docs: Clarify --ext only works with directories (fixes #7939) (#8095)
  • 013a454 Docs: Add TSC meeting quorum requirement (#8086)
  • 7516303 Fix: sourceCode.getTokenAfter shouldn't skip tokens after comments (#8055)
  • c53e034 Fix: unicode-bom fixer insert BOM in appropriate location (fixes #8083) (#8084)
  • 55ac302 Chore: fix the timing to define rules for tests (#8082)

There are 31 commits in total. See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Parity error

Hi, trying to evaluate:

10/-1 gives a parity error.

It solves, this way:

10/(-1)

"Unexpected number" Exception

I have a Three.js project where i want to calculate the tangential plane for a given function.

In order to do so I create a function as string for the tangential plane. For most cases that works fine, but in some cases the string can not be parsed in a JSFunction.

My function string looks like this:
"-0.7157103444368793*(x-(3.2981185793406347))+(-0.7157103444368793)*(y-(-0.9296815687840398))+0.698397238587069"

My Browser gives me this error:
Uncaught SyntaxError: Unexpected number
at new Function ()
at Expression.toJSFunction (parser.js:293)
at createTangentialPlane (main.js:185)
at createGraph (main.js:165)
at :1:1

Can please someone say me whats wrong with my function string? Are the parenthesis wrong?

Parser Bug with comparison operator

Howdy,

I believe I've found a small bug in your parser here:

Bug Screenshot

Somehow the '-' sign in the expression gets transformed into a '+' in the tokens. Any ideas on how to fix this sucker?

Thanks,
Joey

An in-range update of mocha is breaking the build 🚨

Version 3.4.0 of mocha just got published.

Branch Build failing 🚨
Dependency mocha
Current Version 3.3.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As mocha is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes v3.4.0

Mocha is now moving to a quicker release schedule: when non-breaking changes are merged, a release should happen that week.

This week's highlights:

  • allowUncaught added to commandline as --allow-uncaught (and bugfixed)
  • warning-related Node flags

🎉 Enhancements

🐛 Fixes

🔩 Other

Commits

The new version differs by 9 commits0.

  • 7554b31 Add Changelog for v3.4.0
  • 9f7f7ed Add --trace-warnings flag
  • 92561c8 Add --no-warnings flag
  • ceee976 lint test/integration/fixtures/simple-reporter.js
  • dcfc094 Revert "use semistandard directly"
  • 93392dd no special case for macOS running Karma locally
  • 4d1d91d --allow-uncaught cli option
  • fb1e083 fix allowUncaught in browser
  • 4ed3fc5 Add license report and scan status

false

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Find a Chai alternative

Chai uses getters instead of function calls for things like expect(NaN).to.be.NaN, which is confusing, potentially hides errors, and doesn't play well with eslint.

Another possibility that works around the last problem would be to keep Chai, but use something like chai-lint (currently doesn't support NaN, but there's a pull request) or eslint-plugin-chai-friendly.

Parser crashes with certain variables names

I found a strange bug earlier when trying to parse the following expression EBE/CEX
The js is not able to parse EBE but works with lowercased ebe. I don't think it is intended?

Thanks

Cannot uglify with latest version

➜  front-end git:(staging-schedule) ✗ ./node_modules/.bin/uglifyjs bower_components/js-expression-eval/parser.js 
Parse error at bower_components/js-expression-eval/parser.js:1169,7
SyntaxError: Unexpected token: keyword (default)
Error
    at new JS_Parse_Error (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:1545:18)
    at js_error (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:1553:11)
    at croak (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2092:9)
    at token_error (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2100:9)
    at unexpected (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2106:9)
    at semicolon (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2126:56)
    at simple_statement (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2317:73)
    at eval (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2186:19)
    at eval (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2139:24)
    at eval (eval at <anonymous> (/Users/juggy/Documents/porkepic/vroom/front-end/node_modules/uglify-js/tools/node.js:28:1), <anonymous>:2907:23)

toJSFunction with Content Security Policy

expression.toJSFunction(...) doesn't work with CSP, unless unsafe-eval is included. We should consider wrapping a normal evaluate call in a function as a fallback in case new Function fails. The behavior is slightly different with respect to unbound variables though, so that consistency should be cleared up since the difference in behavior would be unexpected.

Alternatively, the restriction should at least be mentioned in the documentation.

Add minified version

Thanks for developing this awesome library! Great work.

Would you mind adding a minified version to the build?

Hexadecimal numerals

Could you please implement hex numbers?

Like 0xFE (cpp style) or $FE (pascal style), or both.

Binary numbers (0b10101) also would be usefull I guess.

Named prefix operators should be more consistent with functions

Prefix operators have a lower precedence than exponentiation, which could be confusing when they are used like functions. For example, sin(2)^3 looks like it would be parsed as (sin 2) ^ 3, but is actually sin (2^3).

To be less surprising, a prefix operator (other than + and -, which don't look like functions) followed by ( should be parsed as a function call.

What is the security like for this library?

README.md says:

There’s no security risk currently, because you can only run code in your own browser

What does this mean?

  • Can an expression have any side effects? Suppose I'm not passing in any custom functions
  • To your knowledge, is it safe to evaluate a user-supplied expression? Can user B safely run user A's expression in their browser?

Variable name confusion

Hi, I want to use this library for an app where users can define their own variable names and formulas. Now the issue is that someone might define a variable with the name max and try to use it in a formula.

Because max is also a predefined function, this isn't going to work.

Perhaps there should be a better way to distinguish between whether something is a variable or a function?

Having problem with factorial

Great library!

Having issue with parse accepting 4!, or (4+2)! . Unfortunately, in my case I cannot use fac(4) or fact(2+3) and am stuck with using the ! mark. Can this library handle the ! mark for the factorial purpose?

Add performance tests

We could use some benchmarks to test for performance regressions and to find areas to optimize.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.