l_group_formulas/l_group_term/
parse_l_group_term.rs1use super::super::free_group_term::FreeGroupTerm;
2use super::super::l_group_term::LGroupTerm;
3use super::super::Term;
4use std::collections::BTreeSet;
5use super::super::parsing_error::ParsingError;
6
7
8pub (super) fn parse(s: &str) -> Result<LGroupTerm, ParsingError> {
9 let mut string = s.to_string();
10 string.retain(|c| !c.is_whitespace());
12 string.retain(|c| c.is_alphanumeric() || c == '(' || c == ')' || c == '^' || c == '-');
13 loop {
14 let result = has_outermost_brackets(&string);
15 match result {
16 Err(e) => return Err(e),
17 Ok(can_be_stripped) => {
18 if string.len() >= 2 && can_be_stripped {
19 string = string[1..string.len() - 1].to_string();
20 }
21 else {
22 break;
23 }
24 }
25 }
26 }
27
28 if is_atom(&string) {
29 let parsed_free_group_term = std::panic::catch_unwind(|| FreeGroupTerm::from(string.as_str()));
30 match parsed_free_group_term {
31 Err(_) => return Err(ParsingError::ParsingAtomError(string)),
32 Ok(term) => return Ok(LGroupTerm::Atom(term))
33 };
34 }
35
36 if is_inverse(&string) {
37 let result = parse(&string[1..string.len()].to_string());
38 match result {
39 Ok(term) => return Ok(term.inverse()),
40 Err(e) => return Err(ParsingError::ParsingInverseError(string, e.to_string()))
41 };
42 }
43
44 if is_meet(&string) {
45 let mut meetands = BTreeSet::new();
46 let result = split_at_outermost_meet(&string);
47 match result {
48 Err(e) => return Err(e),
49 Ok(strings) => {
50 for term_string in strings {
51 let result = parse(&term_string);
52 match result {
53 Ok(term) => meetands.insert(term),
54 Err(e) => return Err(ParsingError::ParsingMeetError(string, e.to_string()))
55 };
56 }
57 }
58 };
59 return Ok(LGroupTerm::Meet(meetands));
60 }
61
62 if is_join(&string) {
63 let mut joinands = BTreeSet::new();
64 let result = split_at_outermost_join(&string);
65 match result {
66 Err(e) => return Err(e),
67 Ok(strings) => {
68 for term_string in strings {
69 let result = parse(&term_string);
70 match result {
71 Ok(term) => joinands.insert(term),
72 Err(e) => return Err(ParsingError::ParsingJoinError(string, e.to_string()))
73 };
74 }
75 }
76 };
77 return Ok(LGroupTerm::Join(joinands));
78 }
79
80 let mut factors = Vec::new();
81 let mut current_factor = String::new();
82 let mut depth = 0;
83 for c in string.chars() {
84 match &c {
85 '(' => {
86 if depth == 0 && current_factor.len() > 0 {
87 let result = parse(¤t_factor);
88 match result {
89 Ok(term) => factors.push(term),
90 Err(e) => return Err(ParsingError::ParsingProductError(string, current_factor, e.to_string()))
91 };
92 current_factor = String::new();
93 }
94 depth += 1;
95 current_factor.push(c);
96 },
97 ')' => {
98 match depth {
99 0 => return Err(ParsingError::NonMatchingBracketsError(string.to_string())),
100 _ => depth -= 1
101 };
102 current_factor.push(c);
103 if depth == 0 {
104 let result = parse(¤t_factor);
105 match result {
106 Ok(term) => factors.push(term),
107 Err(e) => return Err(ParsingError::ParsingProductError(string, current_factor, e.to_string()))
108 };
109 current_factor = String::new();
110 }
111 },
112 '-' => {
113 if depth == 0 && current_factor.len() > 0 {
114 let result = parse(¤t_factor);
115 match result {
116 Ok(term) => factors.push(term),
117 Err(e) => return Err(ParsingError::ParsingProductError(string, current_factor, e.to_string()))
118 };
119 current_factor = String::new();
120 }
121 current_factor.push(c);
122 }
123 _ => current_factor.push(c)
124 };
125 }
126 if current_factor.len() > 0 {
127 let result = parse(¤t_factor);
128 match result {
129 Ok(term) => factors.push(term),
130 Err(e) => return Err(ParsingError::ParsingProductError(string, current_factor, e.to_string()))
131 };
132 }
133 return Ok(LGroupTerm::Prod(factors));
134}
135
136fn split_at_outermost_join(s: &String) -> Result<Vec<String>, ParsingError> {
137 let mut depth = 0;
138 let mut strings = Vec::new();
139 let mut current_string = String::new();
140 for c in s.chars() {
141 match c {
142 '(' => {
143 depth += 1;
144 current_string.push(c);
145 },
146 ')' => {
147 match depth {
148 0 => return Err(ParsingError::NonMatchingBracketsError(s.clone())),
149 _ => depth -= 1
150 };
151 current_string.push(c);
152 },
153 'v' => {
154 if depth == 0 {
155 strings.push(current_string.clone());
156 current_string = String::new();
157 }
158 else {
159 current_string.push(c);
160 }
161 },
162 _ => current_string.push(c)
163 };
164 }
165 strings.push(current_string);
166 return Ok(strings);
167}
168
169fn split_at_outermost_meet(s: &String) -> Result<Vec<String>, ParsingError> {
170 let mut depth = 0;
171 let mut strings = Vec::new();
172 let mut current_string = String::new();
173 for c in s.chars() {
174 match c {
175 '(' => depth += 1,
176 ')' => {
177 match depth {
178 0 => return Err(ParsingError::NonMatchingBracketsError(s.clone())),
179 _ => depth -= 1
180 };
181 },
182 '^' => {
183 if depth == 0 {
184 strings.push(current_string.clone());
185 current_string = String::new();
186 }
187 else {
188 current_string.push(c);
189 }
190 },
191 _ => current_string.push(c)
192 };
193 }
194 strings.push(current_string);
195 return Ok(strings);
196}
197
198fn is_atom(s: &String) -> bool {
200 for c in s.chars() {
201 if c == '^' || c == 'v' || c == '-' { return false; }
202 }
203 return true;
204}
205
206fn is_inverse(s: &String) -> bool {
208 let mut chars = s.chars();
209 let c = chars.next();
210 if c != Some('-') { return false };
211 let mut depth = 0;
212 for c in chars {
213 match &c {
214 '(' => depth += 1,
215 ')' => depth -= 1,
216 'v' | '^' | '-' => { if depth == 0 { return false; }},
217 _ => {}
218 };
219 }
220 return true;
221}
222
223fn is_meet(s: &String) -> bool {
225 let mut depth = 0;
226 for c in s.chars() {
227 match &c {
228 '(' => depth += 1,
229 ')' => depth -= 1,
230 _ => {}
231 };
232 if depth == 0 && c == '^' { return true };
233 }
234 return false;
235}
236
237fn is_join(s: &String) -> bool {
239 let mut depth = 0;
240 for c in s.chars() {
241 match &c {
242 '(' => depth += 1,
243 ')' => depth -= 1,
244 _ => {}
245 };
246 if depth == 0 && c == 'v' { return true };
247 }
248 return false;
249}
250
251
252fn has_outermost_brackets(s: &String) -> Result<bool, ParsingError> {
255 let mut depth = 0;
256 let s = s[0 .. s.len() - 1].to_string();
257 for c in s.chars() {
258 match c {
259 '(' => depth += 1,
260 ')' => {
261 match depth {
262 0 => return Err(ParsingError::NonMatchingBracketsError(s)),
263 _ => depth -= 1
264 }
265 },
266 _ => {}
267 };
268 if depth == 0 { return Ok(false); }
269 }
270 return Ok(true);
271}
272
273#[cfg(test)]
274mod tests {
275
276 #[test]
277 fn test_does_not_crash() {
278 let string = String::from("(x v (z v (x ^ y)))");
279 assert_eq!(string, super::parse(&string).expect("crashed ...").to_string());
280 }
281}