|
PH Logo
Logo intepreter modeled after UCB Logo.
|
00001 /* 00002 * Interpreter.cpp 00003 * 00004 * Author: Paul Hamilton 00005 * Date: 6 Jun 2011 00006 * 00007 */ 00008 00009 #include "Interpreter.h" 00010 00011 #include "World.h" 00012 #include "Verbs.h" 00013 #include "Func.h" 00014 #include "Console.h" 00015 #include "Exceptions.h" 00016 #include "Thing.h" 00017 #include "List.h" 00018 #include "Array.h" 00019 #include "Tokenizer.h" 00020 #include "StringTokenStream.h" 00021 00022 #include <iostream> 00023 #include <sstream> 00024 #include <algorithm> 00025 #include <boost/lexical_cast.hpp> 00026 00027 using namespace std; 00028 using namespace boost; 00029 00030 namespace phlogo { 00031 00032 Interpreter::Interpreter(World *world) { 00033 _verbs.reset(new Verbs(this, world)); 00034 _tk.reset(new Tokenizer(_verbs.get())); 00035 _openfunc = 0; 00036 _debug = false; 00037 } 00038 00039 wList Interpreter::sentence2words(const string &sentence) { 00040 vector<string> words; 00041 istringstream iss(sentence); 00042 copy(istream_iterator<string>(iss), 00043 istream_iterator<string>(), 00044 back_inserter<vector<string> >(words)); 00045 return words; 00046 } 00047 00048 void Interpreter::run(World *world, const string &sentence) { 00049 00050 if (_debug) { 00051 cout << "i: " << sentence << std::endl; 00052 } 00053 try { 00054 string tokenized = _tk->tokenizeToString(sentence); 00055 runTokenized(world, tokenized); 00056 } 00057 catch( dont_know_how_exception & x ) { 00058 string *tokens=boost::get_error_info<errinfo_bad_tokens>(x); 00059 string *verb=boost::get_error_info<errinfo_curr_verb>(x); 00060 string *tag=boost::get_error_info<errinfo_tag>(x); 00061 string *value=boost::get_error_info<errinfo_value>(x); 00062 00063 string err = "dont know how to"; 00064 if (verb && *verb != "") 00065 err += " " + *verb; 00066 if (tokens && *tokens != "") 00067 err += " " + *tokens; 00068 if (tag && *tag != "") { 00069 if (*tag == "expr" && value && *value != "") 00070 err += " " + *value; 00071 else 00072 err += " " + *tag; 00073 } 00074 world->getConsole()->outputError(err); 00075 } 00076 } 00077 00078 void Interpreter::runTokenized(World *world, const string &tokenized) { 00079 00080 try { 00081 if (_debug) { 00082 cout << "t: " << tokenized << std::endl; 00083 } 00084 00085 if (_openfunc) { 00086 _openfunc->addWords(tokenized); 00087 } 00088 else { 00089 // execute the words. 00090 StringTokenStream ts(tokenized); 00091 while (ts.hasMore()) 00092 _verbs->run(&ts); 00093 } 00094 } 00095 catch( no_thing_exception & x ) { 00096 string *name=boost::get_error_info<errinfo_name>(x); 00097 world->getConsole()->outputError(*name + " has no value"); 00098 } 00099 catch( bad_index_exception & x ) { 00100 world->getConsole()->outputError("bad index to array or list"); 00101 } 00102 catch( interpreter_exception & x ) { 00103 world->getConsole()->outputError("unknown exception: " + current_exception_diagnostic_information()); 00104 } 00105 } 00106 00107 void Interpreter::defun(const string &name, const string &args) { 00108 _openfunc = _verbs->createFunction(name, args); 00109 } 00110 00111 void Interpreter::end() { 00112 if (_openfunc == 0) { 00113 BOOST_THROW_EXCEPTION( 00114 no_open_function_exception() ); 00115 } 00116 else { 00117 _openfunc = 0; 00118 } 00119 } 00120 00121 boost::shared_ptr<Thing> Interpreter::varOrLiteral(World *world, const string &s) { 00122 00123 if (Verbs::isVariable(s)) 00124 return world->getThing(Verbs::getVariable(s)); 00125 else { 00126 boost::shared_ptr<Thing> thing(new Thing()); 00127 thing->set(s); 00128 return thing; 00129 } 00130 00131 } 00132 00143 void Interpreter::getNextThing(World *world, TokenStream *ts, pThing *thing) { 00144 00145 StringTokenStream *sts = static_cast<StringTokenStream *>(ts); 00146 00147 // skip over leading space. 00148 sts->skipWs(); 00149 00150 switch (sts->nextChar()) { 00151 00152 case '[': 00153 { 00154 thing->reset(new Thing()); 00155 List list = (*thing)->allocList(); 00156 list.fromWord(sts); 00157 } 00158 break; 00159 00160 case '{': 00161 { 00162 thing->reset(new Thing()); 00163 Array array = (*thing)->allocArray(0); 00164 array.fromWord(sts); 00165 } 00166 break; 00167 00168 case '(': 00169 { 00170 // find the last paren. 00171 size_t i = sts->findEndSubExpression(); 00172 00173 // run from here. 00174 _verbs->run(sts); 00175 *thing = world->getResult(); 00176 00177 // skip over closing paren, and then 00178 sts->finishSubExpression(i); 00179 } 00180 break; 00181 00182 case '$': 00183 case '#': 00184 { 00185 // run the verb, and get the resulting thing. 00186 _verbs->run(sts); 00187 *thing = world->getResult(); 00188 } 00189 break; 00190 00191 default: 00192 { 00193 string t = sts->nextWord(); 00194 if (Verbs::isVariable(t)) 00195 *thing = world->getThing(Verbs::getVariable(t)); 00196 else { 00197 thing->reset(new Thing()); 00198 (*thing)->set(t); 00199 } 00200 } 00201 break; 00202 } 00203 if (_debug) { 00204 cout << thing->get()->type() << ": " << thing->get()->str() << std::endl; 00205 } 00206 00207 } 00208 00209 }
1.7.4