Never Pet Mermaids

# npm

Miss any of our Open RFC calls?Watch the recordings here! »

## bet

0.2.0 • Public • Published

# A Mathematical Evaluator for CoffeeScript and JavaScript

This project makes use of Binary Expression Trees and the Shunting-Yard algorithm to evaluate infix equations and produce a numerical result.

## Installing

Typical NPM installation:

## Usage

The library expects that you have some way of separating your tokens, whether it is a `string.split`, or something more involved, is up to you.

### Simple Example

In CoffeeScript

In JavaScript

There is also a synchronous method

You will want to check the source to see the full list of built-in operators and functions that are currently supported.

### Custom Operators

You can define or redefine operators as you wish.

Operators require the following attributes:

1. assoc: Associativity ['left' or 'right'] Associativity indicates the order in which operators of the same precedence are executed. For instance, `&&` has an associativity of 'left' and thus `a && b && c` is evaluated as `(a && b) && c`.

2. prec: Precedence [integer] Operators with a higher precedence (higher value) are executed first. For instance, `1 + 2 * 3` is evaluated as `1 + (2 * 3)`.

3. argc: Argument count [integer] The number of numerical operands an operator needs to execute. In practice this is usually only 1 (for unary) or 2 (for binary) operators. For instance, `+` requires 2 operands e.g. `1 + 2`, whereas `1 +` will produce an error.

4. fix: How the operator is 'fixed' ['in', 'pre', or 'post'] Most binary operators are infixed, meaning the operator is between the operands e.g. `1 / 2`. Unary operators are usually either pre or post fixed, e.g. `5 !` (postfixed) or `not 1` (prefixed). However, you can also have infixed unary operators (just be careful with associativity!) such as pre and post increment/decrement, e.g. `++1` and `1++` are both valid.

5. exec: Evaluator [function] This is the function that is called to evaluate the operator. It is given a single argument as an array, with length argc. All values are numerical.

### Custom Functions

Functions are similar to operators. You can also define new or redefine functions. Functions in this library are invoked C style `fn(arg1,arg2,arg3)`. Currently, variable argument functions are not supported. Function arguments can be expressions in themselves. Functions cannot have the same name as an operator.

Declaration of a function is much like an operator. However it requires only 2 attributes:

1. argc: Argument count [integer] The number or arguments the function takes.

2. exec: Evaluator [function] This is the function that is called to evaluate the function. It is passed an array of in order numerical arguments.

## But JavaScript IS a Mathematical Evaluator

Good point. Here is one particular use case that prompted me to write this library:

### A Basic Approach

You are writting a game involves players entering equations. You may at first do something like this:

This will work, and for most basic math operators will do what you need.

### A More Complicated Example

Let's say you don't want to deal with fractions or decimals, you want your operations to have integer only results. So then you may say "Ok, I'll write a preprocessor to `Math.floor` division operators"

But then the User enters something invalid:

Or should it have been?:

You also have to watch out for:

Anyways, the problem starts to compound when you need things like:

1. Custom operators
2. Built-in and user-defined functions
3. Associativity, precedence, and argument length control
4. Error reporting of what went wrong when an expression does not evaluate

## Using Binary Expression Trees to your Advantage

Luckily this problem has been solved long before I was born. The idea is, once you have separated the equation into individual tokens to rearrange them according to their precedence. Then you can the equation, in Reverse Polish Notation, and execute it.

So, if you start with an equation like this:

``````1 + 2 * 3 + 4 ^ 5
``````

You produce the expression tree in RPN format as follows:

``````1 2 3 * + 2 3 2 ^ ^ +
``````

Which gives you the correct order of operations, so you can simply execute the equation as a stack if you know how many arguments each operator takes:

``````> pop
[1]
> pop
[1, 2]
> pop
[1, 2, 3]
> evaluate *
[1, 6]
> evaluate +
[7]
> pop
[7, 2]
> pop
[7, 2, 3]
> pop
[7, 2, 3, 2]
> evaluate ^
[7, 2, 9]
> evaluate ^
[7, 512]
> evaluate +
> [519]
``````

...Or you can find a better explanation of BETs and RPN works here

## Keywords

none

### Install

`npm i bet`

7

0.2.0

none

### Repository

github.com/paulmoore/BET