jetcrab\lexer\utils/
position.rs

1use crate::vm::types::{ColumnNumber, LineNumber};
2
3pub trait PositionManager {
4    fn skip_whitespace(&mut self);
5    fn advance(&mut self);
6    fn peek_char(&self, offset: usize) -> Option<char>;
7    fn update_position(&mut self, start_line: LineNumber, start_col: ColumnNumber);
8}
9
10pub trait PositionCore {
11    fn source(&self) -> &[char];
12    fn pos(&self) -> usize;
13    fn line(&self) -> LineNumber;
14    fn column(&self) -> ColumnNumber;
15    fn set_pos(&mut self, pos: usize);
16    fn set_line(&mut self, line: LineNumber);
17    fn set_column(&mut self, column: ColumnNumber);
18}
19
20impl<T> PositionManager for T
21where
22    T: PositionCore,
23{
24    fn skip_whitespace(&mut self) {
25        while self.pos() < self.source().len() {
26            let c = self.source()[self.pos()];
27            if c.is_whitespace() {
28                if c == '\n' {
29                    let mut new_line = self.line();
30                    new_line += 1;
31                    self.set_line(new_line);
32                    self.set_column(ColumnNumber::new(1));
33                } else {
34                    let mut new_column = self.column();
35                    new_column += 1;
36                    self.set_column(new_column);
37                }
38                self.advance();
39            } else {
40                break;
41            }
42        }
43    }
44
45    fn advance(&mut self) {
46        if self.pos() < self.source().len() {
47            self.set_pos(self.pos() + 1);
48            let mut new_column = self.column();
49            new_column += 1;
50            self.set_column(new_column);
51        }
52    }
53
54    fn peek_char(&self, offset: usize) -> Option<char> {
55        if self.pos() + offset < self.source().len() {
56            Some(self.source()[self.pos() + offset])
57        } else {
58            None
59        }
60    }
61
62    fn update_position(&mut self, _start_line: LineNumber, _start_col: ColumnNumber) {}
63}