2个不稳定版本
使用旧的Rust 2015
0.2.0 | 2019年6月24日 |
---|---|
0.1.0 | 2019年4月11日 |
在#parser-combinator 中排名 115
用于 ms-oforms
22KB
493 行
nom方法
nom-methods提供nom组合器,可以将解析器作为方法使用,而不是独立的函数。
lib.rs
:
方法宏组合器
这些宏将解析器作为结构体的方法,并可以接受将结构体的方法作为解析器。
为了便于组装,组合器是这样定义的
macro_rules! tag (
($i:expr, $inp: expr) => (
{
...
}
);
);
但当作为其他组合器中的方法使用时,是这样使用的
method!(my_function<Parser<'a> >, self, tag!("abcd"));
内部,其他组合器将重写该调用以将输入作为第二个参数传递
macro_rules! method (
($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: &[u8] ) -> IResult<&[u8], &[u8]> {
$submac!(i, $($args)*)
}
);
);
method!
宏与宏模块中的 named!
宏类似。虽然 named!
将创建一个解析器函数,但 method!
将在定义它的结构体上创建一个解析器方法。
与 named!
宏相比,它们在调用方式上略有不同。一个 method!
调用必须声明 self
的类型,并且由于Rust的借用生命周期限制,它不能是引用
// -`self`'s type-
method!(method_name< Parser<'a> >, ...);
self
的类型始终位于第一位。下一个不同之处在于你必须输入 self 结构体。由于Rust的宏卫生,宏不能自行声明它。
// -self-
method!(method_name<Parser<'a>, &'a str, &'a str>, self, ...);
在创建具有解析器方法的解析器结构体时,由于静态借用检查器,调用 self(或任何其他解析器结构体)上的任何解析器方法将导致 self 在整个方法中移动。为了绕过这个限制,所有 self 都被移动到被调用的方法中,然后被调用的方法将返回 self 给调用者。
要调用 self 上的方法,你需要使用 call_m!
宏。例如
struct<'a> Parser<'a> {
parsed: &'a str,
}
impl<'a> Parser<'a> {
// Constructor omitted for brevity
method!(take4<Parser<'a>, &'a str, &'a str>, self, take!(4));
method!(caller<Parser<'a>, &'a str, &'a str>, self, call_m!(self.take4));
}
更复杂的组合仍然基本上与它们的 named!
对应物看起来一样
method!(pub simple_chain<&mut Parser<'a>, &'a str, &'a str>, self,
do_parse!(
call_m!(self.tag_abc) >>
call_m!(self.tag_def) >>
call_m!(self.tag_ghi) >>
last: map!(call_m!(self.simple_peek), |parsed| sb.parsed = parsed) >>
(last)
)
);
在方法定义中需要记住三个添加项
- 指定
self
的类型 - 将
self
传递给宏 - 使用
call_m!
宏调用解析器方法。
依赖关系
~1MB
~18K SLoC