#include #include #include #include #include #include #include using namespace std; enum class valtype { INT, DEC, STR, BOOL, KEYWORD, UNKNOWN }; enum class keywords { IF, ELSE, WHILE, INT, DEC, STR, BOOL, FUN, RETURN, OPARE, CPARE, OBRAC, CBRAC, ADDTO, TAKEFROM, MULTIPLYTO, DIVIDEFROM, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, LESS, GREATER, EQLESS, EQGREATER, INCREMENT, DECREMENT, PRINT, INPUT, VALUE, SEMICOLON }; struct Token { keywords keyword; string value; valtype type = valtype::KEYWORD; }; struct var { valtype type; variant value; string toString() const { if (type == valtype::INT) { return to_string(get(value)); } else if (type == valtype::DEC) { return to_string(get(value)); } else if (type == valtype::STR) { return get(value); } else if (type == valtype::BOOL) { return to_string(get(value)); } else { return "unknown"; } } }; class Logger { private: bool isDebug = false; string log; void writeToLog(string type, string in) { log += type + ": " + in + "\n"; } public: string getLog() { return log; } void toggleDebugPrint() { isDebug = !isDebug; } void error(string in) { cout << "Error: " + in + "\n"; writeToLog("Error", in); } void fatalError(string in, int code) { cout << "Error: " + in + "\n"; writeToLog("Error", in); exit(code); } void info(string in) { cout << "Info: " + in + "\n"; writeToLog("Info", in); } void debug(string in) { if (isDebug) cout << "Debug: " + in + "\n"; writeToLog("Debug", in); } }; class Parser { private: string buffer; vector lines; vector termBuffer; vector tokens; vector> terms; vector> things; vector>> stuff; bool canInt(string in) { try { stoi(in); return true; } catch (...) { return false; } } bool canDec(string in) { try { stod(in); return true; } catch (...) { return false; } } public: void parseLines(string in, Logger log) { log.debug("Parsing lines..."); buffer = ""; bool isString = false; for (int i = 0; i < in.size(); i++) { if (in[i] == '"') { isString = !isString; } else if (in[i] == '\n') { // whole lotta nothing } else if (in[i] == ';' && !isString) { // Push back and clear the buffer of terms if (!buffer.empty()) termBuffer.push_back(buffer); terms.push_back(termBuffer); termBuffer.clear(); buffer = ""; } else if (in[i] == ',' && !isString) { // Push back the buffer and the ',' seperately termBuffer.push_back(buffer); termBuffer.push_back(","); buffer = ""; } else if (in[i] == '{' && !isString) { // Push back the buffer and the '{' seperately termBuffer.push_back(buffer); termBuffer.push_back("{"); buffer = ""; } else if (in[i] == '}' && !isString) { // Push back the buffer and the '}' seperately termBuffer.push_back(buffer); termBuffer.push_back("}"); buffer = ""; } else if (in[i] == '(' && !isString) { // Push back the buffer and the '(' seperately termBuffer.push_back(buffer); termBuffer.push_back("("); buffer = ""; } else if (in[i] == ')' && !isString) { // Push back the buffer and the ')' seperately termBuffer.push_back(buffer); termBuffer.push_back(")"); buffer = ""; } else if (in[i] == ' ' && !isString) { // Push back and reset buffer for that term if (!buffer.empty()) termBuffer.push_back(buffer); buffer = ""; } else { buffer += in[i]; } } if (!buffer.empty()) termBuffer.push_back(buffer); if (!termBuffer.empty()) terms.push_back(termBuffer); string debugString; log.debug("Lines have been parsed."); for (int i = 0; i < terms.size(); i++) { for (int j = 0; j < terms[i].size(); j++) { debugString += terms[i][j] + ", "; } debugString += "\n"; } log.debug(debugString); } void processLines() { // Process vector> terms for (int i = 0; i < terms.size(); i++) { for (int j = 0; j < terms[i].size(); j++) { Token token; string ct = terms[i][j]; if (ct == " ") {} // Oh boy here we go else if (ct == "fun") token.keyword = keywords::FUN; else if (ct == "return") token.keyword = keywords::RETURN; else if (ct == "int") token.keyword = keywords::INT; else if (ct == "{") token.keyword = keywords::OBRAC; else if (ct == "}") token.keyword = keywords::CBRAC; else if (ct == "(") token.keyword = keywords::OPARE; else if (ct == ")") token.keyword = keywords::CPARE; else if (ct == "+") token.keyword = keywords::ADD; else if (ct == "-") token.keyword = keywords::SUBTRACT; else if (ct == "*") token.keyword = keywords::MULTIPLY; else if (ct == "/") token.keyword = keywords::DIVIDE; else { token.keyword = keywords::VALUE; token.value = ct; if (canInt(ct)) token.type = valtype::INT; if (canDec(ct)) token.type = valtype::DEC; if (ct == "true" || ct == "false") token.type = valtype::BOOL; } tokens.push_back(token); } Token semi; semi.keyword = keywords::SEMICOLON; tokens.push_back(semi); } } }; class Interpreter { private: vector tokens; int tokenIndex = 0; Token consume() { return tokens[tokenIndex++]; } Token peek(int index = 1) { return tokens[tokenIndex + index]; } public: void interpret(vector tokenList) { tokens = tokenList; while (tokenIndex < tokens.size()) { } } }; int main(int argc, char* argv[]) { // Initialise the logger and parser Logger log; log.toggleDebugPrint(); log.debug("Logger initialised!"); Parser parser; // Exit if file doesn't exist if (argc < 2) log.fatalError("Please provide a file", 1); // Read the file ifstream inputFile(argv[1]); string input; string file; while(getline(inputFile, input)) { file += input; } parser.parseLines(file, log); parser.processLines(); return 0; }