summaryrefslogtreecommitdiff
path: root/src/nodedumper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nodedumper.cc')
-rw-r--r--src/nodedumper.cc103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/nodedumper.cc b/src/nodedumper.cc
new file mode 100644
index 0000000..d75c703
--- /dev/null
+++ b/src/nodedumper.cc
@@ -0,0 +1,103 @@
+#include "nodedumper.h"
+#include <string>
+#include <map>
+#include <list>
+#include "visitor.h"
+#include "state.h"
+#include "nodecache.h"
+
+#include <sstream>
+#include <iostream>
+#include <assert.h>
+
+/*!
+ \class NodeDumper
+
+ A visitor responsible for creating a text dump of a node tree. Also
+ contains a cache for fast retrieval of the text representation of
+ any node or subtree.
+*/
+
+bool NodeDumper::isCached(const AbstractNode &node) const
+{
+ return !this->cache[node].empty();
+}
+
+/*!
+ Indent or deindent. Must be called before we output any children.
+*/
+void NodeDumper::handleIndent(const State &state)
+{
+ if (state.isPrefix()) {
+ this->currindent += "\t";
+ }
+ else if (state.isPostfix()) {
+ this->currindent.erase((this->currindent.length() >= 1) ?
+ this->currindent.length() - 1 : 0);
+ }
+}
+
+/*!
+ Dumps the block of children contained in this->visitedchildren,
+ including braces and indentation.
+ All children are assumed to be cached already.
+ */
+string NodeDumper::dumpChildren(const AbstractNode &node)
+{
+ std::stringstream dump;
+ if (!this->visitedchildren[node.index()].empty()) {
+ dump << " {\n";
+
+ for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
+ iter != this->visitedchildren[node.index()].end();
+ iter++) {
+ assert(isCached(**iter));
+ dump << this->cache[**iter] << "\n";
+ }
+
+ dump << this->currindent << "}";
+ }
+ else {
+ dump << ";";
+ }
+ return dump.str();
+}
+
+/*!
+ Called for each node in the tree.
+ Will abort traversal if we're cached
+*/
+Response NodeDumper::visit(State &state, const AbstractNode &node)
+{
+ if (isCached(node)) return PruneTraversal;
+
+ handleIndent(state);
+ if (state.isPostfix()) {
+ std::stringstream dump;
+ dump << this->currindent;
+ if (this->idprefix) dump << "n" << node.index() << ":";
+ dump << node;
+ dump << dumpChildren(node);
+ this->cache.insert(node, dump.str());
+ }
+
+ handleVisitedChildren(state, node);
+ return ContinueTraversal;
+}
+
+/*!
+ Adds this given node to its parent's child list.
+ Should be called for all nodes, including leaf nodes.
+*/
+void NodeDumper::handleVisitedChildren(const State &state, const AbstractNode &node)
+{
+ if (state.isPostfix()) {
+ this->visitedchildren.erase(node.index());
+ if (!state.parent()) {
+ this->root = &node;
+ }
+ else {
+ this->visitedchildren[state.parent()->index()].push_back(&node);
+ }
+ }
+}
contact: Jan Huwald // Impressum