PH Logo
Logo intepreter modeled after UCB Logo.
/Users/paul/Documents/phlogo/core/Interpreter.cpp
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 }
 All Classes Functions