diff options
1 files changed, 249 insertions, 0 deletions
| -rw-r--r-- | JSImpl/src/main.cpp | 249 |
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp new file mode 100644 index 0000000..aee465d --- /dev/null +++ b/JSImpl/src/main.cpp @@ -0,0 +1,249 @@ +#include "Lexer.h" +#include "Parser.h" +#include "ASTPrinter.h" +#include "ASTInterpreter.h" +#include "ByteCodeGenerator.h" +#include <iostream> +#include <cstring> +#include <unordered_map> +#include <sstream> +#include <fstream> +#include <iterator> + +#if defined(_WIN32) +#include <Windows.h> +#endif + +void RunParseCalc() +{ + //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); + auto tokens = Tokenize("var a = 5; if(a == 5){a++;}").tokens; + + // TODO make actual test :D + auto expr = Parse(tokens); + PrintAST(expr, std::cout); + //ASTInterpreter i; + //std::cout << "Running" << std::endl; + //auto result = i.Run(expr.get()); + //std::cout << "Stack after run, top to bottom:" << std::endl; + //while (!result.empty()) { + // std::cout << result.back() << std::endl; + // result.pop_back(); + //} + //std::cout << "S = " << i.ModifyVariable("a") << std::endl; +} + +class InterpreterPrinter : public ASTInterpreter::Printer +{ +public: + virtual void PrintVariable(const char* name, double value) override + { + std::cout << name << ": number : " << value << std::endl; + } + virtual void PrintVariable(const char* name, const IPLString& value) override + { + std::cout << name << ": string : " << value << std::endl; + } +}; + +void InteractiveInterpreter() +{ + char command[1000]; + ASTInterpreter i; + InterpreterPrinter p; + do + { + std::cin.getline(command, 1000); + if (std::strcmp(command, "exit") == 0) + { + break; + } + if (std::strcmp(command, "print") == 0) + { + i.Print(p); + continue; + } + auto tokens = Tokenize(command).tokens; + auto result = i.Run(Parse(tokens).get()); + while (!result.empty()) { + std::cout << result.back() << std::endl; + result.pop_back(); + } + } while (true); +} + +void Generate() +{ + //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); + /*Tokenize("var a; if(a < 4) { a = 8; if(a < 7) {var b = 4;}} else { a = 2} ", tokens);*/ + //IPLString source = "var i = 0; \n" + // "for (var j = 0; j < 10; j++)\n" + // "{\n" + // " i = i + j;\n" + // "}"; + IPLString source = "var a = 5; do{ a--; if(a == 4) continue; }while(a != 0)\n"; + auto tokens = Tokenize(source.c_str()).tokens; + + auto asmb = GenerateByteCode(Parse(tokens), source, + ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false)); + + //sets the color to intense red on blue background +#if defined(_WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + std::istringstream asmbStream(asmb); + while (asmbStream.good()) + { + IPLString it; + std::getline(asmbStream, it); + if (it[0] == 'D') + { + SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN| BACKGROUND_BLUE | FOREGROUND_INTENSITY); + auto dd = it.find("@@=>"); + std::cout << it.substr(0, dd); + SetConsoleTextAttribute(hStdout, FOREGROUND_RED | BACKGROUND_BLUE | FOREGROUND_INTENSITY); + std::cout << it.substr(dd, 4); + SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | BACKGROUND_BLUE | FOREGROUND_INTENSITY); + std::cout << it.substr(dd + 4, it.size()) << std::endl; + } + else + { + std::cout << it << std::endl; + } + SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + } +#else + std::cout << asmb; +#endif +} + + +class CammandLineApp +{ +public: + CammandLineApp() + : m_PrintAst(false) + , m_PrintTokens(false) + { + m_CommandMapping["--output"] = CommandType::Output; + m_CommandMapping["--input"] = CommandType::Input; + m_CommandMapping["--ast"] = CommandType::PrintAST; + m_CommandMapping["--tokens"] = CommandType::PrintTokens; + m_CommandMapping["--help"] = CommandType::Help; + } + + enum class CommandType + { + Output, + Input, + PrintAST, + PrintTokens, + Help + }; + + void PrintHelp() + { + std::cout << "Supports following arguments:" << std::endl + << "--output - output file path" << std::endl + << "--input - input file path" << std::endl + << "--ast - will write ast of the input in the output" << std::endl + << "--tokens - will tokenize input file and will write the result as json in the output" << std::endl + << "--help - this message" << std::endl; + } + + void ParseArguments(int argcount, char* arguments[]) + { + for (int i = 1; i < argcount; ) + { + auto it = m_CommandMapping.find(arguments[i]); + if (it == m_CommandMapping.end()) + { + PrintHelp(); + } + auto command = it->second; + ++i; + switch (command) + { + case CommandType::Output: + assert(i < argcount); + m_Output = arguments[i]; + ++i; + break; + case CommandType::Input: + assert(i < argcount); + m_Input = arguments[i]; + ++i; + break; + case CommandType::PrintAST: + m_PrintAst = true; + break; + case CommandType::PrintTokens: + m_PrintTokens = true; + break; + case CommandType::Help: + default: + PrintHelp(); + return; + } + } + } + + void ExecuteCommands() + { + std::ifstream input(m_Input.c_str()); + input.seekg(0, std::ios::end); + std::string code; + int size = (int)input.tellg(); + code.resize(size); + input.seekg(0, std::ios::beg); + input.read(&code[0], code.size()); + input.close(); + + auto tokenizationResult = Tokenize(code.c_str()); + if (!tokenizationResult.IsSuccessful) + { + return; + } + auto programAst = Parse(tokenizationResult.tokens); + if (m_PrintAst) + { + std::ofstream output(m_Output, std::ofstream::trunc); + PrintAST(programAst, output); + output.close(); + } + + if (m_PrintTokens) + { + + } + } + + void RunAsCommandLine(int argcount, char* arguments[]) + { + ParseArguments(argcount, arguments); + ExecuteCommands(); + } +private: + std::string m_Output; + std::string m_Input; + bool m_PrintAst; + bool m_PrintTokens; + std::unordered_map<std::string, CommandType> m_CommandMapping; +}; + +int main(int argc, char* argv[]) +{ + (void)argv; + (void)argc; + // You can try => + // Working dir: $(ProjectDir) + // Command arguments: --input ./../examples/code.js --output ./../examples/some.ast --ast + //CammandLineApp cmd; + //cmd.RunAsCommandLine(argc, argv); + //auto r = Tokenize("a#4", {true ,true}); + //RunParseCalc(); + Generate(); +#if defined(_WIN32) + //std::system("pause"); +#endif + return 0; +} |
