13 个版本 (8 个破坏性更新)

使用旧的 Rust 2015

0.8.0 2017 年 2 月 1 日
0.6.0 2017 年 1 月 29 日
0.4.0 2016 年 12 月 31 日

#2082解析器实现


用于 peel-ip

MIT 许可证

50KB
418 代码行

peel

Build Status Build status Coverage Status master doc peel License MIT Crates.io doc.rs

树内的动态解析 🌲 🌳 🌴

该库的目标是提供一种灵活的解析数据的方法。这主要将在基于 区域内存管理解析树 中完成,这些树可以在运行时进行修改。每个解析器都使用 nom 框架来完成实际的解析工作。完整的源代码示例可以在 crate 的 src/example 目录中找到。

架构和用法

每个 Peel 实例可以看作是一个解析图结构,具有不同的状态和转换。在 crate 中的示例中,结构看起来是这样的

Example parser diagram

无论这些解析器做什么,结构的创建都是在 peel_example 函数中完成的

pub fn peel_example() -> Peel<()> {
    // Create a tree
    let mut p = Peel::new();

    // Create some parsers
    let parser_1 = p.new_parser(Parser1);
    let parser_2 = p.new_parser(Parser2);
    let parser_3 = p.new_parser(Parser3);
    let parser_4 = p.new_parser(Parser4);

    // Link the parsers together
    p.link_nodes(&[(parser_1, parser_2),
                   (parser_1, parser_3),
                   (parser_2, parser_3),
                   (parser_3, parser_3),
                   (parser_3, parser_4)]);

    p
}

第一个创建的解析器将自动成为根解析器,树遍历的入口点。每个后续的解析器都会返回一个特定的结果,该结果将作为 Box<Any> 推入向量中,可以向下转换为其他类型。

这意味着 Peel 的遍历方法将尝试在树结构中找到最深的有效路径。结构创建后,可以开始遍历

let mut peel = peel_example();
peel.set_log_level(LogLevel::Trace);
let result = peel.traverse(b"1234", vec![]).unwrap();

assert_eq!(result.len(), 4);
println!("{:?}", result);

借助 log crate 它将输出

[peel] [DEBUG] Parser 1 parsing succeed, left input length: 3
[peel] [DEBUG] Failed parser: Parser 3
[peel] [DEBUG] Parser 2 parsing succeed, left input length: 2
[peel] [DEBUG] Parser 3 parsing succeed, left input length: 1
[peel] [DEBUG] Parser 4 parsing succeed, left input length: 0

一个最小的解析器必须实现 Parser 特性,这可能看起来像这样

use example::prelude::*;

/// The first example parser
pub struct Parser1;

#[derive(Debug, PartialEq)]
/// The result of the first example parser
pub struct Parser1Result;

impl Parsable<()> for Parser1 {
    /// The actual parsing entry point
    fn parse<'a>(&mut self,
                 input: &'a [u8],                    // The input for the parser
                 result: Option<&ParserResultVec>,   // The current parsing result
                 data: Option<&mut ()>)              // Additional data which will
                                                     // be shared accross parsers
                 -> IResult<&'a [u8], ParserResult> {

        do_parse!(input, tag!("1") >> (Box::new(Parser1Result)))
    }
}

impl fmt::Display for Parser1 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Parser 1")
    }
}

可以访问当前的解析 result 以实现更高级的行为,如解析过程中的依赖项检查。此外,可以使用附加数据 data 在解析器之间共享数据。

贡献

你想为此项目做出贡献?太棒了!所以请把它分叉并发送给我一个 pull 请求。

依赖项

~8MB
~139K SLoC