/** * * generates a program to execute a script * * @author http://bumble.sf.net */ #include <iostream> #include <fstream> #include <vector> #include <stack> #include <string> #include <sstream> #include <stdlib.h> #include <ctype.h> //#include "Interpret.h" //#include "Machine.h" #include "Program.h" using namespace std; //-------------------------------------------- /** this program uses the Machine class to parse a script and * */ Program::Program() { Machine cpu; string errors; vector<Instruction> instructionSet; instructionPointer = 0; } //-------------------------------------------- string Program::toString() { string sReturn(""); stringstream ssReturn; Instruction currentItem; ssReturn << "------------------------------" << endl; ssReturn << "--program--" << endl; ssReturn << "------------------------------" << endl; ssReturn << "IP:" << this->instructionPointer << endl; if (this->instructionSet.size() == 0) { ssReturn << "(no instructions)" << endl; } else { for (int ii = 0; ii < this->instructionSet.size(); ii++) { currentItem = this->instructionSet[ii]; if (ii == this->instructionPointer) { ssReturn << " >"; } else { ssReturn << " "; } ssReturn << ii << ": " << currentItem.toString() << endl; } //-- for } //-- if, else ssReturn << "--cpu--\n" << this->cpu.toString() << endl; ssReturn << "--errors--\n" << this->errors << endl; sReturn = ssReturn.str(); return sReturn; } //-- method: toString //-------------------------------------------- string Program::showErrors() { return this->errors; } //-- method: //-------------------------------------------- int Program::length() { return this->instructionSet.size(); } //-------------------------------------------- int Program::size() { return this->instructionSet.size(); } //-------------------------------------------- int Program::pointer() { return this->instructionPointer; } //-------------------------------------------- string Program::print() { return ""; } //-- method: //-------------------------------------------- string Program::listing() { stringstream ssReturn; Instruction currentItem; ssReturn << "IP:" << this->instructionPointer << endl; if (this->instructionSet.size() == 0) { ssReturn << "(no instructions)" << endl; return ssReturn.str(); } for (int ii = 0; ii < this->instructionSet.size(); ii++) { currentItem = this->instructionSet[ii]; if (ii == this->instructionPointer) { ssReturn << " >"; } else { ssReturn << " "; } ssReturn << ii << ": " << currentItem.toString() << endl; } return ssReturn.str(); } //-- method: //-------------------------------------------- int Program::findLastJump() { return 1; } //-- method: //-------------------------------------------- string Program::showMachine() { return this->cpu.toString(); } //-- method: //-------------------------------------------- string Program::showNext() { stringstream ssReturn; if ((this->instructionPointer >= this->instructionSet.size()) || (this->instructionSet.size() == 0)) { this->errors.append("attempt to access instruction out of range ("); //this->errors += this->instructionPointer; this->errors.append(")"); return ""; } ssReturn << this->instructionPointer << ":" << this->instructionSet.at(this->instructionPointer).toString(); return ssReturn.str(); } //-- method: //-------------------------------------------- void Program::setJump(int iInstruction, int iJump) { if (this->instructionSet.size() == 0) { return; } this->instructionSet.at(iInstruction).setJump(iJump); } //-- method: //-------------------------------------------- void Program::addParameter(string sParameter) { if (this->instructionSet.size() == 0) { this->instructionSet.at(this->instructionPointer - 1).addParameter(sParameter); } } //-- method: //-------------------------------------------- void Program::addInstruction(string ssCommand) { Instruction newInstruction(ssCommand); //newInstruction.setCommand(ssCommand); //cout << "new instruction:" << newInstruction.toString() << endl; this->instructionSet.push_back(newInstruction); } //-- method: //-------------------------------------------- void Program::addInstruction(string sCommand, string sParameter) { Instruction newInstruction(sCommand, sParameter); this->instructionSet.push_back(newInstruction); } //-- method: //-------------------------------------------- /* adds an instruction to the program */ void Program::addInstruction(string sCommand, string sFirstParameter, string sSecondParameter) { Instruction newInstruction(sCommand, sFirstParameter, sSecondParameter); this->instructionSet.push_back(newInstruction); } //-- method: //-------------------------------------------- void Program::addInstruction(string sCommand, vector<string> vParameters) { Instruction newInstruction(sCommand, vParameters); this->instructionSet.push_back(newInstruction); } //-- method: //-------------------------------------------- void Program::run(istream& inputstream) { this->run(inputstream, false); } //-------------------------------------------- void Program::run(istream& inputstream, bool bDebug) { if (bDebug) { cout << this->showMachine(); } while (!inputstream.eof()) { if (bDebug) { //cout << this->showMachine(); cout << this->toString(); } if (this->pointer() >= this->length()) { this->reset(); } this->execute(inputstream); } } //-------------------------------------------- /* resets the instructionPointer to zero */ void Program::reset() { this->instructionPointer = 0; } //-------------------------------------------- void Program::execute(istream& inputstream) { string sCommand(""); string sParameterA(""); string sParameterB(""); Instruction currentInstruction; if ((this->instructionPointer >= this->instructionSet.size()) || (this->instructionSet.size() == 0)) { this->errors.append("attempt to access instruction out of range ("); //this->errors += this->instructionPointer; this->errors.append(")\n"); return; } currentInstruction = this->instructionSet.at(this->instructionPointer); int iInstruction = this->instructionPointer; sCommand = this->instructionSet[iInstruction].getCommand(); sParameterA = this->instructionSet[iInstruction].getParameter(0); sParameterB = this->instructionSet[iInstruction].getParameter(1); // sParameterC = this->instructionSet[iInstruction].getParameter(2); if (sCommand == "add") { this->cpu.add(sParameterA); this->instructionPointer++; } else if (sCommand == "nop") { this->instructionPointer++; } else if (sCommand == "crash") { exit(-1); this->instructionPointer++; } else if (sCommand == "flag") { this->cpu.setFlag(); this->instructionPointer++; } else if (sCommand == "print") { this->cpu.print(); this->instructionPointer++; } else if (sCommand == "clear") { this->cpu.clear(); this->instructionPointer++; } else if (sCommand == "read") { /* if in a stack reduction loop, no read should be performed */ if (!cpu.stackFlag()) { this->cpu.readNext(inputstream); this->instructionPointer++; } } else if (sCommand == "push") { this->cpu.push(); this->instructionPointer++; } else if (sCommand == "pop") { this->cpu.pop(); this->instructionPointer++; } else if (sCommand == "put") { this->cpu.put(); this->instructionPointer++; } else if (sCommand == "get") { this->cpu.get(); this->instructionPointer++; } else if (sCommand == "++") { this->cpu.incrementTape(); this->instructionPointer++; } else if (sCommand == "--") { this->cpu.decrementTape(); this->instructionPointer++; } else if (sCommand == "newline") { this->cpu.newline(); this->instructionPointer++; } else if (sCommand == "indent") { this->cpu.indent(); this->instructionPointer++; } else if (sCommand == "clip") { this->cpu.clip(); this->instructionPointer++; } else if (sCommand == "state") { cout << this->cpu.printState(); this->instructionPointer++; } else if (sCommand == "while") { this->cpu.readWhile(inputstream, sParameterA); this->instructionPointer++; } else if (sCommand == "whilenot") { this->cpu.readWhileNot(inputstream, sParameterA); this->instructionPointer++; } else if (sCommand == "until") { if (this->instructionSet[instructionPointer].size() == 2) { this->cpu.readUntil(inputstream, sParameterA); } else if (this->instructionSet[instructionPointer].size() == 3) { this->cpu.readUntil(inputstream, sParameterA, sParameterB); } this->instructionPointer++; } else if (sCommand == "replace") { this->cpu.replace(sParameterA, sParameterB); this->instructionPointer++; } else if (sCommand == "test-is") { if (this->cpu.workspace() != sParameterA) { this->instructionPointer = currentInstruction.getJump(); } else { this->instructionPointer++; } } else if (sCommand == "test-begins-with") { if (!cpu.beginsWith(sParameterA)) { this->instructionPointer = currentInstruction.getJump(); } else { this->instructionPointer++; } } else if (sCommand == "test-class") { if (sParameterA == ":space:") { this->instructionPointer = currentInstruction.getJump(); } else { this->instructionPointer++; } } else { this->errors.append("unrecognized instruction at "); this->errors += this->instructionPointer; this->errors.append("(" + this->instructionSet[this->instructionPointer].toString() + ")"); this->instructionPointer++; } //-- if } //-- method: execute