#[derive(Debug, Clone)]
pub(crate) struct Position {
pub line: usize,
pub column: usize,
}
impl Position {
pub fn new() -> Self {
Self { line: 1, column: 1 }
}
pub fn advance_char(&mut self, ch: char) {
if ch == '\n' {
self.line += 1;
self.column = 1;
} else {
self.column += 1;
}
}
}
pub(crate) struct InputReader {
input: Vec<char>,
position: usize,
location: Position,
}
impl InputReader {
pub fn new(input: &str) -> Self {
Self {
input: input.chars().collect(),
position: 0,
location: Position::new(),
}
}
pub fn peek(&self) -> Option<char> {
self.input.get(self.position).copied()
}
pub fn peek_ahead(&self, offset: usize) -> Option<char> {
self.input.get(self.position + offset).copied()
}
pub fn advance(&mut self) -> Option<char> {
if let Some(ch) = self.input.get(self.position) {
self.position += 1;
self.location.advance_char(*ch);
Some(*ch)
} else {
None
}
}
pub fn line(&self) -> usize {
self.location.line
}
pub fn column(&self) -> usize {
self.location.column
}
}