diff options
| author | John Turner <jturner.usa@gmail.com> | 2025-10-21 20:48:00 -0400 |
|---|---|---|
| committer | John Turner <jturner.usa@gmail.com> | 2025-10-21 20:48:21 -0400 |
| commit | 0e23b9fa82d95ca365523afac554a4fb6d461a23 (patch) | |
| tree | 296fc7fc3e8208198b7e87adf4a016a9ea93aedf /src/input.rs | |
| parent | 876855e826bf3c7bd47b822fb41fd91ab46ad7e5 (diff) | |
| download | mon-0e23b9fa82d95ca365523afac554a4fb6d461a23.tar.gz | |
impl some basic parsers and combinators
Diffstat (limited to 'src/input.rs')
| -rw-r--r-- | src/input.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/input.rs b/src/input.rs new file mode 100644 index 0000000..0857c8c --- /dev/null +++ b/src/input.rs @@ -0,0 +1,127 @@ +use core::{fmt, iter, slice, str::CharIndices}; + +use crate::Span; + +pub trait Input: Clone { + type Item; + type Items: Clone + Iterator<Item = (usize, Self::Item)>; + + fn items(&self) -> Self::Items; + + fn slice(&self, span: Span) -> Self; + + fn len(&self) -> usize; +} + +impl<'a> Input for &'a str { + type Item = char; + type Items = CharIndices<'a>; + + fn items(&self) -> Self::Items { + self.char_indices() + } + + fn slice(&self, span: Span) -> Self { + &self[span] + } + + fn len(&self) -> usize { + (*self).len() + } +} + +impl<'a> Input for &'a [u8] { + type Item = u8; + type Items = iter::Enumerate<iter::Copied<slice::Iter<'a, u8>>>; + + fn items(&self) -> Self::Items { + self.iter().copied().enumerate() + } + + fn slice(&self, span: Span) -> Self { + &self[span] + } + + fn len(&self) -> usize { + (*self).len() + } +} + +pub trait Character { + fn is_alphabetic(&self) -> bool; + + fn is_numeric(&self) -> bool; + + fn is_whitespace(&self) -> bool; + + fn is_alphanumeric(&self) -> bool { + self.is_alphabetic() || self.is_numeric() + } +} + +impl Character for char { + fn is_alphabetic(&self) -> bool { + (*self).is_ascii_alphabetic() + } + + fn is_numeric(&self) -> bool { + (*self).is_numeric() + } + + fn is_whitespace(&self) -> bool { + (*self).is_whitespace() + } +} + +#[derive(Clone)] +pub struct InputIter<I: Input> { + pub it: I::Items, + pub input: I, +} + +impl<I> InputIter<I> +where + I: Input, +{ + pub fn new(input: I) -> Self { + Self { + it: input.items(), + input, + } + } + + pub fn position(&self) -> usize { + match self.it.clone().next() { + Some((i, _)) => i, + None => self.input.len(), + } + } + + pub fn is_finished(&self) -> bool { + self.clone().next().is_none() + } + + pub fn rest(&self) -> I { + self.input.slice(self.position()..self.input.len()) + } +} + +impl<I> Iterator for InputIter<I> +where + I: Input, +{ + type Item = (usize, I::Item); + + fn next(&mut self) -> Option<Self::Item> { + self.it.next() + } +} + +impl<I> fmt::Debug for InputIter<I> +where + I: Input + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.rest()) + } +} |
