math-expression-evaluator
math-expression-evaluator parses calculator-style text such as `2(3+4)`, `sin90`, `5C2`, and `Sigma(1,5,n)` without calling JavaScript eval. A stateful `Mexp` instance tokenizes the input, converts it to postfix notation, and evaluates it as a JavaScript number. It includes degree-based trigonometry, factorials, permutations, combinations, summation, products, implicit multiplication, and an extension API for custom constants and functions. It is a calculator grammar, not a general symbolic algebra system or spreadsheet engine.
A useful compact parser for a calculator UI whose grammar matches its unusual choices. Do not use it for finance, exact computation, unrestricted server input, or any product where left-associative powers and degree-default trig would surprise users.
Use it if
- You need a small dependency-free calculator parser with implicit multiplication and parenthesis-free functions such as sin90
- Your input needs built-in factorial, permutation, combination, Sigma, or Pi product notation
- You want to add a few application-specific constants or numeric functions through a token table
- All results can use JavaScript Number precision and expressions come from a controlled calculator-style UI
- You need conventional mathematical exponent rules: the README explicitly says `^` is left-associative like Microsoft Office, so `2^3^2` evaluates to 64 rather than 512
- You accept arbitrary public input on a server and need predictable work limits: the shipped Sigma, Pi, factorial, permutation, and combination implementations use plain loops with no iteration or magnitude cap
- You need exact decimals, big integers, fractions, units, matrices, complex numbers, or symbolic manipulation: the type declarations return only number, and evaluation rounds through `toFixed(15)` before parsing the result back
- You want a polished, complete API reference: the README omits the required import in its main usage sample, still suggests Bower, contains a `lexed` method typo, and gives an incorrect numeric example for natural log
- You need normal programming-language variables and named arguments without configuring tokens: the built-in grammar only knows its fixed token list and the special `n` used inside Sigma and Pi
Setup reality
`npm install math-expression-evaluator` is the whole install: version 2.0.7 has no runtime dependencies, peer dependencies, native code, credentials, or configuration files, and it includes declarations under `dist/types`. The package entry is CommonJS and does not publish an exports map or module field, so default-import behavior depends on your TypeScript and bundler interop settings; `const Mexp = require('math-expression-evaluator')` matches the emitted entry exactly. Create an instance before calling `eval`. Trigonometric functions start in degree mode, which makes `sin90` equal 1 but makes radian-oriented formulas wrong until you set `mexp.math.isDegree = false`. Exponentiation is left-associative. The parser permits implicit multiplication and parenthesis-free function calls, conveniences that can make ambiguous user input harder to explain. Invalid syntax throws ordinary Error objects, so validate length and catch failures at the boundary. Custom tokens mutate the evaluator and remain available in later calls; use a dedicated, preconfigured instance rather than mixing user-defined token sets between tenants. Constants need both a token definition and a values object during evaluation. There are no built-in CPU guards, so impose expression-length, numeric-range, and Sigma or Pi bounds before evaluating untrusted text. Results use JavaScript floating-point arithmetic and are normalized to 15 decimal places internally, which is unsuitable for money or exact science work.
Patterns
Evaluate a basic arithmetic expressionevaluate-arithmetic
const Mexp = require('math-expression-evaluator');
const mexp = new Mexp();
const value = mexp.eval('2 + 3 * 4');
console.log(value); // 14Invalid characters or grammar throw an Error. Catch it when the expression comes from user input.
Use implicit multiplicationuse-implicit-multiplication
const value = mexp.eval('2(3 + 4)');
console.log(value); // 14Adjacent values and parentheses can imply multiplication. This is convenient for calculator input but differs from JavaScript syntax.
Evaluate trigonometry in degree modeevaluate-degree-trig
const value = mexp.eval('sin90 + cos(0)');
console.log(value); // 2Degree mode is enabled on every new instance, and function parentheses are optional.
Switch trigonometry to radiansswitch-to-radians
mexp.math.isDegree = false;
const value = mexp.eval('sin(pi / 2)');
console.log(value); // 1The mode is mutable instance state. Do not share one instance between callers that expect different angle units.
Evaluate powers with explicit groupingevaluate-powers
const squaredCube = mexp.eval('(2^3)^2'); // 64
const powerTower = mexp.eval('2^(3^2)'); // 512Without parentheses, `2^3^2` is evaluated left to right and returns 64. Group power towers explicitly.
Use factorial, combination, and permutationevaluate-combinatorics
const factorial = mexp.eval('5!'); // 120
const combinations = mexp.eval('5C2'); // 10
const permutations = mexp.eval('5P2'); // 20These operations use JavaScript Number and plain loops. Large inputs overflow or consume noticeable CPU.
Sum a sequence with Sigmasum-a-sequence
const total = mexp.eval('Sigma(1, 100, n)');
console.log(total); // 5050Only `n` is the built-in sequence variable, and there is no iteration limit. Validate both bounds before evaluation.
Multiply a sequence with Pimultiply-a-sequence
const product = mexp.eval('Pi(1, 5, n)');
console.log(product); // 120Pi with a capital P is the product function; lowercase pi is the mathematical constant. Tokens are case-sensitive.
Split lexing, postfix conversion, and evaluationreuse-parsed-expression
const lexed = mexp.lex('2 * (3 + 4)');
const postfix = mexp.toPostfix(lexed);
const value = mexp.postfixEval(postfix);
console.log(value); // 14The method is named lex, not lexed as one README example states. Reusing postfix output avoids parsing the same fixed expression again.
Add a named numeric constantadd-custom-constant
const T = Mexp.TOKEN_TYPES;
mexp.addToken([{
token: 'x',
show: 'x',
type: T.CONSTANT,
value: 'x',
precedence: 0,
}]);
const value = mexp.eval('2x + 1', undefined, { x: 3 });
console.log(value); // 7Defining the token makes the name parseable; the third argument supplies its numeric value for that evaluation.
Add a custom unary functionadd-custom-function
const T = Mexp.TOKEN_TYPES;
mexp.addToken([{
token: 'abs',
show: 'abs',
type: T.FUNCTION_WITH_ONE_ARG,
value: Math.abs,
precedence: 11,
}]);
console.log(mexp.eval('abs(-4)')); // 4Added tokens persist on the evaluator instance. Register a fixed trusted set during startup, not from arbitrary user input.
Reject invalid calculator inputhandle-invalid-expression
function calculate(input) {
if (input.length > 200) throw new Error('Expression too long');
try {
const value = mexp.eval(input);
if (!Number.isFinite(value)) throw new Error('Non-finite result');
return value;
} catch {
throw new Error('Invalid expression');
}
}Length is only a first guard. Also restrict numeric and Sigma or Pi bounds when evaluating input from untrusted callers.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| mathjs | npm | You need units, matrices, fractions, big numbers, complex values, typed functions, and a much broader expression language |
| expr-eval-fork | npm | You want a maintained expression-parser fork with variables, exports-map support, and published security fixes |
| @cortex-js/compute-engine | npm | You need symbolic mathematics, LaTeX input, exact forms, or expression trees rather than calculator-only numeric output |