Ceval
expression eval
Install / Use
/learn @yzw7489757/CevalREADME
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<CevalOptions>) => void| | getOptions| get Options | () => Readonly<CevalOptions>|
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
Related Skills
node-connect
349.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
