首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rust Nom:输入的多个和结尾

Rust Nom:输入的多个和结尾
EN

Stack Overflow用户
提问于 2019-08-22 19:35:20
回答 1查看 609关注 0票数 3

我正在尝试熟悉Nom,目前是版本5,其中没有CompleteStr和其他东西,所以相关问题没有太大帮助。

我如何解析像这样的东西呢?

代码语言:javascript
复制
"@pook Some free text @another_pook And another text"

转到

代码语言:javascript
复制
vec![("pook", "Some free text"), ("another_pook", "And another text")]

前缀的字符串称为“字段标识符”;下一个子字符串是描述;两者都称为“@”。

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

代码语言:javascript
复制
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))),但如果我在输入的末尾放入@,它就可以工作。如何在输入结束时将其标记为已完成?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-22 22:53:33

您需要的是many_till组合器,而不是many1,如下所示:

代码语言:javascript
复制
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的流媒体特性有关。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57608442

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档