use crate::{
Language,
tree::red_tree::{RedLeaf, RedNode, RedTree},
};
pub trait Visitor<'a, L: Language> {
fn visit_node(&mut self, node: RedNode<'a, L>);
fn visit_token(&mut self, token: RedLeaf<L>);
fn walk_node(&mut self, node: RedNode<'a, L>) {
for child in node.children() {
match child {
RedTree::Node(n) => self.visit_node(n),
RedTree::Leaf(t) => self.visit_token(t),
}
}
}
}
pub struct PreOrder<'a, L: Language> {
stack: Vec<RedTree<'a, L>>,
}
impl<'a, L: Language> PreOrder<'a, L> {
pub fn new(root: RedTree<'a, L>) -> Self {
Self { stack: vec![root] }
}
}
impl<'a, L: Language> Iterator for PreOrder<'a, L> {
type Item = RedTree<'a, L>;
fn next(&mut self) -> Option<Self::Item> {
let next = self.stack.pop()?;
if let RedTree::Node(node) = next {
let children = node.green.children();
let mut offset = node.offset + node.green.text_len() as usize;
for child in children.iter().rev() {
offset -= child.len() as usize;
match child {
crate::GreenTree::Node(n) => self.stack.push(RedTree::Node(RedNode::new(n, offset))),
crate::GreenTree::Leaf(t) => self.stack.push(RedTree::Leaf(RedLeaf { kind: t.kind, span: core::range::Range { start: offset, end: offset + t.length as usize } })),
}
}
}
Some(next)
}
}