peeking_iter/parser.rs
1//! Parsing-specific iterator, with full peeking support.
2
3use crate::peeking::{Peeking, PeekingIter};
4
5/// An iterator implementing [`Peeking`], but designed specifically for parsing
6/// string input.
7///
8/// **NOTE:** By convention, line numbers start at `1`, while column numbers
9/// start at `0`.
10pub struct Parser<I>
11where
12 I: Iterator,
13{
14 peeking: PeekingIter<I>,
15 line: u16,
16 col: u16,
17}
18
19impl<I: Iterator<Item = char> + Clone> Peeking for Parser<I> {
20 fn peek(&mut self) -> Option<Self::Item> {
21 self.peeking.peek()
22 }
23
24 fn rewind_peeking(&mut self) {
25 self.peeking.rewind_peeking();
26 }
27
28 fn advance_to_peeked(&mut self) {
29 self.peeking.advance_to_peeked();
30 }
31}
32
33// TODO?: Implement whitespace-skipping
34impl<I: Iterator<Item = char> + Clone> Parser<I> {
35 /// Wraps the given iterator.
36 pub fn new(iter: I) -> Self {
37 Self {
38 peeking: PeekingIter::new(iter),
39 line: 1,
40 col: 0,
41 }
42 }
43
44 /// Returns the next item in the inner iterator.
45 ///
46 /// Resets the peeking iterator.
47 ///
48 /// ```rust
49 /// # use peeking_iter::peeking::Peeking;
50 /// # use peeking_iter::parser::Parser;
51 /// let mut parser = Parser::new("abcd".chars());
52 ///
53 /// assert_eq!(parser.peek(), Some('a'));
54 /// assert_eq!(parser.next(), Some('a'));
55 /// assert_eq!(parser.peek(), Some('b'));
56 /// assert_eq!(parser.next(), Some('b'));
57 /// ```
58 pub fn next(&mut self) -> Option<char> {
59 let next = self.peeking.next();
60
61 // NOTE: This assumes that all characters (except newline)
62 // advance the col by 1.
63 match next {
64 None => (),
65 Some('\n') => {
66 self.line += 1;
67 self.col = 0;
68 }
69 _ => {
70 self.col += 1;
71 }
72 }
73
74 next
75 }
76
77 /// Consumes `self` and returns the inner iterator.
78 pub fn into_inner(self) -> I {
79 PeekingIter::into_inner(self.peeking)
80 }
81
82 /// Returns the line number.
83 ///
84 /// ```rust
85 /// # use peeking_iter::parser::Parser;
86 /// let mut it = Parser::new("ab\nc".chars());
87 ///
88 /// it.next();
89 /// it.next();
90 /// it.next();
91 ///
92 /// assert_eq!(it.line(), 2);
93 /// ```
94 pub fn line(&self) -> u16 {
95 self.line
96 }
97
98 /// Returns the column number.
99 ///
100 /// **NOTE:** Every _character_ is considered to have the column size of 1.
101 pub fn col(&self) -> u16 {
102 self.col
103 }
104}
105
106impl<I: Iterator<Item = char> + Clone> Iterator for Parser<I> {
107 type Item = char;
108
109 fn next(&mut self) -> Option<char> {
110 Parser::next(self)
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use crate::parser::Parser;
117 use crate::peeking::Peeking;
118
119 fn next_while() {
120 let mut it = Parser::new("ABc".chars());
121
122 assert_eq!(
123 it.next_while(|c| c.is_uppercase()),
124 "AB".chars().collect::<Vec<_>>()
125 );
126 assert_eq!(it.peek(), Some('c'));
127 assert_eq!(it.next(), Some('c'));
128 }
129}