alith_client/components/grammar/
exact_string.rs

1use super::{Grammar, GrammarError, GrammarSetterTrait};
2use std::cell::RefCell;
3
4#[derive(Clone, Default, PartialEq)]
5pub struct ExactStringGrammar {
6    pub exact_strings: Vec<String>,
7    pub stop_word_done: Option<String>,
8    pub stop_word_no_result: Option<String>,
9    grammar_string: RefCell<Option<String>>,
10}
11
12impl ExactStringGrammar {
13    #[inline]
14    pub fn wrap(self) -> Grammar {
15        Grammar::ExactString(self)
16    }
17
18    pub fn add_exact_strings<T: AsRef<str>>(mut self, exact_strings: &[T]) -> Self {
19        for incoming_string in exact_strings {
20            if !self.exact_strings.is_empty()
21                && self
22                    .exact_strings
23                    .iter()
24                    .any(|s| s == incoming_string.as_ref())
25            {
26                continue;
27            }
28            self.exact_strings.push(incoming_string.as_ref().to_owned());
29        }
30        self
31    }
32
33    #[inline]
34    pub fn add_exact_string<T: AsRef<str>>(self, exact_string: T) -> Self {
35        self.add_exact_strings(&[exact_string])
36    }
37
38    pub fn grammar_string(&self) -> String {
39        if self.exact_strings.is_empty() {
40            panic!("ExactStringGrammar must have at least one exact string");
41        }
42        let mut grammar_string = self.grammar_string.borrow_mut();
43        if grammar_string.is_none() {
44            *grammar_string = Some(exact_string_grammar(
45                &self.exact_strings,
46                &self.stop_word_done,
47                &self.stop_word_no_result,
48            ));
49        }
50        grammar_string.as_ref().unwrap().clone()
51    }
52
53    #[inline]
54    pub fn validate_clean(&self, content: &str) -> Result<String, GrammarError> {
55        exact_string_validate_clean(content, &self.exact_strings)
56    }
57
58    #[inline]
59    pub fn grammar_parse(&self, content: &str) -> Result<String, GrammarError> {
60        exact_string_parse(content, &self.exact_strings)
61    }
62}
63
64impl GrammarSetterTrait for ExactStringGrammar {
65    fn stop_word_done_mut(&mut self) -> &mut Option<String> {
66        &mut self.stop_word_done
67    }
68
69    fn stop_word_no_result_mut(&mut self) -> &mut Option<String> {
70        &mut self.stop_word_no_result
71    }
72}
73
74pub fn exact_string_grammar<T: AsRef<str>>(
75    exact_strings: &[String],
76    stop_word_done: &Option<T>,
77    stop_word_no_result: &Option<T>,
78) -> String {
79    let mut pattern = String::new();
80    for text in exact_strings {
81        if pattern.is_empty() {
82            pattern.push('(');
83        } else {
84            pattern.push('|');
85        }
86        pattern.push_str(&format!(" \"{}\" ", text));
87    }
88    pattern.push(')');
89    match (stop_word_done, stop_word_no_result) {
90        (Some(stop_word_done), Some(stop_word_no_result)) => format!(
91            "root ::= ( {pattern} | \"{}\" ) \" {}\"",
92            stop_word_no_result.as_ref(),
93            stop_word_done.as_ref()
94        ),
95        (None, Some(stop_word_no_result)) => {
96            format!(
97                "root ::= ( {pattern} | \"{}\" )",
98                stop_word_no_result.as_ref()
99            )
100        }
101        (Some(stop_word_done), None) => {
102            format!("root ::= {pattern} \" {}\"", stop_word_done.as_ref())
103        }
104        (None, None) => format!("root ::= {pattern}"),
105    }
106}
107
108pub fn exact_string_validate_clean(
109    content: &str,
110    exact_strings: &[String],
111) -> Result<String, GrammarError> {
112    let content = content.trim();
113    if exact_string_parse(content, exact_strings).is_ok() {
114        Ok(content.to_string())
115    } else {
116        Err(GrammarError::ParseValueError {
117            content: content.to_string(),
118            parse_type: "exact_string".to_string(),
119        })
120    }
121}
122
123pub fn exact_string_parse(content: &str, exact_strings: &[String]) -> Result<String, GrammarError> {
124    exact_strings
125        .iter()
126        .find(|&text| content.contains(text))
127        .map(|text| text.to_string())
128        .ok_or_else(|| GrammarError::ParseValueError {
129            content: format!("Content: {}, Exact Strings: {:?}", content, exact_strings),
130            parse_type: "exact_string".to_string(),
131        })
132}