lang-evolve-core/src/settings/rule/mod.rs

132 lines
3.3 KiB
Rust

use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use lazy_static::lazy_static;
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),
}
}
fn detect_categories(&self) -> (u8, u8) {
let captures_from = match RE.captures(self.from.as_str()) {
None => 0 as u8,
Some(c) => c.len() as u8,
};
let captures_to = match RE.captures(&self.to) {
None => 0 as u8,
Some(c) => c.len() as u8,
};
(captures_from, captures_to)
}
fn simple_rewrite(&self, categories: &HashMap<String, String>) -> 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<String, String>,
) -> std::result::Result<Rule, String> {
let mut rule = self.clone();
let (from_match, to_match) = self.detect_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<String> for Rule {
fn from(source: String) -> Self {
let components: Vec<&str> = source.split_terminator('>').collect();
Self {
from: Regex::new(components[0]),
to: String::from(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);
}