use phf::{phf_map, Map};
static TRULY_RESERVED: Map<&'static str, ()> = phf_map! {
"if" => (),
"elif" => (),
"else" => (),
"chk" => (),
"miss" => (),
"then" => (),
"return" => (),
"and" => (),
"or" => (),
"not" => (),
"true" => (),
"false" => (),
"null" => (),
"global" => (),
"const" => (),
"let" => (),
"mut" => (),
"from" => (),
"from_cloud" => (),
"verify" => (),
};
static DATA_TYPE_KEYWORDS: Map<&'static str, ()> = phf_map! {
"int" => (),
"float" => (),
"double" => (),
"string" => (),
"bool" => (),
"array" => (),
"tuple" => (),
"hex" => (),
"blob" => (),
"regex" => (),
"object" => (),
"timestamp" => (),
"date" => (),
"enum" => (),
"any" => (),
};
static ALL_LANGUAGE_KEYWORDS: Map<&'static str, ()> = phf_map! {
"if" => (), "elif" => (), "else" => (),
"chk" => (), "miss" => (), "then" => (),
"return" => (), "and" => (), "or" => (),
"not" => (), "true" => (), "false" => (),
"null" => (), "global" => (), "const" => (),
"let" => (), "mut" => (), "from" => (),
"from_cloud" => (), "verify" => (),
"int" => (), "float" => (), "double" => (),
"string" => (), "bool" => (), "array" => (),
"tuple" => (), "hex" => (), "blob" => (),
"regex" => (), "object" => (), "timestamp" => (),
"date" => (), "enum" => (), "any" => (),
};
static CONFIG_SECTION_KEYWORDS: Map<&'static str, ()> = phf_map! {
"version" => (),
"encoding" => (),
"author" => (),
"created" => (),
"features" => (),
"debug_mode" => (),
"error_handling" => (),
"compatibility_mode" => (),
};
static SECURITY_SECTION_KEYWORDS: Map<&'static str, ()> = phf_map! {
"encryption" => (),
"validation" => (),
"keystore" => (),
"override" => (),
"metadata" => (),
};
static DLM_KEYWORDS: Map<&'static str, ()> = phf_map! {
"dcompressor" => (),
"dauditor" => (),
"dencryptor" => (),
"gzip" => (),
"bzip2" => (),
"lzma" => (),
"diy" => (),
"enhanced" => (),
"xor" => (),
"aes128" => (),
"aes256" => (),
"chacha20" => (),
};
static CONFIG_VALUE_KEYWORDS: Map<&'static str, ()> = phf_map! {
"halt" => (),
"continue" => (),
"recover" => (),
"strict" => (),
"best_effort" => (),
"permissive" => (),
"off" => (),
"regular" => (),
"verbose" => (),
"basic" => (),
"advanced" => (),
"quickfuncs" => (),
"enums" => (),
"dlm" => (),
"data" => (),
};
static CONTEXTUAL_IDENTIFIERS: Map<&'static str, ()> = phf_map! {
"config" => (),
"dix" => (),
};
static ALL_KEYWORDS_COMBINED: Map<&'static str, ()> = phf_map! {
"if" => (), "elif" => (), "else" => (), "chk" => (), "miss" => (),
"then" => (), "return" => (), "and" => (), "or" => (), "not" => (),
"true" => (), "false" => (), "null" => (), "global" => (),
"const" => (), "let" => (), "mut" => (), "from" => (),
"from_cloud" => (), "verify" => (),
"int" => (), "float" => (), "double" => (), "string" => (), "bool" => (),
"array" => (), "tuple" => (), "hex" => (), "blob" => (), "regex" => (),
"object" => (), "timestamp" => (), "date" => (), "enum" => (), "any" => (),
"version" => (), "encoding" => (), "author" => (), "created" => (),
"features" => (), "debug_mode" => (), "error_handling" => (),
"compatibility_mode" => (),
"halt" => (), "continue" => (), "recover" => (), "strict" => (),
"best_effort" => (), "permissive" => (), "off" => (), "regular" => (),
"verbose" => (), "basic" => (), "advanced" => (), "quickfuncs" => (),
"enums" => (), "dlm" => (), "data" => (),
"encryption" => (), "validation" => (), "keystore" => (),
"override" => (), "metadata" => (),
"dcompressor" => (), "dauditor" => (), "dencryptor" => (),
"gzip" => (), "bzip2" => (), "lzma" => (), "diy" => (), "enhanced" => (),
"xor" => (), "aes128" => (), "aes256" => (), "chacha20" => (),
};
#[inline]
fn map_contains_ci(map: &Map<&'static str, ()>, word: &str) -> bool {
let lower = word.to_lowercase();
map.contains_key(&*lower)
}
pub struct Keywords;
impl Keywords {
#[inline]
pub fn truly_reserved_keywords() -> &'static Map<&'static str, ()> {
&TRULY_RESERVED
}
#[inline]
pub fn data_type_keywords() -> &'static Map<&'static str, ()> {
&DATA_TYPE_KEYWORDS
}
#[inline]
pub fn language_keywords() -> &'static Map<&'static str, ()> {
&ALL_LANGUAGE_KEYWORDS
}
#[inline]
pub fn config_section_keywords() -> &'static Map<&'static str, ()> {
&CONFIG_SECTION_KEYWORDS
}
#[inline]
pub fn security_section_keywords() -> &'static Map<&'static str, ()> {
&SECURITY_SECTION_KEYWORDS
}
#[inline]
pub fn dlm_keywords() -> &'static Map<&'static str, ()> {
&DLM_KEYWORDS
}
#[inline]
pub fn config_value_keywords() -> &'static Map<&'static str, ()> {
&CONFIG_VALUE_KEYWORDS
}
#[inline]
pub fn contextual_identifiers() -> &'static Map<&'static str, ()> {
&CONTEXTUAL_IDENTIFIERS
}
#[inline]
pub fn is_data_type_keyword(word: &str) -> bool {
map_contains_ci(&DATA_TYPE_KEYWORDS, word)
}
#[inline]
pub fn is_keyword(word: &str) -> bool {
map_contains_ci(&ALL_KEYWORDS_COMBINED, word)
}
#[inline]
pub fn is_contextual_identifier(word: &str) -> bool {
map_contains_ci(&CONTEXTUAL_IDENTIFIERS, word)
}
pub fn is_control_flow_keyword(word: &str) -> bool {
matches!(
word.to_lowercase().as_str(),
"if" | "elif" | "else" | "chk" | "miss" | "then" | "return" | "log"
)
}
pub fn is_section_keyword(word: &str) -> bool {
matches!(
word.to_uppercase().as_str(),
"@CONFIG" | "@DLM" | "@ENUMS" | "@IMPORTS"
| "@QUICKFUNCS" | "@DATA" | "@SECURITY"
)
}
pub fn get_valid_section_keywords() -> &'static [&'static str] {
&[
"@CONFIG", "@IMPORTS", "@DLM", "@ENUMS",
"@QUICKFUNCS", "@DATA", "@SECURITY",
]
}
pub fn is_reserved_in_context(word: &str, context: &str) -> bool {
let context_upper = context.to_uppercase();
if map_contains_ci(&TRULY_RESERVED, word) {
return true;
}
if map_contains_ci(&DATA_TYPE_KEYWORDS, word) {
return context_upper == "QUICKFUNCS";
}
match context_upper.as_str() {
"CONFIG" => {
map_contains_ci(&CONFIG_SECTION_KEYWORDS, word)
|| map_contains_ci(&CONFIG_VALUE_KEYWORDS, word)
}
"SECURITY" => map_contains_ci(&SECURITY_SECTION_KEYWORDS, word),
"DLM" => map_contains_ci(&DLM_KEYWORDS, word),
_ => false,
}
}
#[inline]
pub fn can_be_identifier_in_context(word: &str, context: &str) -> bool {
!Keywords::is_reserved_in_context(word, context)
}
pub fn get_keyword_category(word: &str) -> &'static str {
if map_contains_ci(&TRULY_RESERVED, word) { return "Reserved Keyword"; }
if map_contains_ci(&DATA_TYPE_KEYWORDS, word) { return "Data Type Keyword (can be identifier)"; }
if map_contains_ci(&CONFIG_SECTION_KEYWORDS, word) { return "Config Keyword"; }
if map_contains_ci(&SECURITY_SECTION_KEYWORDS, word){ return "Security Keyword"; }
if map_contains_ci(&DLM_KEYWORDS, word) { return "DLM Keyword"; }
if map_contains_ci(&CONFIG_VALUE_KEYWORDS, word) { return "Config Value Keyword"; }
if map_contains_ci(&CONTEXTUAL_IDENTIFIERS, word) { return "Contextual Identifier"; }
"Unknown"
}
pub fn get_keyword_usage_error(word: &str, context: &str) -> String {
if map_contains_ci(&TRULY_RESERVED, word) {
return format!(
"'{}' is a reserved keyword and cannot be used as an identifier",
word
);
}
if map_contains_ci(&DATA_TYPE_KEYWORDS, word) {
if context == "QUICKFUNCS" {
let capitalized = {
let mut c = word.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().to_string() + c.as_str(),
}
};
return format!(
"'{}' is a data type keyword and cannot be used as a variable or \
parameter name. Consider: 'my{}' or '{}Value'",
word, capitalized, word
);
}
return format!(
"'{}' is a data type keyword but can be used as a property name in {}",
word, context
);
}
let context_upper = context.to_uppercase();
if map_contains_ci(&CONFIG_SECTION_KEYWORDS, word) && context_upper == "CONFIG" {
return format!("'{}' is a CONFIG section keyword and cannot be used here", word);
}
if map_contains_ci(&SECURITY_SECTION_KEYWORDS, word) && context_upper == "SECURITY" {
return format!("'{}' is a SECURITY section keyword and cannot be used here", word);
}
if map_contains_ci(&DLM_KEYWORDS, word) && context_upper == "DLM" {
return format!("'{}' is a DLM keyword and cannot be used here", word);
}
format!("'{}' can be used as an identifier in the {} section", word, context)
}
}