From cfb43069cc5175a3e0874e7c0b5e5f6486f8e5ca Mon Sep 17 00:00:00 2001 From: Aron Widforss <aron@antarkt.is> Date: Fri, 6 Sep 2019 16:47:45 +0200 Subject: [PATCH] Adds custom Error type to main_span_expr --- examples/main_span_expr.rs | 78 +++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/examples/main_span_expr.rs b/examples/main_span_expr.rs index b0b3771..3efbe08 100644 --- a/examples/main_span_expr.rs +++ b/examples/main_span_expr.rs @@ -6,13 +6,34 @@ use nom::{ character::complete::{digit1, multispace0}, combinator::map, sequence::{preceded, tuple}, - IResult, + Err, + error, }; use nom_locate::LocatedSpan; type Span<'a> = LocatedSpan<&'a str>; +#[derive(Debug)] +pub struct Error<'a>(Span<'a>, Option<Span<'a>>, ErrorKind); +type IResult<'a, I, O, E = Error<'a>> = Result<(I, O), Err<E>>; + +impl<'a> error::ParseError<Span<'a>> for Error<'a> { + fn from_error_kind(input: Span<'a>, kind: error::ErrorKind) -> Self { + Error(input, None, ErrorKind::Nom(kind)) + } + + fn append(_: Span<'a>, _: error::ErrorKind, other: Self) -> Self { + other + } +} + +#[derive(Debug)] +enum ErrorKind { + Parse, + Nom(error::ErrorKind) +} + #[derive(Debug, PartialEq)] pub enum Op { Add, @@ -36,13 +57,20 @@ pub enum Expr<'a> { type SpanExpr<'a> = (Span<'a>, Expr<'a>); -pub fn parse_i32(i: Span) -> IResult<Span, SpanExpr> { - map(digit1, |digit_str: Span| { - ( - digit_str, - Expr::Num(digit_str.fragment.parse::<i32>().unwrap()), - ) - })(i) +pub fn parse_i32<'a>(i: Span<'a>) -> IResult<Span<'a>, SpanExpr> { + let (i, digits) = digit1(i)?; + if let Ok(int) = digits.fragment.parse() { + Ok(( + i, + (digits, Expr::Num(int)), + )) + } else { + Err(Err::Failure(Error( + i, + Some(digits), + ErrorKind::Parse, + ))) + } } fn parse_expr(i: Span) -> IResult<Span, SpanExpr> { @@ -81,16 +109,30 @@ fn dump_expr(se: &SpanExpr) -> String { } fn main() { - let (_, (s, e)) = parse_expr_ms(Span::new("\n 1+2 - \n3")).unwrap(); - println!( - "span for the whole,expression: {:?}, \nline: {:?}, \ncolumn: {:?}", - s, - s.line, - s.get_column() - ); - - println!("raw e: {:?}", &e); - println!("pretty e: {}", dump_expr(&(s, e))); + let i = "\n 1+2+10000- \n3"; + match parse_expr_ms(Span::new(i)) { + Ok((_, (s, e))) => { + println!( + "span for expression: {:?}, \nline: {:?}, \ncolumn: {:?}", + s, + s.line, + s.get_column() + ); + println!("raw e: {:?}", &e); + println!("pretty e: {}", dump_expr(&(s, e))); + }, + Err(Err::Failure(Error(_, Some(s), err))) => { + println!( + "{:?} error at:\n\tLine: {:?}\n\tOffset: {:?}\n\tValue: {:?}", + err, + s.line, + s.get_column(), + s.fragment, + ); + println!("raw s: {:?}", &s); + } + Err(err) => Err(err).unwrap(), + } } // In this example, we have a `parse_expr_ms` is the "top" level parser. -- GitLab