我正在尝试熟悉Nom,目前是版本5,其中没有CompleteStr和其他东西,所以相关问题没有太大帮助。
我如何解析像这样的东西呢?
"@pook Some free text @another_pook And another text"转到
vec![("pook", "Some free text"), ("another_pook", "And another text")]前缀的字符串称为“字段标识符”;下一个子字符串是描述;两者都称为“@”。
下面是我如何成功解析一个字段:
use nom::bytes::complete::take_while1;
use nom::*;
use nom::character::is_alphabetic;
fn ident(c: char) -> bool {
is_alphabetic(c as u8) || c == '_'
}
fn freetext(c: char) -> bool {
c != '@'
}
fn parse_ident(s: &str) -> IResult<&str, &str> {
take_while1(ident)(s)
}
fn parse_freetext(s: &str) -> IResult<&str, &str> {
take_while1(freetext)(s)
}
named! {field_ident<&str, &str>,
do_parse!(
tag!("@") >>
name: parse_ident >>
(name)
)
}
named! { field <&str, (&str, &str)>,
do_parse!(
name: ws!(field_ident) >>
description: parse_freetext >>
(name, description)
)
}当我将它包装到many1中并提供前面所述的输入时,我收到了Err(Incomplete(Size(1))),但如果我在输入的末尾放入@,它就可以工作。如何在输入结束时将其标记为已完成?
发布于 2019-08-22 22:53:33
您需要的是many_till组合器,而不是many1,如下所示:
use nom::bytes::complete::take_while1;
use nom::character::is_alphabetic;
use nom::*;
fn ident(c: char) -> bool {
is_alphabetic(c as u8) || c == '_'
}
fn freetext(c: char) -> bool {
c != '@'
}
fn parse_ident(s: &str) -> IResult<&str, &str> {
take_while1(ident)(s)
}
fn parse_freetext(s: &str) -> IResult<&str, &str> {
take_while1(freetext)(s)
}
named! {field_ident<&str, &str>,
do_parse!(
tag!("@") >>
name: parse_ident >>
(name)
)
}
named! { field <&str, (&str, &str)>,
do_parse!(
name: ws!(field_ident) >>
description: parse_freetext >>
(name, description)
)
}
named!(fields<&str, (Vec<(&str, &str)>, &str)>, many_till!(field, eof!()));
fn main() {
println!("{:?}", field("@pook Some free text"));
println!(
"{:?}",
fields("@pook Some free text @another_pook And another text")
);
}这是违反直觉的。我想,这与nom的流媒体特性有关。
https://stackoverflow.com/questions/57608442
复制相似问题