1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
use nom::error::{ErrorKind, ParseError}; use nom_locate::LocatedSpanEx; #[derive(Clone, Debug, PartialEq)] pub struct GreedyError<I> { pub errors: Vec<(I, GreedyErrorKind)>, } #[derive(Clone, Debug, PartialEq)] pub enum GreedyErrorKind { Context(&'static str), Char(char), Nom(ErrorKind), } impl<I> ParseError<I> for GreedyError<I> where I: Position, { fn from_error_kind(input: I, kind: ErrorKind) -> Self { GreedyError { errors: vec![(input, GreedyErrorKind::Nom(kind))], } } fn append(input: I, kind: ErrorKind, mut other: Self) -> Self { other.errors.push((input, GreedyErrorKind::Nom(kind))); other } fn from_char(input: I, c: char) -> Self { GreedyError { errors: vec![(input, GreedyErrorKind::Char(c))], } } fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self { other.errors.push((input, GreedyErrorKind::Context(ctx))); other } fn or(self, other: Self) -> Self { let pos_self = if let Some(x) = self.errors.first() { x.0.position() } else { 0 }; let pos_other = if let Some(x) = other.errors.first() { x.0.position() } else { 0 }; if pos_other > pos_self { other } else { self } } } pub fn error_position<T: Position>(e: &GreedyError<T>) -> Option<usize> { e.errors.first().map(|x| x.0.position()) } pub trait Position { fn position(&self) -> usize; } impl<T, U> Position for LocatedSpanEx<T, U> { fn position(&self) -> usize { self.offset } }