From 3f30676b59d69b1d658f734db458fd06e6b3ed75 Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Sat, 30 Jan 2021 13:49:28 +0000 Subject: Add convenience methods for hand-writing parsers. --- chewed/src/parse.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/chewed/src/parse.rs b/chewed/src/parse.rs index 2d01757..3d37739 100644 --- a/chewed/src/parse.rs +++ b/chewed/src/parse.rs @@ -44,6 +44,81 @@ pub trait Parser { Ok(()) } + + fn skip_while bool>(&mut self, mut f: F) { + while self.peek().map_or(false, &mut f) { + self.next(); + } + } + + fn take_chars_from(&mut self, set: &'static [char], buffer: &mut [char]) -> Result<(), TakeError> { + for pos in buffer { + match self.next() { + None => return Err(TakeError::EndOfStream(self.pos())), + Some(c) if set.contains(&c) => *pos = c, + Some(c) => return Err(TakeError::BadBranch(self.pos(), c, set)) + } + } + + Ok(()) + } + + fn iter_strict Result, R>( + &mut self, + item_parse: F, + sep: char, + stop: char, + sep_stop_set: &'static [char], + first: &'static [char], + ) -> Iter { + Iter { + iter: self, + parse: item_parse, + strict_sep: true, + sep, + stop, + sep_stop_set, + first, + } + } +} + +pub struct Iter<'a, P: ?Sized, F> { + iter: &'a mut P, + parse: F, + strict_sep: bool, + sep: char, + stop: char, + sep_stop_set: &'static [char], + first: &'static [char], +} + +impl Result, R> Iterator for Iter<'_, P, F> { + type Item = Result; + + fn next(&mut self) -> Option { + let c = self.iter.peek()?; + if c == self.stop { + None + } else { + let res = (self.parse)(self.iter).map(Some).transpose()?; + + match self.iter.peek() { + None => Some(Err(TakeError::EndOfStream(self.iter.pos()))), + Some(c) if c == self.sep => { + self.next(); + match self.iter.peek() { + None => Some(Err(TakeError::EndOfStream(self.iter.pos()))), + Some(c) if self.first.contains(&c) => Some(res), + Some(c) if !self.strict_sep && c == self.stop => Some(res), + Some(c) => Some(Err(TakeError::BadBranch(self.iter.pos(), c, self.first))), + } + } + Some(c) if c == self.stop => Some(res), + Some(c) => Some(Err(TakeError::BadBranch(self.iter.pos(), c, self.sep_stop_set))) + } + } + } } pub struct IterWrapper { -- cgit v1.2.3