use std::iter::Peekable; use super::error::{ParseError, TakeError}; pub trait Parser: Iterator { fn peek(&mut self) -> Option; fn take(&mut self) -> Result { P::take(self) } fn parse(self) -> Result where Self: Sized, { P::parse(self) } fn take_str(&mut self, s: &'static str) -> Result<(), TakeError> { let mut count = 0; for exp in s.chars() { if let Some(got) = self.peek() { if got == exp { self.next(); count += 1 } else { let mut out = String::from(&s[..count]); out.push(got); return Err(TakeError::BadString(out, s)); } } else { return Err(TakeError::EndOfStream); } } Ok(()) } } impl> Parser for Peekable { fn peek(&mut self) -> Option { Peekable::peek(self).copied() } } pub trait Parse: Sized { fn take(input: &mut P) -> Result; fn parse(mut input: P) -> Result { let res = Self::take(&mut input)?; if input.peek().is_some() { Err(ParseError::InputContinues) } else { Ok(res) } } } impl Parse for () { fn take(_: &mut P) -> Result { Ok(()) } } impl Parse for (A, B) { fn take(input: &mut P) -> Result { let a = input.take()?; let b = input.take()?; Ok((a, b)) } fn parse(mut input: P) -> Result { let a = A::take(&mut input)?; let b = B::parse(input)?; Ok((a, b)) } } impl Parse for Box { fn take(input: &mut P) -> Result { Ok(Box::new(input.take()?)) } fn parse(input: P) -> Result { Ok(Box::new(input.parse()?)) } }