pear/input/
cursor.rs

1use std::fmt::Debug;
2
3use crate::input::{Input, Show, Rewind, ParserInfo, Length};
4
5#[derive(Debug)]
6pub struct Cursor<T> {
7    pub start: T,
8    pub items: T,
9}
10
11impl<T: Copy> From<T> for Cursor<T> {
12    fn from(items: T) -> Self {
13        Cursor { start: items, items }
14    }
15}
16
17#[derive(Debug, PartialEq, Eq, Copy, Clone)]
18pub struct Extent<T> {
19    pub start: usize,
20    pub end: usize,
21    pub values: T,
22}
23
24impl<T: Length> From<T> for Extent<T> {
25    fn from(values: T) -> Self {
26        Extent { start: 0, end: values.len(), values }
27    }
28}
29
30impl<T> std::ops::Deref for Extent<T> {
31    type Target = T;
32
33    fn deref(&self) -> &Self::Target {
34        &self.values
35    }
36}
37
38impl<T: PartialEq> PartialEq<T> for Extent<T> {
39    fn eq(&self, other: &T) -> bool {
40        &self.values == other
41    }
42}
43
44impl PartialEq<Extent<&str>> for &str {
45    fn eq(&self, other: &Extent<&str>) -> bool {
46        other == self
47    }
48}
49
50impl<T: PartialEq> PartialEq<Extent<&[T]>> for &[T] {
51    fn eq(&self, other: &Extent<&[T]>) -> bool {
52        other == self
53    }
54}
55
56macro_rules! impl_for_slice_len {
57    ($($n:expr),*) => ($(
58        impl<T: PartialEq> PartialEq<Extent<&[T]>> for &[T; $n] {
59            fn eq(&self, other: &Extent<&[T]>) -> bool {
60                &other.values[..] == *self
61            }
62        }
63    )*)
64}
65
66impl_for_slice_len!(
67    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
68    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
69);
70
71impl<T> Length for Extent<T> {
72    fn len(&self) -> usize {
73        self.end - self.start
74    }
75}
76
77impl<T: Show> Show for Extent<T> {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        write!(f, "{}..{} {}", self.start, self.end, &self.values as &dyn Show)
80    }
81}
82
83impl<T: ?Sized + ToOwned> Extent<&T> {
84    pub fn into_owned(self) -> Extent<T::Owned> {
85        Extent {
86            start: self.start,
87            end: self.end,
88            values: self.values.to_owned(),
89        }
90    }
91}
92
93pub trait Indexable: Sized {
94    type One: Clone;
95    type Iter: Iterator<Item = Self::One>;
96
97    fn head(&self) -> Option<Self::One>;
98    fn length_of(token: Self::One) -> usize;
99    fn slice<R: std::ops::RangeBounds<usize>>(&self, range: R) -> Option<Self>;
100    fn iter(&self) -> Self::Iter;
101}
102
103use std::ops::{Bound, RangeBounds, Range};
104
105fn abs<R: RangeBounds<usize>>(range: R, start: usize, end: usize) -> Range<usize> {
106    let start = match range.start_bound() {
107        Bound::Unbounded => start,
108        Bound::Included(&n) => n,
109        Bound::Excluded(&n) => n.saturating_add(1),
110    };
111
112    let end = match range.end_bound() {
113        Bound::Unbounded => end,
114        Bound::Included(&n) => n.saturating_add(1),
115        Bound::Excluded(&n) => n,
116    };
117
118    Range { start, end }
119}
120
121impl<'a> Indexable for &'a str {
122    type One = char;
123    type Iter = std::str::Chars<'a>;
124
125    fn head(&self) -> Option<Self::One> {
126        self.chars().next()
127    }
128
129    fn length_of(token: Self::One) -> usize {
130        token.len_utf8()
131    }
132
133    fn slice<R: std::ops::RangeBounds<usize>>(&self, range: R) -> Option<Self> {
134        self.get(abs(range, 0, self.len()))
135    }
136
137    fn iter(&self) -> Self::Iter {
138        self.chars()
139    }
140}
141
142impl<'a, T: Clone> Indexable for &'a [T] {
143    type One = T;
144    type Iter = std::iter::Cloned<std::slice::Iter<'a, T>>;
145
146    fn head(&self) -> Option<Self::One> {
147        self.first().cloned()
148    }
149
150    fn length_of(_: Self::One) -> usize {
151        1
152    }
153
154    fn slice<R: std::ops::RangeBounds<usize>>(&self, range: R) -> Option<Self> {
155        self.get(abs(range, 0, self.len()))
156    }
157
158    fn iter(&self) -> Self::Iter {
159        (*self as &[T]).iter().cloned()
160    }
161}
162
163impl<T: Length> Cursor<T> {
164    fn offset(&self) -> usize {
165        self.start.len() - self.items.len()
166    }
167}
168
169impl<T: Indexable + Length> Cursor<T> {
170    /// Returns an `Extent` that spans from `a` to `b` if `a..b` is in bounds.
171    pub fn span(&self, a: Extent<T>, b: Extent<T>) -> Option<Extent<T>> {
172        let start = std::cmp::min(a.start, b.start);
173        let end = std::cmp::max(a.end, b.end);
174        let values = self.start.slice(start..end)?;
175        Some(Extent { start, end, values })
176    }
177}
178
179impl<T: Indexable + Show + Length + PartialEq> Input for Cursor<T>
180    where T::One: Show + PartialEq
181{
182    type Token = T::One;
183    type Slice = Extent<T>;
184    type Many = Extent<T>;
185
186    type Marker = usize;
187    type Context = Extent<T>;
188
189    /// Returns a copy of the current token, if there is one.
190    fn token(&mut self) -> Option<Self::Token> {
191        self.items.head()
192    }
193
194    /// Returns a copy of the current slice of size `n`, if there is one.
195    fn slice(&mut self, n: usize) -> Option<Self::Slice> {
196        Some(Extent {
197            start: self.offset(),
198            end: self.offset() + n,
199            values: self.items.slice(..n)?
200        })
201    }
202
203    /// Checks if the current token fulfills `cond`.
204    fn peek<F>(&mut self, mut cond: F) -> bool
205        where F: FnMut(&Self::Token) -> bool
206    {
207        self.token().map(|t| cond(&t)).unwrap_or(false)
208    }
209
210    /// Checks if the current slice of size `n` (if any) fulfills `cond`.
211    fn peek_slice<F>(&mut self, n: usize, mut cond: F) -> bool
212        where F: FnMut(&Self::Slice) -> bool
213    {
214        self.slice(n).map(|s| cond(&s)).unwrap_or(false)
215    }
216
217    /// Checks if the current token fulfills `cond`. If so, the token is
218    /// consumed and returned. Otherwise, returns `None`.
219    fn eat<F>(&mut self, mut cond: F) -> Option<Self::Token>
220        where F: FnMut(&Self::Token) -> bool
221    {
222        let token = self.token()?;
223        if cond(&token) {
224            self.items = self.items.slice(T::length_of(token.clone())..).unwrap();
225            Some(token)
226        } else {
227            None
228        }
229    }
230
231    /// Checks if the current slice of size `n` (if any) fulfills `cond`. If so,
232    /// the slice is consumed and returned. Otherwise, returns `None`.
233    fn eat_slice<F>(&mut self, n: usize, mut cond: F) -> Option<Self::Slice>
234        where F: FnMut(&Self::Slice) -> bool
235    {
236        let slice = self.slice(n)?;
237        if cond(&slice) {
238            self.items = self.items.slice(n..).unwrap();
239            Some(slice)
240        } else {
241            None
242        }
243    }
244
245    /// Takes tokens while `cond` returns true, collecting them into a
246    /// `Self::Many` and returning it.
247    fn take<F>(&mut self, cond: F) -> Self::Many
248        where F: FnMut(&Self::Token) -> bool
249    {
250        let start = self.offset();
251        let matches: usize = self.items.iter()
252            .take_while(cond)
253            .map(T::length_of)
254            .sum();
255
256        let values = self.items.slice(..matches).unwrap();
257        self.items = self.items.slice(matches..).unwrap();
258        Extent { start, end: self.offset(), values }
259    }
260
261    /// Skips tokens while `cond` returns true. Returns the number of skipped
262    /// tokens.
263    fn skip<F>(&mut self, cond: F) -> usize
264        where F: FnMut(&Self::Token) -> bool
265    {
266        self.take(cond).len()
267    }
268
269    /// Returns `true` if there are at least `n` tokens remaining.
270    fn has(&mut self, n: usize) -> bool {
271        self.items.len() >= n
272    }
273
274    fn mark(&mut self, _: &ParserInfo) -> Self::Marker {
275        self.offset()
276    }
277
278    /// Optionally returns a context to identify the current input position. By
279    /// default, this method returns `None`, indicating that no context could be
280    /// resolved.
281    fn context(&mut self, mark: Self::Marker) -> Self::Context {
282        let end = self.offset();
283        let values = self.start.slice(mark..end).unwrap();
284        Extent { start: mark, end, values }
285    }
286}
287
288impl<T: Indexable + Show + Length + PartialEq> Rewind for Cursor<T>
289    where T::One: Show + PartialEq
290{
291    fn rewind_to(&mut self, marker: Self::Marker) {
292        self.items = self.start.slice(marker..).unwrap();
293    }
294}