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 | /// Look at the parent node. |
125 | pub(crate) fn peek_up(&self) -> Option<TreeIndex> { |
126 | self.spine.last().copied() |
127 | } |
128 | |
129 | /// Look at grandparent node. |
130 | pub(crate) fn peek_grandparent(&self) -> Option<TreeIndex> { |
131 | if self.spine.len() >= 2 { |
132 | Some(self.spine[self.spine.len() - 2]) |
133 | } else { |
134 | None |
135 | } |
136 | } |
137 | |
138 | /// Returns true when there are no nodes other than the root node |
139 | /// in the tree, false otherwise. |
140 | pub(crate) fn is_empty(&self) -> bool { |
141 | self.nodes.len() <= 1 |
142 | } |
143 | |
144 | /// Returns the length of the spine. |
145 | pub(crate) fn spine_len(&self) -> usize { |
146 | self.spine.len() |
147 | } |
148 | |
149 | /// Resets the focus to the first node added to the tree, if it exists. |
150 | pub(crate) fn reset(&mut self) { |
151 | self.cur = if self.is_empty() { |
152 | None |
153 | } else { |
154 | Some(TreeIndex::new(1)) |
155 | }; |
156 | self.spine.clear(); |
157 | } |
158 | |
159 | /// Walks the spine from a root node up to, but not including, the current node. |
160 | pub(crate) fn walk_spine(&self) -> impl std::iter::DoubleEndedIterator<Item = &TreeIndex> { |
161 | self.spine.iter() |
162 | } |
163 | |
164 | /// Moves focus to the next sibling of the given node. |
165 | pub(crate) fn next_sibling(&mut self, cur_ix: TreeIndex) -> Option<TreeIndex> { |
166 | self.cur = self[cur_ix].next; |
167 | self.cur |
168 | } |
169 | } |
170 | |
171 | impl Tree<Item> { |
172 | /// Truncates the preceding siblings to the given end position, |
173 | /// and returns the new current node. |
174 | pub(crate) fn truncate_siblings(&mut self, bytes: &[u8], end_byte_ix: usize) { |
175 | let parent_ix = self.peek_up().unwrap(); |
176 | let mut next_child_ix = self[parent_ix].child; |
177 | let mut prev_child_ix = None; |
178 | |
179 | // drop or truncate children based on its range |
180 | while let Some(child_ix) = next_child_ix { |
181 | let child_end = self[child_ix].item.end; |
182 | if child_end < end_byte_ix { |
183 | // preserve this node, and go to the next |
184 | prev_child_ix = Some(child_ix); |
185 | next_child_ix = self[child_ix].next; |
186 | continue; |
187 | } else if child_end == end_byte_ix { |
188 | // this will be the last node |
189 | self[child_ix].next = None; |
190 | // focus to the new last child (this node) |
191 | self.cur = Some(child_ix); |
192 | } else if self[child_ix].item.start == end_byte_ix { |
193 | // check whether the previous character is a backslash |
194 | let is_previous_char_backslash_escape = |
195 | end_byte_ix.checked_sub(1).map_or(false, |prev| { |
196 | (bytes[prev] == b' \\' ) && (self[child_ix].item.body == ItemBody::Text) |
197 | }); |
198 | if is_previous_char_backslash_escape { |
199 | // rescue the backslash as a plain text content |
200 | let last_byte_ix = end_byte_ix - 1; |
201 | self[child_ix].item.start = last_byte_ix; |
202 | self[child_ix].item.end = end_byte_ix; |
203 | self.cur = Some(child_ix); |
204 | } else if let Some(prev_child_ix) = prev_child_ix { |
205 | // the node will become empty. drop the node |
206 | // a preceding sibling exists |
207 | self[prev_child_ix].next = None; |
208 | self.cur = Some(prev_child_ix); |
209 | } else { |
210 | // no preceding siblings. remove the node from the parent |
211 | self[parent_ix].child = None; |
212 | self.cur = None; |
213 | } |
214 | } else { |
215 | debug_assert!(self[child_ix].item.start < end_byte_ix); |
216 | debug_assert!(end_byte_ix < child_end); |
217 | // truncate the node |
218 | self[child_ix].item.end = end_byte_ix; |
219 | self[child_ix].next = None; |
220 | // focus to the new last child |
221 | self.cur = Some(child_ix); |
222 | } |
223 | break; |
224 | } |
225 | } |
226 | } |
227 | |
228 | impl<T> std::fmt::Debug for Tree<T> |
229 | where |
230 | T: std::fmt::Debug, |
231 | { |
232 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
233 | fn debug_tree<T>( |
234 | tree: &Tree<T>, |
235 | cur: TreeIndex, |
236 | indent: usize, |
237 | f: &mut std::fmt::Formatter, |
238 | ) -> std::fmt::Result |
239 | where |
240 | T: std::fmt::Debug, |
241 | { |
242 | for _ in 0..indent { |
243 | write!(f, " " )?; |
244 | } |
245 | writeln!(f, " {:?}" , &tree[cur].item)?; |
246 | if let Some(child_ix) = tree[cur].child { |
247 | debug_tree(tree, child_ix, indent + 1, f)?; |
248 | } |
249 | if let Some(next_ix) = tree[cur].next { |
250 | debug_tree(tree, next_ix, indent, f)?; |
251 | } |
252 | Ok(()) |
253 | } |
254 | |
255 | if self.nodes.len() > 1 { |
256 | let cur = TreeIndex(NonZeroUsize::new(1).unwrap()); |
257 | debug_tree(self, cur, 0, f) |
258 | } else { |
259 | write!(f, "Empty tree" ) |
260 | } |
261 | } |
262 | } |
263 | |
264 | impl<T> std::ops::Index<TreeIndex> for Tree<T> { |
265 | type Output = Node<T>; |
266 | |
267 | fn index(&self, ix: TreeIndex) -> &Self::Output { |
268 | self.nodes.index(ix.get()) |
269 | } |
270 | } |
271 | |
272 | impl<T> std::ops::IndexMut<TreeIndex> for Tree<T> { |
273 | fn index_mut(&mut self, ix: TreeIndex) -> &mut Node<T> { |
274 | self.nodes.index_mut(index:ix.get()) |
275 | } |
276 | } |
277 | |