Skip to content

Commit 94f3c81

Browse files
authored
add recursive walker (#16)
1 parent 07195d9 commit 94f3c81

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

bindings/src/node.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ impl<'tree> Node<'tree> {
9595
unsafe { ts_node_is_named(self.as_raw()) }
9696
}
9797

98+
/// Returns true if and only if this node is contained "inside" the given
99+
/// input range, i.e. either start_new > start_old and end_new <= end_old OR
100+
/// start_new >= start_old and end_new < end_old
101+
pub fn is_contained_within(&self, range: Range<u32>) -> bool {
102+
(self.start_byte() > range.start && self.end_byte() <= range.end)
103+
|| (self.start_byte() >= range.start && self.end_byte() < range.end)
104+
}
105+
98106
/// Check if this node is *missing*.
99107
///
100108
/// Missing nodes are inserted by the parser in order to recover from

bindings/src/tree_cursor.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use ::std::os::raw;
22
use std::cell::Cell;
3+
use std::collections::VecDeque;
34
use std::ffi::{c_char, CStr};
45
use std::marker::PhantomData;
56
use std::{fmt, mem};
@@ -76,6 +77,10 @@ impl<'tree> TreeCursor<'tree> {
7677
}
7778
}
7879

80+
pub fn reset(&mut self, node: &Node<'tree>) {
81+
unsafe { ts_tree_cursor_reset(&mut self.inner, node.as_raw()) }
82+
}
83+
7984
pub fn node(&self) -> Node<'tree> {
8085
unsafe { Node::from_raw(ts_tree_cursor_current_node(&self.inner)).unwrap_unchecked() }
8186
}
@@ -109,6 +114,54 @@ impl Clone for TreeCursor<'_> {
109114
}
110115
}
111116

117+
impl<'tree> IntoIterator for &'tree mut TreeCursor<'tree> {
118+
type Item = Node<'tree>;
119+
type IntoIter = TreeRecursiveWalker<'tree>;
120+
121+
fn into_iter(self) -> Self::IntoIter {
122+
let mut queue = VecDeque::new();
123+
let root = self.node();
124+
queue.push_back(root.clone());
125+
126+
TreeRecursiveWalker {
127+
cursor: self,
128+
queue,
129+
root,
130+
}
131+
}
132+
}
133+
134+
pub struct TreeRecursiveWalker<'tree> {
135+
cursor: &'tree mut TreeCursor<'tree>,
136+
queue: VecDeque<Node<'tree>>,
137+
root: Node<'tree>,
138+
}
139+
140+
impl<'tree> Iterator for TreeRecursiveWalker<'tree> {
141+
type Item = Node<'tree>;
142+
143+
fn next(&mut self) -> Option<Self::Item> {
144+
let current = self.cursor.node();
145+
146+
if current != self.root && self.cursor.goto_next_sibling() {
147+
self.queue.push_back(current);
148+
return Some(self.cursor.node());
149+
}
150+
151+
while let Some(queued) = self.queue.pop_front() {
152+
self.cursor.reset(&queued);
153+
154+
if !self.cursor.goto_first_child() {
155+
continue;
156+
}
157+
158+
return Some(self.cursor.node());
159+
}
160+
161+
None
162+
}
163+
}
164+
112165
extern "C" {
113166
/// Create a new tree cursor starting from the given node.
114167
///

highlighter/src/tree_cursor.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::VecDeque;
2+
13
use crate::tree_sitter::Node;
24
use crate::{Layer, Syntax};
35

@@ -129,3 +131,51 @@ impl<'tree> Iterator for ChildIter<'_, 'tree> {
129131
}
130132
}
131133
}
134+
135+
impl<'cursor, 'tree> IntoIterator for &'cursor mut TreeCursor<'tree> {
136+
type Item = Node<'tree>;
137+
type IntoIter = TreeRecursiveWalker<'cursor, 'tree>;
138+
139+
fn into_iter(self) -> Self::IntoIter {
140+
let mut queue = VecDeque::new();
141+
let root = self.node();
142+
queue.push_back(root.clone());
143+
144+
TreeRecursiveWalker {
145+
cursor: self,
146+
queue,
147+
root,
148+
}
149+
}
150+
}
151+
152+
pub struct TreeRecursiveWalker<'cursor, 'tree> {
153+
cursor: &'cursor mut TreeCursor<'tree>,
154+
queue: VecDeque<Node<'tree>>,
155+
root: Node<'tree>,
156+
}
157+
158+
impl<'tree> Iterator for TreeRecursiveWalker<'_, 'tree> {
159+
type Item = Node<'tree>;
160+
161+
fn next(&mut self) -> Option<Self::Item> {
162+
let current = self.cursor.node();
163+
164+
if current != self.root && self.cursor.goto_next_sibling() {
165+
self.queue.push_back(current);
166+
return Some(self.cursor.node());
167+
}
168+
169+
while let Some(queued) = self.queue.pop_front() {
170+
self.cursor.cursor.reset(&queued);
171+
172+
if !self.cursor.goto_first_child() {
173+
continue;
174+
}
175+
176+
return Some(self.cursor.node());
177+
}
178+
179+
None
180+
}
181+
}

0 commit comments

Comments
 (0)