#include "molasses/lexer.h" #include "molasses/parser_primitives.h" #include #include #include #include #include #include #include #include using compile_element = std::variant; int main(int argc, char** argv) { std::vector arguments; while(argc > 1) { argv++; arguments.emplace_back(*argv, strlen(*argv)); argc--; } std::stack compile_stack; for(auto elem : arguments) { if(elem == "generate") { if(std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); compile_stack.pop(); if(std::holds_alternative(compile_stack.top())) { auto generator = std::get(compile_stack.top()); compile_stack.pop(); auto assembler = molasses::generate(generator); std::ofstream output(filename+".s"); for(const auto& line : assembler) { output << line; } compile_stack.emplace(filename); } else throw std::runtime_error("generate expects a parsed output"); } else throw std::runtime_error("generate expects a filename"); } else if(elem == "parse") { molasses::parser_context ctx; ctx = molasses::register_integers(ctx); ctx = molasses::register_i32_operations(ctx); if(std::holds_alternative(compile_stack.top())) { auto lexer = std::get(compile_stack.top()); compile_stack.pop(); auto generator = molasses::parse(ctx, lexer); compile_stack.emplace(generator); } else throw std::runtime_error("parse expects a lexed output"); } else if(elem == "lex") { if(std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); compile_stack.pop(); if(not std::filesystem::exists(filename)) throw std::runtime_error("file "+filename+" does not exist"); std::ifstream t(filename); std::stringstream buffer; buffer << t.rdbuf(); auto lexed = molasses::lex(buffer.str()); compile_stack.emplace(lexed); } else throw std::runtime_error("lex expects a filename"); } else if(elem == "merge") { if(std::holds_alternative(compile_stack.top())) { auto lexer_1 = std::get(compile_stack.top()); compile_stack.pop(); if(std::holds_alternative(compile_stack.top())) { auto lexer_2 = std::get(compile_stack.top()); compile_stack.pop(); compile_stack.emplace(molasses::concatenate(lexer_1, lexer_2)); } else throw std::runtime_error("merge expects 2 lexed outputs"); } else throw std::runtime_error("merge expects 2 lexed outputs"); } else if(elem == "assemble") { if(std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); compile_stack.pop(); std::stringstream compile; compile << "clang -c " << filename << ".s -o " << filename << ".o"; std::stringstream link; link << "ld -e _start " << filename << ".o -o " << filename; std::cout << compile.str() << std::endl; system(compile.str().c_str()); std::cout << link.str() << std::endl; system(link.str().c_str()); } else throw std::runtime_error("assemble expects an assembly file"); } else compile_stack.emplace(elem); } }