add recursive walker (#16)

This commit is contained in:
Skyler Hawthorne
2025-06-01 13:11:15 -04:00
committed by GitHub
parent 07195d921c
commit 94f3c81d14
3 changed files with 111 additions and 0 deletions

View File

@@ -95,6 +95,14 @@ impl<'tree> Node<'tree> {
unsafe { ts_node_is_named(self.as_raw()) }
}
/// Returns true if and only if this node is contained "inside" the given
/// input range, i.e. either start_new > start_old and end_new <= end_old OR
/// start_new >= start_old and end_new < end_old
pub fn is_contained_within(&self, range: Range<u32>) -> bool {
(self.start_byte() > range.start && self.end_byte() <= range.end)
|| (self.start_byte() >= range.start && self.end_byte() < range.end)
}
/// Check if this node is *missing*.
///
/// Missing nodes are inserted by the parser in order to recover from

View File

@@ -1,5 +1,6 @@
use ::std::os::raw;
use std::cell::Cell;
use std::collections::VecDeque;
use std::ffi::{c_char, CStr};
use std::marker::PhantomData;
use std::{fmt, mem};
@@ -76,6 +77,10 @@ impl<'tree> TreeCursor<'tree> {
}
}
pub fn reset(&mut self, node: &Node<'tree>) {
unsafe { ts_tree_cursor_reset(&mut self.inner, node.as_raw()) }
}
pub fn node(&self) -> Node<'tree> {
unsafe { Node::from_raw(ts_tree_cursor_current_node(&self.inner)).unwrap_unchecked() }
}
@@ -109,6 +114,54 @@ impl Clone for TreeCursor<'_> {
}
}
impl<'tree> IntoIterator for &'tree mut TreeCursor<'tree> {
type Item = Node<'tree>;
type IntoIter = TreeRecursiveWalker<'tree>;
fn into_iter(self) -> Self::IntoIter {
let mut queue = VecDeque::new();
let root = self.node();
queue.push_back(root.clone());
TreeRecursiveWalker {
cursor: self,
queue,
root,
}
}
}
pub struct TreeRecursiveWalker<'tree> {
cursor: &'tree mut TreeCursor<'tree>,
queue: VecDeque<Node<'tree>>,
root: Node<'tree>,
}
impl<'tree> Iterator for TreeRecursiveWalker<'tree> {
type Item = Node<'tree>;
fn next(&mut self) -> Option<Self::Item> {
let current = self.cursor.node();
if current != self.root && self.cursor.goto_next_sibling() {
self.queue.push_back(current);
return Some(self.cursor.node());
}
while let Some(queued) = self.queue.pop_front() {
self.cursor.reset(&queued);
if !self.cursor.goto_first_child() {
continue;
}
return Some(self.cursor.node());
}
None
}
}
extern "C" {
/// Create a new tree cursor starting from the given node.
///

View File

@@ -1,3 +1,5 @@
use std::collections::VecDeque;
use crate::tree_sitter::Node;
use crate::{Layer, Syntax};
@@ -129,3 +131,51 @@ impl<'tree> Iterator for ChildIter<'_, 'tree> {
}
}
}
impl<'cursor, 'tree> IntoIterator for &'cursor mut TreeCursor<'tree> {
type Item = Node<'tree>;
type IntoIter = TreeRecursiveWalker<'cursor, 'tree>;
fn into_iter(self) -> Self::IntoIter {
let mut queue = VecDeque::new();
let root = self.node();
queue.push_back(root.clone());
TreeRecursiveWalker {
cursor: self,
queue,
root,
}
}
}
pub struct TreeRecursiveWalker<'cursor, 'tree> {
cursor: &'cursor mut TreeCursor<'tree>,
queue: VecDeque<Node<'tree>>,
root: Node<'tree>,
}
impl<'tree> Iterator for TreeRecursiveWalker<'_, 'tree> {
type Item = Node<'tree>;
fn next(&mut self) -> Option<Self::Item> {
let current = self.cursor.node();
if current != self.root && self.cursor.goto_next_sibling() {
self.queue.push_back(current);
return Some(self.cursor.node());
}
while let Some(queued) = self.queue.pop_front() {
self.cursor.cursor.reset(&queued);
if !self.cursor.goto_first_child() {
continue;
}
return Some(self.cursor.node());
}
None
}
}