automata_like_programming/simple_impl/
mod.rs

1//! # Example of automaton implementation for finding "ab" pattern
2//! 
3//! ```
4//! use automata_like_programming::{
5//!         automaton::
6//!         {
7//!             Automaton,
8//!             AutomatonResult
9//!         },    
10//!         automaton_state::new_shared_concrete_state,
11//!         simple_impl::simple_state::
12//!         {
13//!             KeyProvidingData,
14//!             SimpleInterStateConnection,
15//!             SimpleStateImplementation
16//!         }
17//! };
18//! 
19//!  struct TextMatching<'a> {
20//!     text: &'a str,
21//!     matches: Vec<usize>,
22//!     iter: usize,
23//! }
24//! 
25//! impl <'a> TextMatching<'a> {
26//!     pub fn new(
27//!         text: &'a str
28//!     ) -> Self {
29//!         Self { text, matches: Vec::new(), iter: 0}
30//!     }
31//!     pub fn add_match(
32//!         &mut self, index: usize
33//!     ) -> () {
34//!         self.matches.push(index);
35//!     }
36//! }
37//! 
38//! impl <'a> KeyProvidingData<(usize, char)> for TextMatching<'a> {
39//!     fn next_key(
40//!         &mut self
41//!     ) -> Option<(usize, char)> {
42//!         if self.iter >= self.text.len() {
43//!             Option::None
44//!         } else {
45//!             self.iter += 1;
46//!             Option::Some((self.iter - 1, self.text.chars().nth(self.iter)?))
47//!         }
48//!     }
49//! }
50//! 
51//! fn char_matcher(
52//!     c: char,
53//!     reversed: bool
54//! ) -> impl Fn(&(usize, char)) -> bool {
55//!     move |k| (k.1 == c) ^ reversed
56//! }
57//! 
58//! let mut matching_data = TextMatching::new("aabbacacaabab");
59//! let mut automaton: Automaton<u32, TextMatching, String> = Automaton::new(|| {
60//!     let non_match_state = new_shared_concrete_state(SimpleStateImplementation::new(0));
61//!     non_match_state.borrow_mut().register_connection(
62//!         SimpleInterStateConnection::new_no_action(char_matcher('a', true), &non_match_state)
63//!     );
64//!
65//!     let a_state = new_shared_concrete_state(SimpleStateImplementation::new(1));
66//!     non_match_state.borrow_mut().register_connection(
67//!         SimpleInterStateConnection::new_no_action(char_matcher('a', false), &a_state)
68//!     );
69//!     a_state.borrow_mut().register_connection(
70//!         SimpleInterStateConnection::new_no_action(char_matcher('a', false), &a_state)
71//!     );
72//!     a_state.borrow_mut().register_connection(
73//!         SimpleInterStateConnection::new_no_action(char_matcher('b', true), &non_match_state)
74//!     );
75//!     
76//!     let b_state = new_shared_concrete_state(SimpleStateImplementation::new(2));
77//!     a_state.borrow_mut().register_connection(
78//!         SimpleInterStateConnection::new(char_matcher('b', false),
79//!         |data: &mut TextMatching, key| {
80//!             data.add_match(key.0);
81//!             Result::Ok(())
82//!         }, &b_state)
83//!     );
84//!     b_state.borrow_mut().register_connection(
85//!         SimpleInterStateConnection::new_no_action(char_matcher('a', false), &a_state)
86//!     );
87//!     b_state.borrow_mut().register_connection(
88//!         SimpleInterStateConnection::new_no_action(char_matcher('a', true), &non_match_state)
89//!     );
90//!     non_match_state
91//! });
92//! let result = automaton.run(&mut matching_data);
93//! assert!(result.is_empty_iter());
94//! assert_eq!(matching_data.matches, vec![1, 9, 11]);
95//! ```
96
97
98/// Basic implementation of an automaton state. Provides management for handling connections between
99/// states and allows for some action to be executed while changing states. Designed to be used
100/// in parser like solutions.
101pub mod simple_state;