welly_parser/
tree.rs

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