10个版本

0.2.4 2020年1月25日
0.2.3 2020年1月17日
0.1.9 2019年12月30日

#428 in 解析器实现

Download history 1010/week @ 2024-03-14 1075/week @ 2024-03-21 1284/week @ 2024-03-28 1091/week @ 2024-04-04 995/week @ 2024-04-11 1268/week @ 2024-04-18 1196/week @ 2024-04-25 1202/week @ 2024-05-02 1035/week @ 2024-05-09 1168/week @ 2024-05-16 777/week @ 2024-05-23 964/week @ 2024-05-30 989/week @ 2024-06-06 834/week @ 2024-06-13 812/week @ 2024-06-20 816/week @ 2024-06-27

3,564 每月下载量
用于 15 个crate(12个直接使用)

MIT 许可证

270KB
2.5K SLoC

fasteval

快速且安全的代数表达式评估

fasteval 是一个用于解析、编译和评估代数表达式的库。它可以直接作为计算器语言使用(类似于 python),并且是构建高级语言的良好基础。

文档

用法

将此添加到您的 Cargo.toml

[dependencies]
fasteval = "0.2.4"

您应该 始终 使用 RUSTFLAGS="--emit=asm" 来构建,因为它会大大提高 LLVM 的编译时优化。

如果您使用的是 'nightly' Rust 编译器,您可以使用 --features nightly 来启用 'stable' Rust 中尚不可用的优化。

您可以使用 --no-default-features 来禁用诸如 andorNaNinf 等字母顺序关键字。 (这些单词可能对您的应用程序很重要。)

您可以使用 --features unsafe-vars 来启用 不安全变量

功能

  • 无依赖项。
  • 安全执行不受信任的表达式。
  • 支持稳定版Rust。
  • 支持解释(即解析和评估)以及编译执行(即解析、编译、评估)。
  • 支持变量和自定义函数。
  • fasteval 是构建高级语言的良好基础。
  • 支持许多内置函数和常量。
  • 支持所有标准代数一元和二元运算符(+ - * / ^ %),以及比较运算符(< <= == != >= >)和逻辑运算符(&& ||)以及短路支持。
  • 易于集成到多种不同类型的应用程序中,包括作用域评估。
  • 非常快速的性能。

简单示例

这里有一个简单的示例。更多示例请参阅API参考

ez_eval()函数为您执行整个分配-解析-评估过程。它稍微低效,因为它总是分配一个新的Slab,但使用起来非常简单。

fn main() -> Result<(), fasteval::Error> {
    // This example doesn't use any variables, so just use an EmptyNamespace:
    let mut ns = fasteval::EmptyNamespace;

    let val = fasteval::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()将返回一个错误

请注意,您(开发者)可以定义可能执行危险操作的自定义函数。确保所有自定义功能安全是您的责任。

性能基准

以下是一个性能基准的简要总结。对于更完整的报告和分析,请参阅官方文档

图表

请注意,以下图表使用对数刻度。因此,微小的视觉差异实际上代表了非常显著的性能差异。

编译表达式评估的性能
Compiled Eval Performance

一次性解释(解析和评估)的性能
Interpretation Performance

编译的不安全变量的性能,与C库tinyexpr(我们测试集中唯一支持此模式的库)相比
Unsafe Compiled Eval Performance

解释的不安全变量的性能,与C库tinyexpr(我们测试集中唯一支持此模式的库)相比
Unsafe Interpretation Performance

总结

这些结果令人印象深刻的是,fasteval在所有基准和每种操作模式(解释、编译和不安全)中始终实现了最快的时间。要牺牲其他指标的性能来声称在任何单一指标中排名第一是很容易的,但要创建一个全面排名第一的设计是困难的。

由于广泛的强大性能优势,fasteval很可能成为您动态评估需求的绝佳选择。

许可证

fasteval根据MIT许可证条款分发。

有关详细信息,请参阅许可证

无运行时依赖

功能