Files Classes Functions Hierarchy
00001 #ifndef RAWINTERPRETER_H 00002 #define RAWINTERPRETER_H 00003 00004 #include <cassert> 00005 #include <string> 00006 #include <map> 00007 #include <vector> 00008 #include <iostream> 00009 using namespace std; 00010 00011 #include <rpn.h> 00012 #include <singleton.h> 00013 00014 00015 // Helper class for fdatainterp. 00016 // Funtion builder - build function and instanciate. 00017 class fbuildbase 00018 { 00019 public: 00020 00021 virtual ~fbuildbase() {} 00022 00023 // Name of function. 00024 virtual string const name() const { return string(); } 00025 // Create a function and transfer/execute on the data stack. 00026 virtual void make() const = 0; 00027 00028 // Make a copy of the class through new. 00029 virtual fbuildbase* copy() const = 0; 00030 00031 }; 00032 00033 // Helper class for fdatainterp. 00034 // Automate code generation for rpn functions. 00035 template< typename F > 00036 class fbuild : public fbuildbase 00037 { 00038 public: 00039 00040 string const name() const 00041 { return F().name(); } 00042 void make() const; 00043 00044 fbuildbase* copy() const 00045 { return new fbuild<F>(); } 00046 00047 }; 00048 00049 // Helper class for fdatainterp. 00050 // Allow rpn data type functions which are runtime in nature. 00051 class fbuilduser : public fbuildbase 00052 { 00053 rpnbase* x; 00054 string nm; 00055 public: 00056 00057 fbuilduser(rpnbase* _x, string const & _nm); 00058 ~fbuilduser(); 00059 00060 string const name() const; 00061 void make() const; 00062 00063 fbuildbase* copy() const; 00064 00065 }; 00066 00067 00068 // Function templates need type passed through arguments. 00069 // Avoid construction of T as is the case with dummy arguments. 00070 template< typename T > 00071 class passtype 00072 { 00073 public: 00074 00075 typedef T type; 00076 }; 00077 00078 // 00079 // Brief: function/data interpreter. Contains the dictionary. 00080 // 00081 class fdatainterp 00082 { 00083 // Load dicttable and build the dictionary. 00084 void init(); 00085 00086 void dictionarydelete(); 00087 00088 // Conversions. 00089 rpnreal::type const real(string const & word) const; 00090 rpninteger::type const integer(string const & word) const; 00091 public: 00092 00093 // The dictionary table can be used to build the dictionary. 00094 vector< fbuildbase* > dicttable; 00095 // The dictionary. 00096 map<string,fbuildbase*> dict; 00097 00098 // Construct an instance. 00099 fdatainterp(); 00100 ~fdatainterp(); 00101 00102 // From the dictionary table build the dictionary. 00103 void reset(); 00104 00105 // Interpret the word. 00106 void eval(string const &word); 00107 00108 // Process the input. 00109 void process2_silent( istream & is); 00110 template< typename T > 00111 void process2( istream & is, T& prnt ); 00112 00113 // Add a function to the dictionary. 00114 void add(fbuildbase* x) 00115 { dict.insert( make_pair(x->name(),x) ); } 00116 00117 // Add a function to the dictionary table and dictionary. 00118 template< typename T > 00119 void addtodictionary(T) 00120 { 00121 // No support for inc() dec() with building 00122 // functions. fn is copied twice and the 00123 // functions themselves are not persistant 00124 // with a reset. 00125 fbuildbase* fn = new fbuild< typename T::type>(); 00126 dicttable.push_back(fn); 00127 add(fn->copy()); 00128 } 00129 00130 }; 00131 00132 class inputstate; 00133 class innerinput; 00134 class outerinput; 00135 00136 // Brief: The interface and state machine for token parsing. 00137 // 00138 00139 // <TODO> The difference in the two states is trivial and 00140 // they could be merged to one. This was made possible by 00141 // a change in design where the dhome directory/program 00142 // is treated like anyother directory and doesn't get 00143 // a special evaluation mode. Instead the client is responsible 00144 // for the evaluation mode. 00145 // 00146 // Implemented as a singleton state machine interface. 00147 class inputstatescope 00148 { 00149 innerinput* inner; // Inner input state. 00150 outerinput* outer; // Outer input state. 00151 public: 00152 00153 static inputstatescope* cscope; // The current scope. 00154 static inputstate* cstate; // The current state. 00155 00156 bool evaloverride; 00157 bool evalpreserved; 00158 bool evalimmediate; // The evaluation mode is either immediate or not. 00159 00160 bool error; // Was there an error in processng the token? 00161 00162 inputstatescope(); // Initialize the scope. 00163 ~inputstatescope(); // Release the scopes rescources. 00164 00165 // Forward the processing of the word to the current state. 00166 void eval(string const & word); 00167 00168 fdatainterp fd; // The states need to access the interpreter. 00169 00170 // Change states. 00171 void setinner(); 00172 void setouter(); 00173 00174 }; 00175 00176 00177 // The input state is contained within a scope. 00178 class inputstate 00179 { 00180 public: 00181 00182 inputstate() {} 00183 00184 // Process the word in the current state. 00185 virtual void eval(string const & word) = 0; 00186 00187 }; 00188 00189 class innerinput : public inputstate 00190 { 00191 public: 00192 00193 void eval(string const & word); 00194 }; 00195 00196 class outerinput : public inputstate 00197 { 00198 public: 00199 00200 void eval(string const & word); 00201 }; 00202 00203 // 00204 // Functions derived from rpnfunction can call this class to 00205 // add themselves to the dictoinary and hence the interpreters scope. 00206 // 00207 template< typename T > 00208 class addtothedictionary 00209 { 00210 public: 00211 00212 addtothedictionary(); 00213 }; 00214 00215 00216 00217 00218 // --------------------------------------------------------------- 00219 // Implementation 00220 00221 00222 template< typename T > 00223 addtothedictionary<T>::addtothedictionary() 00224 { 00225 fdatainterp& fd = SingletonPtr<inputstatescope>()->fd; 00226 fd.addtodictionary(passtype<T>()); 00227 } 00228 00229 00230 template< typename F > 00231 void fbuild<F>::make() const 00232 { 00233 new F 00234 ( 00235 rpnprogramstackstate().ds(), 00236 inputstatescope::cscope->evalimmediate 00237 ); 00238 } 00239 00240 00241 template< typename T > 00242 void fdatainterp::process2( istream & is, T& prnt ) 00243 { 00244 char c; 00245 char const quote('"'); 00246 char const space(' '); 00247 char const ret('\n'); 00248 00249 string s; 00250 00251 string const quit("quit"); 00252 00253 while ((c = is.peek())) 00254 { 00255 s.clear(); 00256 00257 if (c==quote) 00258 { 00259 is.get(c); 00260 is.get(c); 00261 while (c!=quote) 00262 { 00263 s += c; 00264 is.get(c); 00265 } 00266 00267 new rpnstring( rpnprogramstackstate().ds(), s ); 00268 } 00269 else 00270 if (c=='(') 00271 { 00272 complex< long double > x; 00273 is >> x; 00274 00275 new rpncomplex( rpnprogramstackstate().ds(), x ); 00276 00277 00278 } 00279 else 00280 { 00281 is.get(c); 00282 if ((c!=space)&&(c!=ret)) 00283 { 00284 s += c; 00285 is.get(c); 00286 while ((c!=space)&&(c!=ret)) 00287 { 00288 s += c; 00289 is.get(c); 00290 } 00291 } 00292 00293 if (!s.empty()) 00294 SingletonPtr<inputstatescope>()->eval(s); 00295 00296 } 00297 00298 if (s==quit) 00299 break; 00300 00301 prnt(); 00302 } 00303 } 00304 00305 00306 00307 00308 #endif 00309 00310 00311
1.5.8