#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Pos {
pub line: usize,
pub col: usize,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Mark {
pos: usize,
line: usize,
col: usize,
}
pub(crate) struct Scanner {
chars: Vec<char>,
pos: usize,
line: usize,
col: usize,
}
impl Scanner {
pub(crate) fn new(src: &str) -> Self {
Scanner {
chars: src.chars().collect(),
pos: 0,
line: 1,
col: 1,
}
}
pub(crate) fn position(&self) -> Pos {
Pos {
line: self.line,
col: self.col,
}
}
pub(crate) fn mark(&self) -> Mark {
Mark {
pos: self.pos,
line: self.line,
col: self.col,
}
}
pub(crate) fn reset(&mut self, m: Mark) {
self.pos = m.pos;
self.line = m.line;
self.col = m.col;
}
pub(crate) fn peek(&self) -> Option<char> {
self.chars.get(self.pos).copied()
}
pub(crate) fn peek_at(&self, offset: usize) -> Option<char> {
self.chars.get(self.pos + offset).copied()
}
pub(crate) fn rest(&self) -> &[char] {
let start = self.pos.min(self.chars.len());
&self.chars[start..]
}
pub(crate) fn bump(&mut self) -> Option<char> {
let c = self.chars.get(self.pos).copied();
if let Some(ch) = c {
self.pos += 1;
if ch == '\n' {
self.line += 1;
self.col = 1;
} else {
self.col += 1;
}
}
c
}
pub(crate) fn eat(&mut self, c: char) -> bool {
if self.peek() == Some(c) {
self.bump();
true
} else {
false
}
}
}