impral/lexer/
input.rs

1//! Tokenizer input.
2
3use std::str::CharIndices;
4
5/// A stream of positioned characters.
6pub type PosInput<'s> = peekmore::PeekMoreIterator<PosIter<'s>>;
7
8/// The input, tied to some source str.
9#[derive(Debug, Clone)]
10pub struct PosIter<'s> {
11    iter: std::str::CharIndices<'s>,
12    lpos: usize,
13    line: usize,
14}
15
16impl<'s> From<CharIndices<'s>> for PosIter<'s> {
17    /// Creates a new [`PosIter`] from the given [`CharIndices`].
18    fn from(iter: CharIndices<'s>) -> Self {
19        Self { iter, lpos: 0, line: 1 }
20    }
21}
22
23impl Iterator for PosIter<'_> {
24    type Item = PosChar;
25
26    fn next(&mut self) -> Option<Self::Item> {
27        let (index, current) = self.iter.next()?;
28        
29        self.lpos += 1;
30        
31        if current == '\n' {
32            self.line += 1;
33            self.lpos = 0;
34        }
35        
36        Some(PosChar {
37            char: current,
38            line: self.line,
39            col: self.lpos,
40            idx: index
41        })
42    }
43}
44
45/// A char with a position.
46#[derive(Debug, Clone, Copy)]
47pub struct PosChar {
48    /// The current character.
49    pub char: char,
50    /// Line-number.
51    pub line: usize,
52    /// Position on current line.
53    pub col: usize,
54    /// Absolute byte position.
55    pub idx: usize,
56}
57
58// ...for convenience.
59impl std::ops::Deref for PosChar {
60    type Target = char;
61    fn deref(&self) -> &Self::Target {
62        &self.char
63    }
64}