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;