| 1 | // Copyright 2018 Google LLC |
| 2 | // |
| 3 | // Use of this source code is governed by an MIT-style |
| 4 | // license that can be found in the LICENSE file or at |
| 5 | // https://opensource.org/licenses/MIT. |
| 6 | |
| 7 | //! A Vec-based container for a tree structure. |
| 8 | |
| 9 | use std::num::NonZeroUsize; |
| 10 | use std::ops::{Add, Sub}; |
| 11 | |
| 12 | use crate::parse::{Item, ItemBody}; |
| 13 | |
| 14 | #[derive (Debug, Eq, PartialEq, Copy, Clone, PartialOrd)] |
| 15 | pub(crate) struct TreeIndex(NonZeroUsize); |
| 16 | |
| 17 | impl TreeIndex { |
| 18 | fn new(i: usize) -> Self { |
| 19 | TreeIndex(NonZeroUsize::new(i).unwrap()) |
| 20 | } |
| 21 | |
| 22 | pub fn get(self) -> usize { |
| 23 | self.0.get() |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | impl Add<usize> for TreeIndex { |
| 28 | type Output = TreeIndex; |
| 29 | |
| 30 | fn add(self, rhs: usize) -> Self { |
| 31 | let inner: usize = self.0.get() + rhs; |
| 32 | TreeIndex::new(inner) |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | impl Sub<usize> for TreeIndex { |
| 37 | type Output = TreeIndex; |
| 38 | |
| 39 | fn sub(self, rhs: usize) -> Self { |
| 40 | let inner: usize = self.0.get().checked_sub(rhs).unwrap(); |
| 41 | TreeIndex::new(inner) |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | #[derive (Debug, Clone, Copy)] |
| 46 | pub(crate) struct Node<T> { |
| 47 | pub child: Option<TreeIndex>, |
| 48 | pub next: Option<TreeIndex>, |
| 49 | pub item: T, |
| 50 | } |
| 51 | |
| 52 | /// A tree abstraction, intended for fast building as a preorder traversal. |
| 53 | #[derive (Clone)] |
| 54 | pub(crate) struct Tree<T> { |
| 55 | nodes: Vec<Node<T>>, |
| 56 | spine: Vec<TreeIndex>, // indices of nodes on path to current node |
| 57 | cur: Option<TreeIndex>, |
| 58 | } |
| 59 | |
| 60 | impl<T: Default> Tree<T> { |
| 61 | // Indices start at one, so we place a dummy value at index zero. |
| 62 | // The alternative would be subtracting one from every TreeIndex |
| 63 | // every time we convert it to usize to index our nodes. |
| 64 | pub(crate) fn with_capacity(cap: usize) -> Tree<T> { |
| 65 | let mut nodes = Vec::with_capacity(cap); |
| 66 | nodes.push(Node { |
| 67 | child: None, |
| 68 | next: None, |
| 69 | item: <T as Default>::default(), |
| 70 | }); |
| 71 | Tree { |
| 72 | nodes, |
| 73 | spine: Vec::new(), |
| 74 | cur: None, |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | /// Returns the index of the element currently in focus. |
| 79 | pub(crate) fn cur(&self) -> Option<TreeIndex> { |
| 80 | self.cur |
| 81 | } |
| 82 | |
| 83 | /// Append one item to the current position in the tree. |
| 84 | pub(crate) fn append(&mut self, item: T) -> TreeIndex { |
| 85 | let ix = self.create_node(item); |
| 86 | let this = Some(ix); |
| 87 | |
| 88 | if let Some(ix) = self.cur { |
| 89 | self[ix].next = this; |
| 90 | } else if let Some(&parent) = self.spine.last() { |
| 91 | self[parent].child = this; |
| 92 | } |
| 93 | self.cur = this; |
| 94 | ix |
| 95 | } |
| 96 | |
| 97 | /// Create an isolated node. |
| 98 | pub(crate) fn create_node(&mut self, item: T) -> TreeIndex { |
| 99 | let this = self.nodes.len(); |
| 100 | self.nodes.push(Node { |
| 101 | child: None, |
| 102 | next: None, |
| 103 | item, |
| 104 | }); |
| 105 | TreeIndex::new(this) |
| 106 | } |
| 107 | |
| 108 | /// Push down one level, so that new items become children of the current node. |
| 109 | /// The new focus index is returned. |
| 110 | pub(crate) fn push(&mut self) -> TreeIndex { |
| 111 | let cur_ix = self.cur.unwrap(); |
| 112 | self.spine.push(cur_ix); |
| 113 | self.cur = self[cur_ix].child; |
| 114 | cur_ix |
| 115 | } |
| 116 | |
| 117 | /// Pop back up a level. |
| 118 | pub(crate) fn pop(&mut self) -> Option<TreeIndex> { |
| 119 | let ix = Some(self.spine.pop()?); |
| 120 | self.cur = ix; |
| 121 | ix |
| 122 | } |
| 123 | |
| 124 | /// Remove the last node, as `pop` but removing it. |
| 125 | pub(crate) fn remove_node(&mut self) -> Option<TreeIndex> { |
| 126 | let ix = self.spine.pop()?; |
| 127 | self.cur = Some(ix); |
| 128 | self.nodes.pop()?; |
| 129 | self[ix].child = None; |
| 130 | Some(ix) |
| 131 | } |
| 132 | |
| 133 | /// Look at the parent node. |
| 134 | pub(crate) fn peek_up(&self) -> Option<TreeIndex> { |
| 135 | self.spine.last().copied() |
| 136 | } |
| 137 | |
| 138 | /// Look at grandparent node. |
| 139 | pub(crate) fn peek_grandparent(&self) -> Option<TreeIndex> { |
| 140 | if self.spine.len() >= 2 { |
| 141 | Some(self.spine[self.spine.len() - 2]) |
| 142 | } else { |
| 143 | None |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | /// Returns true when there are no nodes other than the root node |
| 148 | /// in the tree, false otherwise. |
| 149 | pub(crate) fn is_empty(&self) -> bool { |
| 150 | self.nodes.len() <= 1 |
| 151 | } |
| 152 | |
| 153 | /// Returns the length of the spine. |
| 154 | pub(crate) fn spine_len(&self) -> usize { |
| 155 | self.spine.len() |
| 156 | } |
| 157 | |
| 158 | /// Resets the focus to the first node added to the tree, if it exists. |
| 159 | pub(crate) fn reset(&mut self) { |
| 160 | self.cur = if self.is_empty() { |
| 161 | None |
| 162 | } else { |
| 163 | Some(TreeIndex::new(1)) |
| 164 | }; |
| 165 | self.spine.clear(); |
| 166 | } |
| 167 | |
| 168 | /// Walks the spine from a root node up to, but not including, the current node. |
| 169 | pub(crate) fn walk_spine(&self) -> impl std::iter::DoubleEndedIterator<Item = &TreeIndex> { |
| 170 | self.spine.iter() |
| 171 | } |
| 172 | |
| 173 | /// Moves focus to the next sibling of the given node. |
| 174 | pub(crate) fn next_sibling(&mut self, cur_ix: TreeIndex) -> Option<TreeIndex> { |
| 175 | self.cur = self[cur_ix].next; |
| 176 | self.cur |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | impl Tree<Item> { |
| 181 | /// Truncates the preceding siblings to the given end position, |
| 182 | /// and returns the new current node. |
| 183 | pub(crate) fn truncate_siblings(&mut self, end_byte_ix: usize) { |
| 184 | let parent_ix = self.peek_up().unwrap(); |
| 185 | let mut next_child_ix = self[parent_ix].child; |
| 186 | let mut prev_child_ix = None; |
| 187 | |
| 188 | // drop or truncate children based on its range |
| 189 | while let Some(child_ix) = next_child_ix { |
| 190 | let child_end = self[child_ix].item.end; |
| 191 | if child_end < end_byte_ix { |
| 192 | // preserve this node, and go to the next |
| 193 | prev_child_ix = Some(child_ix); |
| 194 | next_child_ix = self[child_ix].next; |
| 195 | continue; |
| 196 | } else if child_end == end_byte_ix { |
| 197 | // this will be the last node |
| 198 | self[child_ix].next = None; |
| 199 | // focus to the new last child (this node) |
| 200 | self.cur = Some(child_ix); |
| 201 | } else if self[child_ix].item.start == end_byte_ix { |
| 202 | // check whether the previous character is a backslash |
| 203 | let is_previous_char_backslash_escape = match self[child_ix].item.body { |
| 204 | ItemBody::Text { backslash_escaped } => backslash_escaped, |
| 205 | _ => false, |
| 206 | }; |
| 207 | if is_previous_char_backslash_escape { |
| 208 | // rescue the backslash as a plain text content |
| 209 | let last_byte_ix = end_byte_ix - 1; |
| 210 | self[child_ix].item.start = last_byte_ix; |
| 211 | self[child_ix].item.end = end_byte_ix; |
| 212 | self.cur = Some(child_ix); |
| 213 | } else if let Some(prev_child_ix) = prev_child_ix { |
| 214 | // the node will become empty. drop the node |
| 215 | // a preceding sibling exists |
| 216 | self[prev_child_ix].next = None; |
| 217 | self.cur = Some(prev_child_ix); |
| 218 | } else { |
| 219 | // no preceding siblings. remove the node from the parent |
| 220 | self[parent_ix].child = None; |
| 221 | self.cur = None; |
| 222 | } |
| 223 | } else { |
| 224 | debug_assert!(self[child_ix].item.start < end_byte_ix); |
| 225 | debug_assert!(end_byte_ix < child_end); |
| 226 | // truncate the node |
| 227 | self[child_ix].item.end = end_byte_ix; |
| 228 | self[child_ix].next = None; |
| 229 | // focus to the new last child |
| 230 | self.cur = Some(child_ix); |
| 231 | } |
| 232 | break; |
| 233 | } |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | impl<T> std::fmt::Debug for Tree<T> |
| 238 | where |
| 239 | T: std::fmt::Debug, |
| 240 | { |
| 241 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 242 | fn debug_tree<T>( |
| 243 | tree: &Tree<T>, |
| 244 | cur: TreeIndex, |
| 245 | indent: usize, |
| 246 | f: &mut std::fmt::Formatter<'_>, |
| 247 | ) -> std::fmt::Result |
| 248 | where |
| 249 | T: std::fmt::Debug, |
| 250 | { |
| 251 | for _ in 0..indent { |
| 252 | write!(f, " " )?; |
| 253 | } |
| 254 | writeln!(f, " {:?}" , &tree[cur].item)?; |
| 255 | if let Some(child_ix) = tree[cur].child { |
| 256 | debug_tree(tree, child_ix, indent + 1, f)?; |
| 257 | } |
| 258 | if let Some(next_ix) = tree[cur].next { |
| 259 | debug_tree(tree, next_ix, indent, f)?; |
| 260 | } |
| 261 | Ok(()) |
| 262 | } |
| 263 | |
| 264 | if self.nodes.len() > 1 { |
| 265 | let cur = TreeIndex(NonZeroUsize::new(1).unwrap()); |
| 266 | debug_tree(self, cur, 0, f) |
| 267 | } else { |
| 268 | write!(f, "Empty tree" ) |
| 269 | } |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | impl<T> std::ops::Index<TreeIndex> for Tree<T> { |
| 274 | type Output = Node<T>; |
| 275 | |
| 276 | fn index(&self, ix: TreeIndex) -> &Self::Output { |
| 277 | self.nodes.index(ix.get()) |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | impl<T> std::ops::IndexMut<TreeIndex> for Tree<T> { |
| 282 | fn index_mut(&mut self, ix: TreeIndex) -> &mut Node<T> { |
| 283 | self.nodes.index_mut(index:ix.get()) |
| 284 | } |
| 285 | } |
| 286 | |