nomRust 解析器组合器框架

联合创作 · 2023-09-28 09:47

nom 是一个用 Rust 编写的解析器组合库。它的目标是在不影响速度或内存消耗的情况下提供构建安全解析器的工具。为此,它广泛使用 Rust 的强类型和内存安全来生成快速和正确的解析器,并提供函数、宏和特征来抽象大多数容易出错的管道。

Hexadecimal color parser:

extern crate nom;
use nom::{
  IResult,
  bytes::complete::{tag, take_while_m_n},
  combinator::map_res,
  sequence::tuple
};

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

fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
  u8::from_str_radix(input, 16)
}

fn is_hex_digit(c: char) -> bool {
  c.is_digit(16)
}

fn hex_primary(input: &str) -> IResult<&str, u8> {
  map_res(
    take_while_m_n(2, 2, is_hex_digit),
    from_hex
  )(input)
}

fn hex_color(input: &str) -> IResult<&str, Color> {
  let (input, _) = tag("#")(input)?;
  let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?;

  Ok((input, Color { red, green, blue }))
}

fn main() {}

#[test]
fn parse_color() {
  assert_eq!(hex_color("#2F14DF"), Ok(("", Color {
    red: 47,
    green: 20,
    blue: 223,
  })));
}

nom 解析器用于:

  • byte-oriented:基本类型是 &[u8],解析器将尽可能在字节数组片上工作(但不限于此)。
  • bit-oriented:nom可以将一个字节片作为一个比特流来处理。
  • string-oriented:同样的组合器也可以适用于 UTF-8 字符串。
  • zero-copy:如果一个分析器返回其输入数据的一个子集,它将返回该输入的一个片断,而不进行复制。
  • streaming:nom 可以在部分数据上工作,并检测它何时需要更多的数据来产生正确的结果。
  • descriptive errors:解析器可以聚合错误代码列表以及指向受控输入切片的指针。这些错误列表可以进行模式匹配以提供有用的消息。
  • custom error types:你可以提供一个特定的类型来改进解析器返回的错误。
  • safe parsing:nom 利用 Rust 的安全内存处理和强大的类型,解析器经常被模糊处理,并用真实世界的数据进行测试。到目前为止,模糊测试发现的唯一缺陷是在 nom 之外编写的代码。
  • speed:基准测试表明,nom 解析器的性能通常优于许多解析器组合库,如 Parsec 和 attoparsec,一些正则表达式引擎,甚至手写的 C 解析器。

Github 上提供了一些基准测试。

浏览 6
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报