SkillAgentSearch skills...

Fparse

A JavaScript Formula Parser

Install / Use

/learn @bylexus/Fparse

README

fparser

A JavaScript Formula Parser

Master Build Develop Build

fparser provides a Formula class that parses strings containing mathematical formulas (e.g. x*sin(PI*x/2)) into an evaluationable object. One can then provide values for all unknown variables / functions and evaluate a numeric value from the formula.

For an example application, see https://fparser.alexi.ch/.

Features

Parses a mathematical formula from a string. Known expressions:

  • Numbers in the form [-]digits[.digits], e.g. "-133.2945"
  • Numbers in scientific notation: e.g. "1.23e5", "1.5E-10", "-2.5e+3"
  • simple operators: '+','-','*','/', '^' expanded in correct order
  • logical operators: '<','<=','>','>=', '=', '!=', which evaluate to 1 or 0. Useful for implementing conditional logic
  • parentheses '(', ')' for grouping (e.g. "5*(3+2)")
  • all JavaScript Math object functions (e.g. "sin(3.14)")
  • all JavaScript Math constants like PI, E
  • the use of own functions
  • the use of variables (like 'x', 'myVar')
  • the use of named variables with optional brackets (like '2*myVar' or '2*[myVar]')
  • the use of strings as function arguments (like 'concat("Size: ", 2, " mm")')
  • the use of strings as variables (like 'concat("Size: ", 2, " ", [unit])')
  • the use of path named variables and functions (like '2*[myVar.property.innerProperty]')
  • memoization: store already evaluated results for faster re-calcs
  • use it in Web pages, as ES6 module or as NodeJS module
  • Example:<br /> <code>-1*(sin(2^x)/(PI*x))*cos(x)</code>

Breaking Changes in v4.0

Version 4.0 introduces significant improvements to the parser architecture, but includes some breaking changes. If you're upgrading from v3.x, please review these changes:

Syntax Changes

Implicit multiplication is no longer supported. You must now use explicit * operators:

| Old Syntax (v3.x) | New Syntax (v4.0) | Status | |-------------------|-------------------|--------| | 2x | 2*x | ❌ No longer supported | | 2xy | 2*x*y | ❌ No longer supported | | -3x | -3*x | ❌ No longer supported | | 3x^2 | 3*x^2 | ❌ No longer supported | | [myVar] | myVar or [myVar] | ✅ Both work (brackets optional) | | PI*x | PI*x | ✅ Still works |

Migration: Update all formulas to use explicit multiplication operators (*).

Semantic Changes

Power operator (^) is now right-associative (following mathematical convention):

| Expression | Old Behavior (v3.x) | New Behavior (v4.0) | |------------|---------------------|---------------------| | 2^3^2 | Left-associative: (2^3)^2 = 64 | Right-associative: 2^(3^2) = 512 | | 2^2^3 | (2^2)^3 = 64 | 2^(2^3) = 256 |

If you have formulas with chained power operators and need the old behavior, add explicit parentheses: (2^3)^2.

Removed Public Methods

The following internal methods are no longer available as they were only used by the old parser:

  • isOperator(char) - Only used internally by old state machine parser
  • isOperatorExpr(expr) - Only used internally by old state machine parser
  • splitFunctionParams(str) - Parser now handles function arguments directly

Benefits

These changes enable a cleaner, more maintainable parser with better error messages and easier extensibility. Multi-character variables no longer require brackets, making formulas more readable.

Usage

Include as ES module directly in your web page:

<!-- Within a web page: Load the fparser library: -->
<script type="module">
	import Formula from "dist/fparser.js";
	const f = new Formula('x+3');
</script>

Use CommonJS / global syntax for non-module environments:

<script src="dist/fparser.umd.cjs"></script>
<script>
	const f = new Formula('x+3');
</script>

Install it from npmjs.org:

# Install it using npm:
$ npm install --save fparser

Then use as ES6 module (recommended):

import Formula from 'fparser';

or use it as UMD module:

const Formula = require('fparser');

... and finally use it:

// 1. Create a Formula object instance by passing a formula string:
const fObj = new Formula('2^x');

// 2. evaluate the formula, delivering a value object for each unknown entity:
let result = fObj.evaluate({ x: 3 }); // result = 8

// or deliver multiple value objects to return multiple results:
let results = fObj.evaluate([{ x: 2 }, { x: 4 }, { x: 8 }]); // results = [4,16,256]

// You can also directly evaluate a value if you only need a one-shot result:
let result = Formula.calc('2^x', { x: 3 }); // result = 8
let results = Formula.calc('2^x', [{ x: 2 }, { x: 4 }, { x: 8 }]); // results = [4,16,256]

// Scientific notation is supported for large or small numbers:
let result = Formula.calc('1.5e3 + 2.5e-2'); // result = 1500.025
let result = Formula.calc('6.022e23 * x', { x: 2 }); // result = 1.2044e24 (Avogadro's number * 2)

More options

Using multiple variables

const fObj = new Formula('a*x^2 + b*x + c');

// Just pass a value object containing a value for each unknown variable:
let result = fObj.evaluate({ a: 2, b: -1, c: 3, x: 3 }); // result = 18

Using named variables

You can use multi-character variable names. Brackets are optional but still supported for backwards compatibility:

const fObj = new Formula('2*var1 + sin(var2+PI)');

// Just pass a value object containing a value for each named variable:
let result = fObj.evaluate({ var1: 5, var2: 0.7 });

// Brackets are still supported if you prefer:
const fObj2 = new Formula('2*[var1] + sin([var2]+PI)');
let result2 = fObj2.evaluate({ var1: 5, var2: 0.7 });

Note: Since v4.0, operators must be explicit. Single-char variable shortcuts like 2x (meaning 2*x) are no longer supported. See Breaking Changes in v4.0 for more details.

Using named object path variables

Named variables in brackets can also describe an object property path:

const fObj = new Formula('2*[var1.propertyA] + 3*[var2.propertyB.propertyC]');

// Just pass a value object containing a value for each named variable:
let result = fObj.evaluate({ var1: { propertyA: 3 }, var2: { propertyB: { propertyC: 9 } } });

This even works for array values: Instead of the property name, use a 0-based index in an array:

// var2.propertyB is an array, so we can use an index for the 3rd entry of propertyB:
const fObj = new Formula('2*[var1.propertyA] + 3*[var2.propertyB.2]');
let result = fObj.evaluate({ var1: { propertyA: 3 }, var2: { propertyB: [2, 4, 6] } });

Using user-defined functions

const fObj = new Formula('sin(inverse(x))');

//Define the function(s) on the Formula object, then use it multiple times:
fObj.inverse = (value) => 1/value;
let results = fObj.evaluate([{ x: 1 }, { x: 2 }, { x: 3 }]);

// Or pass it in the value object, and OVERRIDE an existing function:
let result = fObj.evaluate({
	x: 2/Math.PI,
	inverse: (value) =>  (-1*value)
});

If the function is defined in the value object AND on the formula object, the Value object has precedence

Functions also support the object path syntax:

// in an evaluate() value object:
const fObj = new Formula('sin(lib.inverse([lib.x]))');
const res = fObj.evaluate({
	lib: { inverse: (value) => 1 / value, x: Math.PI }
});

// or set it on the Formula instance:
const fObj2 = new Formula('sin(lib.inverse(x))');
fObj2.lib = { inverse: (value) => 1 / value };
const res2 = fObj2.evaluate({ x: Math.PI });

You can also pass objects as function arguments:

const fObj = new Formula('distance(p1, p2)');
fObj.distance = (point1, point2) =>
	Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));

let result = fObj.evaluate({
	p1: { x: 1, y: 3 },
	p2: { x: 4, y: 7 }
}); // result = 5

Using strings

You can also pass strings as values or variable values (not only numbers): It is then in your responsibility to provide a function that can make sense of the string:

E.g. you can create a function that concats 2 values:

const fObj = new Formula('concat([var1], "Bar")');
let result = fObj.evaluate({ var1: 'Foo', concat: (s1, s2) => s1 + s2 });

Here, the result of the evaluation is again a string.

Of course you can use strings to make decisions: Here, we provide a function longer that returns the length of the longe

View on GitHub
GitHub Stars107
CategoryDevelopment
Updated3mo ago
Forks14

Languages

JavaScript

Security Score

97/100

Audited on Dec 31, 2025

No findings