10 个版本

0.2.0 2022年9月7日
0.1.2 2022年9月2日
0.1.1 2022年8月28日
0.0.6 2022年8月26日
0.0.2 2022年1月23日

#125 in 解析器工具

MIT 许可证

23KB
362

tests

mathematical expression evaluator.

使用方法

use mexe::eval;

fn main() {
    let forty_six = eval("(5 * 8) + 6").unwrap();
    let two = eval("1 + 1").unwrap();
    println!("{} & {}", forty_six, two);

    assert_eq!(forty_six, 46.0);
    assert_eq!(two, 2.0);
}

注意:上面的 assert_eq 可以工作,但为了在一般情况下比较浮点数,请使用 float-cmp 等crate。

为什么?

如果您需要评估简单的算术表达式,此crate提供了一种快速且轻量级的解决方案。

在我们的当前基准测试中,它比 meval 快约 4-10 倍,比 fasteval 快约 2 倍,而功能齐全的 evalexpr 通常是最慢的。请注意,这些crate的功能远不止 mexe -- 尤其是后者。我们对非常小的问题的关注使我们能够轻松地发布一个快速且精简的库。

包含

  • 求和
  • 减法
  • 乘法
  • 除法
  • 整数
  • 浮点数
  • 括号
  • 任意空白

浮点数表示为 X.Y,其中 XY 是非空数字序列。不接受带有指数的浮点数表示法或省略小数点两边的表示法。

目标

  • 最小化
  • 快速:O(n)
  • 无依赖项
  • 最小化分配
  • 彻底测试

运行测试和基准测试

单元测试和集成测试

cargo test

我们利用 glc cratemexe 生成有效的随机输入。下面的命令将运行一个无限运行的忽略集成测试,并在终端中显示输出,直到您使用 CTRL+C 停止它。

cargo test --test integration without_bounds -- --nocapture --ignored

基准测试

cargo bench -- bench_cmp   # comparison with other crates
cargo bench -- bench_mexe  # only mexe

运行模糊测试

使用 cargo-fuzz 运行了模糊测试。

要自行运行,您需要安装夜间工具链(rustup toolchain install nightly)以及工具本身:cargo install cargo-fuzz(更多详细说明和依赖项请查看项目的readme文件)。

之后运行

cargo fuzz init
cargo fuzz add fn_eval

转到 fuzz/fuzz_targets/fn_eval.rs 并粘贴以下代码

#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    // fuzzed code goes here
    if let Ok(text) = std::str::from_utf8(data) {
        let _ = mexe::eval(text);
    }
});

现在终于可以运行了

cargo +nightly fuzz run fn_eval

语法

E  -> T E'
E' -> + T E'
E' -> - T E'
E' -> ε
T  -> F T'
T' -> * F T'
T' -> / F T'
T' -> ε
F  -> ( E )
F  -> n
F  -> - ( E )
F  -> - n

其中 ε 是空字符串,而 n 是一个终端数字标记。语法灵感来源于 这篇文章

我们的第一个实现使用LL(1)解析器。

类似项目

无运行时依赖