use std::any::{Any};
use std::{fmt};
pub trait AsAny: Any {
fn as_any(&self) -> &dyn Any;
fn to_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T: Any> AsAny for T {
fn as_any(&self) -> &dyn Any { self }
fn to_any(self: Box<Self>) -> Box<dyn Any> { self }
}
pub trait Tree: fmt::Debug + AsAny {
fn declare_keywords(#[allow(unused)] declare: impl FnMut(&'static str, Self)) where Self: Sized {}
}
impl dyn Tree {
pub fn is<T: Tree>(&self) -> bool { self.as_any().is::<T>() }
pub fn downcast_ref<T: Tree>(&self) -> Option<&T> { self.as_any().downcast_ref::<T>() }
pub fn downcast<T: Tree>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
if (*self).is::<T>() {
Ok(self.to_any().downcast::<T>().unwrap())
} else {
Err(self)
}
}
}
impl<T: Tree + PartialEq> PartialEq<T> for dyn Tree {
fn eq(&self, other: &T) -> bool {
if let Some(tree) = self.downcast_ref::<T>() { tree == other } else { false }
}
}
impl Tree for () {}
impl Tree for char {}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct EndOfFile;
impl Tree for EndOfFile {}