JavaScript/ TypeScript 的表达式解析器
表达式Parser库又名"@adifkz/exp-p",是解析和评价数学和逻辑表达式的有力工具. 它为将表达解析能力融入您的项目提供了一个灵活而可扩展的解决方案. 此文档将引导您使用、 定制选项和 API 。 您可以在 npm 上找到“ @ adifkz/ exp- p” 软件包名下的库和 GitHub 上的源代码 https://github.com/adyfk/exp-p 页面存档备份,存于互联网档案馆。 。 。 .
特征
- 使用运算符评估数学表达式
+, (中文(简体) ),-, (中文(简体) ),*, (中文(简体) ),/, (中文(简体) ),%, (中文(简体) ),^等 (中文(简体) ). - 使用运算符评估逻辑表达式
AND, (中文(简体) ),OR, (中文(简体) ),NOT等 (中文(简体) ). - 支持括号来控制操作顺序.
- 在表达式中定义和使用变量.
- 定义自定义函数以扩展解析器的功能.
- 评估字符串字元.
- 评估数组字元并在数组上执行操作.
- 动态评估对象字面和访问属性 .
安装
您可以使用 npm 安装表达式Parser :
npm install @adifkz/exp-p
使用量
要在 JavaScript 代码中使用表达式Parser, 您需要导入表达式Parser 类并创建实例 :
import { createParser } from '@adifkz/exp-p';
const parser = createParser();
评价表达式
一旦您创建了表达式Parser实例,您就可以使用评价方法来评价表达式. 评估方法需要两个参数:用于评价的表达和包含表达中使用的变量和函数的可选上下文对象.
const parser = createParser();
const result = parser.evaluate('2 + 3 * 4'); // 14
变量映射
您可以定义变量,并在表达式中使用变量,为评价方法提供上下文对象.
const parser = createParser();
// Define variables
const variables = {
x: 5,
y: 10,
};
// Evaluate expression with variables
const result = parser.evaluate("x + y", variables);
console.log(result); // Output: 15
函数扩展
表达式解析器允许您通过添加自定义函数来扩展其功能. 以下是定义自定义函数的例子:
const parser = createParser();
// Define custom function
const functions = {
square: (_, value: number) => value * value,
};
parser.setFunctions(functions)
// Evaluate expression with custom function
const result = parser.evaluate("square(5)");
console.log(result); // Output: 25
实例
import moment from 'moment'
import { createParser, FunctionMap } from '../'
describe('example', () => {
it('basic operator', () => {
const parser = createParser({
})
expect(parser.evaluate('(2 + 3) * 4 - 4')).toBe(16)
expect(parser.evaluate('-4 + 5')).toBe(1)
expect(parser.evaluate('4 <= (5 + 2)')).toBe(true)
expect(parser.evaluate('4 > 5')).toBe(false)
expect(parser.evaluate('5 ^ 2 + 2')).toBe(27)
expect(parser.evaluate('5 + 4 * 4')).toBe(21)
expect(parser.evaluate('5 % 3')).toBe(2)
expect(parser.evaluate('5.5 * 3')).toBe(16.5)
expect(parser.evaluate('5 == 5')).toBe(true)
});
it('function', () => {
// Usage example
const variables = { x: 5 };
const functions: FunctionMap = {
add: (_, a: number, b: number) => a + b,
length: (_, str: string) => str.length,
length_all: (_, str1: string, str2: string, str3: string) => [str1.length, str2.length, str3.length],
};
const parser = createParser({ variables });
parser.setFunctions(functions)
expect(parser.evaluate('add(1 + 1, 5) + x')).toBe(12)
expect(parser.evaluate('length("ADI") + 5', variables)).toBe(8)
expect(parser.evaluate('length_all("ADI", "FA", "TK")', variables)).toEqual([3, 2, 2])
});
it('string', () => {
const parser = createParser();
expect(parser.evaluate('"ADI"')).toBe("ADI")
expect(parser.evaluate('\'ADI\'')).toBe("ADI")
expect(parser.evaluate('regex("ddd212sdf","\\d\\w\\d")')).toBe(true)
expect(parser.evaluate('regex("ddd212sdf","\\d\\w\\d","y")')).toBe(false)
})
it('boolean', () => {
const parser = createParser();
expect(parser.evaluate('true and false')).toBe(false)
expect(parser.evaluate('true or false')).toBe(true)
expect(parser.evaluate('!true')).toBe(false)
expect(parser.evaluate('!!true')).toBe(true)
})
it('array', () => {
const parser = createParser();
expect(parser.evaluate("[1, 2, 3, 4]")).toEqual([1, 2, 3, 4])
expect(parser.evaluate("[\"2\", 5]")).toEqual(["2", 5])
expect(parser.evaluate("[2 + 5, 5]")).toEqual([7, 5])
expect(parser.evaluate("[5, x]", { x: 2 })).toEqual([5, 2])
})
it('array method', () => {
const parser = createParser();
const products = [
{ name: 'Product 1', price: 150, quantity: 2 },
{ name: 'Product 2', price: 80, quantity: 0 },
{ name: 'Product 3', price: 200, quantity: 5 },
{ name: 'Product 4', price: 120, quantity: 1 }
];
expect(
parser.evaluate('filter(products, "_item_.price > 100 and _item_.quantity > 0")', {
products
})
).toEqual([
{ name: 'Product 1', price: 150, quantity: 2 },
{ name: 'Product 3', price: 200, quantity: 5 },
{ name: 'Product 4', price: 120, quantity: 1 }
])
expect(
parser.evaluate('map(products, "_item_.name")', {
products
})
).toEqual([
'Product 1',
'Product 2',
'Product 3',
'Product 4',
])
expect(
parser.evaluate('find(products, "_item_.price > 0")', {
products
})
).toEqual({
"name": "Product 1",
"price": 150,
"quantity": 2
})
expect(
parser.evaluate('some(products, "_item_.price == 200")', {
products
})
).toBe(true)
expect(
parser.evaluate('reduce(products, "_curr_ + _item_.price", 0)', {
products
})
).toBe(550)
})
it('object', () => {
const parser = createParser();
expect(parser.evaluate("{ name: 'ADI', age: 20 }")).toEqual({
name: "ADI",
age: 20
})
expect(parser.evaluate("{ name: 'ADI', age: 5 + 2 }")).toEqual({
name: "ADI",
age: 7
})
expect(parser.evaluate("object.name", { object: { name: 'ADI' } })).toEqual('ADI')
expect(parser.evaluate("object.name", { object: { name: 'ADI' } })).toEqual('ADI')
expect(parser.evaluate("object.0.name", { object: [{ name: 'ADI' }] })).toEqual('ADI')
expect(parser.evaluate("object.0.object.0.name", { object: [{ name: 'ADI', object: [{ name: "ADI" }] }] })).toEqual('ADI')
})
it('date', () => {
const parser = createParser();
// expect(parser.evaluate(`date()`)).toBe(moment().toISOString())
expect(parser.evaluate(`date("2020-01-01")`)).toBe('2019-12-31T17:00:00.000Z')
expect(parser.evaluate(`date_day(date("2020-01-01"))`)).toBe(1)
expect(parser.evaluate(`date_month(date("2020-01-01"))`)).toBe(1)
expect(parser.evaluate(`date_year(date("2020-01-01"))`)).toBe(2020)
expect(parser.evaluate(`date_format("DD-MM-YYYY", "2020-01-01")`)).toBe("01-01-2020")
expect(parser.evaluate(`date_in_format("YYYY-MM-DD", "2020-01-01")`)).toBe('2019-12-31T17:00:00.000Z')
expect(parser.evaluate(`date_in_millis(${moment("2020/01/01", 'YYYY/MM/DD').valueOf()})`)).toBe('2019-12-31T17:00:00.000Z')
expect(parser.evaluate(`date_millis("2020-01-01")`)).toBe(1577811600000)
expect(parser.evaluate(`date_format("DD-MM-YYYY", date_plus(1, "day", "2020-01-05"))`)).toBe("06-01-2020")
expect(parser.evaluate(`date_format("DD-MM-YYYY", date_plus(-1, "day", "2020-01-05"))`)).toBe("04-01-2020")
expect(parser.evaluate(`date_format("DD-MM-YYYY", date_minus(1, "day", "2020-01-05"))`)).toBe("04-01-2020")
expect(parser.evaluate(`date_format("DD-MM-YYYY", date_minus(-1, "day", "2020-01-05"))`)).toBe("06-01-2020")
})
});