use lexariel::{Token, TokenKind};
use crate::error::ParserError;
pub(crate) struct TokenNavigator {
tokens: Vec<Token>,
position: usize,
}
impl TokenNavigator {
pub fn new(tokens: Vec<Token>) -> Self {
Self { tokens, position: 0 }
}
pub fn peek(&self) -> Option<&Token> {
self.tokens.get(self.position)
}
pub fn _peek_ahead(&self, offset: usize) -> Option<&Token> {
self.tokens.get(self.position + offset)
}
pub fn advance(&mut self) -> Option<&Token> {
if self.position < self.tokens.len() {
let token = &self.tokens[self.position];
self.position += 1;
Some(token)
} else {
None
}
}
pub fn check(&self, kind: TokenKind) -> bool {
if let Some(token) = self.peek() {
token.kind == kind
} else {
false
}
}
pub fn consume(&mut self, kind: TokenKind, expected: &str) -> Result<Token, ParserError> {
if let Some(token) = self.peek() {
if token.kind == kind {
Ok(self.advance().unwrap().clone())
} else {
Err(ParserError::UnexpectedToken {
line: token.line,
column: token.column,
expected: expected.to_string(),
found: format!("{}", token.kind),
})
}
} else {
Err(ParserError::UnexpectedEof {
expected: expected.to_string(),
})
}
}
pub fn consume_value(&mut self, expected: &str) -> Result<Token, ParserError> {
let token = self.peek().ok_or(ParserError::UnexpectedEof {
expected: expected.to_string(),
})?;
match token.kind {
TokenKind::Number | TokenKind::Identifier => Ok(self.advance().unwrap().clone()),
_ => Err(ParserError::UnexpectedToken {
line: token.line,
column: token.column,
expected: expected.to_string(),
found: format!("{}", token.kind),
}),
}
}
}