Skip to content
Snippets Groups Projects
Select Git revision
  • 09056afaa29e9e051f8c87df7eae39dd1baa9310
  • master default protected
  • home_exam
  • wip
4 results

main_span_expr_custom_err2.rs

Blame
  • Forked from Per Lindgren / D7050E
    Source project has a limited visibility.
    main_span_expr_custom_err2.rs 4.17 KiB
    extern crate nom;
    
    use nom::{
        branch::alt,
        bytes::complete::tag,
        character::complete::{digit1, multispace0},
        combinator::map,
        error,
        sequence::{preceded, tuple},
        Err,
    };
    
    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 {
        ParseIntError(std::num::ParseIntError),
        Nom(error::ErrorKind),
    }
    
    #[derive(Debug, PartialEq)]
    pub enum Op {
        Add,
        Sub,
    }
    
    type SpanOp<'a> = (Span<'a>, Op);
    
    fn parse_op(i: Span) -> IResult<Span, SpanOp> {
        alt((
            map(tag("+"), |s| (s, Op::Add)),
            map(tag("-"), |s| (s, Op::Sub)),
        ))(i)
    }
    
    #[derive(Debug, PartialEq)]
    pub enum Expr<'a> {
        Num(i32),
        Num64(i64),
        BinOp(Box<SpanExpr<'a>>, SpanOp<'a>, Box<SpanExpr<'a>>),
    }
    
    type SpanExpr<'a> = (Span<'a>, Expr<'a>);
    
    pub fn parse_i32<'a>(i: Span<'a>) -> IResult<Span<'a>, SpanExpr> {
        let (i, digits) = digit1(i)?;
        match digits.fragment.parse() {
            Ok(int) => Ok((i, (digits, Expr::Num(int)))),
            Err(e) => Err(Err::Error(Error(
                i,
                Some(digits),
                ErrorKind::ParseIntError(e),
            ))),
        }