#parser-combinator #streaming #parser #standard-error

chomp

一个快速的单子式解析器组合器,旨在在稳定的 Rust 上运行

12 个版本

使用旧的 Rust 2015

0.3.1 2016 年 9 月 6 日
0.3.0 2016 年 9 月 1 日
0.2.6 2016 年 7 月 7 日
0.2.5 2016 年 3 月 8 日
0.1.1 2015 年 11 月 28 日

127解析工具

Download history 97/week @ 2024-03-11 120/week @ 2024-03-18 153/week @ 2024-03-25 162/week @ 2024-04-01 88/week @ 2024-04-08 111/week @ 2024-04-15 108/week @ 2024-04-22 99/week @ 2024-04-29 118/week @ 2024-05-06 107/week @ 2024-05-13 123/week @ 2024-05-20 97/week @ 2024-05-27 105/week @ 2024-06-03 113/week @ 2024-06-10 135/week @ 2024-06-17 109/week @ 2024-06-24

474 每月下载量
7 仓库中使用(直接使用 4 个)

MIT/Apache

280KB
4.5K SLoC

Chomp

Gitter Build Status Coverage Status Crates.io Documentation

Chomp 是一个快速的单子式解析器组合器库,旨在在稳定的 Rust 上运行。它是这些博客文章详细描述的实验的最终成果

就其当前功能而言,你会发现 Chomp 的性能与优化过的 C 解析器相当,甚至更好,同时具有更高的可表达性。有关如何使用较小的解析器构建高性能 HTTP 解析器的示例,请参阅 http_parser.rs

##安装

将以下行添加到您的 Cargo.toml 依赖关系部分

[dependencies]
chomp = "0.3.1"

##用法

解析器是从输入类型 Input<I> 的切片到 ParseResult<I, T, E> 的函数,它可以被认为是成功的结果,结果类型为 T,类型为 E 的错误,或者可能仍然消耗更多类型为 I 的部分完成的结果。

输入类型很少手动操作。相反,通过调用 parse! 宏来使用 Chomp 的解析器。这个宏被设计得尽可能接近 Haskell 的 do-语法或 F#'s "计算表达式",这些语法用于序列单子计算。在非常高的层面上,此宏的使用允许您声明性地

  • 按顺序排列解析器,如果任何步骤失败,则短路其他解析器。
  • 将先前成功的结果绑定到稍后用于计算的值。
  • 在计算结束时返回使用先前结果的综合数据结构。

换句话说,就像正常的 Rust 函数通常看起来像这样

fn f() -> (u8, u8, u8) {
    let a = read_digit();
    let b = read_digit();
    launch_missiles();
    return (a, b, a + b);
}

具有类似结构的 Chomp 解析器看起来像这样

fn f<I: U8Input>(i: I) -> SimpleResult<I, (u8, u8, u8)> {
    parse!{i;
        let a = digit();
        let b = digit();
                string(b"missiles");
        ret (a, b, a + b)
    }
}

要实现 read_digit,我们可以利用 map 函数来操作任何成功值,同时保留任何错误或不完整状态

// Standard rust, no error handling:
fn read_digit() -> u8 {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().parse().unwrap()
}

// Chomp, error handling built in, and we make sure we only get a number:
fn read_digit<I: U8Input>(i: I) -> SimpleResult<I, u8> {
    satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0')
}

有关更多信息,请参阅 rust-doc 输出。

示例

#[macro_use]
extern crate chomp;

use chomp::prelude::*;

#[derive(Debug, Eq, PartialEq)]
struct Name<B: Buffer> {
    first: B,
    last:  B,
}

fn name<I: U8Input>(i: I) -> SimpleResult<I, Name<I::Buffer>> {
    parse!{i;
        let first = take_while1(|c| c != b' ');
                    token(b' ');  // skipping this char
        let last  = take_while1(|c| c != b'\n');

        ret Name{
            first: first,
            last:  last,
        }
    }
}

assert_eq!(parse_only(name, "Martin Wernstål\n".as_bytes()), Ok(Name{
    first: &b"Martin"[..],
    last: "Wernstål".as_bytes()
}));
# }

许可证

许可协议为以下之一

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的,您有意提交以包含在作品中的任何贡献,将按照上述方式双许可,不附加任何额外条款或条件。

##联系

在此处提交问题到Github或访问gitter.im/m4rw3r/chomp

依赖项

~0.6–1.2MB
~22K SLoC