use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq)]
pub(super) enum Token {
Ident(String),
Quoted(String),
ArrayLiteral(String),
Pipe,
Space(String),
Other(String),
}
pub(super) fn tokenize_block(inner: &str) -> Vec<Token> {
let mut tokens = Vec::new();
let bytes = inner.as_bytes();
let mut i = 0;
while i < bytes.len() {
if bytes[i].is_ascii_whitespace() {
let start = i;
while i < bytes.len() && bytes[i].is_ascii_whitespace() {
i += 1;
}
tokens.push(Token::Space(inner[start..i].to_string()));
continue;
}
if bytes[i] == b'"' || bytes[i] == b'\'' {
let quote = bytes[i];
let start = i;
i += 1;
while i < bytes.len() && bytes[i] != quote {
if bytes[i] == b'\\' && i + 1 < bytes.len() {
i += 2;
} else {
i += 1;
}
}
if i < bytes.len() {
i += 1; }
tokens.push(Token::Quoted(inner[start..i].to_string()));
continue;
}
if bytes[i] == b'[' {
let start = i;
let mut depth = 1;
i += 1;
while i < bytes.len() && depth > 0 {
if bytes[i] == b'[' {
depth += 1;
} else if bytes[i] == b']' {
depth -= 1;
} else if bytes[i] == b'"' || bytes[i] == b'\'' {
let quote = bytes[i];
i += 1;
while i < bytes.len() && bytes[i] != quote {
if bytes[i] == b'\\' && i + 1 < bytes.len() {
i += 2;
} else {
i += 1;
}
}
if i < bytes.len() {
i += 1; }
continue;
}
i += 1;
}
tokens.push(Token::ArrayLiteral(inner[start..i].to_string()));
continue;
}
if bytes[i] == b'|' {
tokens.push(Token::Pipe);
i += 1;
continue;
}
if bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_' {
let start = i;
while i < bytes.len()
&& (bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_' || bytes[i] == b'.')
{
i += 1;
}
tokens.push(Token::Ident(inner[start..i].to_string()));
continue;
}
let Some(ch) = inner[i..].chars().next() else {
break;
};
tokens.push(Token::Other(ch.to_string()));
i += ch.len_utf8();
}
tokens
}
pub(super) fn significant_tokens(tokens: &[Token]) -> Vec<&Token> {
tokens
.iter()
.filter(|t| !matches!(t, Token::Space(_)))
.collect()
}
pub(super) fn token_to_str(token: &Token) -> Cow<'_, str> {
match token {
Token::Ident(s)
| Token::Quoted(s)
| Token::ArrayLiteral(s)
| Token::Space(s)
| Token::Other(s) => Cow::Borrowed(s.as_str()),
Token::Pipe => Cow::Borrowed("|"),
}
}