use std::collections::HashMap; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; mod regex_wrapper; use regex_wrapper::Regex; lazy_static! { static ref RE: Regex = Regex::new("%([A-Z])"); } /// Representation of a rule in LangEvolveRs #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Rule { /// Regex that should match the input text from: Regex, /// Text to replace matched text to: String, } impl Rule { /// Create new rule /// /// # Arguments /// /// * `from` - literal string that represents the regex that should match /// the input text /// * `to` - literal string that represents the regex text that should /// replaced the text matched by `from` /// /// # Example /// ``` /// # use lazy_static::lazy_static; /// # #[path = "mod.rs"] /// # mod rule; /// # use rule::Rule; /// let rule = Rule::new("ab+c*", "ab"); /// ``` pub fn new(from: &str, to: &str) -> Self { Rule { from: Regex::new(from), to: String::from(to), } } pub fn detect_number_categories(&self) -> (u8, u8) { let captures_from = self.from.to_string().matches('%').count() as u8; let captures_to = self.to.matches('%').count() as u8; (captures_from, captures_to) } fn simple_rewrite(&self, categories: &HashMap) -> Self { let mut rule = self.clone(); for (category, content) in categories { rule.from = Regex::new( rule.from .to_string() .replace( format!("%{}", category).as_str(), format!("[{}]", content).as_str(), ) .as_str(), ); } rule } // TODO break categories in different rules pub fn update( &self, categories: &HashMap, ) -> std::result::Result { let mut rule = self.clone(); let (from_match, to_match) = self.detect_number_categories(); // If there are only simple rewrites to make in the from String if from_match > 0 && to_match == 0 { rule = self.simple_rewrite(&categories); } // If there are equivalences between from and to if from_match > 0 && to_match <= from_match && to_match > 0 {} Ok(rule) } pub fn get_from(&self) -> &Regex { &self.from } pub fn get_to(&self) -> String { self.to.clone() } } impl From for Rule { fn from(source: String) -> Self { let components: Vec<&str> = source.split_terminator('>').collect(); Rule::new(components[0], components[1]) } } impl PartialEq for Rule { fn eq(&self, other: &Self) -> bool { self.from == other.from && self.to == other.to } } impl Eq for Rule {} #[test] fn rule_new() { let rule1 = Rule::new("([ae]+)i", "${1}i"); let rule2 = Rule { from: Regex::new("([ae]+)i"), to: String::from("${1}i"), }; assert_eq!(rule1, rule2); }