summaryrefslogtreecommitdiff
path: root/src/traverser.cc
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2011-11-25 21:41:36 (GMT)
committerMarius Kintel <marius@kintel.net>2011-11-25 21:41:36 (GMT)
commit60e4c81b4304d40d2e77990d746a9e387d1637d7 (patch)
treedfe5bfa4afc435496fe2bf1cdbf1626fcebbc2f5 /src/traverser.cc
parent7996b8ed8d84be9c95ff083973754b4d85eb2d42 (diff)
Support for traversal pruning and abortion
Diffstat (limited to 'src/traverser.cc')
-rw-r--r--src/traverser.cc47
1 files changed, 25 insertions, 22 deletions
diff --git a/src/traverser.cc b/src/traverser.cc
index a87449b..d9b3dc1 100644
--- a/src/traverser.cc
+++ b/src/traverser.cc
@@ -3,6 +3,7 @@
#include "node.h"
#include "state.h"
#include <algorithm>
+#include <boost/foreach.hpp>
void Traverser::execute()
{
@@ -10,35 +11,37 @@ void Traverser::execute()
traverse(this->root, state);
}
-struct TraverseNode
+Response Traverser::traverse(const AbstractNode &node, const State &state)
{
- Traverser *traverser;
- const State &state;
- TraverseNode(Traverser *traverser, const State &state) :
- traverser(traverser), state(state) {}
- void operator()(const AbstractNode *node) { traverser->traverse(*node, state); }
-};
-
-void Traverser::traverse(const AbstractNode &node, const State &state)
-{
- // FIXME: Handle abort
-
State newstate = state;
newstate.setNumChildren(node.getChildren().size());
+ Response response;
if (traversaltype == PREFIX || traversaltype == PRE_AND_POSTFIX) {
newstate.setPrefix(true);
newstate.setParent(state.parent());
- node.accept(newstate, this->visitor);
+ response = node.accept(newstate, this->visitor);
}
-
- newstate.setParent(&node);
- std::for_each(node.getChildren().begin(), node.getChildren().end(), TraverseNode(this, newstate));
-
- if (traversaltype == POSTFIX || traversaltype == PRE_AND_POSTFIX) {
- newstate.setParent(state.parent());
- newstate.setPrefix(false);
- newstate.setPostfix(true);
- node.accept(newstate, this->visitor);
+
+ // Pruned traversals mean don't traverse children
+ if (response == ContinueTraversal) {
+ newstate.setParent(&node);
+ BOOST_FOREACH(const AbstractNode *chnode, node.getChildren()) {
+ response = this->traverse(*chnode, newstate);
+ if (response == AbortTraversal) return response; // Abort immediately
+ }
}
+
+ // Postfix is executed for all non-aborted traversals
+ if (response != AbortTraversal) {
+ if (traversaltype == POSTFIX || traversaltype == PRE_AND_POSTFIX) {
+ newstate.setParent(state.parent());
+ newstate.setPrefix(false);
+ newstate.setPostfix(true);
+ response = node.accept(newstate, this->visitor);
+ }
+ }
+
+ if (response != AbortTraversal) response = ContinueTraversal;
+ return response;
}
contact: Jan Huwald // Impressum