I am developing a compiler and in order to parse the source code, I must backtrack. To do this I developed an iterator adaptor that stores a list of items to pop off in the future.
Source code:
pub struct PrefixIterator<I: Iterator> {
iter: I,
prefix: Vec<I::Item>,
}
impl<I: Iterator> PrefixIterator<I> {
pub fn new(iter: I) -> Self {
PrefixIterator {
iter,
prefix: Vec::new(),
}
}
pub fn push(&mut self, item: I::Item) {
self.prefix.push(item);
}
}
impl<I: Iterator> Iterator for PrefixIterator<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.prefix.is_empty() {
self.iter.next()
} else {
self.prefix.pop()
}
}
}
I called the mechanism of "unpoping" push
because of the underlying mechanic. The opposite of next
is previous
, which isn't appropriate for this context.
Example usage:
let iter = PrefixIterator::new(iter);
match iter.next() {
Some(';') => {
iter.push(';');
return already_parsed_statement;
},
Some(c) => {
...
}
None => (),
}
I also think you want "unpopping". I think that "unpoping" would be something to do with the Vatican ;-)
Most helpful comment
I also think you want "unpopping". I think that "unpoping" would be something to do with the Vatican ;-)