3xpr
3xpr is an extensible expression evaluator and parser.
Besides the operators, functions, variables, objects and arrays that are supported.
It is possible to extend it with your own functions, operators, etc
Features
- Constants, enums, number, string, datetime, variables, objects and array
- Arithmetic
, assignment
, comparison
, logical
and bitwise operators
- Number
, string
, datetime
, array
and nullable functions
- Conversion functions
- Arrow functions
- Group functions (distinct, first, last, min, max, sum and avg)
- Sets functions (union, intersection, difference and symmetric difference)
- Control flows flows
- Environment variables
- Extend
- Metadata
Quick start
import { expressions as exp } from '3xpr'
const context = {
name: 'Spain',
region: 'Europe',
phoneCode: '34',
timezones: [
{ name: 'Madrid', offset: 1, pos: { lat: 40.4165, log: -3.70256 } },
{ name: 'Ceuta', offset: 1, pos: { lat: 35.8883, log: -5.3162 } },
{ name: 'Canary', offset: 0, pos: { lat: 28.1248, log: -15.43 } }
]
}
const result = exp.eval('5*(7+9)==(5*7+5*9)')
console.log(result)
exp.eval('toNumber(phoneCode) <= 30', context)
exp.eval('`${name} belongs to ${region}`', context)
exp.eval('timezones.filter(p => substring(p.name,0,1)=="C")', context)
exp.eval('timezones.filter(p => p.offset == 1).sort(p => p.pos.lat).name', context)
exp.eval('stringify(timezones.first(p => p.name == "Madrid").pos)', context)
exp.eval('timezones.filter(p => p.pos.lat > 30 && p.pos.log > -4).pos.lat', context)
exp.eval('sort(timezones.name)', context)
exp.eval('timezones[0].name', context)
exp.eval('round(timezones.first(p=> p.name =="Madrid").pos.lat - timezones.first(p=> p.name =="Ceuta").pos.lat,2)', context)
exp.eval('timezones.each(p => p.pos={lat:round(p.pos.lat,2),log:round(p.pos.log,2)}).map(p=> stringify(p))', context)
exp.eval(`
list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
total = 0;
for (i = 0; i < list.length(); i += 1) {
total += list[i];
}
`, context)
console.log(context.total)
exp.eval(`
while (p=timezones.pop()) {
console(p);
}
`, context)
Extend
You can extend the library by adding enums, constants, formats, operators, and functions.
To do this, use the following functions:
- AddConstant: Adds a constant to the library.
- AddEnum: Adds an enumeration to the library.
- AddFormat: Adds a format to the library.
- AddOperator: Adds an operator to the library.
- AddFunction: Adds a function to the library.
Example
import { expressions as exp } from '3xpr'
const CryptoJS = require('crypto-js')
exp.addFunction(
'encrypt(value:string):string',
(value: string, key:string):string => CryptoJS.AES.encrypt(value, key).toString(),
{ description: 'Encrypt a string' }
)
exp.addFunction(
'decrypt(value:string):string',
(value: string, key:string):string => CryptoJS.AES.decrypt(value, key).toString(CryptoJS.enc.Utf8),
{ description: 'Decrypt a string' }
)
Related projects
Documentation
Full documentation is available in the Wiki.