// computer.cpp : Problem #4 Virtual Computer // #include #include #include #include #include #include #define MAX_TOKENS 5 #define MAX_LINE_LENGTH 100 #define MAX_TOKEN_LENGTH 10 #define MAX_PROGRAM_LENGTH 100 #define MAX_VARS 26 class Program { public: Program(); bool end() { return programEnd; } void init(); void addLine(char line[]) { strcpy(prog[numLines++], line); } void executeLine(); int readNumber(char *number); private: char prog[MAX_PROGRAM_LENGTH][MAX_LINE_LENGTH]; char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH]; int vars[MAX_VARS]; bool programEnd; bool ifStatement; int programName; int numLines; int currentLine; int currentChar; void resetTokens(); void getTokens(); void executeStart(); void executeSet(); void executeStore(); void executeMult(); void executeSub(); void executeDiv(); void executeAdd(); void executePrint(); void executeGoto(); void executeIf(); void executeEnd() { programEnd = true; } }; bool readProgram(Program& currentProgram); int main(int argc, char* argv[]) { Program currentProgram; //Continue until EOF or invalid program read while (readProgram(currentProgram)) while (!currentProgram.end()) currentProgram.executeLine(); return 0; } bool readProgram(Program& currentProgram) { bool programRead = false; bool startRead = false; bool validProgram = true; char line[MAX_LINE_LENGTH] = ""; char firstToken[MAX_TOKEN_LENGTH] = ""; char restOfLine[MAX_LINE_LENGTH] = ""; currentProgram.init(); cin >> firstToken; while (cin && !programRead && validProgram) { strcpy(line, firstToken); if (strcmp(firstToken, "START") == 0) { if (startRead) { validProgram = false; cout << "Program contained two START statements" << endl; } else startRead = true; } else if (strcmp(firstToken, "END") == 0) { if (!startRead) { validProgram = false; cout << "Program contained END statement before START statement" << endl; } else programRead = true; } else { if (!startRead) { validProgram = false; cout << "Program did not begin with a START statement" << endl; } } //If the first token is not an END statement, //read in rest of line and add complete line to the program if (!programRead) { cin.get(restOfLine, MAX_LINE_LENGTH - strlen(line)); strcat(line, restOfLine); currentProgram.addLine(line); //Read in firstToken of next line cin >> firstToken; } else currentProgram.addLine(line); } return validProgram && cin; } Program::Program() { init(); } void Program::init() { currentLine = 0; numLines = 0; programEnd = false; ifStatement = false; for (int i = 0; i < MAX_VARS; i++) vars[i] = 0; } void Program::executeLine() { resetTokens(); getTokens(); if (strcmp(tokens[0], "START") == 0) executeStart(); else if (strcmp(tokens[0], "SET") == 0) { executeSet(); } else if (strcmp(tokens[0], "STORE") == 0) executeStore(); else if (strcmp(tokens[0], "MULT") == 0) executeMult(); else if (strcmp(tokens[0], "SUB") == 0) { executeSub(); } else if (strcmp(tokens[0], "DIV") == 0) executeDiv(); else if (strcmp(tokens[0], "ADD") == 0) executeAdd(); else if (strcmp(tokens[0], "PRINT") == 0) { executePrint(); } else if (strcmp(tokens[0], "GOTO") == 0) executeGoto(); else if (strcmp(tokens[0], "IF") == 0 && strcmp(tokens[2], "IS") == 0 && strcmp(tokens[4], "THEN") == 0) executeIf(); else if (strcmp(tokens[0], "END") == 0) executeEnd(); else { cout << "ERROR: invalid statement" << endl; cout << prog[currentLine] << endl; programEnd = true; } } void Program::resetTokens() { for (int i = 0; i < MAX_TOKENS; i++) tokens[i][0] = '\0'; } void Program::getTokens() { int currentToken = 0; if (ifStatement) ifStatement = false; else currentChar = 0; //Continue until EOL or an if statement is encountered while (prog[currentLine][currentChar] != '\0' && !ifStatement) { //If not at beginning of line, go to next token if (currentChar) currentChar++; int currentTokenChar = 0; while (prog[currentLine][currentChar] != ' ' && prog[currentLine][currentChar] != '\0' && currentTokenChar < MAX_TOKEN_LENGTH) tokens[currentToken][currentTokenChar++] = prog[currentLine][currentChar++]; tokens[currentToken][currentTokenChar] = '\0'; if (currentToken == 4 && strcmp(tokens[currentToken], "THEN") == 0) ifStatement = true; currentToken++; } } int Program::readNumber(char *number) { int return_value; int start = 0; char actual_number[MAX_TOKEN_LENGTH]; if (number[0] == '-') { for (int i = 1; i < (strlen(number) + 1); i++) { actual_number[i-1] = number[i]; } return_value = -1 * atoi(actual_number); } else { return_value = atoi(number); } //cout << return_value << endl; return return_value; } void Program::executeStart() { programName = readNumber(tokens[1]); cout << prog[currentLine++] << endl; } void Program::executeSet() { if (!tokens[1][0] || !isalpha(tokens[1][0])) { cout << "ERROR: SET " << endl; cout << "variable should be an alpha character" << endl; programEnd = true; } else if (!tokens[2][0]) { cout << "ERROR: SET " << endl; cout << "value should be specified" << endl; programEnd = true; } else { vars[tokens[1][0] - 'a'] = readNumber(tokens[2]); currentLine++; } } void Program::executeStore() { if (!tokens[1][0] || !isalpha(tokens[1][0]) || !tokens[2][0] || !isalpha(tokens[2][0]) ) { cout << "ERROR: STORE " << endl; cout << "variables should be alpha characters" << endl; programEnd = true; } else vars[tokens[1][0] - 'a'] = vars[tokens[2][0] - 'a']; currentLine++; } void Program::executeMult() { if (!tokens[1][0] || !isalpha(tokens[1][0]) || !tokens[2][0] || !isalpha(tokens[2][0]) ) { cout << "ERROR: MULT " << endl; cout << "variables should be alpha characters" << endl; programEnd = true; } else vars[tokens[1][0] - 'a'] = vars[tokens[1][0] - 'a'] * vars[tokens[2][0] - 'a']; currentLine++; } void Program::executeSub() { if (!tokens[1][0] || !isalpha(tokens[1][0]) || !tokens[2][0] || !isalpha(tokens[2][0]) ) { cout << "ERROR: SUB " << endl; cout << "variables should be alpha characters" << endl; programEnd = true; } else vars[tokens[1][0] - 'a'] = vars[tokens[1][0] - 'a'] - vars[tokens[2][0] - 'a']; currentLine++; } void Program::executeDiv() { if (!tokens[1][0] || !isalpha(tokens[1][0]) || !tokens[2][0] || !isalpha(tokens[2][0]) ) { cout << "ERROR: DIV " << endl; cout << "variables should be alpha characters" << endl; programEnd = true; } else if (vars[tokens[2][0] - 'a'] == 0) { } else { vars[tokens[1][0] - 'a'] = (int) floor(((double) vars[tokens[1][0] - 'a']) / ((double)vars[tokens[2][0] - 'a'])); } currentLine++; } void Program::executeAdd() { if (!tokens[1][0] || !isalpha(tokens[1][0]) || !tokens[2][0] || !isalpha(tokens[2][0]) ) { cout << "ERROR: ADD " << endl; cout << "variables should be alpha characters" << endl; programEnd = true; } else vars[tokens[1][0] - 'a'] = vars[tokens[1][0] - 'a'] + vars[tokens[2][0] - 'a']; currentLine++; } void Program::executePrint() { if (!tokens[1][0] || !isalpha(tokens[1][0])) { cout << "ERROR: PRINT " << endl; cout << "variable should be an alpha character" << endl; programEnd = true; } else cout << vars[tokens[1][0] - 'a'] << endl; currentLine++; } void Program::executeGoto() { if (!tokens[1][0]) { cout << "ERROR: GOTO " << endl; cout << "line number should be specified" << endl; programEnd = true; } else { int lineNum = readNumber(tokens[1]); if (lineNum < 1 || lineNum > numLines) { cout << "ERROR: GOTO " << endl; cout << "line number should be a valid program line" << endl; cout << "numLines is " << numLines << endl; } else currentLine = lineNum - 1; //offset for first line being 1 } } void Program::executeIf() { if (!tokens[1][0] || !isalpha(tokens[1][0])) { cout << "ERROR: IF IS THEN " << endl; cout << "variable should be an alpha character" << endl; programEnd = true; } else if (!tokens[3][0]) { cout << "ERROR: IF IS THEN " << endl; cout << "value should be specified" << endl; programEnd = true; } else { if (vars[tokens[1][0] - 'a'] == readNumber(tokens[3])) executeLine(); else { ifStatement = false; currentLine++; } } }