Files Classes Functions Hierarchy
00001 #ifndef RPN_H 00002 #define RPN_H 00003 00004 #include <iostream> 00005 #include <iomanip> 00006 #include <deque> 00007 #include <string> 00008 00009 // Toggle ALL debug code. 00010 //#define NDEBUG 00011 #include <cassert> 00012 00013 using namespace std; 00014 00015 #include <html.h> 00016 00017 #ifndef NDEBUG 00018 // Toggle Debug code. 00019 #define DEBUG_RFC 00020 #endif 00021 00022 00023 class rpnfunction; 00024 00025 class rpnbase 00026 { 00027 public: 00028 00029 /* Reference counting for memory management. */ 00030 unsigned int counter; 00031 virtual void inc() 00032 { ++counter; } 00033 void dec() 00034 { --counter; if (counter==0) delete this; } 00035 00036 /* Constructors, destructors and deep copy. */ 00037 rpnbase() : counter(1) {} 00038 virtual ~rpnbase()=0; 00039 virtual rpnbase* copy() const=0; 00040 00041 virtual ostream& print(ostream& os) const 00042 { return os << this->name(); } 00043 /* Associated symbol with the class. */ 00044 virtual string const name() const 00045 { return string("undefined"); } 00046 00047 /* Evaluation on the stack. */ 00048 virtual void eval( deque<rpnbase*>& ds ) 00049 { ds.push_front(this); } 00050 00051 /* Visitor patterns accept function forwards data type. */ 00052 virtual void accept(deque<rpnbase*>& ds,rpnfunction& f) {} 00053 00054 /* Real time type information. */ 00055 virtual bool const isinteger() const { return false; } 00056 virtual bool const isreal() const { return false; } 00057 virtual bool const isstring() const { return false; } 00058 virtual bool const isprogram() const { return false; } 00059 virtual bool const isvariable() const { return false; } 00060 virtual bool const isvector() const { return false; } 00061 bool const isnumber() const 00062 { return this->isreal() || this->isinteger(); } 00063 00064 }; 00065 00066 ostream& operator << (ostream& os, rpnbase* const p) 00067 { return p->print(os); } 00068 00069 class rpnprogram; 00070 class rpnstring; 00071 class rpnreal; 00072 class rpninteger; 00073 class rpnvar; 00074 class rpnvector; 00075 00076 00077 /* Derive functions */ 00078 class rpnfunction : public rpnbase 00079 { 00080 public: 00081 00082 rpnfunction() {} 00083 ~rpnfunction() {} 00084 rpnbase* copy() const; 00085 00086 virtual void visit(deque<rpnbase*>& ds,rpnprogram& p) {} 00087 virtual void visit(deque<rpnbase*>& ds,rpnstring& s) {} 00088 virtual void visit(deque<rpnbase*>& ds,rpnreal& n) {} 00089 virtual void visit(deque<rpnbase*>& ds,rpninteger& n) {} 00090 virtual void visit(deque<rpnbase*>& ds,rpnvar& n) {} 00091 virtual void visit(deque<rpnbase*>& ds,rpnvector& v) {} 00092 00093 string const name() const 00094 { return string("rpnfunction"); } 00095 }; 00096 00097 00098 class rpnreal : public rpnbase 00099 { 00100 public: 00101 00102 long double num; 00103 typedef long double type; 00104 00105 rpnreal() {} 00106 rpnreal(double const n) : num(n) {} /* <TODO> Is this necessary? */ 00107 rpnreal(deque<rpnbase*>& ds,double const n); 00108 ~rpnreal() {} 00109 rpnbase* copy() const; 00110 00111 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00112 { f.visit(ds,*this); } 00113 00114 ostream& print(ostream& os) const; 00115 string const name() const 00116 { return string("rpnreal"); } 00117 00118 bool const isreal() const 00119 { return true; } 00120 }; 00121 00122 00123 class rpninteger: public rpnbase 00124 { 00125 public: 00126 /* <TODO> - template the integer so much better integer arithmetic 00127 * can be used. 00128 */ 00129 long int num; 00130 typedef long int type; 00131 00132 rpninteger() {} 00133 rpninteger(deque<rpnbase*>& ds,long int const n); 00134 ~rpninteger() {} 00135 rpnbase* copy() const; 00136 00137 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00138 { f.visit(ds,*this); } 00139 00140 ostream& print(ostream& os) const; 00141 string const name() const 00142 { return string("rpninteger"); } 00143 00144 bool const isinteger() const 00145 { return true; } 00146 }; 00147 00148 00149 class rpnstring : public rpnbase 00150 { 00151 public: 00152 00153 string str; 00154 00155 rpnstring() {} 00156 rpnstring(deque<rpnbase*>& ds,string const & s); 00157 ~rpnstring() {} 00158 rpnbase* copy() const; 00159 00160 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00161 { f.visit(ds,*this); } 00162 00163 ostream& print(ostream& os) const; 00164 00165 void eval( deque<rpnbase*>& ds ); 00166 00167 bool const isstring() const 00168 { return true; } 00169 }; 00170 00171 00172 /* <TODO> Restrict to access by rpnprogram, don't create on the stack. */ 00173 00174 /* Rpn Variable class. - Used by rpnprogram. 00175 */ 00176 class rpnvar : public rpnbase 00177 { 00178 public: 00179 00180 string varname; 00181 rpnbase* x; 00182 00183 void inc(); 00184 00185 rpnvar(rpnbase* x_, string const & s); 00186 rpnvar(rpnprogram& prog, rpnbase* x_, string const & s); 00187 ~rpnvar(); 00188 00189 rpnbase* copy() const; 00190 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00191 { f.visit(ds,*this); } 00192 00193 void eval( deque<rpnbase*>& ds ) 00194 { rpnbase* w = x->copy(); w->eval(ds); } 00195 00196 ostream& print(ostream& os) const; 00197 string const name() const 00198 { return varname; } 00199 00200 bool const isvariable() const 00201 { return true; } 00202 }; 00203 00204 00205 00206 00207 class rpnvector : public rpnbase 00208 { 00209 /* Counting from the stack bottom is 0 as the first element. 00210 Counting from the stack end is 1 as the first element. 00211 Then can convert between the two with the same formula: 00212 f(k) = n-k eg n=6, k=1 then f(1)=5 which is 1: ,f( f(1) ) = 1. 00213 */ 00214 public: 00215 00216 /* Counting from the end of the stack. */ 00217 int reverseindex; 00218 00219 rpnvector(int index); 00220 00221 rpnbase* copy() const; 00222 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00223 { f.visit(ds,*this); } 00224 00225 ostream& print(ostream& os) const; 00226 string const name() const 00227 { return "rpnvector"; } 00228 00229 /* Convert between counting from the start of the stack 00230 and the end of the stack. */ 00231 int const indexcomplement(int const n) const; 00232 /* Return the index relative to the current stack. */ 00233 const int rpnvector::index() const; 00234 00235 bool const isvector() const 00236 { return true; } 00237 }; 00238 00239 00240 00241 class rpnprogram : public rpnbase 00242 { 00243 public: 00244 00245 deque<rpnbase*> v; 00246 deque<rpnvar*> variables; 00247 00248 void inc(); 00249 00250 bool const valid() const; 00251 00252 rpnprogram(); 00253 rpnprogram(deque<rpnbase*>& ds); 00254 rpnprogram 00255 ( 00256 deque<rpnbase*>& ds, 00257 deque<rpnbase*>& ds2, 00258 bool const evaluate=true 00259 ); 00260 ~rpnprogram(); 00261 rpnbase* copy() const; 00262 00263 void accept(deque<rpnbase*>& ds,rpnfunction& f) 00264 { f.visit(ds,*this); } 00265 00266 ostream& print(ostream& os) const; 00267 00268 void eval( deque<rpnbase*>& ds ); 00269 00270 bool const isprogram() const 00271 { return true; } 00272 }; 00273 00274 00275 /* Access the programs state. Its a singleton class 00276 * which holds pointers to the systems state. 00277 * Also supports variable operations for var suggesting 00278 * that this class should be made into two classes. */ 00279 00280 class rpnprogramstackstate 00281 { 00282 static string findprogrampath; 00283 void findprogram 00284 ( 00285 bool& found, 00286 rpnprogram* p, 00287 string const path, 00288 rpnprogram* targ 00289 ); 00290 public: 00291 00292 static rpnprogram rpnhome; 00293 00294 /* The primary program pointer, is never empty. */ 00295 static deque<rpnprogram*>* ps; 00296 00297 /* Minor stack. */ 00298 static deque<rpnbase*> ds2; 00299 00300 rpnprogramstackstate() {} 00301 00302 /* Client must call before and after use. */ 00303 void init(); 00304 00305 /* Access the most recent program's stack. */ 00306 deque<rpnbase*>& ds() 00307 { return ps->front()->v; } 00308 /* Access the most recent programs's variables. */ 00309 deque<rpnvar*>& vs() 00310 { return ps->front()->variables; } 00311 00312 ostream& print(ostream& os) const; 00313 00314 /* Control scoping/visability of programs and consequently variables. */ 00315 void push(rpnprogram* p) 00316 { ps->push_front(p); } 00317 void pop() 00318 { if(ps->size()>1) ps->pop_front(); } 00319 00320 /* Add a variable to the most rescent stack program. */ 00321 void add(rpnbase* x, string const & s); 00322 00323 /* Find the program in the rpnhome tree. */ 00324 void findprogram(bool& found, string& path, rpnprogram* targ); 00325 00326 /* Searches for a named variable, in the stack order. */ 00327 void find 00328 ( 00329 bool & result, 00330 unsigned int & indexi, 00331 unsigned int & indexk, 00332 rpnvar* & x, 00333 string const & nm 00334 ) const; 00335 00336 /* Support operations on variables. */ 00337 void erase(string const &nm); 00338 void replace(rpnbase* x, string const & nm); 00339 void exists(bool& res, string const & nm) const; 00340 void evaluate(deque<rpnbase*>& ds, string const & nm) const; 00341 void recall(deque<rpnbase*>& ds, string const & nm) const; 00342 void recallpointer(deque<rpnbase*>& ds, string const & nm) const; 00343 00344 }; 00345 00346 ostream& operator << (ostream& os, rpnprogramstackstate const & ps) 00347 { return ps.print(os); } 00348 00349 00350 // Implementation 00351 // ------------------------------------------------------------ 00352 // 00353 00354 /* g++ wants these. */ 00355 rpnbase::~rpnbase() {} 00356 rpnbase* rpnbase::copy() const { return 0; } 00357 00358 00359 rpnreal::rpnreal(deque<rpnbase*>& ds, double const n) 00360 : num(n) 00361 { 00362 eval(ds); 00363 } 00364 00365 /* 00366 This is a MAGIC NUMBER. 00367 00368 <TODO> Make configurable for user. 00369 00370 Why 30? I do not know, but it is beyond the accuracy 00371 of my type and hence displaysed the computers approximation. 00372 00373 eg. On my machine 00374 73.4 resulted in 00375 0: 73.40000000000000568434 00376 00377 An accuracy of 15 digits. Ofcourse the computer has 00378 a binary representation/approximation. 00379 00380 The good thing about displaying the garbage is you 00381 get to see how inaccurate the computer actually is, 00382 and its scary. 00383 00384 */ 00385 ostream& rpnreal::print(ostream& os) const 00386 { 00387 return os << fixed << showpoint 00388 << setprecision( 30 ) << num; 00389 } 00390 00391 rpnbase* rpnreal::copy() const 00392 { 00393 rpnreal* n = new rpnreal(); 00394 n->num = num; 00395 return n; 00396 } 00397 00398 00399 rpninteger::rpninteger(deque<rpnbase*>& ds, long int const n) 00400 : num(n) 00401 { 00402 eval(ds); 00403 } 00404 00405 ostream& rpninteger::print(ostream& os) const 00406 { 00407 return os << num; 00408 } 00409 00410 rpnbase* rpninteger::copy() const 00411 { 00412 rpninteger* n = new rpninteger(); 00413 n->num = num; 00414 return n; 00415 } 00416 00417 00418 rpnstring::rpnstring(deque<rpnbase*>& ds,string const & s) 00419 :str(s) 00420 { 00421 eval(ds); 00422 } 00423 00424 ostream& rpnstring::print(ostream& os) const 00425 { 00426 if (str != "/") 00427 return os << str; 00428 00429 /* To distinguish between division and root node. */ 00430 return os << string("\"/"); 00431 } 00432 00433 rpnbase* rpnstring::copy() const 00434 { 00435 rpnstring* s = new rpnstring(); 00436 s->str = str; 00437 return s; 00438 } 00439 00440 inline void rpnstring::eval( deque<rpnbase*>& ds ) 00441 { 00442 ds.push_front(this); 00443 } 00444 00445 00446 void rpnprogram::inc() 00447 { 00448 ++ counter; 00449 00450 if (!v.empty()) 00451 { 00452 for (unsigned int i=0, imax=v.size(); i<imax; ++i) 00453 v[i]->inc(); 00454 } 00455 00456 if (!variables.empty()) 00457 { 00458 for (unsigned int i=0, imax=variables.size(); i<imax; ++i) 00459 variables[i]->inc(); 00460 } 00461 } 00462 00463 00464 rpnprogram::rpnprogram 00465 ( 00466 deque<rpnbase*>& ds, 00467 deque<rpnbase*>& ds2, 00468 bool const evaluate 00469 ) 00470 { 00471 v = ds2; 00472 reverse(v.begin(),v.end()); /* <TODO> make efficent with reverse copy? */ 00473 00474 if (evaluate) 00475 { 00476 eval(ds); 00477 return; 00478 } 00479 00480 ds.push_front(this); 00481 } 00482 00483 rpnprogram::rpnprogram(deque<rpnbase*>& ds) 00484 { 00485 ds.push_front(this); 00486 } 00487 00488 rpnprogram::rpnprogram() 00489 { 00490 } 00491 00492 ostream& rpnprogram::print(ostream& os) const 00493 { 00494 os << "{"; 00495 if( v.empty()) 00496 return os << " }"; 00497 00498 for (unsigned int i=0,imax=v.size(); i<imax; ++i) 00499 { 00500 os << " "; 00501 v[i]->print(os); 00502 } 00503 00504 return os << " }"; 00505 } 00506 00507 rpnbase* rpnprogram::copy() const 00508 { 00509 /* A deep copy is required. */ 00510 00511 rpnprogram* p = new rpnprogram(); 00512 00513 if (v.empty()) 00514 { 00515 if (variables.empty()) 00516 return p; 00517 00518 for (unsigned int i=0, imax=variables.size(); i<imax; ++i) 00519 { 00520 rpnbase* tmp = variables[i]->copy(); 00521 p->variables.push_back( (rpnvar*)tmp ); 00522 } 00523 00524 return p; 00525 } 00526 00527 deque<rpnbase*> &v2 = p->v; 00528 00529 for (unsigned int i=0, imax=v.size(); i<imax; ++i) 00530 v2.push_back( v[i]->copy() ); 00531 00532 if (variables.empty()) 00533 return p; 00534 00535 for (unsigned int i=0, imax=variables.size(); i<imax; ++i) 00536 { 00537 rpnbase* tmp = variables[i]->copy(); 00538 p->variables.push_back( (rpnvar*)tmp ); 00539 } 00540 00541 return p; 00542 }; 00543 00544 rpnprogram::~rpnprogram() 00545 { 00546 if (!v.empty()) 00547 { 00548 for (unsigned int i=0, imax=v.size(); i<imax; ++i) 00549 v[i]->dec(); 00550 v.clear(); 00551 } 00552 00553 if (!variables.empty()) 00554 { 00555 for (unsigned int i=0, imax=variables.size(); i<imax; ++i) 00556 variables[i]->dec(); 00557 variables.clear(); 00558 } 00559 } 00560 00561 void rpnprogram::eval( deque<rpnbase*>& ds ) 00562 { 00563 rpnprogramstackstate().push(this); 00564 00565 if(!v.empty()) 00566 { 00567 for (unsigned int i=0,imax=v.size(); i<imax; ++i ) 00568 { 00569 if (v[i]->isprogram()) 00570 ds.push_front(v[i]); 00571 else 00572 v[i]->eval(ds); 00573 } 00574 } 00575 00576 rpnprogramstackstate().pop(); 00577 00578 dec(); 00579 } 00580 00581 inline void rpnvar::inc() 00582 { 00583 ++counter; 00584 x->inc(); 00585 } 00586 00587 inline rpnvar::~rpnvar() 00588 { 00589 if (x==0) 00590 return; 00591 00592 x->dec(); 00593 } 00594 00595 inline rpnvar::rpnvar(rpnprogram& prog, rpnbase* x_, string const & s) 00596 : varname(s), x(x_) 00597 { 00598 prog.variables.push_front(this); 00599 } 00600 00601 inline rpnvar::rpnvar(rpnbase* x_, string const & s) 00602 : varname(s), x(x_) 00603 { 00604 } 00605 00606 rpnbase* rpnvar::copy() const 00607 { 00608 return new rpnvar( x->copy(),varname); 00609 } 00610 00611 ostream& rpnvar::print(ostream& os) const 00612 { 00613 os << varname << " : "; 00614 return x->print(os); 00615 } 00616 00617 00618 rpnvector::rpnvector(int index) 00619 { 00620 reverseindex = indexcomplement(index); 00621 } 00622 00623 rpnbase* rpnvector::copy() const 00624 { 00625 /* I do not want a default contructor, so put a dummy 00626 argument in. The reverseindex should be preserved 00627 with a copy as they point to the same place. 00628 */ 00629 rpnvector* p = new rpnvector((int)0); 00630 p->reverseindex = reverseindex; 00631 return p; 00632 } 00633 00634 int const rpnvector::indexcomplement(int const n) const 00635 { 00636 int k = rpnprogramstackstate().ds().size(); 00637 k -= n; 00638 return k; 00639 } 00640 00641 const int rpnvector::index() const 00642 { 00643 return indexcomplement(reverseindex); 00644 } 00645 00646 00647 ostream& rpnvector::print(ostream& os) const 00648 { 00649 return os << " " << index() << " [] "; 00650 //return os << " " << indexcomplement(reverseindex) << " [] "; 00651 } 00652 00653 00654 rpnbase* rpnfunction::copy() const 00655 { 00656 return 0; 00657 } 00658 00659 00660 deque<rpnbase*> rpnprogramstackstate::ds2; 00661 deque<rpnprogram*>* rpnprogramstackstate::ps = 00662 new deque<rpnprogram*>(); 00663 rpnprogram rpnprogramstackstate::rpnhome; 00664 string rpnprogramstackstate::findprogrampath; 00665 00666 void rpnprogramstackstate::find 00667 ( 00668 bool & result, 00669 unsigned int & indexi, 00670 unsigned int & indexk, 00671 rpnvar* & x, 00672 string const & nm 00673 ) const 00674 { 00675 result=false; 00676 00677 for (unsigned int i=0, imax=ps->size(); i<imax; ++i) 00678 { 00679 deque<rpnprogram*>& w = *ps; // <TODO> optimize. 00680 if ( ! w[i]->variables.empty() ) 00681 { 00682 deque<rpnvar*>& z = w[i]->variables; 00683 for (unsigned int k=0, kmax=z.size(); k<kmax; ++k) 00684 { 00685 if (z[k]->varname==nm) 00686 { 00687 result=true; 00688 indexi = i; 00689 indexk = k; 00690 x = z[k]; 00691 00692 return; 00693 } 00694 } 00695 } 00696 } 00697 } 00698 00699 00700 00701 /* While developing rely on general find, optimize at a later date. */ 00702 00703 00704 00705 void rpnprogramstackstate::exists 00706 ( 00707 bool & res, 00708 string const & nm 00709 ) const 00710 { 00711 unsigned int i,k; 00712 rpnvar* x; 00713 00714 find(res,i,k,x,nm); 00715 } 00716 00717 00718 void rpnprogramstackstate::evaluate 00719 ( 00720 deque<rpnbase*>& ds, 00721 string const & nm 00722 ) const 00723 { 00724 bool res; 00725 unsigned int i,k; 00726 rpnvar* x; 00727 00728 find(res,i,k,x,nm); 00729 if (res) 00730 x->x->copy()->eval(ds); 00731 } 00732 00733 void rpnprogramstackstate::recall 00734 ( 00735 deque<rpnbase*>& ds, 00736 string const & nm 00737 ) const 00738 { 00739 bool res; 00740 unsigned int i,k; 00741 rpnvar* x; 00742 00743 find(res,i,k,x,nm); 00744 if (res) 00745 ds.push_front(x->x->copy()); 00746 } 00747 00748 void rpnprogramstackstate::recallpointer 00749 ( 00750 deque<rpnbase*>& ds, 00751 string const & nm 00752 ) const 00753 { 00754 bool res; 00755 unsigned int i,k; 00756 rpnvar* x; 00757 00758 find(res,i,k,x,nm); 00759 if (res) 00760 { 00761 x->x->inc(); 00762 ds.push_front(x->x); 00763 } 00764 } 00765 00766 00767 void rpnprogramstackstate::replace(rpnbase* x, string const & nm) 00768 { 00769 bool res; 00770 unsigned int i,k; 00771 rpnvar* x2; 00772 00773 find(res,i,k,x2,nm); 00774 if (res) 00775 { 00776 x2->x->dec(); 00777 x2->x = x; 00778 } 00779 else 00780 x->dec(); /* harsh */ 00781 } 00782 00783 void rpnprogramstackstate::erase(string const & nm) 00784 { 00785 bool res; 00786 unsigned int i,k; 00787 rpnvar* x2; 00788 00789 find(res,i,k,x2,nm); 00790 if (res) 00791 { 00792 deque<rpnprogram*>& w = *ps; 00793 w[i]->variables.erase( w[i]->variables.begin()+k ); 00794 } 00795 } 00796 00797 void rpnprogramstackstate::init() 00798 { 00799 ps->push_front( &rpnhome ); 00800 } 00801 00802 ostream& rpnprogramstackstate::print(ostream& os) const 00803 { 00804 for (unsigned int i=0, imax=ps->size(); i<imax; ++i) 00805 { 00806 os << "{ "; 00807 deque<rpnprogram*>& w = *ps; 00808 if ( ! w[i]->variables.empty() ) 00809 { 00810 deque<rpnvar*>& z = w[i]->variables; 00811 for (unsigned int k=0, kmax=z.size(); k<kmax; ++k) 00812 { 00813 os << "(" << z[k]->varname << ","; 00814 z[k]->x->print(os); 00815 os << ") "; 00816 } 00817 } 00818 os << "}" << endl; 00819 } 00820 return os; 00821 } 00822 00823 void rpnprogramstackstate::add(rpnbase* x, string const & s) 00824 { 00825 ps->front()->variables.push_front( new rpnvar(x,s) ); 00826 } 00827 00828 00829 void rpnprogramstackstate::findprogram 00830 ( 00831 bool& found, 00832 string& path, 00833 rpnprogram* targ 00834 ) 00835 { 00836 found = false; 00837 00838 00839 if (targ==&rpnhome) 00840 { 00841 findprogrampath = path = "/"; 00842 found = true; 00843 return; 00844 } 00845 00846 findprogram(found,&rpnhome,"",targ); 00847 00848 if (found) 00849 path = findprogrampath; 00850 } 00851 00852 void rpnprogramstackstate::findprogram 00853 ( 00854 bool& found, 00855 rpnprogram* p, 00856 string const path, 00857 rpnprogram* targ 00858 ) 00859 { 00860 /* Depth first search. */ 00861 /* Assume non-cyclic data structure. */ 00862 00863 if (!p->variables.empty()) 00864 { 00865 for (unsigned int i=0, imax=p->variables.size(); i<imax; ++i) 00866 { 00867 if (found) 00868 return; 00869 00870 if (p->variables[i]->x->isprogram()) 00871 { 00872 rpnprogram* pr = (rpnprogram*)(p->variables[i]->x); 00873 00874 string pathnew( path + string("/") + p->variables[i]->varname ); 00875 00876 if (pr == targ) 00877 { 00878 found = true; 00879 findprogrampath = pathnew; 00880 return; 00881 } 00882 else 00883 findprogram(found,pr,pathnew,targ); 00884 00885 } 00886 } 00887 } 00888 } 00889 00890 00891 00892 00893 00894 #endif 00895 00896 00897
1.5.8