#statemachine #fsm #state #automaton #macros

statemachine-macro

Provides the statemachine!() macro for easily creating statemachines

2 releases

0.1.1 Sep 9, 2020
0.1.0 Sep 9, 2020

#176 in Parser tooling


Used in statemachine

MIT license

28KB
515 lines

statemachine-macro

A Rust crate providing a macro to easily create state machines. Documentation is available on docs.rs.

Usage

Add this to your Cargo.toml:

[dependencies]
statemachine-macro = "0.1"

Getting Started

use statemachine_macro::*;

statemachine! {
    struct Foo;

    enum FooState consumes [char] from Start accepts [NonEmpty];

    Start => {
        char match _ => NonEmpty
    },

    NonEmpty => {
        _ => NonEmpty
    }
}

fn main() {
    let mut foo: Foo = statemachine_new!(Foo{});
    assert!(!foo.is_accepting());
    foo.consume('a');
    assert!(foo.is_accepting());
    foo.consume('b');
    assert!(foo.is_accepting());
    foo.consume('c');
    assert!(foo.is_accepting());
}

License

This crate is published under the terms of the MIT license. See the LICENSE file for details.


lib.rs:

Provides the statemachine!() macro.

Examples

use statemachine_macro::*;

statemachine! {
    #[derive(Default)]
    pub struct Foo {
        pub allow_x: bool
    }

    enum FooState consumes [char, i32] from Start accepts [Done];

    Start => {
        @enter => {
            println!("Entering Start!");
        },
        @leave => {
            println!("Leaving Start!");
        },
        @loop => {
            println!("Looping inside Start!");
        },
        char match 'a' => {
            println!("Got 'a'... Going to 'Done'!");
            Done
        },
        char match 'b' => {
            println!("Got 'b'... allowing 'x'!");
            self.allow_x = true;
            Start
        },
        char match 'x' => if self.allow_x {
            println!("Got authorized 'x'.");
            Done
        },
        char match 'x' => if !self.allow_x {
            println!("Got unauthorized 'x'.");
            Error
        },
        i32 match 42 => {
            println!("It is the answer!");
            Error
        },
        i32 match val => {
            println!("Got {}", val);
            Error
        },
        _ => Error
    },

    Error => {
        _ => Error
    },

    Done => {
        _ => Error
    }
}

let mut foo: Foo = Default::default();
foo.consume('a');
assert!(foo.is_accepting());
assert!(!foo.allow_x);
foo.reset(FooState::Start);

foo.consume('b');
assert!(!foo.is_accepting());
assert!(foo.allow_x);
foo.consume('x');
assert!(foo.is_accepting());

Dependencies

~290–710KB
~18K SLoC