我有一个Nom解析器,解析字符串,但失败的关键字。
当给定关键字时,下面的解析器正确地失败。
但是由于遇到关键字而失败的错误消息没有传播。
问题是,当label
失败时,many0(label)
成功了,少了一个结果。随后,eof
失败了,因为并非所有内容都被解析了。这正确地失败了,但是错误消息丢失了。
如何传播本地错误消息?
(参见下面操场上的代码)
use nom::bytes::complete::{take_while, take_while1};
use nom::error::{VerboseError};
use nom::multi::{many0};
use nom::{IResult};
use nom::error::{context};
use nom::combinator::{eof, fail};
type ParseResult<'input, Out> = IResult<&'input str, Out, VerboseError<&'input str>>;
fn label(s1: &str) -> ParseResult<&str> {
let (s2, a) = take_while1(|c: char| c.is_alphabetic())(s1)?;
let (s3, _) = take_while(|c: char| c.is_whitespace())(s2)?;
if a == "derp" {
return context("this message is lost", fail)(s1);
}
Ok((s3, a))
}
fn parse(s: &str) -> ParseResult<Vec<&str>> {
let (s, labels) = many0(label)(s)?;
let (s, _) = eof(s)?;
Ok((s, labels))
}
fn main() {
println!("{:?}", parse("foo bar herp flerp"));
// Ok(("", ["foo", "bar", "herp", "flerp"]))
// This fails with Nom(Eof), both Nom(Fail) and context is lost
println!("{:?}", parse("foo bar herp derp"));
// Err(Error(VerboseError { errors: [("derp", Nom(Eof))] }))
}
您可以使用cut
来阻止many0
在失败情况下探索替代方案(消耗更少):
use nom::combinator::cut;
return cut(context("this message is lost", fail))(s1);
游乐场