Files Classes Functions Hierarchy
00001 #include <cassert> 00002 #include <sstream> 00003 #include <map> 00004 #include <string> 00005 using namespace std; 00006 00007 #include <rpn.h> 00008 #include <rpnfunc.h> 00009 #include <mathfunc.h> 00010 #include <singleton.h> 00011 00012 #include <rawinterpreter.h> 00013 00014 00015 #ifndef NDEBUG 00016 //#define DEBUG_INTERPRETER 00017 #endif 00018 00019 00020 fbuildbase* fbuilduser::copy() const 00021 { 00022 x->inc(); 00023 return new fbuilduser(x,nm); 00024 } 00025 00026 void fbuilduser::make() const 00027 { 00028 x->inc(); 00029 if (inputstatescope::cscope->evalimmediate) 00030 x->eval(rpnprogramstackstate().ds()); 00031 else 00032 rpnprogramstackstate().ds().push_front(x); 00033 } 00034 00035 fbuilduser::fbuilduser(rpnbase* _x, string const & _nm) 00036 : x(_x), nm(_nm) 00037 { 00038 } 00039 00040 fbuilduser::~fbuilduser() 00041 { 00042 x->dec(); 00043 } 00044 00045 string const fbuilduser::name() const 00046 { 00047 return nm; 00048 } 00049 00050 00051 fdatainterp::fdatainterp() 00052 { 00053 init(); 00054 } 00055 00056 void fdatainterp::init() 00057 { 00058 addtodictionary( passtype<rpnprogset>() ); 00059 addtodictionary( passtype<rpnpush>() ); 00060 addtodictionary( passtype<rpnpop>() ); 00061 addtodictionary( passtype<rpnpushn>() ); 00062 addtodictionary( passtype<rpnpopn>() ); 00063 addtodictionary( passtype<dssize2>() ); 00064 addtodictionary( passtype<rpneval>() ); 00065 addtodictionary( passtype<rpnclear>() ); 00066 addtodictionary( passtype<rpnclearvar>() ); 00067 addtodictionary( passtype<rpnclearboth>() ); 00068 addtodictionary( passtype<rpndup>() ); 00069 addtodictionary( passtype<rpndupn>() ); 00070 addtodictionary( passtype<dssize>() ); 00071 addtodictionary( passtype<rev>() ); 00072 addtodictionary( passtype<rot>() ); 00073 addtodictionary( passtype<rotn>() ); 00074 addtodictionary( passtype<rpnswap>() ); 00075 addtodictionary( passtype<rpnswap2>() ); 00076 addtodictionary( passtype<drop>() ); 00077 addtodictionary( passtype<dropi>() ); 00078 addtodictionary( passtype<dropsymb>() ); 00079 addtodictionary( passtype<dropn>() ); 00080 addtodictionary( passtype<ifthen>() ); 00081 addtodictionary( passtype<thenif>() ); 00082 addtodictionary( passtype<ifthenelse>() ); 00083 addtodictionary( passtype<thenelseif>() ); 00084 addtodictionary( passtype<var>() ); 00085 addtodictionary( passtype<vardel>() ); 00086 addtodictionary( passtype<vareval>() ); 00087 addtodictionary( passtype<varpushd>() ); 00088 addtodictionary( passtype<varpopd>() ); 00089 addtodictionary( passtype<depthd>() ); 00090 addtodictionary( passtype<varls>() ); 00091 addtodictionary( passtype<vartree>() ); 00092 addtodictionary( passtype<varpwd>() ); 00093 addtodictionary( passtype<pathtoggle>() ); 00094 addtodictionary( passtype<varinc>() ); 00095 addtodictionary( passtype<vardec>() ); 00096 addtodictionary( passtype<varexists>() ); 00097 addtodictionary( passtype<varreplace>() ); 00098 addtodictionary( passtype<varrecall>() ); 00099 addtodictionary( passtype<rpnnot>() ); 00100 addtodictionary( passtype<rpnneg>() ); 00101 addtodictionary( passtype<rpnadd>() ); 00102 addtodictionary( passtype<rpnmultiply>() ); 00103 addtodictionary( passtype<rpnsubtract>() ); 00104 addtodictionary( passtype<rpndivide>() ); 00105 addtodictionary( passtype<rpnlessthan>() ); 00106 addtodictionary( passtype<rpnlessthanequal>() ); 00107 addtodictionary( passtype<rpngreaterthan>() ); 00108 addtodictionary( passtype<rpngreaterthanequal>() ); 00109 addtodictionary( passtype<rpnequal>() ); 00110 addtodictionary( passtype<rpnfor>() ); 00111 addtodictionary( passtype<rpnforn>() ); 00112 addtodictionary( passtype<prognew>() ); 00113 addtodictionary( passtype<progdecompose>() ); 00114 addtodictionary( passtype<progrev>() ); 00115 addtodictionary( passtype<isrpnstring>() ); 00116 addtodictionary( passtype<isrpninteger>() ); 00117 addtodictionary( passtype<isrpnreal>() ); 00118 addtodictionary( passtype<isrpncomplex>() ); 00119 addtodictionary( passtype<isrpnprogram>() ); 00120 addtodictionary( passtype<pathcd>() ); 00121 addtodictionary( passtype<pathquery>() ); 00122 addtodictionary( passtype<varmv>() ); 00123 addtodictionary( passtype<rpncp>() ); 00124 addtodictionary( passtype<rpninsert>() ); 00125 addtodictionary( passtype<rpnerase>() ); 00126 addtodictionary( passtype<rpnpointermake>() ); 00127 addtodictionary( passtype<rpnvectormake>() ); 00128 addtodictionary( passtype<rpnvectorpointermake>() ); 00129 addtodictionary( passtype<pstream>() ); 00130 addtodictionary( passtype<rpnintegerconvert>() ); 00131 addtodictionary( passtype<rpnstringconvert>() ); 00132 addtodictionary( passtype<rpnfactorial>() ); 00133 addtodictionary( passtype<rpnmod>() ); 00134 addtodictionary( passtype<rpngcd>() ); 00135 addtodictionary( passtype<rpnascii>() ); 00136 00137 00138 addtodictionary( passtype<rpnfcos>() ); 00139 addtodictionary( passtype<rpnfsin>() ); 00140 addtodictionary( passtype<rpnftan>() ); 00141 addtodictionary( passtype<rpnflog>() ); 00142 addtodictionary( passtype<rpnflog10>() ); 00143 addtodictionary( passtype<rpnfexp>() ); 00144 addtodictionary( passtype<rpnfsqrt>() ); 00145 addtodictionary( passtype<rpnfcosh>() ); 00146 addtodictionary( passtype<rpnfsinh>() ); 00147 addtodictionary( passtype<rpnftanh>() ); 00148 addtodictionary( passtype<rpnfacos>() ); 00149 addtodictionary( passtype<rpnfasin>() ); 00150 addtodictionary( passtype<rpnfatan>() ); 00151 addtodictionary( passtype<rpnffloor>() ); 00152 addtodictionary( passtype<rpnfceil>() ); 00153 addtodictionary( passtype<rpnpow>() ); 00154 addtodictionary( passtype<rpnfabs>() ); 00155 addtodictionary( passtype<rpnfarg>() ); 00156 addtodictionary( passtype<rpnfnorm>() ); 00157 addtodictionary( passtype<rpnfimag>() ); 00158 addtodictionary( passtype<rpnfconj>() ); 00159 addtodictionary( passtype<rpnrealconvert>() ); 00160 addtodictionary( passtype<rpnr_to_d>() ); 00161 addtodictionary( passtype<rpnd_to_r>() ); 00162 addtodictionary( passtype<rpnp_to_c>() ); 00163 addtodictionary( passtype<rpnr_to_c>() ); 00164 00165 00166 00167 addtodictionary( passtype< rpnintegerhex >() ); 00168 addtodictionary( passtype< rpnintegeroct >() ); 00169 addtodictionary( passtype< rpnintegerdec >() ); 00170 addtodictionary( passtype< rpnintegerbin >() ); 00171 addtodictionary( passtype< rpnbitnot >() ); 00172 addtodictionary( passtype< rpnbitxor>() ); 00173 addtodictionary( passtype< rpnbitor >() ); 00174 addtodictionary( passtype< rpnbitand>() ); 00175 addtodictionary( passtype< rpnbitshiftleft>() ); 00176 addtodictionary( passtype< rpnbitshiftright>() ); 00177 00178 00179 } 00180 00181 void fdatainterp::dictionarydelete() 00182 { 00183 if (!dict.empty()) 00184 { 00185 for( map<string,fbuildbase*>::iterator i = dict.begin(); 00186 i!=dict.end(); ++i ) 00187 delete i->second; 00188 00189 dict.clear(); 00190 } 00191 } 00192 00193 void fdatainterp::reset() 00194 { 00195 dictionarydelete(); 00196 00197 // Build the dictionary. 00198 for (unsigned int i=0, n=dicttable.size(); i<n; ++i) 00199 add( dicttable[i]->copy() ); 00200 } 00201 00202 fdatainterp::~fdatainterp() 00203 { 00204 dictionarydelete(); 00205 } 00206 00207 rpnreal::type const fdatainterp::real(string const & word) const 00208 { 00209 stringstream ss(word); 00210 rpnreal::type var; 00211 ss >> var; 00212 00213 return var; 00214 } 00215 00216 rpninteger::type const fdatainterp::integer(string const & word) const 00217 { 00218 stringstream ss(word); 00219 rpninteger::type var; 00220 ss >> var; 00221 00222 return var; 00223 } 00224 00225 void fdatainterp::eval(string const & word) 00226 { 00227 // 1. Determine if word is a number else 00228 // 2. Determine if word is in the dictionary else 00229 // 3. assume word is a string. 00230 char ch = word[0]; 00231 00232 if ( (ch=='-') && (word.size()>1)) 00233 ch = word[1]; 00234 00235 if ( (ch=='.') && (word.size()>1)) 00236 ch = word[1]; 00237 00238 if ( isdigit(ch) ) 00239 { 00240 // Is the number real or integer. 00241 bool integertype=true; 00242 for (unsigned int i=0, imax=word.size(); i<imax; ++i) 00243 { 00244 if( word[i]=='.') 00245 { 00246 integertype=false; 00247 i=imax; 00248 } 00249 } 00250 00251 // Construct the number. 00252 if (integertype) 00253 new rpninteger( rpnprogramstackstate().ds(), integer(word) ); 00254 else 00255 new rpnreal( rpnprogramstackstate().ds(), real(word) ); 00256 00257 return; 00258 } 00259 00260 // Not a number 00261 00262 #ifdef DEBUG_INTERPRETER 00263 cout << "Input: Not a number." << endl; 00264 #endif 00265 00266 // The user can force a string onto the stack. 00267 /* 00268 if (ch=='"') 00269 { 00270 if (word.size()==1) 00271 return; 00272 00273 string w(word.begin()+1,word.end()); 00274 new rpnstring( rpnprogramstackstate().ds(), w ); 00275 00276 return; 00277 } 00278 */ 00279 00280 // Search the dictionary. 00281 00282 // The # symbol indicates the item should not be evaluated. 00283 // The @ symbol indicates the item should be evaluated. 00284 if ((ch=='#')||(ch=='@')) 00285 { 00286 if (word.size()<=2) 00287 { 00288 if (word.size()==1) 00289 return; // Ignore lone # or @ character. 00290 00291 // Setting the mode was so important that I took it away 00292 // from the standard function system. 00293 if (word=="@+") 00294 { // Set immediate evaluation mode. 00295 inputstatescope::cscope->evalimmediate = true; 00296 return; 00297 } 00298 00299 if (word=="@-") 00300 { // Unset immediate evaluation mode. 00301 inputstatescope::cscope->evalimmediate = false; 00302 return; 00303 } 00304 } 00305 00306 bool tmpeval = true; 00307 if (ch=='#') 00308 tmpeval = false; 00309 00310 string word2(word.begin()+1,word.end()); 00311 00312 map<string,fbuildbase*>::iterator i = dict.find(word2); 00313 if (i!=dict.end()) 00314 { 00315 inputstatescope::cscope->evaloverride = true; 00316 inputstatescope::cscope->evalpreserved = 00317 inputstatescope::cscope->evalimmediate; 00318 inputstatescope::cscope->evalimmediate = tmpeval; 00319 00320 i->second->make(); 00321 00322 inputstatescope::cscope->evalimmediate = 00323 inputstatescope::cscope->evalpreserved; 00324 inputstatescope::cscope->evaloverride = false; 00325 00326 return; 00327 } 00328 00329 } 00330 else 00331 { 00332 00333 #ifdef DEBUG_INTERPRETER 00334 cout << "Input: Not a evaluation directive, word=" << 00335 word << "." << endl; 00336 #endif 00337 00338 map<string,fbuildbase*>::iterator i = dict.find(word); 00339 if (i!=dict.end()) 00340 { 00341 i->second->make(); 00342 00343 return; 00344 } 00345 } 00346 00347 // Assume a string 00348 00349 #ifdef DEBUG_INTERPRETER 00350 cout << "Input: string*" << word << "*" << endl; 00351 #endif 00352 00353 new rpnstring( rpnprogramstackstate().ds(), word ); 00354 }; 00355 00356 00357 class noaction 00358 { 00359 public: 00360 00361 void operator()() {} 00362 }; 00363 00364 00365 00366 inputstatescope* inputstatescope::cscope = 0; 00367 inputstate* inputstatescope::cstate = 0; 00368 00369 inputstatescope::inputstatescope() 00370 { 00371 assert(cscope==0); // This is a singleton class. 00372 00373 inner = new innerinput(); 00374 outer = new outerinput(); 00375 error = false; 00376 evalimmediate = true; 00377 evaloverride=false; 00378 00379 cscope = this; 00380 00381 setinner(); 00382 } 00383 00384 inputstatescope::~inputstatescope() 00385 { 00386 delete inner; 00387 delete outer; 00388 cstate=0; 00389 } 00390 00391 void inputstatescope::setinner() 00392 { 00393 cstate = inner; 00394 } 00395 00396 void inputstatescope::setouter() 00397 { 00398 cstate = outer; 00399 } 00400 00401 void inputstatescope::eval(string const & word) 00402 { 00403 cstate->eval(word); 00404 } 00405 00406 00407 void innerinput::eval(string const & word) 00408 { 00409 00410 if (word=="{") 00411 { 00412 rpnprogram* p = new rpnprogram(); 00413 rpnprogramstackstate().ds().push_front(p); 00414 rpnprogramstackstate().push( p ); 00415 00416 // Commented out to treat all programs equally. 00417 // inputstatescope::cscope->evalimmediate = false; 00418 inputstatescope::cscope->setouter(); 00419 return; 00420 } 00421 00422 inputstatescope::cscope->fd.eval(word); 00423 } 00424 00425 00426 void outerinput::eval(string const & word) 00427 { 00428 if (word=="}") 00429 { 00430 if(rpnprogramstackstate().ps->size() == 2) 00431 { 00432 rpnprogramstackstate().pop(); 00433 // Expecting a program on the data stack. 00434 00435 // Programs are not evaluated when placed on the stack. 00436 00437 inputstatescope::cscope->setinner(); 00438 return; 00439 } 00440 00441 // Assume rpnprogramstackstate().ps->size() > 2. 00442 rpnprogramstackstate().pop(); 00443 return; 00444 } 00445 00446 if (word=="{") 00447 { 00448 rpnprogram* p = new rpnprogram(); 00449 rpnprogramstackstate().ds().push_front(p); 00450 rpnprogramstackstate().push( p ); 00451 00452 return; 00453 } 00454 00455 inputstatescope::cscope->fd.eval(word); 00456 } 00457 00458 00459 // 00460 // I am experimenting with streams. In theory 00461 // reading a file and getting user input are both 00462 // istreams so should use the same code, but they 00463 // behave differently. 00464 // 00465 // The code is really similar. This version is 00466 // getting from a file. The end of file needs to 00467 // be checked so that an exit can occure. The keyboard 00468 // read needs no such test. 00469 // 00470 // quit will not work, it leaves the local stream only. 00471 void fdatainterp::process2_silent( istream & is ) 00472 { 00473 char c; 00474 char const quote('"'); 00475 char const space(' '); 00476 char const ret('\n'); 00477 00478 string s; 00479 00480 string const quit("quit"); 00481 00482 while ((c = is.peek())) 00483 { 00484 //cout << "c=" << c << endl; 00485 s.clear(); 00486 00487 if (c==quote) 00488 { 00489 is.get(c); 00490 is.get(c); 00491 while (c!=quote) 00492 { 00493 s += c; 00494 is.get(c); 00495 if (!is) 00496 return; 00497 } 00498 00499 new rpnstring( rpnprogramstackstate().ds(), s ); 00500 } 00501 else 00502 if (c=='(') 00503 { 00504 complex< long double > x; 00505 is >> x; 00506 00507 new rpncomplex( rpnprogramstackstate().ds(), x ); 00508 00509 } 00510 else 00511 { 00512 is.get(c); 00513 if ((c!=space)&&(c!=ret)) 00514 { 00515 s += c; 00516 is.get(c); 00517 //cout << "c=" << c << endl; 00518 while ((c!=space)&&(c!=ret)) 00519 { 00520 s += c; 00521 is.get(c); 00522 //cout << "c=" << c << endl; 00523 if (!is) 00524 return; 00525 } 00526 } 00527 00528 if (!s.empty()) 00529 SingletonPtr<inputstatescope>()->eval(s); 00530 00531 } 00532 00533 if (!is) 00534 return; 00535 00536 if (s==quit) 00537 break; 00538 } 00539 } 00540 00541 00542 00543 00544
1.5.8