使用 nom 和 nom_locate 得到简短的错误消息
我正在尝试按照 本教程使用 nom 和 nom_locate 进行解析。我只想要以下格式的输出:
Error: line 5, column 1
但目前我得到:
Error: Parsing Failure: ParseError { span: LocatedSpan { offset: 37, line: 5, fragment: "{{G]\nK(1)key [J]\n", extra: () }, message: "Error: line 5, column 1" }
相关代码:
pub type Span<'a> = LocatedSpan<&'a str>;
pub type IResult<'a, O> = nom::IResult<Span<'a>, O, ParseError<'a>>;
#[derive(Debug, PartialEq)]
pub struct ParseError<'a> {
span: Span<'a>,
message: String,
}
impl<'a> ParseError<'a> {
pub fn new(message: String, span: Span<'a>) -> Self {
Self {
span,
message,
}
}
}
impl<'a> nom::error::ParseError<Span<'a>> for ParseError<'a> {
fn from_error_kind(input: Span<'a>, _: nom::error::ErrorKind) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
fn append(input: Span<'a>, _: nom::error::ErrorKind, _: Self) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
fn from_char(input: Span<'a>, _: char) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
}
pub fn job(s: Span) -> IResult<Vec<entities::Step>> {
let (s, steps) = many1(job_lines)(s)?;
Ok((s, steps))
}
fn job_lines(s: Span) -> IResult<entities::Step> {
let (s, name) = match step_name(s) {
Ok((s, name)) => (s, name),
Err(nom::Err::Error(_)) => {
let line = s.location_line();
let column = s.get_column();
return Err(nom::Err::Failure(ParseError::new(
format!("Error: line {}, column {}", line, column),
s,
)));
},
Err(e) => return Err(e),
};
Ok((s, name))
}
主要中的相关错误代码:
let steps = match input::parsers::job(input::parsers::Span::new(&input)) {
Ok((_, steps)) => steps,
Err(error) => {
eprintln!("{}", error);
std::process::exit(1)
}
};
我需要做什么才能获得简短的错误消息而不是广泛的错误消息?
编辑: 我从自定义 ParseError 中删除了 span 属性,然后错误输出变为:
Parsing Failure: ParseError { message: "Error: line 5, column 1" }
好多了,但问题仍然存在:我可以获得除消息本身之外的所有内容吗?
I am trying to parse using nom with nom_locate, following this tutorial. I only want output in the format:
Error: line 5, column 1
But currently I get:
Error: Parsing Failure: ParseError { span: LocatedSpan { offset: 37, line: 5, fragment: "{{G]\nK(1)key [J]\n", extra: () }, message: "Error: line 5, column 1" }
Relevant code:
pub type Span<'a> = LocatedSpan<&'a str>;
pub type IResult<'a, O> = nom::IResult<Span<'a>, O, ParseError<'a>>;
#[derive(Debug, PartialEq)]
pub struct ParseError<'a> {
span: Span<'a>,
message: String,
}
impl<'a> ParseError<'a> {
pub fn new(message: String, span: Span<'a>) -> Self {
Self {
span,
message,
}
}
}
impl<'a> nom::error::ParseError<Span<'a>> for ParseError<'a> {
fn from_error_kind(input: Span<'a>, _: nom::error::ErrorKind) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
fn append(input: Span<'a>, _: nom::error::ErrorKind, _: Self) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
fn from_char(input: Span<'a>, _: char) -> Self {
Self::new(format!("Error: line {}, column {}", input.location_line(), input.location_line()), input)
}
}
pub fn job(s: Span) -> IResult<Vec<entities::Step>> {
let (s, steps) = many1(job_lines)(s)?;
Ok((s, steps))
}
fn job_lines(s: Span) -> IResult<entities::Step> {
let (s, name) = match step_name(s) {
Ok((s, name)) => (s, name),
Err(nom::Err::Error(_)) => {
let line = s.location_line();
let column = s.get_column();
return Err(nom::Err::Failure(ParseError::new(
format!("Error: line {}, column {}", line, column),
s,
)));
},
Err(e) => return Err(e),
};
Ok((s, name))
}
Relevant error code in main:
let steps = match input::parsers::job(input::parsers::Span::new(&input)) {
Ok((_, steps)) => steps,
Err(error) => {
eprintln!("{}", error);
std::process::exit(1)
}
};
What do I need to do to get the short error message instead of the extensive one?
EDIT:
I deleted the span property from the custom ParseError and then the Error output becomes:
Parsing Failure: ParseError { message: "Error: line 5, column 1" }
Much better, but question remains: can I get of everything except of the message itself?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如您所猜测的,
error
是nom ::Err::Err
这是一个enum
,因此您需要对其进行匹配才能获取内部错误:As you surmised,
error
is anom::Err::Err
which is anenum
, so you will need to match on that to get at the inner error: