diff options
Diffstat (limited to 'src/traverse.rs')
-rw-r--r-- | src/traverse.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/traverse.rs b/src/traverse.rs new file mode 100644 index 0000000..df13f5d --- /dev/null +++ b/src/traverse.rs | |||
@@ -0,0 +1,51 @@ | |||
1 | // Lazy pre-order traversal over arbitrary tree-sitter trees | ||
2 | |||
3 | // extern | ||
4 | use tree_sitter::{Node, Tree, TreeCursor}; | ||
5 | |||
6 | pub struct PreOrder<'a> { | ||
7 | cursor: TreeCursor<'a>, | ||
8 | done: bool, | ||
9 | } | ||
10 | |||
11 | impl<'a> PreOrder<'a> { | ||
12 | pub fn new(tree: &'a Tree) -> Self { | ||
13 | Self { | ||
14 | cursor: tree.walk(), | ||
15 | done: false, | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | |||
20 | // Traverse the tree in root-left-right fashion | ||
21 | impl<'a> Iterator for PreOrder<'a> { | ||
22 | type Item = Node<'a>; | ||
23 | |||
24 | fn next(&mut self) -> Option<Self::Item> { | ||
25 | if self.done { | ||
26 | return None; | ||
27 | } | ||
28 | |||
29 | // capture the root node | ||
30 | let node = self.cursor.node(); | ||
31 | |||
32 | // if this node has a child, move there and return the root, or | ||
33 | // if this node has a sibling, move there and return the root | ||
34 | if self.cursor.goto_first_child() || self.cursor.goto_next_sibling() { | ||
35 | return Some(node); | ||
36 | } | ||
37 | |||
38 | loop { | ||
39 | // we are done retracing all the way back to the root node | ||
40 | if !self.cursor.goto_parent() { | ||
41 | self.done = true; | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | if self.cursor.goto_next_sibling() { | ||
46 | break; | ||
47 | } | ||
48 | } | ||
49 | Some(node) | ||
50 | } | ||
51 | } | ||