btreebase.cpp

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 }

Generated on Tue May 8 17:05:28 2007 for KTechLab by  doxygen 1.5.1