如何实现一个不跳过标记的类似take_until_and_consume的解析器组合?

时间:2017-11-19 17:21:27

标签: rust nom

我想编写一个nom解析器组合器,它可以获取尽可能多的字节数,包括标记序列。我尝试使用take_until_and_consume!,但我发现生成的解析器组合器丢弃了标记序列:

#[macro_use]
extern crate nom;

named!(up_to_and_including_backslash, take_until_and_consume!("\\"));

fn main() {
    let res = up_to_and_including_backslash(b"    \\");
    println!("{:?}", res);
}

结果:

Done([], [32, 32, 32, 32])

我想要的是标记序列(在这种情况下,反斜杠字符)包含在结果中:

Done([], [32, 32, 32, 32, 92])

我该如何做到这一点?

2 个答案:

答案 0 :(得分:1)

<强>更新
您希望在recognize!上使用take_until_and_consume!("\\")将其消耗的所有内容添加到输出中。

您可以像这样编写解析器函数:

#[macro_use]
extern crate nom;

named!(up_to_and_including_backslash, recognize!( take_until_and_consume!("\\") ));

fn main() {
    let res = up_to_and_including_backslash(b"    \\");
    println!("{:?}", res);
}

如果您需要将多个解析器的消费符号包含在输出中,您可以将它们全部放在do_parse! recognize!内。像这样:

recognize!( do_parse!( tag!("\\") >> take_until_and_consume!("\\") >> take!(4) >> () ) )

<强>旧
我让这个工作的唯一方法是这种丑陋的憎恶。

named!(up_to_and_including_backslash,
    do_parse!(
        line: take_until_and_consume!("\\") >>
        (
            { 
                let mut complete_line:Vec<u8> = line.to_vec();
                complete_line.extend_from_slice(b"\\");
                &*complete_line
            }
        )
    )
);

答案 1 :(得分:-1)

现在您正在使用文档说明的方法take_until_and_consume

  

生成一个消耗字节的解析器,直到指定的字节序列   找到并消耗它

消费部分很重要,因为这是你想要避免的。

你可以做类似的事情:

named!(up_to_and_including_backslash,
    do_parse!(
        line: take_until!("\\") >> char!('\\') >>
        (line)
    )
);

哪个应该与你的分隔符一起返回。