use crate::TokenType;
use std::sync::Arc;
#[allow(dead_code)]
pub struct ModSpec {
pub run: &'static [char], pub allow_charset: bool, }
pub const QR_SPEC: ModSpec = ModSpec { run: &['i', 'm', 's', 'x', 'p', 'n'], allow_charset: true };
pub const M_SPEC: ModSpec =
ModSpec { run: &['i', 'm', 's', 'x', 'p', 'n', 'g', 'c'], allow_charset: true };
pub const S_SPEC: ModSpec =
ModSpec { run: &['i', 'm', 's', 'x', 'p', 'n', 'e', 'r'], allow_charset: true };
pub const TR_SPEC: ModSpec = ModSpec { run: &['c', 'd', 's', 'r'], allow_charset: false };
pub fn paired_close(open: char) -> Option<char> {
match open {
'(' => Some(')'),
'[' => Some(']'),
'{' => Some('}'),
'<' => Some('>'),
_ => None,
}
}
#[allow(dead_code)]
pub fn canon_run(run: &str, spec: &ModSpec) -> String {
let mut out = String::new();
for &c in spec.run {
if run.contains(c) {
out.push(c);
}
}
out
}
#[allow(dead_code)]
pub fn split_tail_for_spec(tail: &str, spec: &ModSpec) -> Option<(String, Option<&'static str>)> {
if !tail.chars().all(|c| c.is_ascii_alphabetic()) {
return None;
}
if !spec.allow_charset {
return if tail.chars().all(|c| spec.run.contains(&c)) {
Some((canon_run(tail, spec), None))
} else {
None
};
}
let (run_part, charset): (&str, Option<&'static str>) =
if let Some(stripped) = tail.strip_suffix("aa") {
(stripped, Some("aa"))
} else if let Some(stripped) = tail.strip_suffix('a') {
(stripped, Some("a"))
} else if let Some(stripped) = tail.strip_suffix('d') {
(stripped, Some("d"))
} else if let Some(stripped) = tail.strip_suffix('l') {
(stripped, Some("l"))
} else if let Some(stripped) = tail.strip_suffix('u') {
(stripped, Some("u"))
} else {
(tail, None)
};
if !run_part.chars().all(|c| spec.run.contains(&c)) {
return None;
}
let run = canon_run(run_part, spec);
Some((run, charset))
}
#[derive(Debug, Clone)]
pub struct QuoteOperatorInfo {
pub operator: String, pub delimiter: char, pub start_pos: usize, }
#[derive(Debug)]
#[allow(dead_code)] pub struct QuoteResult {
pub token_type: TokenType,
pub text: Arc<str>,
pub start: usize,
pub end: usize,
}
pub fn is_quote_operator(word: &str) -> bool {
matches!(word, "q" | "qq" | "qw" | "qr" | "qx" | "m" | "s" | "tr" | "y")
}
pub fn get_quote_token_type(operator: &str) -> TokenType {
match operator {
"q" => TokenType::QuoteSingle,
"qq" => TokenType::QuoteDouble,
"qw" => TokenType::QuoteWords,
"qr" => TokenType::QuoteRegex,
"qx" => TokenType::QuoteCommand,
"m" => TokenType::RegexMatch,
"s" => TokenType::Substitution,
"tr" | "y" => TokenType::Transliteration,
_ => TokenType::Error(Arc::from(format!("Unknown quote operator: {}", operator))),
}
}
#[allow(dead_code)]
pub fn get_mod_spec(operator: &str) -> Option<&'static ModSpec> {
match operator {
"qr" => Some(&QR_SPEC),
"m" => Some(&M_SPEC),
"s" => Some(&S_SPEC),
"tr" | "y" => Some(&TR_SPEC),
_ => None, }
}