fastn_type/evalexpr/tree/
iter.rs

1use fastn_type::evalexpr::ExprNode;
2use std::slice::Iter;
3
4/// An iterator that traverses an operator tree in pre-order.
5pub struct NodeIter<'a> {
6    stack: Vec<Iter<'a, ExprNode>>,
7}
8
9impl<'a> NodeIter<'a> {
10    fn new(node: &'a ExprNode) -> Self {
11        NodeIter {
12            stack: vec![node.children.iter()],
13        }
14    }
15}
16
17impl<'a> Iterator for NodeIter<'a> {
18    type Item = &'a ExprNode;
19
20    fn next(&mut self) -> Option<Self::Item> {
21        loop {
22            let mut result = None;
23
24            if let Some(last) = self.stack.last_mut() {
25                if let Some(next) = last.next() {
26                    result = Some(next);
27                } else {
28                    // Can not fail because we just borrowed last.
29                    // We just checked that the iterator is empty, so we can safely discard it.
30                    let _ = self.stack.pop().unwrap();
31                }
32            } else {
33                return None;
34            }
35
36            if let Some(result) = result {
37                self.stack.push(result.children.iter());
38                return Some(result);
39            }
40        }
41    }
42}
43
44impl ExprNode {
45    /// Returns an iterator over all nodes in this tree.
46    pub fn iter(&self) -> impl Iterator<Item = &ExprNode> {
47        NodeIter::new(self)
48    }
49}