|
|
- #include "molasses/lexer.h"
- #include "molasses/parser_primitives.h"
- #include <cstring>
- #include <filesystem>
- #include <fstream>
- #include <iostream>
- #include <sstream>
- #include <stack>
- #include <string>
- #include <variant>
-
- using compile_element = std::variant<molasses::lexed_output, molasses::generate_context, std::string>;
-
- int main(int argc, char** argv) {
- std::vector<std::string> arguments;
- while(argc > 1) {
- argv++;
- arguments.emplace_back(*argv, strlen(*argv));
- argc--;
- }
-
- std::stack<compile_element> compile_stack;
-
- for(auto elem : arguments) {
- if(elem == "generate") {
- if(std::holds_alternative<std::string>(compile_stack.top())) {
- auto filename = std::get<std::string>(compile_stack.top());
- compile_stack.pop();
- if(std::holds_alternative<molasses::generate_context>(compile_stack.top())) {
- auto generator = std::get<molasses::generate_context>(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<molasses::lexed_output>(compile_stack.top())) {
- auto lexer = std::get<molasses::lexed_output>(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<std::string>(compile_stack.top())) {
- auto filename = std::get<std::string>(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<molasses::lexed_output>(compile_stack.top())) {
- auto lexer_1 = std::get<molasses::lexed_output>(compile_stack.top());
- compile_stack.pop();
- if(std::holds_alternative<molasses::lexed_output>(compile_stack.top())) {
- auto lexer_2 = std::get<molasses::lexed_output>(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<std::string>(compile_stack.top())) {
- auto filename = std::get<std::string>(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);
- }
- }
|