lexer/
input.rs

1use alloc::string::String;
2
3use peek_nth::PeekableNth;
4
5use super::{Line, Lines, State};
6
7pub trait Input {
8  fn peek(&mut self, state: &State, offset: usize) -> Option<char>;
9  fn lines<'a>(&'a mut self, state: &'a mut State) -> Lines<'a>;
10
11  #[inline]
12  fn read(&mut self, state: &mut State) -> Option<char> {
13    match self.peek(state, 0) {
14      Some(ch) => {
15        state.read(ch == '\n');
16        Some(ch)
17      }
18      None => None,
19    }
20  }
21
22  #[inline]
23  fn read_offset(&mut self, state: &mut State, offset: usize) -> usize {
24    let mut read = 0;
25
26    for _ in 0..offset {
27      if self.read(state).is_none() {
28        break;
29      } else {
30        read += 1;
31      }
32    }
33
34    read
35  }
36
37  #[inline]
38  fn skip_line(&mut self, state: &mut State) {
39    if !self.is_done(state) {
40      while let Some(ch) = self.read(state) {
41        if ch == '\n' {
42          break;
43        }
44      }
45    }
46  }
47  #[inline]
48  fn peek_line(&mut self, state: &State) -> Option<Line> {
49    if self.is_done(state) {
50      None
51    } else {
52      let mut string = String::new();
53      let mut index = 0;
54      let offset = state.index();
55
56      while let Some(ch) = self.peek(state, index) {
57        if ch != '\n' {
58          index += 1;
59          string.push(ch);
60        } else {
61          break;
62        }
63      }
64
65      Some((offset, string).into())
66    }
67  }
68  #[inline]
69  fn read_line(&mut self, state: &mut State) -> Option<Line> {
70    if self.is_done(state) {
71      None
72    } else {
73      let mut string = String::new();
74      let offset = state.index();
75
76      while let Some(ch) = self.read(state) {
77        if ch != '\n' {
78          string.push(ch);
79        } else {
80          break;
81        }
82      }
83
84      Some((offset, string).into())
85    }
86  }
87
88  #[inline]
89  fn read_whitespace(&mut self, state: &mut State) -> Option<String> {
90    if self.is_done(state) {
91      None
92    } else {
93      let mut string = String::new();
94
95      while let Some(ch) = self.peek(state, 0) {
96        if ch.is_whitespace() {
97          self.read(state);
98          string.push(ch);
99        } else {
100          break;
101        }
102      }
103
104      if string.is_empty() {
105        None
106      } else {
107        Some(string)
108      }
109    }
110  }
111
112  #[inline]
113  fn skip_whitespaces(&mut self, state: &mut State) {
114    if !self.is_done(state) {
115      while let Some(ch) = self.peek(state, 0) {
116        if ch.is_whitespace() {
117          self.read(state);
118        }
119      }
120    }
121  }
122
123  #[inline]
124  fn is_done(&mut self, state: &State) -> bool {
125    !self.can_peek(state, 0)
126  }
127
128  #[inline]
129  fn can_peek(&mut self, state: &State, offset: usize) -> bool {
130    self.peek(state, offset).is_some()
131  }
132}
133
134impl<I> Input for PeekableNth<I>
135where
136  I: Iterator<Item = char>,
137{
138  #[inline]
139  fn peek(&mut self, state: &State, offset: usize) -> Option<char> {
140    self.peek_nth(state.index() + offset).map(Clone::clone)
141  }
142  #[inline]
143  fn lines<'a>(&'a mut self, state: &'a mut State) -> Lines<'a> {
144    Lines::new(self, state)
145  }
146}