use crate::Symbol;
use smallvec::SmallVec;
use std::hash::Hash;
pub trait BottomUpTa {
type State: Clone + Eq + Hash;
fn step(&self, f: Symbol, children: &[Self::State], out: &mut dyn FnMut(Self::State));
fn is_accepting(&self, q: &Self::State) -> bool;
}
impl<A: BottomUpTa + ?Sized> BottomUpTa for &A {
type State = A::State;
fn step(&self, f: Symbol, children: &[Self::State], out: &mut dyn FnMut(Self::State)) {
(**self).step(f, children, out);
}
fn is_accepting(&self, q: &Self::State) -> bool {
(**self).is_accepting(q)
}
}
pub trait DetBottomUpTa: BottomUpTa {
fn step_det(&self, f: Symbol, children: &[Self::State]) -> Option<Self::State>;
fn det_group(&self, f: Symbol) -> u32 {
f.0
}
}
impl<A: DetBottomUpTa + ?Sized> DetBottomUpTa for &A {
fn step_det(&self, f: Symbol, children: &[Self::State]) -> Option<Self::State> {
(**self).step_det(f, children)
}
fn det_group(&self, f: Symbol) -> u32 {
(**self).det_group(f)
}
}
pub trait StateUniverse: BottomUpTa {
fn all_states(&self, out: &mut dyn FnMut(Self::State));
}
impl<A: StateUniverse + ?Sized> StateUniverse for &A {
fn all_states(&self, out: &mut dyn FnMut(Self::State)) {
(**self).all_states(out);
}
}
pub trait IndexedBottomUpTa: BottomUpTa {
#[allow(clippy::type_complexity)]
fn step_partial(
&self,
f: Symbol,
position: usize,
state_at_position: &Self::State,
out: &mut dyn FnMut(&[Self::State], Self::State),
);
}
impl<A: IndexedBottomUpTa + ?Sized> IndexedBottomUpTa for &A {
fn step_partial(
&self,
f: Symbol,
position: usize,
state_at_position: &Self::State,
out: &mut dyn FnMut(&[Self::State], Self::State),
) {
(**self).step_partial(f, position, state_at_position, out);
}
}
pub trait TopDownTa: BottomUpTa {
fn step_topdown(&self, parent: &Self::State, out: &mut dyn FnMut(Symbol, &[Self::State]));
fn initial_states(&self, out: &mut dyn FnMut(Self::State));
}
impl<A: TopDownTa + ?Sized> TopDownTa for &A {
fn step_topdown(&self, parent: &Self::State, out: &mut dyn FnMut(Symbol, &[Self::State])) {
(**self).step_topdown(parent, out);
}
fn initial_states(&self, out: &mut dyn FnMut(Self::State)) {
(**self).initial_states(out);
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct SymbolSet(SmallVec<[Symbol; 4]>);
impl SymbolSet {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn insert(&mut self, s: Symbol) {
match self.0.binary_search(&s) {
Ok(_) => {}
Err(idx) => self.0.insert(idx, s),
}
}
#[inline]
pub fn contains(&self, s: Symbol) -> bool {
self.0.binary_search(&s).is_ok()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = Symbol> + '_ {
self.0.iter().copied()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
}
impl FromIterator<Symbol> for SymbolSet {
fn from_iter<I: IntoIterator<Item = Symbol>>(iter: I) -> Self {
let mut set = Self::new();
for s in iter {
set.insert(s);
}
set
}
}
pub trait CondensedTa: BottomUpTa {
#[allow(clippy::type_complexity)]
fn condensed_rules(&self, out: &mut dyn FnMut(&[Self::State], &SymbolSet, Self::State));
fn condensed_nullary_rules(&self, out: &mut dyn FnMut(&SymbolSet, Self::State)) {
self.condensed_rules(&mut |children, symbols, result| {
if children.is_empty() {
out(symbols, result);
}
});
}
#[allow(clippy::type_complexity)]
fn condensed_rules_by_child(
&self,
position: usize,
state: &Self::State,
out: &mut dyn FnMut(&[Self::State], &SymbolSet, Self::State),
) {
self.condensed_rules(&mut |children, symbols, result| {
if children.get(position) == Some(state) {
out(children, symbols, result);
}
});
}
}
pub trait CondensedTopDownTa: BottomUpTa {
fn condensed_rules_by_parent(
&self,
parent: &Self::State,
out: &mut dyn FnMut(&SymbolSet, &[Self::State]),
);
fn condensed_initial_states(&self, out: &mut dyn FnMut(Self::State));
}
impl<A: CondensedTopDownTa + ?Sized> CondensedTopDownTa for &A {
fn condensed_rules_by_parent(
&self,
parent: &Self::State,
out: &mut dyn FnMut(&SymbolSet, &[Self::State]),
) {
(**self).condensed_rules_by_parent(parent, out);
}
fn condensed_initial_states(&self, out: &mut dyn FnMut(Self::State)) {
(**self).condensed_initial_states(out);
}
}