proj home

Files   Classes   Functions   Hierarchy  

rpn.h

Go to the documentation of this file.
00001 #ifndef RPN_H
00002 #define RPN_H
00003 
00004 #include <iostream>
00005 #include <deque>
00006 #include <string>
00007 #include <complex>
00008 
00009 using namespace std;
00010 
00011 
00012 
00013 
00014 class rpnfunction;
00015 
00016 class rpnbase 
00017 {
00018 public:
00019 
00020   /* Reference counting for memory management. */
00021   unsigned int counter;
00022   virtual void inc() 
00023     { ++counter; }
00024   void dec() 
00025     { --counter; if (counter==0) delete this; }
00026 
00027   /* Constructors, destructors and deep copy. */
00028   rpnbase() : counter(1) {}
00029   virtual ~rpnbase()=0;
00030   virtual rpnbase* copy() const=0;
00031 
00032   virtual ostream& print(ostream& os) const 
00033     { return os << this->name(); }
00034   /* Associated symbol with the class. */
00035   virtual string const name() const 
00036     { return string("undefined"); }
00037 
00038   /* Evaluation on the stack. */
00039   virtual void eval( deque<rpnbase*>& ds )
00040     { ds.push_front(this); }
00041   
00042   /* Visitor patterns accept function forwards data type. */
00043   virtual void accept(deque<rpnbase*>& ds,rpnfunction& f) {}
00044 
00045   /* Real time type information. */
00046   virtual bool const isinteger() const  { return false; } 
00047   virtual bool const isreal() const     { return false; }
00048   virtual bool const iscomplex() const  { return false; }
00049   virtual bool const isstring() const   { return false; }
00050   virtual bool const isprogram() const  { return false; } 
00051   virtual bool const isvariable() const { return false; }
00052   virtual bool const isvector() const   { return false; }
00053   bool const isnumber() const 
00054     { return this->isreal() || this->isinteger(); }
00055 
00056 };
00057 
00058 ostream& operator << (ostream& os, rpnbase* const p); 
00059 
00060 class rpnprogram;
00061 class rpnstring;
00062 class rpnreal;
00063 class rpncomplex;
00064 class rpninteger;
00065 class rpnvar;
00066 class rpnvector;
00067 
00068 
00069 /* Derive functions */
00070 class rpnfunction : public rpnbase
00071 {
00072 public:
00073 
00074   rpnfunction() {}
00075   ~rpnfunction() {}
00076   rpnbase* copy() const;
00077 
00078   virtual void visit(deque<rpnbase*>& ds,rpnprogram& p) {}
00079   virtual void visit(deque<rpnbase*>& ds,rpnstring& s) {}
00080   virtual void visit(deque<rpnbase*>& ds,rpnreal& n) {}
00081   virtual void visit(deque<rpnbase*>& ds,rpncomplex& n) {}
00082   virtual void visit(deque<rpnbase*>& ds,rpninteger& n) {}
00083   virtual void visit(deque<rpnbase*>& ds,rpnvar& n) {}
00084   virtual void visit(deque<rpnbase*>& ds,rpnvector& v) {}
00085 
00086   void eval( deque<rpnbase*>& ds ) 
00087   {
00088     if (!ds.empty())
00089       ds[0]->accept(ds,*this);
00090 
00091     dec();
00092   };
00093 
00094   string const name() const 
00095     { return string("rpnfunction"); }
00096 };
00097 
00098 
00099 class rpnreal : public rpnbase
00100 {
00101 public:
00102 
00103   long double num;
00104   typedef long double type;
00105 
00106   rpnreal() {}
00107   rpnreal(long double const n) : num(n) {} /* <TODO> Is this necessary? */
00108   rpnreal(deque<rpnbase*>& ds,long double const n); 
00109   ~rpnreal() {}
00110   rpnbase* copy() const;
00111 
00112   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00113     { f.visit(ds,*this); }
00114 
00115   ostream& print(ostream& os) const;
00116   string const name() const 
00117     { return string("rpnreal"); }
00118 
00119   bool const isreal() const 
00120     { return true; }
00121 };
00122 
00123 
00124 class rpncomplex: public rpnbase
00125 {
00126 public:
00127 
00128   complex< long double > num;
00129 
00130   rpncomplex() {}
00131   rpncomplex
00132   (
00133     deque<rpnbase*>& ds,
00134     long double const x, 
00135     long double const y
00136   ); 
00137   rpncomplex
00138   (
00139     deque<rpnbase*>& ds, 
00140     complex<long double> const & x
00141   ); 
00142   ~rpncomplex() {}
00143   rpnbase* copy() const;
00144 
00145   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00146     { f.visit(ds,*this); }
00147 
00148   ostream& print(ostream& os) const;
00149   string const name() const 
00150     { return string("rpncomplex"); }
00151 
00152   bool const iscomplex() const 
00153     { return true; }
00154 };
00155 
00156 
00157 class rpninteger: public rpnbase
00158 {
00159 public:
00160 
00161   long int num;
00162   typedef long int type;
00163 
00164   static unsigned int displaybase;
00165 
00166   rpninteger() {}
00167   rpninteger(deque<rpnbase*>& ds,long int const n);
00168   ~rpninteger() {}
00169   rpnbase* copy() const;
00170 
00171   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00172     { f.visit(ds,*this); }
00173 
00174   ostream& print(ostream& os) const;
00175   string const name() const 
00176     { return string("rpninteger"); }
00177 
00178   bool const isinteger() const 
00179     { return true; }
00180 };
00181 
00182 
00183 class rpnstring : public rpnbase
00184 {
00185 public:
00186 
00187   string str;
00188 
00189   rpnstring() {}
00190   rpnstring(deque<rpnbase*>& ds,string const & s);
00191   ~rpnstring() {}
00192   rpnbase* copy() const;
00193 
00194   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00195     { f.visit(ds,*this); }
00196 
00197   ostream& print(ostream& os) const;
00198 
00199   void eval( deque<rpnbase*>& ds );
00200 
00201   bool const isstring() const 
00202     { return true; }
00203 };
00204 
00205 
00206 /* <TODO> Restrict to access by rpnprogram, don't create on the stack. */
00207 
00208 /* Rpn Variable class. - Used by rpnprogram. 
00209  */
00210 class rpnvar : public rpnbase
00211 {
00212 public:
00213 
00214   string varname;
00215   rpnbase* x;  
00216 
00217   void inc();
00218 
00219   rpnvar(rpnbase* x_, string const & s);
00220   rpnvar(rpnprogram& prog, rpnbase* x_, string const & s);
00221   ~rpnvar();
00222 
00223   rpnbase* copy() const;
00224   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00225     { f.visit(ds,*this); }
00226 
00227   void eval( deque<rpnbase*>& ds )
00228     { rpnbase* w = x->copy(); w->eval(ds); }
00229 
00230   ostream& print(ostream& os) const;
00231   string const name() const 
00232     { return varname; }
00233 
00234   bool const isvariable() const 
00235     { return true; }
00236 };
00237 
00238 
00239 class rpnvector : public rpnbase
00240 {
00241 /* Counting from the stack bottom is 0 as the first element.
00242    Counting from the stack end is 1 as the first element.
00243    Then can convert between the two with the same formula:
00244      f(k) = n-k  eg n=6, k=1 then f(1)=5 which is 1: ,f( f(1) ) = 1.
00245 */
00246 public:
00247 
00248   /* Counting from  the end of the stack. */
00249   int reverseindex;
00250   
00251   rpnvector(int index);
00252 
00253   rpnbase* copy() const;
00254   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00255     { f.visit(ds,*this); }
00256 
00257   ostream& print(ostream& os) const;
00258   string const name() const 
00259     { return "rpnvector"; }
00260 
00261   /* Convert between counting from the start of the stack 
00262      and the end of the stack. */
00263   int const indexcomplement(int const n) const;
00264   /* Return the index relative to the current stack. */
00265   //const int rpnvector::index() const;
00266   const int index() const;
00267 
00268   bool const isvector() const 
00269     { return true; }
00270 };
00271 
00272 
00273 
00274 class rpnprogram : public rpnbase 
00275 {
00276   void vinc();
00277 public:
00278 
00279   deque<rpnbase*> v;
00280   deque<rpnvar*> variables;
00281 
00282   // How the program is interpreted.
00283   //   bit 0 on has the program pushed onto the program stack.
00284   //   bit 1 on has a constant data stack, 
00285   //     off uses the top programs data stack.
00286   //   By default both bits are on.
00287   unsigned int state;
00288 
00289   void eval_11( deque<rpnbase*>& ds ); 
00290   void eval_10(); 
00291   void eval_01( deque<rpnbase*>& ds ); 
00292   void eval_00(); 
00293 
00294   void inc();
00295 
00296   bool const valid() const;
00297 
00298   rpnprogram();
00299   rpnprogram(deque<rpnbase*>& ds);
00300   rpnprogram
00301   (
00302     deque<rpnbase*>& ds,
00303     deque<rpnbase*>& ds2,
00304     bool const evaluate=true
00305   );
00306   ~rpnprogram();
00307   rpnbase* copy() const;
00308 
00309   void accept(deque<rpnbase*>& ds,rpnfunction& f) 
00310     { f.visit(ds,*this); }
00311 
00312   ostream& print(ostream& os) const;
00313 
00314   void eval( deque<rpnbase*>& ds ); 
00315 
00316 
00317 
00318   bool const isprogram() const 
00319     { return true; }
00320 };
00321 
00322 
00323 /* Access the programs state. Its a singleton class
00324  * which holds pointers to the systems state.
00325  * Also supports variable operations for var suggesting
00326  * that this class should be made into two classes. */ 
00327 
00328 class rpnprogramstackstate
00329 {
00330   static string findprogrampath;
00331   void findprogram
00332   (
00333     bool& found, 
00334     rpnprogram* p, 
00335     string const path, 
00336     rpnprogram* targ
00337   );
00338 public:
00339 
00340   static rpnprogram rpnhome;
00341 
00342   /* The primary program pointer, is never empty. */
00343   static deque<rpnprogram*>* ps;
00344 
00345   /* Minor stack. */
00346   static deque<rpnbase*> ds2;
00347 
00348   rpnprogramstackstate() {}
00349 
00350   /* Client must call before and after use. */
00351   void init();
00352 
00353   /* Access the most recent program's stack. */
00354   deque<rpnbase*>& ds() 
00355     { return ps->front()->v; }
00356   /* Access the most recent programs's variables. */
00357   deque<rpnvar*>& vs() 
00358     { return ps->front()->variables; }
00359 
00360   ostream& print(ostream& os) const;
00361 
00362   /* Control scoping/visability of programs and consequently variables. */
00363   void push(rpnprogram* p)
00364     { ps->push_front(p); }
00365   void pop()
00366     { if(ps->size()>1) ps->pop_front(); }
00367 
00368   /* Add a variable to the most rescent stack program. */
00369   void add(rpnbase* x, string const & s);
00370 
00371   /* Find the program in the rpnhome tree. */
00372   void findprogram(bool& found, string& path, rpnprogram* targ);
00373 
00374   /* Searches for a named variable, in the stack order. */
00375   void find
00376   (
00377     bool & result,
00378     unsigned int & indexi,
00379     unsigned int & indexk,
00380     rpnvar* & x,
00381     string const & nm
00382   ) const;
00383 
00384   /* Support operations on variables. */
00385   void erase(string const &nm);
00386   void replace(rpnbase* x, string const & nm);
00387   void exists(bool& res, string const & nm) const;
00388   void evaluate(deque<rpnbase*>& ds, string const & nm) const;
00389   void recall(deque<rpnbase*>& ds, string const & nm) const; 
00390   void recallpointer(deque<rpnbase*>& ds, string const & nm) const;
00391 
00392 };
00393 
00394 ostream& operator << (ostream& os, rpnprogramstackstate const & ps);
00395 
00396 
00397 
00398 
00399 #endif
00400 
00401 
00402 

Generated on Fri Mar 4 00:49:30 2011 for Chelton Evans Source by  doxygen 1.5.8