#include "Interpreter.hpp" using namespace std; void interpreter::load_commands() { while (input_.good()) { string line; getline(input_, line); process_line_(line); } } void interpreter::execute_commands() { while (current_instruction_ < instructions_.size()) { instructions_.at(current_instruction_)->execute(*this); current_instruction_++; } } void interpreter::process_line_(const std::string& line) { // Nejdriv se zbavim pripadnych komentaru. string line_ = line; for (int i = 0; i < line.size(); i++) { if (line_.at(i) == '#') { line_ = line.substr(0, i); break; } } if (line_ == "") return; // Prazdna radka, jenom komentar. // Nyni odeberu prebytecne whitespace a rozdelim radku na jednotlive tokeny. Na to mam funkci. vector<string> tokens_with_label = get_tokens_(line_); vector<string> tokens; // Nyni se podivam, jestli radka obsahuje navesti. Muze byt pouze v prvnim tokenu. if (tokens_with_label.at(0)[tokens_with_label.at(0).size() - 1] == ':') { labels_.insert(make_pair(tokens_with_label.at(0), instructions_.size() - 1)); for (int i = 1; i < tokens_with_label.size(); i++) { tokens.push_back(tokens_with_label.at(i)); } } else tokens = tokens_with_label; if (tokens_with_label.at(tokens.size() - 1) == "") tokens.pop_back(); if (tokens.at(tokens.size() - 1) == "") tokens.pop_back(); if (tokens.size() == 0 && tokens_with_label.size() > 0) throw invalid_argument("Label found but no instruction given."); // Na nultem miste ve vektoru by mel byt vzdy nazev instrukce. if (tokens.size() == 0) return; // Prazdna radka -> skip. if (tokens.at(0) == "ldconst") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); int value; try { value = stoi(tokens.at(1)); } catch (exception ex) { throw invalid_argument("Error while parsing constant."); } instructions_.push_back(make_unique<ldconst>(value)); } else if (tokens.at(0) == "stloc") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); int index; try { index = stoi(tokens.at(1)); } catch (exception ex) { throw invalid_argument("Error while parsing constant."); } if (index < 0 || index > 9) throw invalid_argument("Invalid index of variable."); instructions_.push_back(make_unique<stloc>(index)); } else if (tokens.at(0) == "ldloc") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); int index; try { index = stoi(tokens.at(1)); } catch (exception ex) { throw invalid_argument("Error while parsing constant."); } if (index < 0 || index > 9) throw invalid_argument("Invalid index of variable."); instructions_.push_back(make_unique<ldloc>(index)); } else if (tokens.at(0) == "pop") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<pop>()); } else if (tokens.at(0) == "out") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<out>()); } else if (tokens.at(0) == "add") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<add>()); } else if (tokens.at(0) == "sub") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<sub>()); } else if (tokens.at(0) == "div") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<div>()); } else if (tokens.at(0) == "mul") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<mul>()); } else if (tokens.at(0) == "lt") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<lt>()); } else if (tokens.at(0) == "gt") { if (tokens.size() != 1) throw invalid_argument("Invalid argument count."); instructions_.push_back(make_unique<gt>()); } else if (tokens.at(0) == "goto") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); string label = tokens.at(1); instructions_.push_back(make_unique<gotoi>(label)); } else if (tokens.at(0) == "brt") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); string label = tokens.at(1); instructions_.push_back(make_unique<brt>(label)); } else if (tokens.at(0) == "brf") { if (tokens.size() != 2) throw invalid_argument("Invalid argument count."); string label = tokens.at(1); instructions_.push_back(make_unique<brf>(label)); } else throw invalid_argument("Unknown token."); } std::vector<std::string> interpreter::get_tokens_(const std::string& line) { vector<string> tokens; tokens.push_back(string()); for (auto&& c : line) { if (c == ' ' || c == '\t') { if (tokens.at(tokens.size() - 1) != "") { // Pokud je posledni token prazdny, tzn. ze zatim tam byly pouze whitespace, nedelame nic. Jinak vytvorime novy token. tokens.push_back(string()); } } else tokens.at(tokens.size() - 1) += c; // Jinak pridame znak do posledniho tokenu. } return tokens; }