use crate::{
config::{Configuration, TokenConfiguration}, iter::StreamIterator, tokens::{Branch, Token, TreeNode}
};
pub mod config;
pub mod record;
pub mod tokens;
#[doc(hidden)]
pub mod iter;
pub mod prelude {
pub use crate::config::*;
pub use crate::Tokenizer;
}
pub struct Tokenizer<'items, K: Default + Clone> {
config: &'items Configuration<'items, K>,
iter: StreamIterator<'items>,
}
impl<'items, K: Default + Clone> Tokenizer<'items, K> {
pub fn new(config: &'items Configuration<'items, K>, contents: &'items str) -> Self {
Self {
config,
iter: StreamIterator::new(contents),
}
}
#[must_use]
#[inline(always)]
fn matches(&mut self, chars: &[char]) -> bool {
let mut iter = self.iter;
let mut matches = false;
for (i, char) in (0..chars.len()).zip(iter.last()) {
if char == chars[i] {
matches = true;
} else {
matches = false;
break;
}
if i + 1 != chars.len() {
let _ = iter.next();
}
}
if matches {
self.iter = iter;
}
matches
}
#[doc(hidden)]
fn tokenize(&mut self) -> TreeNode<K> {
let start_iter_pos = self.iter.position() - 1;
for (config, kind) in self.config.0.iter() {
match config {
TokenConfiguration::Rule(rule) => {
let record = self.iter.record().clone();
if rule(&mut self.iter, &record) == true {
return TreeNode::Leaf(Token {
value: self.iter.grab(start_iter_pos..self.iter.position()),
kind: kind.clone(),
record,
});
}
},
TokenConfiguration::Boring(chars) => {
let record = self.iter.record().clone();
if self.matches(chars) {
return TreeNode::Leaf(Token {
value: self.iter.grab(start_iter_pos..self.iter.position()),
kind: kind.clone(),
record,
});
}
},
TokenConfiguration::Branch(start_chars, end_chars) => {
let record = self.iter.record().clone();
if self.matches(start_chars) {
let start_token = Token {
value: self.iter.grab(start_iter_pos..self.iter.position()),
kind: kind.clone(),
record,
};
let mut stream = Vec::new();
let mut end_token = None;
while let Some(char) = self.iter.next() {
if char.is_whitespace() { continue; }
let token = self.tokenize();
if let TreeNode::Leaf(token) = &token {
if token.value == end_chars.iter().collect::<String>() {
end_token = Some(token.clone());
break;
}
}
stream.push(token);
}
return TreeNode::Branch(Branch {
value: (
start_token.value,
if let Some(end_token) = &end_token {
end_token.value.clone()
} else {
"?".to_string()
},
),
kind: kind.clone(),
stream,
record,
has_end: end_token.is_some(),
});
}
},
}
}
TreeNode::Leaf(Token {
value: self.iter.last().unwrap().to_string(),
kind: K::default(),
record: self.iter.record().clone(),
})
}
pub fn build(&mut self) -> Vec<TreeNode<K>> {
let mut stream = Vec::new();
while let Some(char) = self.iter.next() {
if char.is_whitespace() { continue; }
stream.push(self.tokenize());
}
stream
}
}