From eb280a903f8f20d0b0c0ef5acae955a20929d100 Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Wed, 6 Jan 2021 16:36:46 +0000 Subject: Create Chewed, the consumer crate. --- chewed/src/parse.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 chewed/src/parse.rs (limited to 'chewed/src/parse.rs') diff --git a/chewed/src/parse.rs b/chewed/src/parse.rs new file mode 100644 index 0000000..0687ea5 --- /dev/null +++ b/chewed/src/parse.rs @@ -0,0 +1,82 @@ +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(()) + } +} + +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()?)) + } +} -- cgit v1.2.3