oneparse/
lexer.rs

1use crate::position::{Located, Positon};
2
3pub trait Lexable
4where
5    Self: Sized,
6{
7    type Error;
8    /// provides a lexer to lex the next token with
9    fn lex(lexer: &mut Lexer) -> Result<Option<Located<Self>>, Located<Self::Error>>;
10}
11
12pub struct Lexer {
13    pub text: String,
14    pub idx: usize,
15    pub ln: usize,
16    pub col: usize,
17}
18impl Lexer {
19    pub fn new(text: String) -> Self {
20        Self {
21            text,
22            idx: 0,
23            ln: 0,
24            col: 0,
25        }
26    }
27    /// lexes and collects all the tokens in a vector until `T::lex` returns `Ok(None)`
28    pub fn lex<T: Lexable>(&mut self) -> Result<Vec<Located<T>>, Located<T::Error>> {
29        let mut tokens = vec![];
30        while let Some(token) = T::lex(self)? {
31            tokens.push(token)
32        }
33        Ok(tokens)
34    }
35    /// returns the current character
36    pub fn get(&self) -> Option<char> {
37        self.text.get(self.idx..=self.idx)?.chars().next()
38    }
39    /// returns the current characters position
40    pub fn pos(&self) -> Positon {
41        Positon::new(self.ln..self.ln, self.col..self.col + 1)
42    }
43    /// advances to the next character updating the `ln`, `col` and `idx`
44    pub fn advance(&mut self) {
45        if self.get() == Some('\n') {
46            self.ln += 1;
47            self.col = 0;
48        } else {
49            self.col += 1;
50        }
51        self.idx += 1;
52    }
53}