1.0.0-beta • Published 5 years ago

dl-math-eval-ts v1.0.0-beta

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

TypeScript's Math Evaluator

This is a library for parsing and evaluating string arithmetic expressions.

Installation

Using NPM

npm i dl-math-eval-ts

Using GitHub Repository

Clone or download the repository and add the import references accordingly in your TypeScript source code.

git clone

Build

To build the source and generate the corresponding JS source code:

git clone 
cd 
tsc

Note: You must have TypeScript compiler installed in your system to use tsc. Refer to this page for more information.

Usage

To use the library, simply use the appropriate imports in the source code. For example, if you wish to evaluate an expression then:

import { DLMathEval } from './node-modules/dl-math-eval-ts';

let exp : string = 'your expression';
let ref : any = {}; // your references and methods definitions
let result : number = DLMathEval.evaluateExpression( exp, ref );

This is an example of a scenario where you have used npm to install the library. There are several other static methods in DLMathEval that you may find useful so I encourage you to explore the documentation to discover these methods.

However to get a better understanding of the terms and conventions followed in the methods and classes, then reading the description below will help.

Description

Here are the descriptions and elaborations of a few terms which are used in this project:

Token

A token is an independent element in an expression. It can be a number, an operator or a function call. A token in this library is represented by a class named DMEToken. The class has two fields:

FieldTypeDescription
typeTokenTypetype of token
valueanyvalue of the token

The value that must value must hold depends on the type of the token.

TokenTypeValue Type
CloseParenthesis')'
OpenParenthesis'('
Operandnumber
Operator'-' or '+' or '*' or '/'
ReferenceDMEReferenceToken object

The tokenize method on passing a valid expression will provide an array containing the tokens in order corresponding to the expression.

Reference Token

A reference token is one that represents an entity that requires a look-up in a JSON object. For example the token:

f1.f2.f3(2,1)

is a function call and takes two arguments. The function must be declared in the second parameter of the evaluateExpression method. For the above example the parameter can be the following object:

let ref : any = {
	"f1": {
    	"f2": {
        	"f3": function( params : number[] ) : number {
            	return params[1] * params[2];
            }
        }
    }
};

The function takes an array argument where the numbers which are to be passed as arguments are contained in the order of declaration of the function in the params array. The reference need not necessarily be a function but it can also be a number or an expression that results to a number. For example the below expression is still valid:

let ref : any = {
	"f1": {
    	"f2": {
        	"f3": function( params : number[] ) : number {
            	return params[1] * params[2];
            },
            "f4": function() : number {
            	return 101;
            }
        },
        "notAFunction": 5+1
    }
};

let expression : string = 'f1.f2.f3(4,5) + f1.f2.f4 * f1.notAFunction';

Parsing expression will yield three DMEReferenceToken objects which in this scenario are valid. The DMEReferenceToken class has three fields:

FieldTypeDescription
referenceNamestring[]complete name of the reference, which is delimited on . character
typeReferenceTokenTypetype of token, can be Function or Constant
paramsDMEToken[][]parameters to be passed to the function

The params field is an array of expression where the expression is expressed as an array of tokens. A reference token can take any valid expression as a parameter and the expression may include references also. Before evaluation of a reference, all its parameters are evaluated first and then the resulting numerical results are passed to the function (you can see this as a depth-first evaluation).

A Constant type is one which does not have the syntax of a function call. f1.notAFunction or f1.f2.f4 are both Constant types. Intuitively, a Function has the syntax of a function call, example f1.f2.f3(2,3).

Math Library

If there are any references which are of the form Math.cos(2) or references which require the common Math library, on evaluation of the reference, if it is not found in the look-up object then the reference will be looked up in the Mathlibrary as well. That is of course if the look-up in the reference object fails. Even for the methods in Math library, the parameters are evaluated first before being passed to the method, so the expression

Math.cos( 2 + f1.notAFunction )

is still valid.

Regular Expressions

The regular expressions used in this project can be found in regexContainer.ts file in the RegexContainer class.

RegexNameDescription
/^[)]$/ClosingParenthesisClose parenthesis or )
/^[0-9]$/DigitAll digits from 0 to 9
/^[(]$/OpeningParenthesisOpen parenthesis or (
/^[-+*/]$/OperatorThe common arithmetic operators of addition, subtraction, multiplication and division.
/^([a-zA-Z0-9_$]+(\.[a-zA-Z0-9_$]+)*)$/ReferenceNameA reference name is of the form name.name.name.name, where . is the separator and name can be a string of uppercase or lowercase characters, digits, $ or _. A reference name must start with any one of these characters and must have at least one of these characters.
/^[a-zA-Z0-9$_.]$/ReferenceNameCharactersThe characters that are valid in a reference name.
/^[a-zA-Z$]$/ReferenceNameInitialThe valid starting characters of a reference name.

Transition Check

Since the project requires parsing a string, so intuitively there will be a requirement of a transition table. The transition, in this case, performs check on whether a character following or succeeding a token forms a valid expression. The TransitionCheck method, in transitionCheck.ts, is an implementation of this concept. The parameters of the method are: |Parameter|Type|Description| |-|-|-| |currentToken|DMEToken|The token that was generated in the current iteration.| |next|string|The character following the currentToken in the expression.|

This method returns true when the transition from the token to the character is valid or false if invalid. The method uses regular expression which will are self-explanatory.

Algorithm

The algorithm used for evaluating the expression can be found in this page. The algorithm evaluates infix expression using two stacks, one for operands and one for operators. The method evaluateNativeExpression implements the algorithm.

Native Expression - A native expression is one where there are only operands, operators and parenthesis in the expression. In other words, there are no reference tokens in the expression.

Documentation

Please refer to doc/index.html for the complete documentation and API reference. The documentation for this project was generated using Compodoc.

Demo

// Expression string
let exp : string = "a + (1+1.1)/2+$f.$r.w_t_($f.x(2),3) + (-2) + Math.cos(90)";

// Reference object
let ref : any = {
    "$f": {
        "$r": {
            "w_t_": function( params : number[] ) : number {
                return params[0] + params[1];
            }
        },
        "x": function( params : number[] ) : number {
            return params[0] * params[0];
        },
        "a": 2
    },
    "a": 1
};

// Getting the array of tokens
let tokens = DLMathEval.tokenize(exp);

// Evaluating the expression
let result = DLMathEval.evaluateExpression(exp, ref);