welly_parser/tree.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use std::any::{Any};
use std::{fmt};
/// Object-safe methods for turning `self` into `dyn Any`.
///
/// These are blanket-implemented for all [`Sized`] types.
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 }
}
// ----------------------------------------------------------------------------
/// A type that represents a parse tree.
///
/// There are many types that implement `Tree`. It would be inconvenient to
/// define an `enum` that can contain any of them. Instead, we use `dyn Tree`.
/// You can use the methods of `dyn Tree` to match its actual type:
///
/// ```
/// use welly_parser::{Tree};
///
/// // Invent a new kind of `Tree`.
/// #[derive(Debug)]
/// struct Fruit(&'static str);
/// impl Tree for Fruit {}
///
/// // An example `Fruit` wrapped as a `dyn Tree`.
/// let tree: Box<dyn Tree> = Box::new(Fruit("Apple"));
///
/// // Test whether `tree` is a `Fruit`.
/// let is_fruit: bool = tree.is::<Fruit>();
/// println!("{}", is_fruit);
///
/// // Borrow the `Fruit`.
/// let borrowed_fruit: Option<&Fruit> = tree.downcast_ref::<Fruit>();
/// println!("{}", borrowed_fruit.expect("Not a Fruit").0);
///
/// // Move the `Fruit`.
/// let owned_fruit: Result<Box<Fruit>, Box<dyn Tree>> = tree.downcast::<Fruit>();
/// println!("{}", owned_fruit.expect("Not a Fruit").0);
/// ```
pub trait Tree: fmt::Debug + AsAny {
/// `declare()` all the keywords whose parse trees are `Self`s.
///
/// The default implementation declares no keywords.
fn declare_keywords(#[allow(unused)] declare: impl FnMut(&'static str, Self)) where Self: Sized {}
}
impl dyn Tree {
/// Returns `true` if the actual type of `self` is `T`.
pub fn is<T: Tree>(&self) -> bool { self.as_any().is::<T>() }
/// Returns `Some` if the actual type of `self` is `T`.
pub fn downcast_ref<T: Tree>(&self) -> Option<&T> { self.as_any().downcast_ref::<T>() }
/// Returns `Ok` if the actual type of `self` is `T`.
pub fn downcast<T: Tree>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
if (*self).is::<T>() {
// Annoying that we have to check the type a second time.
// However, this second check must not fail, otherwise we will have
// a `dyn Any` that we can't turn back into a `dyn Tree`.
Ok(self.to_any().downcast::<T>().unwrap())
} else {
Err(self)
}
}
}
impl Tree for () {}
impl Tree for char {}
// ----------------------------------------------------------------------------
/// Represents the end of the source code.
///
/// Parsers must return this [`Tree`] unchanged. It must never be incorporated
/// into a larger `Tree`.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct EndOfFile;
impl Tree for EndOfFile {}