treebender/
syntree.rs

1use std::fmt;
2
3#[derive(Debug, PartialEq, Clone)]
4pub struct Constituent<T> {
5  pub value: T,
6  pub span: (usize, usize),
7}
8
9impl<T> fmt::Display for Constituent<T>
10where
11  T: fmt::Display,
12{
13  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14    write!(f, "{}..{}: {}", self.span.0, self.span.1, self.value)
15  }
16}
17
18#[derive(Debug, PartialEq, Clone)]
19pub struct Word<U> {
20  pub value: U,
21  pub span: (usize, usize),
22}
23
24impl<U> fmt::Display for Word<U>
25where
26  U: fmt::Display,
27{
28  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29    write!(f, "{}..{}: {}", self.span.0, self.span.1, self.value)
30  }
31}
32
33#[derive(Debug, PartialEq, Clone)]
34pub enum SynTree<T, U> {
35  Branch(Constituent<T>, Vec<SynTree<T, U>>),
36  Leaf(Word<U>),
37}
38
39impl<T, U> SynTree<T, U> {
40  pub fn is_leaf(&self) -> bool {
41    match self {
42      Self::Leaf(_) => true,
43      _ => false,
44    }
45  }
46
47  pub fn is_branch(&self) -> bool {
48    match self {
49      Self::Branch(_, _) => true,
50      _ => false,
51    }
52  }
53
54  pub fn get_leaf(&self) -> Option<&Word<U>> {
55    match self {
56      Self::Leaf(w) => Some(w),
57      _ => None,
58    }
59  }
60
61  pub fn get_branch(&self) -> Option<(&Constituent<T>, &Vec<SynTree<T, U>>)> {
62    match self {
63      Self::Branch(c, cs) => Some((c, cs)),
64      _ => None,
65    }
66  }
67
68  pub fn into_branch(self) -> Option<(Constituent<T>, Vec<SynTree<T, U>>)> {
69    match self {
70      Self::Branch(c, cs) => Some((c, cs)),
71      _ => None,
72    }
73  }
74
75  pub fn map<V, W>(
76    &self,
77    map_branch: fn(&Constituent<T>) -> V,
78    map_leaf: fn(&Word<U>) -> W,
79  ) -> SynTree<V, W> {
80    match self {
81      Self::Branch(t, children) => {
82        let children = children
83          .iter()
84          .map(|c| c.map(map_branch, map_leaf))
85          .collect::<Vec<_>>();
86        SynTree::Branch(
87          Constituent {
88            span: t.span,
89            value: map_branch(&t),
90          },
91          children,
92        )
93      }
94      Self::Leaf(u) => SynTree::Leaf(Word {
95        span: u.span,
96        value: map_leaf(u),
97      }),
98    }
99  }
100}
101
102impl<T, U> fmt::Display for SynTree<T, U>
103where
104  T: fmt::Display,
105  U: fmt::Display,
106{
107  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108    match self {
109      Self::Leaf(t) => write!(f, "{}", t),
110      Self::Branch(t, ts) => {
111        write!(f, "({}", t)?;
112        if ts.len() == 1 {
113          write!(f, " ({}))", ts[0])
114        } else {
115          for t in ts.iter() {
116            // TODO: is there a nice way to do this that doesn't allocate a String?
117            let fmt = format!("{}", t);
118            for line in fmt.lines() {
119              write!(f, "\n  {}", line)?;
120            }
121          }
122          write!(f, ")")
123        }
124      }
125    }
126  }
127}