Crates.io | automafish |
lib.rs | automafish |
version | 0.1.0 |
source | src |
created_at | 2020-11-20 00:30:54.754308 |
updated_at | 2020-11-20 00:30:54.754308 |
description | Automafish is a state machine builder for creating deterministic state machines out of nondeterministic state machine definitions. |
homepage | |
repository | https://github.com/Rantanen/protofish |
max_upload_size | |
id | 314184 |
size | 57,965 |
Automafish is a state machine builder for turning nondeterministic finite automata into deterministic finite automata. Its primary use case is driving the selector logic of metamorfish to enable mutation of protofish values in proxide.
use std::iter::FromIterator;
use automafish::{Builder, State, Transition, Criteria, Condition};
let mut builder : Builder<Condition<char>, &mut dyn FnMut(&mut char)> = Builder::new();
// Set up an automata that capitalizes first character of a word.
let mut upper_case = |mut c: &mut char| { c.make_ascii_uppercase(); };
let wait_not_space = builder.create_initial_state();
let first_not_space = builder.add_state(State::with_action(&mut upper_case));
let wait_for_space = builder.add_state(State::new());
builder.add_transition(Transition::new(
wait_not_space, Condition::Is(vec![' ']), wait_not_space));
builder.add_transition(Transition::new(
wait_not_space, Condition::Not(vec![' ']), first_not_space));
builder.add_transition(Transition::new(
first_not_space, Condition::Not(vec![' ']), wait_for_space));
builder.add_transition(Transition::new(
first_not_space, Condition::Is(vec![' ']), wait_not_space));
builder.add_transition(Transition::new(
wait_for_space, Condition::Not(vec![' ']), wait_for_space));
builder.add_transition(Transition::new(
wait_for_space, Condition::Is(vec![' ']), wait_not_space));
// Set up an automata that counts all exclamation marks.
// This automata modifies a value outside the state machine.
let mut exclamations = 0;
let mut exclamation_counter = |_: &mut char| { exclamations += 1; };
let wait_exclamation = builder.create_initial_state();
let exclamation = builder.add_state(State::with_action(&mut exclamation_counter));
builder.add_transition(Transition::new(
wait_exclamation, Condition::Any, wait_exclamation));
builder.add_transition(Transition::new(
wait_exclamation, Condition::Is(vec!['!']), exclamation));
// Build the machine.
let mut machine = builder.build();
// Execute the machine on an input string.
let mut current_state = machine.start();
let mut input : Vec<char> = "hello world! this is rust!".chars().collect();
for i in &mut input {
current_state = machine.step_and_execute_mut(current_state, i);
}
let output : String = String::from_iter(input);
assert_eq!("Hello World! This Is Rust!", output);
assert_eq!(2, exclamations);
In addition there seem to be other generic state machine crates that I discovered while looking into options. If you ended up here looking for one, you might be interested in the following crates as well. Note that I haven't personally tested any of these crates.
The only current goal for Automafish is providing a somewhat efficient state machine implementation for Metamorfish.
Use cases outside of those required by Metamorfish are definitely not out of scope, but currently it's unlikely I'll be adding new features to Automafish that Metamorfish doesn't need on my own. Feature and pull requests are definitely welcome though! It's just that without any other priorities, Metamorfish and Proxide itself are more interesting to me. :)
Defining custom Criteria
is somewhat painful currently with the need to
resolve intersections and differences for such criteria. I would simplify the
process of handling Criteria
, but currently I don't really know how to build
the powersets without (at the very least) the intersection handling.
Then again, I haven't really looked into available algorithms for such use cases.