laps/
input.rs

1//! Utilities for constructing lexers.
2//!
3//! This module conntains the [`InputStream`] trait, which can be
4//! implemented for input streams, i.e. streams that return characters.
5//! This trait has already been implemented for
6//! [`Reader`](crate::reader::Reader) and
7//! [`ByteReader`](crate::reader::ByteReader).
8//!
9//! The [`InputStream`] trait provides many useful utility methods for
10//! reading characters and the corresponding [`Span`]s from the input stream.
11
12use crate::span::{Location, Result, Span};
13
14/// Trait for input streams.
15pub trait InputStream {
16  /// The type of the character produced by the input stream.
17  type CharType;
18
19  /// Reads the next character from the input stream.
20  ///
21  /// Returns the character and the last location (location before reading
22  /// the character) if successful, or <code>[Ok]&#40;[None]&#41;</code>
23  /// if EOF was encountered, or [`Err`] if something wrong.
24  fn next_char_loc(&mut self) -> Result<(Option<Self::CharType>, Location)>;
25
26  /// Unreads the given character and the last location
27  /// and put it back to the input stream.
28  fn unread(&mut self, last: (Option<Self::CharType>, Location));
29
30  /// Returns a reference to the current span in the lexer.
31  fn span(&self) -> &Span;
32
33  /// Sets the line and column of the current span.
34  ///
35  /// This could be useful if something like the C preprocessor
36  /// is to be supported:
37  ///
38  /// ```text
39  /// # 37 "<stdin>"
40  /// ...
41  /// ```
42  fn set_line_col(&mut self, line: u32, col: u32);
43
44  /// Reads the next character from the input stream.
45  ///
46  /// Returns the character if successful,
47  /// or <code>[Ok]&#40;[None]&#41;</code> if EOF was encountered,
48  /// or [`Err`] if something wrong.
49  fn next_char(&mut self) -> Result<Option<Self::CharType>> {
50    self.next_char_loc().map(|(c, _)| c)
51  }
52
53  /// Reads the next character from the input stream.
54  ///
55  /// Returns the character and its span if successful,
56  /// or <code>[Ok]&#40;([None], _)&#41;</code> if EOF was encountered,
57  /// or [`Err`] if something wrong.
58  fn next_char_span(&mut self) -> Result<(Option<Self::CharType>, Span)> {
59    self.next_char_loc().map(|(c, _)| (c, self.span().clone()))
60  }
61
62  /// Reads the next character from the input stream.
63  ///
64  /// Returns a reference to the span of the read character if successful,
65  /// or [`Err`] if something wrong.
66  fn next_span(&mut self) -> Result<&Span> {
67    self.next_char_loc()?;
68    Ok(self.span())
69  }
70
71  /// Peeks the next character from the input stream.
72  ///
73  /// Does not advance the position of the input stream.
74  fn peek(&mut self) -> Result<Option<Self::CharType>>
75  where
76    Self::CharType: Clone,
77  {
78    let (c, loc) = self.next_char_loc()?;
79    self.unread((c.clone(), loc));
80    Ok(c)
81  }
82
83  /// Peeks the next character from the input stream.
84  /// Returns the peeked character and its span.
85  ///
86  /// Does not advance the position of the input stream.
87  fn peek_with_span(&mut self) -> Result<(Option<Self::CharType>, Span)>
88  where
89    Self::CharType: Clone,
90  {
91    let (c, loc) = self.next_char_loc()?;
92    let span = self.span().clone();
93    self.unread((c.clone(), loc));
94    Ok((c, span))
95  }
96
97  /// Skips characters until a character specified by the predicate is encountered.
98  fn skip_until<F>(&mut self, mut f: F) -> Result<()>
99  where
100    Self::CharType: Clone,
101    F: FnMut(Self::CharType) -> bool,
102  {
103    while self.peek()?.map_or(false, |c| !f(c)) {
104      self.next_char()?;
105    }
106    Ok(())
107  }
108
109  /// Collects characters into a vector until a character specified by the
110  /// predicate is encountered.
111  fn collect_until<F>(&mut self, mut f: F) -> Result<Vec<Self::CharType>>
112  where
113    Self::CharType: Clone,
114    F: FnMut(&Self::CharType) -> bool,
115  {
116    let mut v = Vec::new();
117    while let Some(c) = self.peek()? {
118      if f(&c) {
119        break;
120      }
121      v.push(c);
122      self.next_char()?;
123    }
124    Ok(v)
125  }
126
127  /// Collects characters into a vector until a character specified by the
128  /// predicate is encountered.
129  ///
130  /// Returns the collected vector and its span.
131  fn collect_with_span_until<F>(&mut self, mut f: F) -> Result<(Vec<Self::CharType>, Span)>
132  where
133    Self::CharType: Clone,
134    F: FnMut(&Self::CharType) -> bool,
135  {
136    let mut v = Vec::new();
137    let mut span = match self.peek_with_span()? {
138      (Some(c), span) if !f(&c) => span,
139      (_, span) => return Ok((v, span)),
140    };
141    while let Some(c) = self.peek()? {
142      if f(&c) {
143        break;
144      }
145      v.push(c);
146      span.update_end(self.next_span()?);
147    }
148    Ok((v, span))
149  }
150}
151
152#[cfg(test)]
153mod test {
154  use super::*;
155  use crate::reader::Reader;
156
157  #[test]
158  fn next_char_or_span() {
159    let mut reader = Reader::from("123 abc");
160    assert_eq!(reader.next_char(), Ok(Some('1')));
161    assert_eq!(reader.next_char(), Ok(Some('2')));
162    let (c, span) = reader.next_char_span().unwrap();
163    assert_eq!(c, Some('3'));
164    assert_eq!(format!("{span}"), "1:3-1:3");
165    let (c, span) = reader.next_char_span().unwrap();
166    assert_eq!(c, Some(' '));
167    assert_eq!(format!("{span}"), "1:4-1:4");
168    assert_eq!(format!("{}", reader.next_span().unwrap()), "1:5-1:5");
169    assert_eq!(format!("{}", reader.next_span().unwrap()), "1:6-1:6");
170    assert_eq!(reader.next_char(), Ok(Some('c')));
171    assert_eq!(reader.next_char(), Ok(None));
172    assert_eq!(reader.next_char(), Ok(None));
173  }
174
175  #[test]
176  fn skip_until() {
177    let mut reader = Reader::from("123  abc");
178    assert_eq!(reader.skip_until(|c| c.is_whitespace()), Ok(()));
179    assert_eq!(reader.next_char(), Ok(Some(' ')));
180    assert_eq!(reader.next_char(), Ok(Some(' ')));
181    assert_eq!(reader.next_char(), Ok(Some('a')));
182    assert_eq!(reader.next_char(), Ok(Some('b')));
183    assert_eq!(reader.next_char(), Ok(Some('c')));
184    assert_eq!(reader.next_char(), Ok(None));
185    assert_eq!(reader.next_char(), Ok(None));
186  }
187
188  #[test]
189  fn collect_until() {
190    let mut reader = Reader::from("123 abc");
191    assert_eq!(reader.collect_until(|c| *c == '1'), Ok(vec![]));
192    assert_eq!(
193      reader.collect_with_span_until(|c| *c == '1').unwrap().0,
194      vec![]
195    );
196    assert_eq!(
197      reader.collect_until(|c| c.is_whitespace()),
198      Ok("123".chars().collect())
199    );
200    assert_eq!(reader.next_char(), Ok(Some(' ')));
201    let (s, span) = reader.collect_with_span_until(|_| false).unwrap();
202    assert_eq!(s, "abc".chars().collect::<Vec<_>>());
203    assert_eq!(format!("{span}"), "1:5-1:7");
204    assert_eq!(reader.next_char(), Ok(None));
205    assert_eq!(reader.next_char(), Ok(None));
206  }
207}