mod delimiter;
use delimiter::*;
pub mod del {
pub use super::delimiter::{
Delimiters,
DiscardDelimiters,
KeepDelimiters,
DelimitersParam,
};
}
pub mod prelude {
pub use super::*;
pub use super::del::*;
}
#[derive(Debug, PartialEq, Clone)]
pub struct EndToken;
#[derive(Debug, PartialEq, Clone)]
pub struct NewlineToken;
#[derive(Debug, PartialEq, Clone)]
pub struct TabToken;
#[derive(Debug, PartialEq, Clone)]
pub enum Token {
Newline(NewlineToken),
Tab(TabToken),
End(EndToken),
Str(String)
}
use std::collections::VecDeque;
#[derive(Debug, Clone)]
pub struct Tokens(VecDeque<Token>);
impl Tokens {
fn chars_buf_into_tok(
chars_buf: &mut Vec<char>,
inner: &mut VecDeque<Token>
) {
let new_tok: String = chars_buf.iter().collect();
chars_buf.drain(..);
inner.push_back(Token::Str(
new_tok
));
}
fn char_into_tok(ch: char) -> Token {
match ch {
'\n' => Token::Newline(NewlineToken),
'\t' => Token::Tab(TabToken),
_ => Token::Str(String::from(ch))
}
}
pub fn add_token(&mut self, token: Token) {
self.0.push_back(token)
}
pub fn from_vec(toks: Vec<Token>) -> Tokens {
Tokens(
VecDeque::from(toks)
)
}
pub fn new_empty() -> Tokens {
Tokens(VecDeque::new())
}
pub fn new<T: AsRef<str>>(
value: T,
delimiters: DelimitersParam
) -> Tokens {
let mut inner = VecDeque::<Token>::new();
let mut chars_buf: Vec<char> = Vec::new();
let chars = value.as_ref().chars();
for ch in chars {
let is_d_del = delimiters.discard.contains(ch);
let is_k_del = delimiters.keep.contains(ch);
let is_del = is_d_del | is_k_del;
if is_del {
if !chars_buf.is_empty() {
Tokens::chars_buf_into_tok(&mut chars_buf, &mut inner);
}
if is_k_del {
inner.push_back(Tokens::char_into_tok(ch))
}
} else {
chars_buf.push(ch)
}
}
if !chars_buf.is_empty() {
Tokens::chars_buf_into_tok(&mut chars_buf, &mut inner);
}
inner.push_back(Token::End(EndToken));
Tokens(inner)
}
}
impl Iterator for Tokens {
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop_front()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tokens_new() {
let d_dels = DiscardDelimiters::new( vec![' '] );
let del_params = DelimitersParam{
keep: KeepDelimiters::new( vec!['\n'] ),
discard: d_dels
};
let mut toks = Tokens::new(
"A line.\nA quick brown fox.",
del_params
);
println!("{:#?}", toks);
toks.0.pop_front();
toks.0.pop_front();
let newline = toks.0.pop_front().unwrap();
toks.0.pop_front();
let val = match toks.0.pop_front().unwrap() {
Token::Str(s) => s,
_ => panic!("Expected string.")
};
assert_eq!("quick", val);
assert_eq!(Token::Newline(NewlineToken), newline);
}
}