summaryrefslogtreecommitdiffstats
path: root/lib/antlr/src/BaseAST.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/antlr/src/BaseAST.cpp')
-rw-r--r--lib/antlr/src/BaseAST.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/lib/antlr/src/BaseAST.cpp b/lib/antlr/src/BaseAST.cpp
new file mode 100644
index 00000000..f10f1e16
--- /dev/null
+++ b/lib/antlr/src/BaseAST.cpp
@@ -0,0 +1,281 @@
+/* ANTLR Translator Generator
+ * Project led by Terence Parr at http://www.jGuru.com
+ * Software rights: http://www.antlr.org/license.html
+ *
+ * $Id$
+ */
+
+#include "antlr/config.hpp"
+
+#include <iostream>
+
+#include "antlr/AST.hpp"
+#include "antlr/BaseAST.hpp"
+
+ANTLR_USING_NAMESPACE(std)
+#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
+namespace antlr {
+#endif
+
+size_t BaseAST::getNumberOfChildren() const
+{
+ RefBaseAST t = this->down;
+ size_t n = 0;
+ if( t )
+ {
+ n = 1;
+ while( t->right )
+ {
+ t = t->right;
+ n++;
+ }
+ return n;
+ }
+ return n;
+}
+
+void BaseAST::doWorkForFindAll(
+ ANTLR_USE_NAMESPACE(std)vector<RefAST>& v,
+ RefAST target,bool partialMatch)
+{
+ // Start walking sibling lists, looking for matches.
+ for (RefAST sibling=this;
+ sibling;
+ sibling=sibling->getNextSibling())
+ {
+ if ( (partialMatch && sibling->equalsTreePartial(target)) ||
+ (!partialMatch && sibling->equalsTree(target)) ) {
+ v.push_back(sibling);
+ }
+ // regardless of match or not, check any children for matches
+ if ( sibling->getFirstChild() ) {
+ RefBaseAST(sibling->getFirstChild())->doWorkForFindAll(v, target, partialMatch);
+ }
+ }
+}
+
+/** Is t an exact structural and equals() match of this tree. The
+ * 'this' reference is considered the start of a sibling list.
+ */
+bool BaseAST::equalsList(RefAST t) const
+{
+ // the empty tree is not a match of any non-null tree.
+ if (!t)
+ return false;
+
+ // Otherwise, start walking sibling lists. First mismatch, return false.
+ RefAST sibling=this;
+ for (;sibling && t;
+ sibling=sibling->getNextSibling(), t=t->getNextSibling()) {
+ // as a quick optimization, check roots first.
+ if (!sibling->equals(t))
+ return false;
+ // if roots match, do full list match test on children.
+ if (sibling->getFirstChild()) {
+ if (!sibling->getFirstChild()->equalsList(t->getFirstChild()))
+ return false;
+ }
+ // sibling has no kids, make sure t doesn't either
+ else if (t->getFirstChild())
+ return false;
+ }
+
+ if (!sibling && !t)
+ return true;
+
+ // one sibling list has more than the other
+ return false;
+}
+
+/** Is 'sub' a subtree of this list?
+ * The siblings of the root are NOT ignored.
+ */
+bool BaseAST::equalsListPartial(RefAST sub) const
+{
+ // the empty tree is always a subset of any tree.
+ if (!sub)
+ return true;
+
+ // Otherwise, start walking sibling lists. First mismatch, return false.
+ RefAST sibling=this;
+ for (;sibling && sub;
+ sibling=sibling->getNextSibling(), sub=sub->getNextSibling()) {
+ // as a quick optimization, check roots first.
+ if (!sibling->equals(sub))
+ return false;
+ // if roots match, do partial list match test on children.
+ if (sibling->getFirstChild())
+ if (!sibling->getFirstChild()->equalsListPartial(sub->getFirstChild()))
+ return false;
+ }
+
+ if (!sibling && sub)
+ // nothing left to match in this tree, but subtree has more
+ return false;
+
+ // either both are null or sibling has more, but subtree doesn't
+ return true;
+}
+
+/** Is tree rooted at 'this' equal to 't'? The siblings
+ * of 'this' are ignored.
+ */
+bool BaseAST::equalsTree(RefAST t) const
+{
+ // check roots first
+ if (!equals(t))
+ return false;
+ // if roots match, do full list match test on children.
+ if (getFirstChild()) {
+ if (!getFirstChild()->equalsList(t->getFirstChild()))
+ return false;
+ }
+ // sibling has no kids, make sure t doesn't either
+ else if (t->getFirstChild())
+ return false;
+
+ return true;
+}
+
+/** Is 'sub' a subtree of the tree rooted at 'this'? The siblings
+ * of 'this' are ignored.
+ */
+bool BaseAST::equalsTreePartial(RefAST sub) const
+{
+ // the empty tree is always a subset of any tree.
+ if (!sub)
+ return true;
+
+ // check roots first
+ if (!equals(sub))
+ return false;
+ // if roots match, do full list partial match test on children.
+ if (getFirstChild())
+ if (!getFirstChild()->equalsListPartial(sub->getFirstChild()))
+ return false;
+
+ return true;
+}
+
+/** Walk the tree looking for all exact subtree matches. Return
+ * an ASTEnumerator that lets the caller walk the list
+ * of subtree roots found herein.
+ */
+ANTLR_USE_NAMESPACE(std)vector<RefAST> BaseAST::findAll(RefAST target)
+{
+ ANTLR_USE_NAMESPACE(std)vector<RefAST> roots;
+
+ // the empty tree cannot result in an enumeration
+ if (target) {
+ doWorkForFindAll(roots,target,false); // find all matches recursively
+ }
+
+ return roots;
+}
+
+/** Walk the tree looking for all subtrees. Return
+ * an ASTEnumerator that lets the caller walk the list
+ * of subtree roots found herein.
+ */
+ANTLR_USE_NAMESPACE(std)vector<RefAST> BaseAST::findAllPartial(RefAST target)
+{
+ ANTLR_USE_NAMESPACE(std)vector<RefAST> roots;
+
+ // the empty tree cannot result in an enumeration
+ if (target)
+ doWorkForFindAll(roots,target,true); // find all matches recursively
+
+ return roots;
+}
+
+ANTLR_USE_NAMESPACE(std)string BaseAST::toStringList() const
+{
+ ANTLR_USE_NAMESPACE(std)string ts="";
+
+ if (getFirstChild())
+ {
+ ts+=" ( ";
+ ts+=toString();
+ ts+=getFirstChild()->toStringList();
+ ts+=" )";
+ }
+ else
+ {
+ ts+=" ";
+ ts+=toString();
+ }
+
+ if (getNextSibling())
+ ts+=getNextSibling()->toStringList();
+
+ return ts;
+}
+
+ANTLR_USE_NAMESPACE(std)string BaseAST::toStringTree() const
+{
+ ANTLR_USE_NAMESPACE(std)string ts = "";
+
+ if (getFirstChild())
+ {
+ ts+=" ( ";
+ ts+=toString();
+ ts+=getFirstChild()->toStringList();
+ ts+=" )";
+ }
+ else
+ {
+ ts+=" ";
+ ts+=toString();
+ }
+ return ts;
+}
+
+#ifdef ANTLR_SUPPORT_XML
+/* This whole XML output stuff needs a little bit more thought
+ * I'd like to store extra XML data in the node. e.g. for custom ast's
+ * with for instance symboltable references. This
+ * should be more pluggable..
+ * @returns boolean value indicating wether a closetag should be produced.
+ */
+bool BaseAST::attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const
+{
+ out << "text=\"" << this->getText()
+ << "\" type=\"" << this->getType() << "\"";
+
+ return false;
+}
+
+void BaseAST::toStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const
+{
+ for( RefAST node = this; node != 0; node = node->getNextSibling() )
+ {
+ out << "<" << this->typeName() << " ";
+
+ // Write out attributes and if there is extra data...
+ bool need_close_tag = node->attributesToStream( out );
+
+ if( need_close_tag )
+ {
+ // got children so write them...
+ if( node->getFirstChild() != 0 )
+ node->getFirstChild()->toStream( out );
+
+ // and a closing tag..
+ out << "</" << node->typeName() << ">" << endl;
+ }
+ }
+}
+#endif
+
+// this is nasty, but it makes the code generation easier
+ANTLR_API RefAST nullAST;
+
+#if defined(_MSC_VER) && !defined(__ICL) // Microsoft Visual C++
+extern ANTLR_API AST* const nullASTptr = 0;
+#else
+ANTLR_API AST* const nullASTptr = 0;
+#endif
+
+#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
+}
+#endif