00001 /*************************************************************************** 00002 * Copyright (C) 2004-2005 by Daniel Clarke * 00003 * daniel.jc@gmail.com * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program; if not, write to the * 00017 * Free Software Foundation, Inc., * 00018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00019 ***************************************************************************/ 00020 00021 #include "btreebase.h" 00022 #include "traverser.h" 00023 #include "parser.h" 00024 #include "pic14.h" 00025 00026 BTreeBase::BTreeBase() 00027 { 00028 m_root = 0; 00029 } 00030 00031 void BTreeBase::deleteTree() 00032 { 00033 if(m_root) m_root->deleteChildren(); 00034 delete m_root; 00035 m_root = 0; 00036 } 00037 00038 BTreeBase::~BTreeBase() 00039 { 00040 deleteTree(); 00041 } 00042 00043 void BTreeBase::addNode(BTreeNode *parent, BTreeNode *node, bool left) 00044 { 00045 if(left) parent->setLeft(node); 00046 else parent->setRight(node); 00047 } 00048 00049 void BTreeBase::pruneTree(BTreeNode *root, bool /*conditionalRoot*/) 00050 { 00051 Traverser t(root); 00052 00053 t.descendLeftwardToTerminal(); 00054 bool done = false; 00055 while(!done) { 00056 //t.descendLeftwardToTerminal(); 00057 if(t.current()->parent() && t.oppositeNode()->hasChildren()) 00058 pruneTree(t.oppositeNode()); 00059 00060 t.moveToParent(); 00061 if( !t.current()->hasChildren() ) { 00062 //if(t.current() == t.root()) done = true; 00063 if(!t.current()->parent()) done = true; 00064 continue; 00065 } 00066 00067 BTreeNode *l = t.current()->left(); 00068 BTreeNode *r = t.current()->right(); 00069 BTreeNode *n = 0; 00070 BTreeNode *z = 0; 00071 00072 // Deal with situations where there are two constants so we want 00073 // to evaluate at compile time 00074 if(l->type() == number && r->type() == number) 00075 { 00076 if(t.current()->childOp() == Expression::division && r->value() == "0" ) 00077 { 00078 t.current()->setChildOp(Expression::divbyzero); 00079 return; 00080 } 00081 QString value = QString::number(Parser::doArithmetic(l->value().toInt(), r->value().toInt(), t.current()->childOp())); 00082 t.current()->deleteChildren(); 00083 t.current()->setChildOp(Expression::noop); 00084 t.current()->setType(number); 00085 t.current()->setValue(value); 00086 } 00087 00088 // Addition and subtraction 00089 else if(t.current()->childOp() == Expression::addition || t.current()->childOp() == Expression::subtraction) { 00090 // See if one of the nodes is 0, and set n to the node that actually has data, 00091 // z to the one containing zero. 00092 bool zero = false; 00093 if( l->value() == "0" ) { 00094 zero = true; 00095 n = r; 00096 z = l; 00097 } else if( r->value() == "0" ) { 00098 zero = true; 00099 n = l; 00100 z = r; 00101 } 00102 00103 // Now get rid of the useless nodes 00104 if(zero) { 00105 BTreeNode *p = t.current(); // save in order to delete after 00106 00107 replaceNode(p,n); 00108 t.setCurrent(n); 00109 // Delete the old nodes 00110 delete p; 00111 delete z; 00112 z = 0; 00113 } 00114 } 00115 // Multiplication and division 00116 else if(t.current()->childOp() == Expression::multiplication || t.current()->childOp() == Expression::division) { 00117 // See if one of the nodes is 0, and set n to the node that actually has data, 00118 // z to the one containing zero. 00119 bool zero = false; 00120 bool one = false; 00121 if( l->value() == "1" ) { 00122 one = true; 00123 n = r; 00124 z = l; 00125 } else if( r->value() == "1" ) { 00126 one = true; 00127 n = l; 00128 z = r; 00129 } 00130 00131 if( l->value() == "0" ) { 00132 zero = true; 00133 n = r; 00134 z = l; 00135 } else if( r->value() == "0" ) { 00136 00137 // since we can't call compileError from in this class, we have a special way of handling it: 00138 // Leave the children as they are, and set childOp to divbyzero 00139 if( t.current()->childOp() == Expression::division ) 00140 { 00141 t.current()->setChildOp(Expression::divbyzero); 00142 return; // no point doing any more since we are going to raise a compileError later anyway. 00143 } 00144 zero = true; 00145 n = l; 00146 z = r; 00147 } 00148 00149 // Now get rid of the useless nodes 00150 if(one) { 00151 BTreeNode *p = t.current(); // save in order to delete after 00152 replaceNode(p,n); 00153 t.setCurrent(n); 00154 // Delete the old nodes 00155 delete p; 00156 delete z; 00157 z = 0; 00158 } 00159 00160 if(zero) { 00161 BTreeNode *p = t.current(); 00162 p->deleteChildren(); 00163 p->setChildOp(Expression::noop); 00164 p->setType(number); 00165 p->setValue("0"); 00166 } 00167 00168 // FIXME: A btree should not have only minimial knowledge of what it contains. 00169 // I think there is a C++ STL class for trees, why aren't we using that? 00170 00171 } else if(t.current()->childOp() == Expression::bwand || 00172 t.current()->childOp() == Expression::bwor || 00173 t.current()->childOp() == Expression::bwxor) 00174 { 00175 00176 bool zero = false; 00177 if( l->value() == "0" ) { 00178 zero = true; 00179 n = r; 00180 z = l; 00181 } else if( r->value() == "0" ) { 00182 zero = true; 00183 n = l; 00184 z = r; 00185 } 00186 00187 // Now get rid of the useless nodes 00188 if(zero) { 00189 BTreeNode *p = t.current(); 00190 QString value; 00191 if( p->childOp() == Expression::bwand ) { 00192 value = "0"; 00193 p->deleteChildren(); 00194 p->setChildOp(Expression::noop); 00195 p->setType(number); 00196 } 00197 00198 if(p->childOp() == Expression::bwor || p->childOp() == Expression::bwxor) { 00199 value = n->value(); 00200 BTreeNode *p = t.current(); // save in order to delete after 00201 replaceNode(p,n); 00202 t.setCurrent(n); 00203 // Delete the old nodes 00204 delete p; 00205 delete z; 00206 z = 0; 00207 } 00208 p->setValue(value); 00209 } 00210 } 00211 00212 if(!t.current()->parent() || t.current() == root) done = true; 00213 00214 } 00215 } 00216 00217 void BTreeBase::replaceNode(BTreeNode *node, BTreeNode *replacement) 00218 { 00219 // (This works under the assumption that a node is not linked to two places at once). 00220 if( !node->parent() ) { 00221 setRoot(replacement); 00222 replacement->setParent(0); 00223 return; 00224 } 00225 00226 if(node->parent()->left() == node ) node->parent()->setLeft(replacement); 00227 if(node->parent()->right() == node) node->parent()->setRight(replacement); 00228 }
1.5.1