Rust Nom:许多和输入结束

Rust Nom: many and end of input

我正在尝试熟悉 Nom,目前是第 5 版,其中没有 CompleteStr 和其他内容,因此相关问题不是很有帮助。

我怎样才能解析像

这样的东西
"@pook Some free text @another_pook And another text"

进入

vec![("pook", "Some free text"), ("another_pook", "And another text")]

?

@ 前缀字符串称为 "field identifiers"; 下一个子串是描述; 两者都被称为 "field"

以下是我如何成功解析一个字段:

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))),但如果我将 @ 放在输入的末尾,它就会起作用。如何在输入结束时将其标记为已完成?

你想要 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 的流媒体性质有关。