1#![feature(let_chains)]
2#![feature(if_let_guard)]
3#![feature(trait_alias)]
4#![feature(impl_trait_in_bindings)]
5#![feature(lock_value_accessors)]
6#![feature(pattern)]
7
8use debug_print::debug_println;
9use fsm::NodeType::{self, *};
10use fsm::{CycleAwareOp, Keyword};
11pub use fsm::{FSMNode, ToCSV};
12use regex::Regex;
13use std::cell::RefCell;
14#[cfg(not(feature = "thread-safe"))]
15use std::cell::{Ref, RefMut};
16#[cfg(feature = "thread-safe")]
17use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
18
19pub mod frontend;
20
21mod fsm;
22pub use fsm::FSMNodeWrapper;
23
24pub mod protocol;
25
26thread_local! {
27 static CNT: RefCell<usize> = RefCell::new(0);
28}
29
30fn get_id() -> usize {
31 let mut ret = 0;
32 CNT.with_borrow(|cnt| ret = *cnt);
33 CNT.with_borrow_mut(|cnt| *cnt += 1);
34 return ret;
35}
36fn dbg_id() {
37 debug_println!("{:?}", CNT);
38}
39
40trait PartialMatch {
41 fn partial_match(&self, hay: &str) -> bool;
42}
43
44impl PartialMatch for Regex {
45 fn partial_match(&self, hay: &str) -> bool {
49 let orig = self.as_str();
50 for i in 1..orig.len() {
51 if let Ok(regex) = Regex::new(&orig[0..=i])
52 && regex.is_match(hay)
53 {
54 return true;
55 }
56 }
57 false
58 }
59}
60
61pub fn get_test_fsm() -> FSMNodeWrapper {
62 let root = FSMNode::new_null(None);
63 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
64 let child = FSMNode::new(sign_token.clone(), &root);
65 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
66
67 let child2 = FSMNode::new(sign_token, &root);
68 let types = FSMNode::new_required(NodeType::Null, &child);
69
70 let int = FSMNode::new_keyword_with_parent("int".to_string(), types.clone());
71 let float = FSMNode::new_keyword_with_parent("short".to_string(), types.clone());
72 child.borrow_mut().add_child(&types);
73 child2.borrow_mut().add_child(&types);
74 root
75}
76
77struct NameShortener;
79impl NameShortener {
80 fn expand(old: Option<&str>, full: &str) -> String {
81 if full.is_empty() {
82 panic!("Cannot expand the void!")
83 }
84 let ret = if let Some(old) = old {
85 if old == full {
86 return old.to_string(); }
90 if full.len() < old.len() {
91 panic!("NS: There is nothing left...")
92 }
93 let mut ret = old.to_string();
94 ret.push_str(&full[old.len()..old.len() + 1]);
95 ret
96 } else {
97 full[0..1].to_string()
98 };
99 debug_println!("Got {} instead of {old:?}", ret);
100 ret
101 }
102}
103
104#[cfg(not(feature = "thread-safe"))]
105type FSMRc<T> = std::rc::Rc<T>;
106#[cfg(not(feature = "thread-safe"))]
107type FSMWeak<T> = std::rc::Weak<T>;
108#[cfg(not(feature = "thread-safe"))]
109#[derive(Debug, PartialEq)]
110pub struct FSMLock<T>(RefCell<T>);
111#[cfg(not(feature = "thread-safe"))]
112impl<T> FSMLock<T> {
113 fn new(val: T) -> Self {
114 Self(RefCell::new(val))
115 }
116 pub fn borrow(&self) -> Ref<'_, T> {
117 self.0.borrow()
118 }
119 fn borrow_mut(&self) -> RefMut<'_, T> {
120 self.0.borrow_mut()
121 }
122 fn replace_with(&self, op: impl FnOnce(&mut T) -> T) {
123 self.0.replace_with(op);
124 }
125}
126
127#[cfg(feature = "thread-safe")]
128type FSMRc<T> = std::sync::Arc<T>;
129#[cfg(feature = "thread-safe")]
130type FSMWeak<T> = std::sync::Weak<T>;
131#[cfg(feature = "thread-safe")]
132#[derive(Debug)]
133pub struct FSMLock<T>(RwLock<T>);
134#[cfg(feature = "thread-safe")]
135impl<T> FSMLock<T> {
136 pub fn borrow(&self) -> RwLockReadGuard<'_, T> {
137 self.0.read().expect("FSMLock borrow()")
138 }
139 fn borrow_mut(&self) -> RwLockWriteGuard<'_, T> {
140 self.0.write().expect("FSMLock borrow()")
141 }
142 fn new(val: T) -> Self {
143 Self(RwLock::new(val))
144 }
145 fn replace_with(&self, op: impl FnOnce(&mut T) -> T) {
146 let new = op(&mut self.0.write().unwrap());
147 self.0.set(new).unwrap();
148 }
149}
150#[cfg(feature = "thread-safe")]
151impl<T: PartialEq> PartialEq for FSMLock<T> {
152 fn eq(&self, other: &Self) -> bool {
153 self.0.read().unwrap().eq(&other.0.read().unwrap())
154 }
155}
156type InternalCursor = FSMWeak<FSMLock<FSMNode>>;
157#[derive(Clone, Debug, Default)]
158pub struct FSMCursor {
159 root: InternalCursor,
160 cur_ast_pos: InternalCursor,
161 input_buf: String,
162 unfinished_nodes: Vec<InternalCursor>,
163 path: Vec<InternalCursor>,
164}
165
166impl FSMCursor {
167 pub fn new(fsm_root: &FSMRc<FSMLock<FSMNode>>) -> Self {
168 Self {
169 root: FSMRc::downgrade(fsm_root),
170 cur_ast_pos: FSMRc::downgrade(fsm_root),
171 ..Default::default()
172 }
173 }
174 pub fn reset(&mut self) {
175 self.cur_ast_pos = FSMWeak::clone(&self.root);
176 self.input_buf.clear();
177 }
178 fn handle_userdefined_combo(&mut self, input: char, final_chars: &Vec<char>) -> Option<String> {
179 let child_idx = final_chars.iter().position(|char| *char == input);
180 if let Some(_) = child_idx {
181 let strong_ref = self.get_cur_ast_binding();
182 let mut ret = None;
185 strong_ref.walk_fsm_depth(
186 &mut |_, _, c, _| {
187 if let Keyword(Keyword {
188 short, expanded, ..
189 }) = &c.borrow().value
190 && short.starts_with(input)
191 {
192 self.update_cursor(&c);
193 self.input_buf.clear();
194 ret = Some(expanded.clone());
195 true
196 } else {
197 false
198 }
199 },
200 false,
201 );
202 ret
203 } else {
204 if let UserDefinedCombo(r, _) = self.get_current_nodeval()
205 && !r.is_match(&self.input_buf)
206 {
207 self.input_buf.pop();
208 }
209 None
210 }
211 }
212 fn handle_userdefined(&mut self, input: char, final_chars: &Vec<char>) -> Option<String> {
213 let child_idx = final_chars.iter().position(|char| *char == input);
214 if let Some(child_idx) = child_idx {
215 let strong_ref = self.get_cur_ast_binding();
216 let borrow = strong_ref.borrow();
217 let next_node = FSMRc::clone(&borrow.children[child_idx]);
218 self.update_cursor(&next_node);
219 let ret = if let NodeType::Keyword(Keyword {
220 short,
221 expanded,
222 closing_token: None,
223 ..
224 }) = &next_node.borrow().value
225 && *short == String::from(input)
226 {
227 Some(expanded.clone())
228 } else {
229 Some(String::from(final_chars[child_idx]))
230 };
231 self.input_buf.clear();
232 ret
233 } else {
234 None
235 }
236 }
237 pub fn clear_inputbuf(&mut self) {
238 self.input_buf.clear();
239 }
240 fn search_for_userdefs(
241 &self,
242 treenode: &FSMRc<FSMLock<FSMNode>>,
243 ) -> Option<FSMRc<FSMLock<FSMNode>>> {
244 treenode.borrow().walk_fsm_breadth(
245 &mut |_, _, child, _| match &child.value {
246 UserDefined { .. } => true,
247 UserDefinedRegex(regex) | UserDefinedCombo(regex, _)
248 if regex.partial_match(&self.input_buf) =>
249 {
250 true
251 }
252 _ => false,
253 },
254 false,
255 )
256 }
257 pub fn search_rec(
258 &mut self,
259 treenode: &FSMRc<FSMLock<FSMNode>>,
260 ) -> Option<FSMRc<FSMLock<FSMNode>>> {
261 self.search_rec_internal(treenode, false)
262 }
263 pub fn search_rec_internal(
264 &mut self,
265 treenode: &FSMRc<FSMLock<FSMNode>>,
266 best_effort: bool, ) -> Option<FSMRc<FSMLock<FSMNode>>> {
268 debug_println!(
269 "search_rec at {:?} {}",
270 treenode.borrow().value,
271 treenode.borrow().short_id()
272 );
273 debug_println!("search_rec input buf: {}", self.input_buf);
274 let mut keyword_match = None;
275 let mut potential_matches = 0;
276 let mut visited_keywords = 0;
277 let mut last_keyword = None;
278 treenode.walk_fsm_allow_cycle_to_self(
279 &mut |_, _, child, _| {
280 let node_val = &child.borrow().value;
281 debug_println!(
282 "search_rec closure at {:?} {}",
283 child.borrow().value,
284 child.borrow().short_id()
285 );
286 match node_val {
287 NodeType::Keyword(Keyword { short, .. }) => {
288 if short.starts_with(&self.input_buf) {
289 debug_println!("{:?}", child.borrow().value);
290 debug_println!("{short} == {}", self.input_buf);
291 keyword_match = Some(child.clone());
292 potential_matches += 1;
293 potential_matches > 1
294 } else {
295 visited_keywords += 1;
297 if visited_keywords == 1 {
298 last_keyword = Some(child.clone());
299 }
300 false
301 }
302 }
303 _ => false,
304 }
305 },
306 false,
307 false,
308 );
309 debug_println!("pm: {potential_matches}");
310 if keyword_match.is_some() && potential_matches == 1 {
311 return keyword_match;
312 }
313
314 debug_println!("vk: {visited_keywords}");
315 if visited_keywords == 1 && best_effort {
316 return last_keyword;
318 }
319
320 let userdef_match = self.search_for_userdefs(treenode);
321 if userdef_match.is_some() {
322 return userdef_match;
323 }
324
325 if potential_matches == 0 {
327 self.input_buf.pop();
329 }
330 None
331 }
332 pub fn advance(&mut self, input: char) -> Option<String> {
333 let binding = self.get_cur_ast_binding();
334 let borrow = binding.borrow();
335 debug_println!(
336 "advance with cursor {:?} {}",
337 borrow.value,
338 borrow.short_id()
339 );
340 self.input_buf.push(input);
341 if borrow.is_done() {
343 let res = self.search_rec(&binding);
344 if let Some(node) = res {
345 self.update_cursor(&node);
346 return match &node.borrow().value {
347 NodeType::Keyword(Keyword { expanded, .. }) => {
348 self.input_buf.clear();
349 Some(expanded.clone())
350 }
351 NodeType::UserDefined { final_chars } => {
352 let res = self.handle_userdefined(input, &final_chars);
353 res
354 }
355 NodeType::UserDefinedRegex(_) => None,
356 _ => unreachable!(),
357 };
358 }
359 }
360 match &borrow.value {
361 NodeType::UserDefined { final_chars, .. } => {
362 let res = self.handle_userdefined(input, final_chars);
363 if res.is_some() {
364 return res;
365 }
366 }
367 NodeType::UserDefinedRegex(r) => {
368 debug_println!("Checking regex against '{}'", &self.input_buf);
369 if r.is_match(&self.input_buf) {
370 drop(borrow);
371 binding.borrow_mut().set_is_done(true);
372 self.input_buf.clear();
373 self.input_buf.push(input);
374 let next_node = self.search_rec_internal(&binding, true);
375 if next_node.is_none() {
376 debug_println!("No node found");
377 self.input_buf.clear();
378 return Some(input.to_string());
379 }
380 let next_node = next_node.unwrap();
381 self.update_cursor(&next_node);
382 let ret = if let NodeType::Keyword(Keyword {
383 short,
384 expanded,
385 closing_token: None,
386 ..
387 }) = &next_node.borrow().value
388 {
389 if short.starts_with(input) {
390 Some(expanded.clone())
391 } else {
392 if let Some(next_node) = self.search_rec_internal(&next_node, true) {
394 self.update_cursor(&next_node);
395 if let Keyword(Keyword {
396 expanded,
397 closing_token: None,
398 ..
399 }) = &next_node.borrow().value
400 {
402 Some(expanded.clone())
403 } else {
404 Some(input.to_string())
405 }
406 } else {
407 Some(input.to_string())
408 }
409 }
410 } else {
411 Some(input.to_string())
412 };
413 self.input_buf.clear();
414 return ret;
415 }
416 }
417 UserDefinedCombo(_, f) => {
418 let ret = self.handle_userdefined_combo(input, f);
419 if ret.is_some() {
420 return ret;
421 }
422 }
423 _ => {
424 let res = self.search_rec(&binding);
425 if let Some(node) = res {
426 self.update_cursor(&node);
427 return match &node.borrow().value {
428 NodeType::Keyword(Keyword { expanded, .. }) => {
429 self.input_buf.clear();
430 Some(expanded.clone())
431 }
432 NodeType::UserDefined { final_chars } => {
433 let res = self.handle_userdefined(input, &final_chars);
434 res
435 }
436 NodeType::UserDefinedRegex(_) => None,
437 NodeType::UserDefinedCombo(r, f) => {
438 let res = self.handle_userdefined_combo(input, f);
439 res
440 }
441 _ => unreachable!(),
442 };
443 }
444 }
445 }
446 None
447 }
448
449 pub fn revert(&mut self) {
450 if self.input_buf.is_empty()
451 && let Some(new_cursor_pos) = self.path.pop()
452 {
453 self.cur_ast_pos = new_cursor_pos;
454 } else if !self.input_buf.is_empty() {
455 self.input_buf.pop();
456 }
457 }
458
459 fn update_cursor(&mut self, node: &FSMRc<FSMLock<FSMNode>>) {
460 self.path.push(self.cur_ast_pos.clone());
461 self.cur_ast_pos = FSMRc::downgrade(&FSMRc::clone(&node));
462 if let NodeType::Keyword(Keyword {
463 closing_token: Some(_),
464 ..
465 }) = &node.borrow().value
466 {
467 self.unfinished_nodes.push(FSMRc::downgrade(&node));
468 } else if node.borrow().children.is_empty() && self.unfinished_nodes.len() > 1 {
469 self.cur_ast_pos = self.unfinished_nodes.pop().unwrap();
471 }
472 debug_println!(
473 "uc: {:?} {}",
474 self.get_cur_ast_binding().borrow().value,
475 self.get_cur_ast_binding().borrow().id()
476 );
477 }
478 fn dump(&self) {
479 println!(
480 "Last matched node: {:?}",
481 self.cur_ast_pos.upgrade().unwrap().borrow().value
482 );
483 println!("Input buf: {}", self.input_buf);
484 }
485
486 pub fn is_done(&self) -> bool {
487 let ast_ref = self.cur_ast_pos.upgrade().unwrap();
488 let binding = ast_ref.borrow();
489 match binding.value {
490 UserDefinedRegex(..) | UserDefined { .. } if !binding.is_done() => false,
491 _ => binding.children.is_empty() || !binding.has_useful_children(),
492 }
493 }
494
495 fn get_cur_ast_binding(&self) -> FSMRc<FSMLock<FSMNode>> {
496 self.cur_ast_pos.upgrade().unwrap()
497 }
498 pub fn is_in_userdefined_stage(&self) -> bool {
499 match self.get_cur_ast_binding().borrow().value {
500 NodeType::UserDefined { .. }
501 | NodeType::UserDefinedRegex(..)
502 | NodeType::UserDefinedCombo(_, _) => true,
503 _ => false,
504 }
505 }
506
507 fn get_current_nodeval(&self) -> NodeType {
508 println!("{}", self.get_cur_ast_binding().borrow().id());
509 self.get_cur_ast_binding().borrow().value.clone()
510 }
511 fn find_node_with_code(&self, short: &str) -> Option<FSMRc<FSMLock<FSMNode>>> {
512 let binding = self.get_cur_ast_binding();
513 let binding = binding.borrow();
514 binding.find_node_with_code(short)
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use crate::frontend::create_graph_from_ebnf;
521
522 use super::*;
523
524 #[test]
525 fn simple_tree() {
526 let root = FSMNode::new_keyword("int".to_string());
527 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), root.clone());
528 assert_eq!(root.borrow().children.len(), 1);
529 }
530
531 #[test]
532 fn simple_cursor_steps() {
533 let root = FSMNode::new_null(None);
534 let second = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
535 FSMNode::new_keyword_with_parent("asdf".to_string(), second.clone());
536 let mut cursor = FSMCursor::new(&root);
537 assert_eq!(cursor.get_current_nodeval(), Null);
538 cursor.advance('i').unwrap();
539 assert_eq!(
540 cursor.get_current_nodeval(),
541 NodeType::Keyword(Keyword::new("int".to_string(), None)),
542 );
543 cursor.advance('a').unwrap();
544 assert_eq!(
545 cursor.get_current_nodeval(),
546 NodeType::Keyword(Keyword::new("asdf".to_string(), None)),
547 );
548 }
549
550 #[test]
551 fn test_conflict_check() {
552 let root = FSMNode::new_null(None);
553 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
554 let child = FSMNode::new(sign_token.clone(), &root);
555 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
556
557 let child2 = FSMNode::new(sign_token, &root);
558 let types = FSMNode::new_required(NodeType::Null, &child);
559
560 let int = FSMNode::new_keyword_with_parent("int".to_string(), types.clone());
561 let float = FSMNode::new_keyword_with_parent("short".to_string(), types.clone());
562 child.borrow_mut().add_child(&types);
563 child2.borrow_mut().add_child(&types);
564
565 assert!(root.borrow().check_for_conflicts("s"));
566 assert!(child2.borrow().check_for_conflicts("s"));
567 assert!(types.borrow().check_for_conflicts("s"));
568 assert!(!int.borrow().check_for_conflicts("s"));
569 }
570
571 #[test]
572 fn test_keyword_matching() {
573 let root = FSMNode::new_null(None);
574 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
575 let child = FSMNode::new(sign_token.clone(), &root);
576 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
577
578 let child2 = FSMNode::new(sign_token, &root);
579 let types = FSMNode::new_required(NodeType::Null, &child);
580
581 let int = FSMNode::new_keyword_with_parent("int".to_string(), types.clone());
582 let float = FSMNode::new_keyword_with_parent("short".to_string(), types.clone());
583 root.borrow_mut().add_child(&types);
584 child2.borrow_mut().add_child(&types);
585
586 let mut cursor = FSMCursor::new(&root);
587 assert!(cursor.advance('s').is_none());
588 assert!(cursor.advance('h').is_some());
589 let mut cursor = FSMCursor::new(&root);
590 assert!(cursor.advance('u').is_some());
591 assert!(cursor.advance('s').is_some());
592 }
593
594 #[test]
595 fn test_deep_clone() {
596 let root = FSMNode::new_null(None);
597 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
598 let child = FSMNode::new(sign_token.clone(), &root);
599 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
600
601 let child2 = FSMNode::new(sign_token, &root);
602 let types = FSMNode::new_required(NodeType::Null, &child);
603 println!("hi?");
604 FSMNode::add_child_cycle_safe(&types, &root);
605 let cloned_root = root.borrow().deep_clone();
606 let root = root.borrow();
607 let cloned_root = cloned_root.borrow();
608 assert_eq!(root.value, cloned_root.value);
609 for (i, child) in root.children.iter().enumerate() {
611 assert_eq!(child.borrow().value, cloned_root.children[i].borrow().value);
612 }
613 }
614
615 #[test]
616 fn simple_full() {
617 let bnf = r"
618 t1 ::= t2 | t3;
619 t2 ::= 'r' t3;
620 t3 ::= 'a';
621 ";
622 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
623 let mut cursor = FSMCursor::new(&root);
624 assert_eq!("r", cursor.advance('r').unwrap());
625 assert_eq!("a", cursor.advance('a').unwrap());
626 assert!(cursor.is_done());
627 }
628
629 #[test]
630 fn test_optional() {
631 let bnf = r"
632 t1 ::= 't' ( 'e' t2 )? 't';
633 t2 ::= 's' ( t3 )?;
634 t3 ::= 'a';
635 ";
636 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
637 let mut cursor = FSMCursor::new(&root);
638 assert_eq!("t", cursor.advance('t').unwrap());
639 assert_eq!("t", cursor.advance('t').unwrap());
640 assert!(cursor.is_done());
641
642 let mut cursor = FSMCursor::new(&root);
643 assert_eq!("t", cursor.advance('t').unwrap());
644 assert_eq!("e", cursor.advance('e').unwrap());
645 assert_eq!("s", cursor.advance('s').unwrap());
646 assert_eq!("a", cursor.advance('a').unwrap());
647 assert_eq!("t", cursor.advance('t').unwrap());
648 assert!(cursor.is_done());
649
650 let mut cursor = FSMCursor::new(&root);
651 assert_eq!("t", cursor.advance('t').unwrap());
652 assert_eq!("e", cursor.advance('e').unwrap());
653 assert_eq!("s", cursor.advance('s').unwrap());
654 assert_eq!("t", cursor.advance('t').unwrap());
655 assert!(cursor.is_done());
656 }
657
658 #[test]
659 fn test_optional2() {
660 let bnf = r"
661 t1 ::= 'te' t2 't';
662 t2 ::= ( 's' )?;
663 ";
664 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
665 let mut cursor = FSMCursor::new(&root);
666 assert_eq!("te", cursor.advance('t').unwrap());
667 assert_eq!("t", cursor.advance('t').unwrap());
668 assert!(cursor.is_done());
669 let mut cursor = FSMCursor::new(&root);
670 assert_eq!("te", cursor.advance('t').unwrap());
671 assert_eq!("s", cursor.advance('s').unwrap());
672 assert_eq!("t", cursor.advance('t').unwrap());
673 assert!(cursor.is_done());
674 }
675
676 #[test]
680 fn test_sql() {
681 let bnf = r"
682 query ::= select | insert;
683 select ::= 'SELECT' '*' | collist 'FROM' #'^.*$' ';';
684 insert ::= 'INSERT INTO' #'^.*$' ' ' 'VALUES' '(' collist ')';
685 collist ::= col ( ',' collist )?;
686 col ::= #'^.*[, ]$';
687 ";
688 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
689 root.borrow().dbg();
690 let mut cursor = FSMCursor::new(&root);
691 assert_eq!("SELECT", cursor.advance('S').unwrap());
692 assert_eq!(None, cursor.advance('a'));
693 assert_eq!(",", cursor.advance(',').unwrap());
694 assert_eq!(None, cursor.advance('b'));
695 cursor.advance(' ');
696 assert_eq!("FROM", cursor.advance('F').unwrap());
697 cursor.advance('a');
698 assert_eq!(";", cursor.advance(';').unwrap());
699 assert!(cursor.is_done());
700 }
701
702 #[test]
703 fn test_repeat() {
704 let bnf = r"
705 t1 ::= 't' { 'e' } 'st';
706 ";
707 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
708 for i in 0..=30 {
710 let mut cursor = FSMCursor::new(&root);
711 assert_eq!("t", cursor.advance('t').unwrap());
712 for _ in 0..i {
713 assert_eq!("e", cursor.advance('e').unwrap());
714 }
715 assert_eq!("st", cursor.advance('s').unwrap());
716 assert!(cursor.is_done());
717 }
718 }
719
720 #[test]
721 fn test_terminal() {
722 let terms: usize = 100;
723 let mut bnf = String::with_capacity(terms * 14);
724 for i in 1..terms {
725 bnf.push_str(&format!("t{i:0>3} ::= t{:0>3};\n", i + 1));
726 }
727 bnf.push_str(&format!("t{terms:0>3} ::= 't' 'st';"));
728 println!("{bnf}");
729 let root = frontend::create_graph_from_ebnf(&bnf).unwrap();
730 let mut cursor = FSMCursor::new(&root);
731 assert_eq!("t", cursor.advance('t').unwrap());
732 assert_eq!("st", cursor.advance('s').unwrap());
733 assert!(cursor.is_done());
734 }
735
736 fn util_check_str(root: &FSMRc<FSMLock<FSMNode>>, str: &str) {
737 let mut cursor = FSMCursor::new(root);
738 for char in str.chars() {
739 cursor.advance(char);
740 }
741 assert!(cursor.is_done())
742 }
743
744 #[test]
745 fn test_combi() {
746 let bnf = r"
747 t1 ::= ( 'u' | 'a' | 'o' ) { 'w' | 'v' } ( 'u' | 'a' | 'o' );
748 ";
749 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
750 util_check_str(&root, "uwu");
751 util_check_str(&root, "owo");
752 util_check_str(&root, "owwwwwo");
753 util_check_str(&root, "owwwwwu");
754 }
755
756 #[test]
757 fn test_repeat_multiple() {
758 let bnf = r"
759 t1 ::= 't' t2 't';
760 t2 ::= 'oas' | ( 'e' { 'a' 's' } );
761 ";
762 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
763 let mut cursor = FSMCursor::new(&root);
764 assert_eq!("t", cursor.advance('t').unwrap());
765 assert_eq!("oas", cursor.advance('o').unwrap());
766 assert_eq!("t", cursor.advance('t').unwrap());
767 assert!(cursor.is_done());
768
769 let mut cursor = FSMCursor::new(&root);
770 assert_eq!("t", cursor.advance('t').unwrap());
771 assert_eq!("e", cursor.advance('e').unwrap());
772 assert_eq!("a", cursor.advance('a').unwrap());
773 assert_eq!("s", cursor.advance('s').unwrap());
774 assert_eq!("a", cursor.advance('a').unwrap());
775 assert_eq!("s", cursor.advance('s').unwrap());
776 assert_eq!("t", cursor.advance('t').unwrap());
777 assert!(cursor.is_done());
778 }
779
780 #[test]
781 fn test_userdefs() {
782 let bnf = r"
783 t1 ::= ( #'[0-9]' 't' ) | ( #'[a-z]' 'e' );
784 ";
785 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
786 let mut cursor = FSMCursor::new(&root);
787 assert_eq!(None, cursor.advance('1'));
788 assert_eq!("t", cursor.advance('t').unwrap());
789 assert!(cursor.is_done());
790
791 let mut cursor = FSMCursor::new(&root);
792 assert_eq!(None, cursor.advance('a'));
793 assert_eq!("e", cursor.advance('e').unwrap());
794 assert!(cursor.is_done());
795 }
796 fn test_minify() {
797 let root = FSMNode::new_null(None);
798 let child = FSMNode::new_null(Some(&root));
799 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child);
800 root.borrow().dbg();
802 FSMNode::minify(&root);
803 root.borrow().dbg();
804 assert_eq!(Null, root.borrow().value);
805 assert_eq!(
806 Keyword(Keyword::new("asdf".to_string(), None)),
807 root.borrow().children[0].borrow().value
808 );
809 assert_eq!(1, root.borrow().children.len())
810 }
811
812 #[test]
813 fn test_minify_multiple() {
814 let root = FSMNode::new_null(None);
815 let child = FSMNode::new_null(Some(&root));
816 let child = FSMNode::new_null(Some(&child));
817 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child);
818 root.borrow().dbg();
820 FSMNode::minify(&root);
821 root.borrow().dbg();
822 assert_eq!(Null, root.borrow().value);
823 assert_eq!(
824 Keyword(Keyword::new("asdf".to_string(), None)),
825 root.borrow().children[0].borrow().value
826 );
827 assert_eq!(1, root.borrow().children.len())
828 }
829
830 #[test]
831 fn test_minify_cycles() {
832 let root = FSMNode::new_null(None);
833 let child = FSMNode::new_null(Some(&root));
834 let child2 = FSMNode::new_null(Some(&child));
835 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child2.clone());
836 FSMNode::add_child_cycle_safe(&child, &child2);
837 FSMNode::minify(&root);
838
839 assert_eq!(Null, root.borrow().value);
840 assert_eq!(
841 Keyword(Keyword::new("asdf".to_string(), None)),
842 root.borrow().children[0].borrow().value
843 );
844 assert_eq!(1, root.borrow().children.len());
845 assert_eq!(1, root.borrow().children[0].borrow().children.len());
846 }
847
848 #[test]
849 fn test_userdef_links() {
850 let root = create_graph_from_ebnf(
851 r"
852 main ::= #'[0-9]+' ( ('-' 'test') | (';' 'uwu') );
853",
854 )
855 .unwrap();
856 let mut cursor = FSMCursor::new(&root);
857 for i in 0..=9 {
858 assert_eq!(None, cursor.advance(i.to_string().chars().nth(0).unwrap()));
859 }
860 let mut cursor2 = cursor.clone();
861 assert_eq!("-", cursor.advance('-').unwrap());
862 assert_eq!("test", cursor.advance('t').unwrap());
863 assert_eq!(";", cursor2.advance(';').unwrap());
864 assert_eq!("uwu", cursor2.advance('u').unwrap());
865 root.borrow().dbg();
866 }
867
868 #[test]
869 fn test_fancy_regex_usecase() {
870 let root = create_graph_from_ebnf(
871 r"
872 main ::= (#'[0-9]+' 'uwu') | (#'[a-z]' 'awa');
873",
874 )
875 .unwrap();
876 let mut cursor = FSMCursor::new(&root);
877 let mut cursor2 = cursor.clone();
878 assert_eq!(None, cursor.advance('0'));
879 assert_eq!("uwu", cursor.advance('u').unwrap());
880 assert_eq!(None, cursor2.advance('b'));
881 assert_eq!("awa", cursor2.advance('a').unwrap());
882 root.borrow().dbg();
883 }
884
885 #[test]
886 fn test_reset() {
887 let root = FSMNode::new_null(None);
888 let other = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
889 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), other.clone());
890 assert_eq!(root.borrow().children.len(), 1);
891 let mut cursor = FSMCursor::new(&root);
892 assert_eq!("int", cursor.advance('i').unwrap());
893 assert_eq!(None, cursor.advance('i'));
894 cursor.reset();
895 assert_eq!("int", cursor.advance('i').unwrap());
896 }
897
898 #[test]
899 fn test_revert() {
900 let root = FSMNode::new_null(None);
901 let other = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
902 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), other.clone());
903 let mut cursor = FSMCursor::new(&root);
904
905 assert_eq!("int", cursor.advance('i').unwrap());
906 assert_eq!("asdf", cursor.advance('a').unwrap());
907 cursor.revert();
908 assert_eq!("asdf", cursor.advance('a').unwrap());
909 }
910
911 #[test]
912 fn test_dead_end_prevention() {
913 let root = FSMNode::new_null(None);
914 let other = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
915 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), other.clone());
916 let mut cursor = FSMCursor::new(&root);
917
918 assert_eq!("int", cursor.advance('i').unwrap());
919 assert_eq!(None, cursor.advance('i'));
920 assert_eq!(None, cursor.advance('?'));
921 assert_eq!("asdf", cursor.advance('a').unwrap());
922 }
923 #[test]
924 fn test_dead_end_prevention_userdef() {
925 let ebnf = r"
926 t1 ::= ( #'[0-9]' 'asdf' ) | ( #'[a-z]' 'test' );
927 ";
928 let root = create_graph_from_ebnf(ebnf).unwrap();
929 let mut cursor = FSMCursor::new(&root);
930
931 assert_eq!(None, cursor.advance('0'));
932 assert_eq!("asdf", cursor.advance('a').unwrap());
933 cursor.reset();
934 assert_eq!(None, cursor.advance('a'));
935 assert_eq!("test", cursor.advance('t').unwrap());
936 cursor.reset();
937 assert_eq!(None, cursor.advance('A'));
938 assert_eq!(None, cursor.advance('B'));
939 assert_eq!(None, cursor.advance('!'));
940
941 assert_eq!(None, cursor.advance('a'));
942 assert_eq!("test", cursor.advance('t').unwrap());
943 }
944}