use super::{IssueCollector, Token, TokenContext, TokenIssue, TokenScanner};
use crate::Result;
use alloc::vec::Vec;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[derive(Debug, Clone)]
pub struct AssTokenizer<'a> {
pub(super) source: &'a str,
pub(super) scanner: TokenScanner<'a>,
pub(super) context: TokenContext,
issues: IssueCollector<'a>,
}
impl<'a> AssTokenizer<'a> {
#[must_use]
pub fn new(source: &'a str) -> Self {
let initial_position = if source.starts_with('\u{FEFF}') {
3 } else {
0
};
Self {
source,
scanner: TokenScanner::new(source, initial_position, 1, 1),
context: TokenContext::Document,
issues: IssueCollector::new(),
}
}
pub fn tokenize_all(&mut self) -> Result<Vec<Token<'a>>> {
let mut tokens = Vec::new();
let mut iteration_count = 0;
while let Some(token) = self.next_token()? {
tokens.push(token);
iteration_count += 1;
if iteration_count > 50 {
return Err(crate::utils::CoreError::internal(
"Too many tokenizer iterations",
));
}
}
Ok(tokens)
}
#[must_use]
pub fn issues(&self) -> &[TokenIssue<'a>] {
self.issues.issues()
}
#[must_use]
pub const fn position(&self) -> usize {
self.scanner.navigator().position()
}
#[must_use]
pub const fn line(&self) -> usize {
self.scanner.navigator().line()
}
#[must_use]
pub const fn column(&self) -> usize {
self.scanner.navigator().column()
}
pub fn reset(&mut self) {
let initial_position = if self.source.starts_with('\u{FEFF}') {
3
} else {
0
};
self.scanner = TokenScanner::new(self.source, initial_position, 1, 1);
self.context = TokenContext::Document;
self.issues.clear();
}
}