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
50KB
418 代码行
peel
树内的动态解析 🌲 🌳 🌴
该库的目标是提供一种灵活的解析数据的方法。这主要将在基于 区域内存管理 的 解析树 中完成,这些树可以在运行时进行修改。每个解析器都使用 nom 框架来完成实际的解析工作。完整的源代码示例可以在 crate 的 src/example
目录中找到。
架构和用法
每个 Peel
实例可以看作是一个解析图结构,具有不同的状态和转换。在 crate 中的示例中,结构看起来是这样的
无论这些解析器做什么,结构的创建都是在 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