9个稳定版本
2.1.1 | 2023年1月13日 |
---|---|
2.0.6 | 2022年12月5日 |
2.0.3 | 2022年5月27日 |
2.0.1 | 2022年5月26日 |
2.0.0 | 2022年5月24日 |
#305 in 解析器实现
315 每月下载量
在 3 个crate(2直接) 中使用
270KB
3K SLoC
fasteval
代数表达式的快速且安全评估
fasteval
是一个用于解析、编译和评估代数表达式的库。它可以直接用作计算器语言(类似于 python
),并且是构建高级语言的优秀基础。
文档
使用方法
将此内容添加到您的Cargo.toml中
[dependencies]
fasteval2 = "0.2.4"
您可以使用 codegen-units=1
以获得更好的运行时性能。在某些情况下,它将极大地提高LLVM的编译时优化。(请参阅 如何编写快速的Rust代码)。
如果您使用的是 'nightly' Rust编译器,您可以使用 --features nightly
来构建以启用在 'stable' Rust中尚不可用的优化。
您可以使用 --no-default-features
来禁用诸如 and
、or
、NaN
、inf
等字母顺序关键字。 (这些单词可能对您的应用程序很重要。)
您可以使用 --features unsafe-vars
来启用 不安全变量。
特性
- 无依赖项。
- 安全执行不受信任的表达式。
- 支持稳定Rust。
- 支持解释(即解析和评估)以及编译执行(即解析、编译、评估)。
- 支持变量和自定义函数。
fasteval
是构建高级语言的优秀基础。- 支持许多内置函数和常量。
- 支持所有标准的代数一元和二元运算符(+ - * / ^ %),以及比较运算符(< <= == != >= >)和逻辑运算符(&& ||)并支持短路。
- 易于集成到多种不同的应用中,包括作用域评估。
- 性能非常快。
简单示例
这里有一个简单的示例。更多示例请参阅API参考!
函数ez_eval()
为您执行整个分配-解析-评估过程。它稍微有些低效,因为它总是分配一个新的Slab
,但它使用起来非常简单
fn main() -> Result<(), fasteval2::Error> {
// This example doesn't use any variables, so just use an EmptyNamespace:
let mut ns = fasteval2::EmptyNamespace;
let val = fasteval2::ez_eval(
"1+2*3/4^5%6 + log(100K) + log(e(),100) + [3*(3-3)/3] + (2<3) && 1.23", &mut ns)?;
// | | | | | | | |
// | | | | | | | boolean logic with short-circuit support
// | | | | | | comparisons
// | | | | | square-brackets act like parenthesis
// | | | | built-in constants: e(), pi()
// | | | 'log' can take an optional first 'base' argument, defaults to 10
// | | numeric literal with suffix: p, n, µ, m, K, M, G, T
// | many built-in functions: print, int, ceil, floor, abs, sign, log, round, min, max, sin, asin, ...
// standard binary operators
assert_eq!(val, 1.23);
Ok(())
}
REPL演示
github.com/likebike/fasteval$ rlwrap cargo run --release --example repl
Finished release [optimized] target(s) in 0.01s
Running `target/release/examples/repl`
>>> print("Hello fasteval", 1, 2, 3)
Hello fasteval 1 2 3
3
>>> _ + 1
4
>>> _ + 1
5
>>> _ * 2
10
>>> _ ^ 0.5
3.1622776601683795
>>> let a = 1
1
>>> let b = a + 1
2
>>> let c = a + b * 3
7
>>> a + b + c
10
>>> push
Entered scope[1]
>>> let b = b + 10
12
>>> a + b + c
20
>>> pop
Exited scope[1]
>>> a + b + c
10
>>> 1+2*3/4^5%6 + log(100K) + log(e(),100) + [3*(3-3)/3] + (2<3) && 1.23
1.23
>>> 1+2*3/4^5%6 + print("log(100K) =",log(100K)) + log(e(),100) + [3*(3-3)/3] + (2<3) && 1.23
log(100K) = 5
1.23
安全性
fasteval
旨在安全地评估不受信任的表达式。默认情况下,表达式只能执行数学运算;它无法访问其他类型的操作(如网络、文件系统或外部命令)。此外,我们还能防止恶意表达式
- 过长(大于4KB)的表达式。
- 过深嵌套(大于32层)的表达式。
- 值过多(大于64)的表达式。
- 子表达式过多(大于64)的表达式。
所有限制都可以在解析时自定义。如果任何限制被超过,parse()
将返回一个Error。
请注意,您(开发者)可以定义可能执行危险操作的函数。确保所有自定义功能安全是您的责任。
性能基准
以下是性能基准的简要总结。对于更完整报告和分析,请参阅官方文档。
图表
请注意,以下图表使用对数刻度。因此,微小的视觉差异实际上代表了非常显著的性能差异。
编译表达式的评估性能
一次性解释(解析和评估)的性能
编译不安全变量的性能,与C库tinyexpr(我们测试集中唯一支持此模式的库)相比
解释不安全变量的性能,与C库tinyexpr(我们测试集中唯一支持此模式的库)相比
总结
这些结果令人印象深刻的是,fasteval
在每次基准测试的每个操作模式(解释、编译和不安全)中都始终达到最快的时间。要牺牲其他方面的性能来获得任何这些指标的排名第一,很容易,但要创建一个在所有方面都能排名第一的设计是困难的。
由于广泛的强大性能优势,fasteval
很可能成为您动态评估需求的绝佳选择。
许可证
fasteval
根据MIT许可证条款分发。
有关详细信息,请参阅LICENSE。