8 个不稳定版本 (3 个破坏性更新)

0.3.0 2024年3月26日
0.2.0 2024年3月22日
0.1.1 2024年3月22日
0.0.3 2024年3月13日
0.0.1 2021年10月31日

#105解析工具


3 crate 中使用

Zlib 许可证

200KB
6.5K SLoC

Binator

Binator 是一种解析器组合器,类似于 nom 或 combine。它需要 nightly 来使用实验性的 try trait 和 trait alias 特性。

示例

来自 nom 的相同十六进制颜色示例,但使用 binator

use binator::{
  Parse,
  Parsed,
  base::{
    is,
    uint_radix,
    IntRadixParse,
    Radix,
  },
  context::Ignore,
  utils::Utils,
};

#[derive(Debug, PartialEq)]
pub struct Color {
  pub red: u8,
  pub green: u8,
  pub blue: u8,
}

fn hex_primary<Stream, Context>(stream: Stream) -> Parsed<u8, Stream, Context>
where
  (): IntRadixParse<Stream, Context, u8>,
{
  uint_radix(2, Radix::HEX).parse(stream)
}

fn hex_color<Stream, Context>(stream: Stream) -> Parsed<Color, Stream, Context>
where
  (): IntRadixParse<Stream, Context, u8>,
{
  (is(b'#'), hex_primary, hex_primary, hex_primary)
    .map(|(_, red, green, blue)| Color { red, green, blue })
    .parse(stream)
}

assert_eq!(
  hex_color::<_, Ignore>.parse("#2F14DF".as_bytes()),
  Parsed::Success {
    stream: "".as_bytes(),
    token: Color {
      red: 0x2F,
      green: 0x14,
      blue: 0xDF,
    }
  }
);

更大的示例,一个简单的 JSON 解析器 这里,或者一个网络数据包解析器 这里

影响

  • 该项目受到了 nom 的影响很大。然而,它与 nom 非常不同,需要 nightly,并且非常实验性,而 nom 则更加稳定。
  • combine 也在一定程度上影响了该项目,但不如 nom

与 nom 的不同之处

binator 使用 alias trait 和 try trait 提供更好的体验,但这需要 nightly。

nom 可以处理八位字节和字符,binator 只接受八位字节。不要运行!binator 选择包含一个 utf8 组合器,这意味着在 nom 中你需要为每个组合器提供两个版本,一个用于字符,一个用于八位字节,而在 binator 中你只需要一个用于八位字节,当你在数据中期望 utf8 时,你必须使用我们的 utf8 组合器(或者你可以编写自己的)。我们不希望你验证数据是否是有效的 utf8,然后对其进行解析。对于不完整的数据来说,这要好得多。额外的好处是,在理论上这更快。

binator 中的错误比 nom 中的错误更灵活,你可以创建自己的错误,并且它们将被添加到你在构建的大解析器中的错误池中。所有错误都会被展平,无论你在哪里创建它们,这意味着你的自定义错误与 binator 错误处于同一级别,它们之间没有区别。这是通过泛型工作完成的,这使得与 binator 一起工作变得困难。Nom 选择在这一点上更简单,限制了用户自定义错误的定制。

binator的核心特性是流式处理,该特性的主要操作是split_first,它会简单地从您的流中取出一个Item,因此99%的情况下是数据的一个八位字节。而nom需要实现多个特性才能使用自定义的流,而binator只有一个,且非常简单。

限制

目前,数组被用作“或”分支,如果数组为空(因此没有解析器),那么就没有意义,因为数组解析器需要返回某些内容,因此需要一个自己的错误“空数组”,不应该使用空数组,但实际上可以,因为我们使用了const generic来实现Parse,这是可能的。然而,编写这样的代码非常困难,因为编译器无法仅从空数组推断任何信息,用户确实需要强制进行。这将在我们能够使用const generic做更多事情时被移除,并且在任何时候都不会被视为破坏性变更。

性能

虽然这不是主要目标,但它仍然是目标。目前的主要测试表明,它的性能与nom相似。因此,如果您的主要目标是峰值性能,那么binator可能不适合您,但如果目标是“足够快”,binator应该是可以的。欢迎提供一些基准测试,已经有为binator设计的json解析器crate。

许可证

本项目选择Zlib许可证,因为它几乎与MIT许可证相同,但它对二进制中许可证的包含更为灵活,并且包括修改共享。它还限制了分叉,这意味着不允许在未明确声明其为分叉而不是原始项目的情况下将副本上传到crates.io

贡献

除非您明确声明,否则您提交的任何旨在包含在您的工作中的贡献,都应按照上述(Zlib许可证)许可,不附加任何额外条款或条件。大贡献者最终将被添加到作者列表中。

Binator Contributors

语法

我显然不是英语母语者,因此我会接受使文档更清晰的PR,但是我不希望对“US vs UK”版本进行小的修正,我也不希望PR只是移除“!”或“?”之前的空格,因为我喜欢这种风格。我希望PR尊重原句的作者,但是如果你添加了新句子,请使用自己的风格。总之,我会接受任何增加清晰度的PR,但不会接受语法狂热者的PR。

依赖关系

~1–3MB
~54K SLoC