ceval
v1.2.5
Published
calculation expression, support broswer and node
Downloads
11
Maintainers
Readme
Ceval
中文文档 零依赖,适合表达式运算;
No dependence, suitable for calculating expressions;
┌───────────────────────────────┐
│ │
│ Destination: lib/index.js │
│ Bundle Size: 21.92 KB │
│ Minified Size: 21.89 KB │
│ Gzipped Size: 6.76 KB │
│ │
└───────────────────────────────┘
usage
npm i ceval -S
introduce
Options
const Parser = require('ceval')
const analysis = new Parser({
/**
* @desc Allow operators
* @type {boolean}
*/
endableOperators?: boolean = true;
/**
* @desc number enable multi bit base
* @type {boolean}
*/
endableBitNumber?: boolean = true;
/**
* @desc Allow access to members
* @type {boolean}
*/
allowMemberAccess?: boolean = true;
/**
* @desc Zoom in calculation allowed by default
* @see To process the results of arithmetic e.g 0.1+0.2 !== 0.3 || 1.0-0.9 !== 0.1
* Beyond the boundary(ta > Number.MAX_SAFE_INTEGER || ta < Number.MIN_SAFE_INTEGER)will not do processing, restore arithmetic
* @requires false
* @type {boolean}
*/
allowHandleNumberPrecision?: boolean = true;
/**
* @desc Operators are not allowed to be overridden by presetvalue by default
* @see In some cases, developers want to make more accurate calculations, such as BigInt, presetValue={'+':Function}
* @requires false
* @type {boolean}
* @memberof CevalOptions
*/
allowOperatorsCovered?: boolean;
/**
* @desc Trigger default return value when there is no return value or undefined
* @type {any}
*/
defaultReturnValues?: any = '' // done
})
API
Parser Instance API
| api | desc | type | | --- | --- | --- | | operatorMap | Operators mapping table, which can be used in preset values overlay operation | Record<string, Function>| | getSupportOperationMap | The name of the operator method supported by the query can be overridden | (ops: string) => null | Function;| | parseString | Parsing strings, exposing methods to the outside world | (expression: string, values?: Record<string, any>) => any;| | getCurrentValues | Get current datapool preset + external + internal declaration | () => Record<string, any> | | updatePresetValues| Update PresetValues |(values: Record<string, any>) => void| | updateOptions| Update Option | (Options: Partial) => void| | getOptions| get Options | () => Readonly|
about Options example test case;
use test262 test case;
rule
There are two rules:
Semicolon at the end
e.g.
parse('0b01 + 0b01;') // 2
Although it is not necessary in a simple expression operation, but it's a good habit.The parser can know exactly where the end is, Although it doesn't have too many restrictions.
e.g.
parse(`
function abs(a,b,c) {
let b = 1 /* ⚠️ error, must has semicolon */
c = 2;
return(a+b+c);
};
abs(3,4,8);
`)
statement
"var" statement does not affect "scope", it's inserted into values "let" and "const" assigned to the current scope, warn if the current scope exists
var Parser = require('ceval');
var instance = new Parser({/*...*/});
var parse = instance.parseString;
parse(`
var obj = { foo:'foo', bar: 'bar'};
function abs(a,b,c) {
var d = 'global';
return (a+b+c);
}
abs(1,2,3)
`)
console.log(instance.getCurrentValues().obj); // { foo:'foo', bar: 'bar'}
console.log(instance.getCurrentValues().d); // 'global'
parse(`
let foo = 'foo';
const bar = 'bar';
function abs(a,b,c) {
let d = 'scope';
const e = 'scope';
return (a+b+c);
}
abs(1,2,3)
`)
console.log(instance.getCurrentValues().foo); // undefined
console.log(instance.getCurrentValues().bar); // undefined
console.log(instance.getCurrentValues().d); // undefined
console.log(instance.getCurrentValues().e); // undefined
basic
const { parse: parse } = analysis
Number
parse('0b01') // 1
parse('0b11') // 3
parse('0b010101') // 21
parse('01') // 1
parse('077') // 63
parse('01111') // 585
parse('.1') // 1
parse('33') // 33
parse('100.00') // 100
parse('0x01') // 1
parse('0xaf') // 175
parse('0x9fac') // 40876
parse(`1e+308*2 === Infinity`) // true
parse(`
var x = NaN;
var y = NaN;
return (x !== y);
`) // true
parse(`
var x = NaN;
return(typeof(x) === 'number');
`) // true
parse(`
var x = NaN;
var x_geq_0=(x >= 0.0);
return(x_geq_0)
`) // false
parse(`
var x=+Infinity;
return(typeof(x) === 'number')
`) // true
More testcase here
calculation
const obj = `{ a: 1, b: 2, c: 3, d: { e: 4, f: 5}}`
parse(`1+1`); // 2
parse(`-1-2-3`); // -6
parse(`1*2*3`); // 6
parse(`1/2/4`); // 0.125
parse(`undefined || 2`); // 2
parse(`~-1 || -2 || 3`); // -2
parse(`-0 == +0`); // true
parse(`~1 > 1`); // false
parse(`false > false > 1`); // false
parse(`5 >= 0`); // true
parse(`1 in [1, 2, 3]`); // true
parse(`undefined in [1, 2, true]`); // false
parse(`'a' in ${obj}`); // true
parse(`\'\'a\'\' in ${obj}`); // true ('"a"' === 'a') is Palindrome
parse(`1 === true`); // false
parse(`3%2`); // 1
Function
parse(`
function abs(a,b,c) {
var a = 5; /* => inject to presetValues */
let b = 1; /* => inject to current scope */
c = 2;
const d = 4; /* If the current scope contains the variable D, It will trigger warning, but the operation will still be completed, is overlay */
return(a+b+c);
};
abs(3,4,8);
`)
Object & Array
parse(`[1*2, false, true, undefined, null]`); // Array[]
parse(`var a = { b: { c: ['a','b','c','d']} };'e' in a.b.c`); // false
parse(`{ a: 1, b: 2, c: { d: undefined, e: { f: false, g: { h: null }}}}`); // object
parse(`var a = { b: 2 };a.b`) //2;
parse(`var a = { b: 2 };a["b"]`) //2;
parse(`var a = { b: 2, c:3 };var b='c';a[b]`) //3;
// data reference
parse(`
var a = { b: 2, c:[1,2,3]};
var b='c';
a[b][0] = '0';
return a[b];
`) // ['0',2,3]
parse(`
var arr = [1,2,3];
arr[0] = 0;
return arr;
`) // [0,2,3]
Variable
parse(`
var a = { foo: 1 };
var b = { bar: 2 };
let a = { state: 1 } // ⚠️, Raise warning, current scope exists key
const b = { state: 1 } // ⚠️, Raise warning, current scope exists key
let c = { coo: 1} // success;
const d = { coo: 1} // success;
`)
parse(`
var a = { a: [false, true, undefined, null, ''] };
var b = { b: true, c: undefined, d:{ e: a, f: '1', g: {}}};
`) // Can be obtained from the instance. api: getCurrentValues
this
Operator
Through instance.operatorMap
Get all operators;
return
return
interrupt this operation cycle; but it doesn't affect the outside world.
parse(`
return 1;
return 2;
`) // 1
parse(`
var foo = 'foo'
function abs(a,b,c) {
return a;
return b;
}
var bar = abs(1,2,3)
return (bar + foo);
`) // foo1
Other
Please move to test case for more examples。
TODO: Test39 Some test cases,
speed of progress
2020-06-24 done: number, null, boolean
In more function extension, welcome to participate or propose feature.
development
develop
npm start
build
# webapck build umd module, No compression
npm run build:umd
# rollup build umd module, Compressed version
npm run build:rollup
# webpack build docs
npm run build:docs
publish
npm publish