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)]
158pub struct FSMCursor {
159 root: InternalCursor,
160 cur_ast_pos: InternalCursor,
161 input_buf: String,
162 unfinished_nodes: Vec<InternalCursor>,
163}
164
165impl FSMCursor {
166 pub fn new(fsm_root: &FSMRc<FSMLock<FSMNode>>) -> Self {
167 Self {
168 root: FSMRc::downgrade(fsm_root),
169 cur_ast_pos: FSMRc::downgrade(fsm_root),
170 input_buf: String::new(),
171 unfinished_nodes: Vec::new(),
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 None
205 }
206 }
207 fn handle_userdefined(&mut self, input: char, final_chars: &Vec<char>) -> Option<String> {
208 let child_idx = final_chars.iter().position(|char| *char == input);
209 if let Some(child_idx) = child_idx {
210 let strong_ref = self.get_cur_ast_binding();
211 let borrow = strong_ref.borrow();
212 let next_node = FSMRc::clone(&borrow.children[child_idx]);
213 self.update_cursor(&next_node);
214 let ret = if let NodeType::Keyword(Keyword {
215 short,
216 expanded,
217 closing_token: None,
218 ..
219 }) = &next_node.borrow().value
220 && *short == String::from(input)
221 {
222 Some(expanded.clone())
223 } else {
224 Some(String::from(final_chars[child_idx]))
225 };
226 self.input_buf.clear();
227 ret
228 } else {
229 None
230 }
231 }
232 pub fn clear_inputbuf(&mut self) {
233 self.input_buf.clear();
234 }
235 fn search_for_userdefs(
236 &self,
237 treenode: &FSMRc<FSMLock<FSMNode>>,
238 ) -> Option<FSMRc<FSMLock<FSMNode>>> {
239 treenode.borrow().walk_fsm_breadth(
240 &mut |_, _, child, _| match &child.value {
241 UserDefined { .. } => true,
242 UserDefinedRegex(regex) | UserDefinedCombo(regex, _)
243 if regex.partial_match(&self.input_buf) =>
244 {
245 true
246 }
247 _ => false,
248 },
249 false,
250 )
251 }
252 pub fn search_rec(
253 &self,
254 treenode: &FSMRc<FSMLock<FSMNode>>,
255 ) -> Option<FSMRc<FSMLock<FSMNode>>> {
256 self.search_rec_internal(treenode, false)
257 }
258 pub fn search_rec_internal(
259 &self,
260 treenode: &FSMRc<FSMLock<FSMNode>>,
261 best_effort: bool,
262 ) -> Option<FSMRc<FSMLock<FSMNode>>> {
263 debug_println!(
264 "search_rec at {:?} {}",
265 treenode.borrow().value,
266 treenode.borrow().short_id()
267 );
268 debug_println!("search_rec input buf: {}", self.input_buf);
269 let mut keyword_match = None;
270 let mut potential_matches = 0;
271 let mut visited_keywords = 0;
272 let mut last_keyword = None;
273 treenode.walk_fsm_allow_cycle_to_self(
275 &mut |_, _, child, _| {
276 let node_val = &child.borrow().value;
277 debug_println!(
278 "search_rec closure at {:?} {}",
279 child.borrow().value,
280 child.borrow().short_id()
281 );
282 match node_val {
283 NodeType::Keyword(Keyword { short, .. }) => {
284 if short.starts_with(&self.input_buf) {
285 debug_println!("{:?}", child.borrow().value);
286 debug_println!("{short} == {}", self.input_buf);
287 keyword_match = Some(child.clone());
288 potential_matches += 1;
289 potential_matches > 1
290 } else {
291 visited_keywords += 1;
293 if visited_keywords == 1 {
294 last_keyword = Some(child.clone());
295 }
296 false
297 }
298 }
299 _ => false,
300 }
301 },
302 false,
303 false,
304 );
305 debug_println!("pm: {potential_matches}");
306 if keyword_match.is_some() && potential_matches == 1 {
307 return keyword_match;
308 }
309
310 debug_println!("vk: {visited_keywords}");
311 if visited_keywords == 1 && best_effort {
312 return last_keyword;
314 }
315
316 let userdef_match = self.search_for_userdefs(treenode);
317 if userdef_match.is_some() {
318 return userdef_match;
319 }
320 None
321 }
322 pub fn advance(&mut self, input: char) -> Option<String> {
323 let binding = self.get_cur_ast_binding();
324 let borrow = binding.borrow();
325 debug_println!(
326 "advance with cursor {:?} {}",
327 borrow.value,
328 borrow.short_id()
329 );
330 self.input_buf.push(input);
331 if borrow.is_done() {
333 let res = self.search_rec(&binding);
334 if let Some(node) = res {
335 self.update_cursor(&node);
336 return match &node.borrow().value {
337 NodeType::Keyword(Keyword { expanded, .. }) => {
338 self.input_buf.clear();
339 Some(expanded.clone())
340 }
341 NodeType::UserDefined { final_chars } => {
342 let res = self.handle_userdefined(input, &final_chars);
343 res
344 }
345 NodeType::UserDefinedRegex(_) => None,
346 _ => unreachable!(),
347 };
348 }
349 }
350 match &borrow.value {
351 NodeType::UserDefined { final_chars, .. } => {
352 let res = self.handle_userdefined(input, final_chars);
353 if res.is_some() {
354 return res;
355 }
356 }
357 NodeType::UserDefinedRegex(r) => {
358 debug_println!("Checking regex against '{}'", &self.input_buf);
359 if r.is_match(&self.input_buf) {
360 drop(borrow);
361 binding.borrow_mut().set_is_done(true);
362 self.input_buf.clear();
363 self.input_buf.push(input);
364 let next_node = self.search_rec_internal(&binding, true);
365 if next_node.is_none() {
366 debug_println!("No node found");
367 self.input_buf.clear();
368 return Some(input.to_string());
369 }
370 let next_node = next_node.unwrap();
371 self.update_cursor(&next_node);
372 let ret = if let NodeType::Keyword(Keyword {
373 short,
374 expanded,
375 closing_token: None,
376 ..
377 }) = &next_node.borrow().value
378 {
379 if short.starts_with(input) {
380 Some(expanded.clone())
381 } else {
382 if let Some(next_node) = self.search_rec_internal(&next_node, true) {
384 self.update_cursor(&next_node);
385 if let Keyword(Keyword {
386 expanded,
387 closing_token: None,
388 ..
389 }) = &next_node.borrow().value
390 {
392 Some(expanded.clone())
393 } else {
394 Some(input.to_string())
395 }
396 } else {
397 Some(input.to_string())
398 }
399 }
400 } else {
401 Some(input.to_string())
402 };
403 self.input_buf.clear();
404 return ret;
405 }
406 }
407 UserDefinedCombo(_, f) => {
408 let ret = self.handle_userdefined_combo(input, f);
409 if ret.is_some() {
410 return ret;
411 }
412 }
413 _ => {
414 let res = self.search_rec(&binding);
415 if let Some(node) = res {
416 self.update_cursor(&node);
417 return match &node.borrow().value {
418 NodeType::Keyword(Keyword { expanded, .. }) => {
419 self.input_buf.clear();
420 Some(expanded.clone())
421 }
422 NodeType::UserDefined { final_chars } => {
423 let res = self.handle_userdefined(input, &final_chars);
424 res
425 }
426 NodeType::UserDefinedRegex(_) => None,
427 NodeType::UserDefinedCombo(r, f) => {
428 let res = self.handle_userdefined_combo(input, f);
429 res
430 }
431 _ => unreachable!(),
432 };
433 }
434 }
435 }
436 None
437 }
438
439 fn update_cursor(&mut self, node: &FSMRc<FSMLock<FSMNode>>) {
440 self.cur_ast_pos = FSMRc::downgrade(&FSMRc::clone(&node));
441 if let NodeType::Keyword(Keyword {
442 closing_token: Some(_),
443 ..
444 }) = &node.borrow().value
445 {
446 self.unfinished_nodes.push(FSMRc::downgrade(&node));
447 } else if node.borrow().children.is_empty() && self.unfinished_nodes.len() > 1 {
448 self.cur_ast_pos = self.unfinished_nodes.pop().unwrap();
450 }
451 debug_println!(
452 "uc: {:?} {}",
453 self.get_cur_ast_binding().borrow().value,
454 self.get_cur_ast_binding().borrow().id()
455 );
456 }
457 fn dump(&self) {
458 println!(
459 "Last matched node: {:?}",
460 self.cur_ast_pos.upgrade().unwrap().borrow().value
461 );
462 println!("Input buf: {}", self.input_buf);
463 }
464
465 pub fn is_done(&self) -> bool {
466 let ast_ref = self.cur_ast_pos.upgrade().unwrap();
467 let binding = ast_ref.borrow();
468 match binding.value {
469 UserDefinedRegex(..) | UserDefined { .. } if !binding.is_done() => false,
470 _ => binding.children.is_empty() || !binding.has_useful_children(),
471 }
472 }
473
474 fn get_cur_ast_binding(&self) -> FSMRc<FSMLock<FSMNode>> {
475 self.cur_ast_pos.upgrade().unwrap()
476 }
477 pub fn is_in_userdefined_stage(&self) -> bool {
478 match self.get_cur_ast_binding().borrow().value {
479 NodeType::UserDefined { .. }
480 | NodeType::UserDefinedRegex(..)
481 | NodeType::UserDefinedCombo(_, _) => true,
482 _ => false,
483 }
484 }
485
486 fn get_current_nodeval(&self) -> NodeType {
487 println!("{}", self.get_cur_ast_binding().borrow().id());
488 self.get_cur_ast_binding().borrow().value.clone()
489 }
490 fn find_node_with_code(&self, short: &str) -> Option<FSMRc<FSMLock<FSMNode>>> {
491 let binding = self.get_cur_ast_binding();
492 let binding = binding.borrow();
493 binding.find_node_with_code(short)
494 }
495}
496
497#[cfg(test)]
498mod tests {
499 use crate::frontend::create_graph_from_ebnf;
500
501 use super::*;
502
503 #[test]
504 fn simple_tree() {
505 let root = FSMNode::new_keyword("int".to_string());
506 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), root.clone());
507 assert_eq!(root.borrow().children.len(), 1);
508 }
509
510 #[test]
511 fn simple_cursor_steps() {
512 let root = FSMNode::new_null(None);
513 let second = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
514 FSMNode::new_keyword_with_parent("asdf".to_string(), second.clone());
515 let mut cursor = FSMCursor::new(&root);
516 assert_eq!(cursor.get_current_nodeval(), Null);
517 cursor.advance('i').unwrap();
518 assert_eq!(
519 cursor.get_current_nodeval(),
520 NodeType::Keyword(Keyword::new("int".to_string(), None)),
521 );
522 cursor.advance('a').unwrap();
523 assert_eq!(
524 cursor.get_current_nodeval(),
525 NodeType::Keyword(Keyword::new("asdf".to_string(), None)),
526 );
527 }
528
529 #[test]
530 fn test_conflict_check() {
531 let root = FSMNode::new_null(None);
532 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
533 let child = FSMNode::new(sign_token.clone(), &root);
534 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
535
536 let child2 = FSMNode::new(sign_token, &root);
537 let types = FSMNode::new_required(NodeType::Null, &child);
538
539 let int = FSMNode::new_keyword_with_parent("int".to_string(), types.clone());
540 let float = FSMNode::new_keyword_with_parent("short".to_string(), types.clone());
541 child.borrow_mut().add_child(&types);
542 child2.borrow_mut().add_child(&types);
543
544 assert!(root.borrow().check_for_conflicts("s"));
545 assert!(child2.borrow().check_for_conflicts("s"));
546 assert!(types.borrow().check_for_conflicts("s"));
547 assert!(!int.borrow().check_for_conflicts("s"));
548 }
549
550 #[test]
551 fn test_keyword_matching() {
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 root.borrow_mut().add_child(&types);
563 child2.borrow_mut().add_child(&types);
564
565 let mut cursor = FSMCursor::new(&root);
566 assert!(cursor.advance('s').is_none());
567 assert!(cursor.advance('h').is_some());
568 let mut cursor = FSMCursor::new(&root);
569 assert!(cursor.advance('u').is_some());
570 assert!(cursor.advance('s').is_some());
571 }
572
573 #[test]
574 fn test_deep_clone() {
575 let root = FSMNode::new_null(None);
576 let mut sign_token = NodeType::Keyword(Keyword::new("unsigned".to_string(), None));
577 let child = FSMNode::new(sign_token.clone(), &root);
578 sign_token = NodeType::Keyword(Keyword::new("signed".to_string(), None));
579
580 let child2 = FSMNode::new(sign_token, &root);
581 let types = FSMNode::new_required(NodeType::Null, &child);
582 println!("hi?");
583 FSMNode::add_child_cycle_safe(&types, &root);
584 let cloned_root = root.borrow().deep_clone();
585 let root = root.borrow();
586 let cloned_root = cloned_root.borrow();
587 assert_eq!(root.value, cloned_root.value);
588 for (i, child) in root.children.iter().enumerate() {
590 assert_eq!(child.borrow().value, cloned_root.children[i].borrow().value);
591 }
592 }
593
594 #[test]
595 fn simple_full() {
596 let bnf = r"
597 t1 ::= t2 | t3;
598 t2 ::= 'r' t3;
599 t3 ::= 'a';
600 ";
601 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
602 let mut cursor = FSMCursor::new(&root);
603 assert_eq!("r", cursor.advance('r').unwrap());
604 assert_eq!("a", cursor.advance('a').unwrap());
605 assert!(cursor.is_done());
606 }
607
608 #[test]
609 fn test_optional() {
610 let bnf = r"
611 t1 ::= 't' ( 'e' t2 )? 't';
612 t2 ::= 's' ( t3 )?;
613 t3 ::= 'a';
614 ";
615 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
616 let mut cursor = FSMCursor::new(&root);
617 assert_eq!("t", cursor.advance('t').unwrap());
618 assert_eq!("t", cursor.advance('t').unwrap());
619 assert!(cursor.is_done());
620
621 let mut cursor = FSMCursor::new(&root);
622 assert_eq!("t", cursor.advance('t').unwrap());
623 assert_eq!("e", cursor.advance('e').unwrap());
624 assert_eq!("s", cursor.advance('s').unwrap());
625 assert_eq!("a", cursor.advance('a').unwrap());
626 assert_eq!("t", cursor.advance('t').unwrap());
627 assert!(cursor.is_done());
628
629 let mut cursor = FSMCursor::new(&root);
630 assert_eq!("t", cursor.advance('t').unwrap());
631 assert_eq!("e", cursor.advance('e').unwrap());
632 assert_eq!("s", cursor.advance('s').unwrap());
633 assert_eq!("t", cursor.advance('t').unwrap());
634 assert!(cursor.is_done());
635 }
636
637 #[test]
638 fn test_optional2() {
639 let bnf = r"
640 t1 ::= 'te' t2 't';
641 t2 ::= ( 's' )?;
642 ";
643 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
644 let mut cursor = FSMCursor::new(&root);
645 assert_eq!("te", cursor.advance('t').unwrap());
646 assert_eq!("t", cursor.advance('t').unwrap());
647 assert!(cursor.is_done());
648 let mut cursor = FSMCursor::new(&root);
649 assert_eq!("te", cursor.advance('t').unwrap());
650 assert_eq!("s", cursor.advance('s').unwrap());
651 assert_eq!("t", cursor.advance('t').unwrap());
652 assert!(cursor.is_done());
653 }
654
655 #[test]
659 fn test_sql() {
660 let bnf = r"
661 query ::= select | insert;
662 select ::= 'SELECT' '*' | collist 'FROM' #'^.*$' ';';
663 insert ::= 'INSERT INTO' #'^.*$' ' ' 'VALUES' '(' collist ')';
664 collist ::= col ( ',' collist )?;
665 col ::= #'^.*[, ]$';
666 ";
667 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
668 root.borrow().dbg();
669 let mut cursor = FSMCursor::new(&root);
670 assert_eq!("SELECT", cursor.advance('S').unwrap());
671 assert_eq!(None, cursor.advance('a'));
672 assert_eq!(",", cursor.advance(',').unwrap());
673 assert_eq!(None, cursor.advance('b'));
674 cursor.advance(' ');
675 assert_eq!("FROM", cursor.advance('F').unwrap());
676 cursor.advance('a');
677 assert_eq!(";", cursor.advance(';').unwrap());
678 assert!(cursor.is_done());
679 }
680
681 #[test]
682 fn test_repeat() {
683 let bnf = r"
684 t1 ::= 't' { 'e' } 'st';
685 ";
686 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
687 for i in 0..=30 {
689 let mut cursor = FSMCursor::new(&root);
690 assert_eq!("t", cursor.advance('t').unwrap());
691 for _ in 0..i {
692 assert_eq!("e", cursor.advance('e').unwrap());
693 }
694 assert_eq!("st", cursor.advance('s').unwrap());
695 assert!(cursor.is_done());
696 }
697 }
698
699 #[test]
700 fn test_terminal() {
701 let terms: usize = 100;
702 let mut bnf = String::with_capacity(terms * 14);
703 for i in 1..terms {
704 bnf.push_str(&format!("t{i:0>3} ::= t{:0>3};\n", i + 1));
705 }
706 bnf.push_str(&format!("t{terms:0>3} ::= 't' 'st';"));
707 println!("{bnf}");
708 let root = frontend::create_graph_from_ebnf(&bnf).unwrap();
709 let mut cursor = FSMCursor::new(&root);
710 assert_eq!("t", cursor.advance('t').unwrap());
711 assert_eq!("st", cursor.advance('s').unwrap());
712 assert!(cursor.is_done());
713 }
714
715 fn util_check_str(root: &FSMRc<FSMLock<FSMNode>>, str: &str) {
716 let mut cursor = FSMCursor::new(root);
717 for char in str.chars() {
718 cursor.advance(char);
719 }
720 assert!(cursor.is_done())
721 }
722
723 #[test]
724 fn test_combi() {
725 let bnf = r"
726 t1 ::= ( 'u' | 'a' | 'o' ) { 'w' | 'v' } ( 'u' | 'a' | 'o' );
727 ";
728 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
729 util_check_str(&root, "uwu");
730 util_check_str(&root, "owo");
731 util_check_str(&root, "owwwwwo");
732 util_check_str(&root, "owwwwwu");
733 }
734
735 #[test]
736 fn test_repeat_multiple() {
737 let bnf = r"
738 t1 ::= 't' t2 't';
739 t2 ::= 'oas' | ( 'e' { 'a' 's' } );
740 ";
741 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
742 let mut cursor = FSMCursor::new(&root);
743 assert_eq!("t", cursor.advance('t').unwrap());
744 assert_eq!("oas", cursor.advance('o').unwrap());
745 assert_eq!("t", cursor.advance('t').unwrap());
746 assert!(cursor.is_done());
747
748 let mut cursor = FSMCursor::new(&root);
749 assert_eq!("t", cursor.advance('t').unwrap());
750 assert_eq!("e", cursor.advance('e').unwrap());
751 assert_eq!("a", cursor.advance('a').unwrap());
752 assert_eq!("s", cursor.advance('s').unwrap());
753 assert_eq!("a", cursor.advance('a').unwrap());
754 assert_eq!("s", cursor.advance('s').unwrap());
755 assert_eq!("t", cursor.advance('t').unwrap());
756 assert!(cursor.is_done());
757 }
758
759 #[test]
760 fn test_userdefs() {
761 let bnf = r"
762 t1 ::= ( #'[0-9]' 't' ) | ( #'[a-z]' 'e' );
763 ";
764 let root = frontend::create_graph_from_ebnf(bnf).unwrap();
765 let mut cursor = FSMCursor::new(&root);
766 assert_eq!(None, cursor.advance('1'));
767 assert_eq!("t", cursor.advance('t').unwrap());
768 assert!(cursor.is_done());
769
770 let mut cursor = FSMCursor::new(&root);
771 assert_eq!(None, cursor.advance('a'));
772 assert_eq!("e", cursor.advance('e').unwrap());
773 assert!(cursor.is_done());
774 }
775 fn test_minify() {
776 let root = FSMNode::new_null(None);
777 let child = FSMNode::new_null(Some(&root));
778 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child);
779 root.borrow().dbg();
781 FSMNode::minify(&root);
782 root.borrow().dbg();
783 assert_eq!(Null, root.borrow().value);
784 assert_eq!(
785 Keyword(Keyword::new("asdf".to_string(), None)),
786 root.borrow().children[0].borrow().value
787 );
788 assert_eq!(1, root.borrow().children.len())
789 }
790
791 #[test]
792 fn test_minify_multiple() {
793 let root = FSMNode::new_null(None);
794 let child = FSMNode::new_null(Some(&root));
795 let child = FSMNode::new_null(Some(&child));
796 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child);
797 root.borrow().dbg();
799 FSMNode::minify(&root);
800 root.borrow().dbg();
801 assert_eq!(Null, root.borrow().value);
802 assert_eq!(
803 Keyword(Keyword::new("asdf".to_string(), None)),
804 root.borrow().children[0].borrow().value
805 );
806 assert_eq!(1, root.borrow().children.len())
807 }
808
809 #[test]
810 fn test_minify_cycles() {
811 let root = FSMNode::new_null(None);
812 let child = FSMNode::new_null(Some(&root));
813 let child2 = FSMNode::new_null(Some(&child));
814 let child = FSMNode::new_keyword_with_parent("asdf".to_string(), child2.clone());
815 FSMNode::add_child_cycle_safe(&child, &child2);
816 FSMNode::minify(&root);
817
818 assert_eq!(Null, root.borrow().value);
819 assert_eq!(
820 Keyword(Keyword::new("asdf".to_string(), None)),
821 root.borrow().children[0].borrow().value
822 );
823 assert_eq!(1, root.borrow().children.len());
824 assert_eq!(1, root.borrow().children[0].borrow().children.len());
825 }
826
827 #[test]
828 fn test_userdef_links() {
829 let root = create_graph_from_ebnf(
830 r"
831 main ::= #'[0-9]+' ( ('-' 'test') | (';' 'uwu') );
832",
833 )
834 .unwrap();
835 let mut cursor = FSMCursor::new(&root);
836 for i in 0..=9 {
837 assert_eq!(None, cursor.advance(i.to_string().chars().nth(0).unwrap()));
838 }
839 let mut cursor2 = cursor.clone();
840 assert_eq!("-", cursor.advance('-').unwrap());
841 assert_eq!("test", cursor.advance('t').unwrap());
842 assert_eq!(";", cursor2.advance(';').unwrap());
843 assert_eq!("uwu", cursor2.advance('u').unwrap());
844 root.borrow().dbg();
845 }
846
847 #[test]
848 fn test_fancy_regex_usecase() {
849 let root = create_graph_from_ebnf(
850 r"
851 main ::= (#'[0-9]+' 'uwu') | (#'[a-z]' 'awa');
852",
853 )
854 .unwrap();
855 let mut cursor = FSMCursor::new(&root);
856 let mut cursor2 = cursor.clone();
857 assert_eq!(None, cursor.advance('0'));
858 assert_eq!("uwu", cursor.advance('u').unwrap());
859 assert_eq!(None, cursor2.advance('b'));
860 assert_eq!("awa", cursor2.advance('a').unwrap());
861 root.borrow().dbg();
862 }
863
864 #[test]
865 fn test_reset() {
866 let root = FSMNode::new_null(None);
867 let other = FSMNode::new_keyword_with_parent("int".to_string(), root.clone());
868 let _other = FSMNode::new_keyword_with_parent("asdf".to_string(), other.clone());
869 assert_eq!(root.borrow().children.len(), 1);
870 let mut cursor = FSMCursor::new(&root);
871 assert_eq!("int", cursor.advance('i').unwrap());
872 assert_eq!(None, cursor.advance('i'));
873 cursor.reset();
874 assert_eq!("int", cursor.advance('i').unwrap());
875 }
876}