/** * SOFTWARE RIGHTS *

* ANTLR 2.6.0 MageLang Insitute, 1998 *

* We reserve no legal rights to the ANTLR--it is fully in the * public domain. An individual or company may do whatever * they wish with source code distributed with ANTLR or the * code generated by ANTLR, including the incorporation of * ANTLR, or its output, into commerical software. *

* We encourage users to develop software with ANTLR. However, * we do ask that credit is given to us for developing * ANTLR. By "credit", we mean that if you use ANTLR or * incorporate any source code into one of your programs * (commercial product, research project, or otherwise) that * you acknowledge this fact somewhere in the documentation, * research report, etc... If you like ANTLR and have * developed a nice tool with the output, please mention that * you developed it using ANTLR. In addition, we ask that the * headers remain intact in our source code. As long as these * guidelines are kept, we expect to continue enhancing this * system and expect to make other tools available as they are * completed. *

* The ANTLR gang: * @version ANTLR 2.6.0 MageLang Insitute, 1998 * @author Terence Parr, MageLang Institute * @author
John Lilley, Empathy Software * @author
Pete Wells */ #include "antlr/BaseAST.h" ANTLR_BEGIN_NAMESPACE(antlr) //bool BaseAST::verboseStringConversion; //ANTLR_USE_NAMESPACE(std)vector BaseAST::tokenNames; void BaseAST::addChild(RefAST c) { if (!c) return; RefBaseAST tmp=down; if (tmp) { while (tmp->right) tmp=tmp->right; tmp->right=c; } else { down=c; } } void BaseAST::doWorkForFindAll( ANTLR_USE_NAMESPACE(std)vector& 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 node t equal to this in terms of token type and text? */ bool BaseAST::equals(RefAST t) const { if (!t) return false; return (getText() == t->getText()) && (getType() == t->getType()); } /** 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 BaseAST::findAll(RefAST target) { ANTLR_USE_NAMESPACE(std)vector 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 BaseAST::findAllPartial(RefAST target) { ANTLR_USE_NAMESPACE(std)vector roots; // the empty tree cannot result in an enumeration if (target) { doWorkForFindAll(roots,target,true); // find all matches recursively } return roots; } RefAST BaseAST::getFirstChild() const { return RefAST(down); } RefAST BaseAST::getNextSibling() const { return RefAST(right); } ANTLR_USE_NAMESPACE(std)string BaseAST::getText() const { return ""; } int BaseAST::getType() const { return 0; } void BaseAST::removeChildren() { down=nullAST; } void BaseAST::setFirstChild(RefAST c) { down=c; } void BaseAST::setNextSibling(RefAST n) { right=n; } void BaseAST::setText(const ANTLR_USE_NAMESPACE(std)string& txt) { } void BaseAST::setType(int type) { } //void BaseAST::setVerboseStringConversion(bool verbose, // const ANTLR_USE_NAMESPACE(std)vector& names) //{ // verboseStringConversion = verbose; // tokenNames = names; //} ANTLR_USE_NAMESPACE(std)string BaseAST::toString() const { // if ( verboseStringConversion && // !getText().equalsIgnoreCase(tokenNames[getType()]) && // !getText().equalsIgnoreCase(Tool.stripFrontBack(tokenNames[getType()],"\"","\"")) ) { // b.append('['); // b.append(getText()); // b.append(",<"); // b.append(tokenNames[getType()]); // b.append(">]"); // return b.toString(); // } return getText(); } 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; } // this is nasty, but it makes the code generation easier RefAST nullAST; AST* const nullASTptr=0; ANTLR_END_NAMESPACE