nom README

The project's README from github.com/rust-bakery/nom. As one markdown file: README.md.

nom, eating data byte by byte

LICENSE Join the chat at https://gitter.im/Geal/nom Build Status Coverage Status crates.io Version Minimum rustc version

nom is a parser combinators library written in Rust. Its goal is to provide tools to build safe parsers without compromising the speed or memory consumption. To that end, it uses extensively Rust's strong typing and memory safety to produce fast and correct parsers, and provides functions, macros and traits to abstract most of the error prone plumbing.

nom logo in CC0 license, by Ange Albertini

nom will happily take a byte out of your files :)

Example

Hexadecimal color parser:

use nom::{
  bytes::complete::{tag, take_while_m_n},
  combinator::map_res,
  sequence::Tuple,
  IResult,
  Parser,
};

#[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
  ).parse(input)
}

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

fn main() {
  println!("{:?}", hex_color("#2F14DF"))
}

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

Documentation

If you need any help developing your parsers, please ping geal on IRC (Libera, Geeknode, OFTC), go to #nom-parsers on Libera IRC, or on the Gitter chat room.

Why use nom

If you want to write:

Binary format parsers

nom was designed to properly parse binary formats from the beginning. Compared to the usual handwritten C parsers, nom parsers are just as fast, free from buffer overflow vulnerabilities, and handle common patterns for you:

Example projects:

Text format parsers

While nom was made for binary format at first, it soon grew to work just as well with text formats. From line based formats like CSV, to more complex, nested formats such as JSON, nom can manage it, and provides you with useful tools:

Example projects:

Programming language parsers

While programming language parsers are usually written manually for more flexibility and performance, nom can be (and has been successfully) used as a prototyping parser for a language.

nom will get you started quickly with powerful custom error types, that you can leverage with nom_locate to pinpoint the exact line and column of the error. No need for separate tokenizing, lexing and parsing phases: nom can automatically handle whitespace parsing, and construct an AST in place.

Example projects:

Streaming formats

While a lot of formats (and the code handling them) assume that they can fit the complete data in memory, there are formats for which we only get a part of the data at once, like network formats, or huge files. nom has been designed for a correct behaviour with partial data: If there is not enough data to decide, nom will tell you it needs more instead of silently returning a wrong result. Whether your data comes entirely or in chunks, the result should be the same.

It allows you to build powerful, deterministic state machines for your protocols.

Example projects:

Parser combinators

Parser combinators are an approach to parsers that is very different from software like lex and yacc. Instead of writing the grammar in a separate file and generating the corresponding code, you use very small functions with very specific purpose, like "take 5 bytes", or "recognize the word 'HTTP'", and assemble them in meaningful patterns like "recognize 'HTTP', then a space, then a version". The resulting code is small, and looks like the grammar you would have written with other parser approaches.

This has a few advantages:

Technical features

nom parsers are for:

Some benchmarks are available on GitHub.

Rust version requirements (MSRV)

The 8.0 series of nom supports Rustc version 1.65 or greater.

The current policy is that this will only be updated in the next major nom release.

Installation

nom is available on crates.io and can be included in your Cargo enabled project like this:

[dependencies]
nom = "8"

There are a few compilation features:

You can configure those features like this:

[dependencies.nom]
version = "8"
default-features = false
features = ["alloc"]

Related projects

Parsers written with nom

Here is a (non exhaustive) list of known projects using nom:

Want to create a new parser using nom? A list of not yet implemented formats is available here.

Want to add your parser here? Create a pull request for it!

Contributors

nom is the fruit of the work of many contributors over the years, many thanks for your help!

nom (rust-bakery/nom)

Searching Database…

10.5K ·GitHub
这是什么?nom 是 Rust 的解析器组合子库:通过组合一个个小函数来构建安全的解析器,同时不牺牲速度和内存效率。
它是要导入到代码里的库,还是用来运行的工具?是库。你把它从 crates.io 加到 Cargo 项目里,然后用普通的 Rust 函数来写解析器——没有可执行文件要运行,也没有单独的语法文件。
怎么把它加到项目里?在 Cargo 项目里运行 cargo add nom。想学习的话,README 指向了 Nominomicon 指南、参考文档,以及一份列出每个组合子及其行为的清单。
需要比较新的 Rust 工具链吗?只要有 Rust 工具链就行:nom 8 要求 Rustc 1.65 或更新版本,而且这个最低要求只会在下一个大版本时才提高,所以小版本更新保持兼容。
有没有 nom 不太适合的场景?对于完整的编程语言,手写解析器在灵活性和速度上仍可能更胜一筹——nom 在这个领域把自己定位为原型解析工具,支持自定义错误类型,并用 nomlocate 精确定位到具体的行和列。
用 nom 写解析器和使用 lex 或 yacc 有什么不同?不需要语法文件,也不生成代码:你直接在 Rust 里拼装像“取 5 个字节”或“识别 HTTP”这样的小函数。代码保持精简,读起来接近你本来要写的语法,而且每个部分都可以单独做单元测试。
人们用它解析哪些格式的数据?很多:二进制格式(FLV、Matroska、tar)、文本格式(CSV、TOML、INI)、编程语言(PHP、SQL、Python)和网络协议(HTTP、TLS、DNS、DHCP)——README 里列出了几十个用 nom 写成的真实解析器。
它能处理分块到达的数据吗,比如来自网络套接字的数据?可以,流式处理是一等公民:当数据不足以做出判断时,nom 会要求更多数据,而不是悄悄返回错误结果,所以分块输入和完整输入得到的结果一致——这对协议状态机很实用。
它真的快吗?README 引用的基准测试显示,nom 的性能超过了 Parsec 和 attoparsec 这类组合子库、部分正则表达式引擎,甚至超过手写的 C 解析器。解析过程还是零拷贝的:结果直接引用输入的切片,而不是复制数据。
What are similar projects?antlr4, liteparse, go, kcp, parsedown, gjson, hyper, REDox
Size
10.5 MB
Stars
10.5K
Updated
CommitAug 26
Age
11y
Commits · 90 Days