use crate::ast::{FiniteStateMachineAst, HeadAst, RuleAst, RuleBlockAst, TailAst};
use proc_macro2::TokenStream;
use quote::quote;
pub fn impl_fsm(input: &FiniteStateMachineAst) -> TokenStream {
let FiniteStateMachineAst {
default_state,
rules,
..
} = input;
let rules_stream = handle_rule_block(rules);
let with_state = default_state.as_ref().map(|ds| {
let state = &ds.state;
quote! { .with_default_state(#state) }
});
quote! {
rstm::MovingHead::tmh(
rstm::Program::from_iter([#(#rules_stream),*]) #with_state
)
}
}
fn handle_rule_block(RuleBlockAst { rules, .. }: &RuleBlockAst) -> Vec<TokenStream> {
rules.into_iter().map(handle_rule).collect()
}
fn handle_rule(
RuleAst {
head: HeadAst { state, symbol, .. },
tail:
TailAst {
direction,
next_state,
next_symbol,
..
},
..
}: &RuleAst,
) -> TokenStream {
quote! {
rstm::Rule {
head: rstm::Head::new(#state, #symbol),
tail: rstm::Tail::new(rstm::Direction::#direction, #next_state, #next_symbol),
}
}
}