use crate::language::Token;
#[derive(Debug, PartialEq, Clone, Eq, serde::Serialize)]
pub struct TokenStream<'a> {
file_name: String,
tokens: Vec<(&'a str, Token)>,
offset: usize,
}
impl<'a> TokenStream<'a> {
#[must_use]
pub fn new(file_name: String, tokens: Vec<(&'a str, Token)>) -> Self {
Self {
file_name,
tokens,
offset: 0,
}
}
#[must_use]
pub fn from_tokens(tokens: Vec<(&'a str, Token)>) -> Self {
Self {
file_name: String::new(),
tokens,
offset: 0,
}
}
#[must_use]
pub fn file_name(&self) -> &str {
&self.file_name
}
#[must_use]
pub fn offset(&self) -> usize {
self.offset
}
#[must_use]
pub fn current(&self) -> Option<&(&'a str, Token)> {
self.tokens.get(self.offset)
}
pub fn advance(&mut self) {
if self.offset < self.tokens.len() {
self.offset += 1;
}
}
pub fn backtrack(&mut self) {
if self.offset > 0 {
self.offset -= 1;
}
}
#[must_use]
pub fn is_at_end(&self) -> bool {
self.offset >= self.tokens.len()
}
#[must_use]
pub fn len(&self) -> usize {
self.tokens.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.tokens.is_empty()
}
#[must_use]
pub fn tokens(&self) -> &Vec<(&'a str, Token)> {
&self.tokens
}
#[must_use]
pub fn into_tokens(self) -> Vec<(&'a str, Token)> {
self.tokens
}
pub fn reset(&mut self) {
self.offset = 0;
}
}
impl<'a> std::ops::Index<usize> for TokenStream<'a> {
type Output = (&'a str, Token);
fn index(&self, index: usize) -> &Self::Output {
&self.tokens[index]
}
}
impl<'a> Iterator for TokenStream<'a> {
type Item = (&'a str, Token);
fn next(&mut self) -> Option<Self::Item> {
if self.offset < self.tokens.len() {
let token = self.tokens[self.offset];
self.offset += 1;
Some(token)
} else {
None
}
}
}