use std::collections::HashMap;
use crate::{
conjugation::Conjugation,
data::{parse_verbs, VERBS_DAT},
stemmer::Stemmer,
types::WordEntry,
word_tokenizer::{WordTokenizer, WordTokenizerConfig, AFTER_VERBS, BEFORE_VERBS},
};
pub struct Lemmatizer {
pub words: HashMap<String, WordEntry>,
pub verbs: HashMap<String, String>,
stemmer: Stemmer,
}
impl Lemmatizer {
pub fn new() -> Self {
Self::with_joined_parts(true)
}
pub fn with_joined_parts(joined_verb_parts: bool) -> Self {
let tokenizer = WordTokenizer::with_config(WordTokenizerConfig {
join_verb_parts: true,
..Default::default()
});
let words = tokenizer.words.clone();
let conj = Conjugation;
let verb_roots = parse_verbs(VERBS_DAT);
let verb_entries: Vec<String> = verb_roots
.iter()
.map(|v| format!("{}#{}", v.past, v.present))
.collect();
let mut verbs: HashMap<String, String> = HashMap::new();
verbs.insert("است".to_string(), "#است".to_string());
for verb_entry in verb_entries.iter().rev() {
for tense in conj.get_all(verb_entry) {
verbs.insert(tense, verb_entry.clone());
}
}
if joined_verb_parts {
for verb_entry in verb_entries.iter().rev() {
let bon = verb_entry.split('#').next().unwrap_or("");
for av in AFTER_VERBS.iter() {
verbs.insert(format!("{bon}ه_{av}"), verb_entry.clone());
verbs.insert(format!("ن{bon}ه_{av}"), verb_entry.clone());
}
for bv in BEFORE_VERBS.iter() {
verbs.insert(format!("{bv}_{bon}"), verb_entry.clone());
}
}
}
Self {
words,
verbs,
stemmer: Stemmer::new(),
}
}
pub fn lemmatize(&self, word: &str, pos: &str) -> String {
if pos.is_empty() && self.words.contains_key(word) {
return word.to_string();
}
if (pos.is_empty() || pos == "VERB") && self.verbs.contains_key(word) {
return self.verbs[word].clone();
}
if pos.starts_with("ADJ") && word.ends_with('ی') {
return word.to_string();
}
if pos == "PRON" {
return word.to_string();
}
if self.words.contains_key(word) {
return word.to_string();
}
let stem = self.stemmer.stem(word);
if !stem.is_empty() && self.words.contains_key(&stem) {
return stem;
}
word.to_string()
}
}
impl Default for Lemmatizer {
fn default() -> Self {
Self::new()
}
}