pub trait ShiftReduceParser {
type Action;
type Token;
type TimerId;
type ReduceRecord;
// Required methods
fn decide(
&mut self,
token: &Self::Token,
) -> ParseAction<Self::Action, Self::Token, Self::TimerId, Self::ReduceRecord>;
fn on_reduce(&mut self, record: Self::ReduceRecord);
}Expand description
A shift-reduce parser that processes tokens with timer support.
Implement this trait to define your parser’s grammar (action table).
The framework provides the main loop via parse().
§Implementing decide
decide is the action table of the parser. It receives a reference
to the current token together with whatever state is stored in self,
and returns a ParseAction describing what to do next.
Typical skeleton:
use timed_fsm::parser::{ShiftReduceParser, ParseAction};
use timed_fsm::TimerCommand;
use std::time::Duration;
#[derive(Clone, Copy, Debug, PartialEq)]
enum Key { Shift, A, Other }
struct MyParser { pending_shift: bool }
impl ShiftReduceParser for MyParser {
type Action = String;
type Token = Key;
type TimerId = ();
type ReduceRecord = ();
fn decide(&mut self, token: &Key)
-> ParseAction<String, Key, (), ()>
{
match (self.pending_shift, token) {
// Shift key down — buffer and open chord window.
(false, Key::Shift) => {
self.pending_shift = true;
ParseAction::Shift {
timers: vec![TimerCommand::Set {
id: (),
duration: Duration::from_millis(50),
}],
}
}
// Shift + A chord recognized.
(true, Key::A) => {
self.pending_shift = false;
ParseAction::Reduce {
actions: vec!["ShiftA".to_string()],
record: (),
timers: vec![TimerCommand::Kill { id: () }],
}
}
// Unrecognized — pass through.
_ => ParseAction::PassThrough { timers: vec![] },
}
}
fn on_reduce(&mut self, (): ()) { /* update history / stats */ }
}
let mut p = MyParser { pending_shift: false };
let _ = timed_fsm::parse(&mut p, Key::Shift); // Shift
let r = timed_fsm::parse(&mut p, Key::A); // Reduce
assert_eq!(r.actions, vec!["ShiftA".to_string()]);Required Associated Types§
Sourcetype ReduceRecord
type ReduceRecord
Metadata attached to each Reduce step (e.g., history tracking).
Use () if no per-reduce bookkeeping is needed.
Required Methods§
Sourcefn decide(
&mut self,
token: &Self::Token,
) -> ParseAction<Self::Action, Self::Token, Self::TimerId, Self::ReduceRecord>
fn decide( &mut self, token: &Self::Token, ) -> ParseAction<Self::Action, Self::Token, Self::TimerId, Self::ReduceRecord>
The action table: given the current state and input token, decide what to do.
This method may mutate internal state (e.g., enter a pending state,
push a token onto a buffer). It is called once per token (or once per
remaining token in a ReduceAndContinue loop iteration) by parse.
Sourcefn on_reduce(&mut self, record: Self::ReduceRecord)
fn on_reduce(&mut self, record: Self::ReduceRecord)
Called after each Reduce or ReduceAndContinue to update internal bookkeeping.
Receives the record from the matching ParseAction. Use this to
maintain reduce-count statistics, history logs, or any per-reduce state
that should not live inside decide.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".