Processing Trees

Hey guys,

So, I'm running into a stack overflow issue (the literal one, not the helpful website variety). Essentially, I have a tree of data, similar to this;

#[derive(PartialEq, Debug, Clone)]
pub enum Tree {
    Leaf(String),
    Branch(vec<Tree>),
    Oasis {
        definitely: Tree,
        maybe: Option<Tree>,
    },
}

Now, I need to manipulate the values of this tree. To test this tree, I would do:

    #[test]
    fn test_modify() {
        let mut tests = vec![
            (Tree::Leaf("a"), Tree::Lead("b")),
            (
              Tree::Branch(vec![Tree::Leaf("a")]),
              Tree::Branch(vec![Tree::Leaf("b")]),
            ),
            (
                Tree::Oasis(
                    definitely: Tree::Branch(vec![Tree::Leaf("a")]),
                    maybe: Some(Tree::Branch(vec![Tree::Leaf("a")])),
                }),
                Tree::Oasis(
                    definitely: Tree::Branch(vec![Tree::Leaf("b")]),
                    maybe: Some(Tree::Branch(vec![Tree::Leaf("b")])),
                }),
            ),
        ];

        while !tests.is_empty() {
            let (input, expected) = tests.pop().unwrap();
            let modified = modify(input, Rc::new(RefCell::new(some_modifier_fun)));
            assert_eq!(modified, expected);
        }
    }

The modifier function might look like this:

pub fn modify<P: FnMut(Tree) -> Tree>(node: Tree, modifier: Rc<RefCell<P>>) -> Option<Tree> {
    match node {
        Tree::Branch(mut node) => {
            for i in 0..node.len() {
                let branch_node = node.swap_remove(i);
                if let Some(tree) = modify(branch_node, Rc::clone(&modifier)) {
                    node.insert(i, tree)
                }
            }
            Some((&mut *modifier.borrow_mut())(Tree::Branch(node)))
        }
        Tree::Leaf(node) => {
            if let Some(leaf_node) = modify(node, Rc::clone(&modifier)) {
                Some((&mut *modifier.borrow_mut())(Tree::Leaf(leaf_node)))
            } else {
                None
            }
        }
        Tree::Oasis {
            definitely,
            maybe,
        } => {
            if let Some(def) = modify(definitely, Rc::clone(&modifier)) {
                if maybe.is_some() {
                    if let Some(mb) = modify(maybe.unwrap(), Rc::clone(&modifier)) {
                        Some((&mut *modifier.borrow_mut())(Tree::Oasis {
                               definitely: def,
                               maybe: Some(mb),
                        }))
                   } else {
                        None
                   }
               } else {
                   Some((&mut *modifier.borrow_mut())(Tree::Oasis {
                       definitely: def,
                       maybe: None,
                    }))
                } else {
                    None
                }
            } else {
                None
            }
        }
        _ => Some((&mut *modifier.borrow_mut())(node)),
    }
}

(Please excuse any mistakes. This is freehand)

The problem, here, is that, since the modify function is recursively called to process the tree, I quite quickly hit a stack overflow problem. My question, therefore, is how do I best process a tree such as this?

Many thanks,
JRod

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.