← index
cplusplus2x.Examples/C++20/scanner/ETL/test.cpp
Source: cplusplus2x.Examples/C++20/scanner/ETL/test.cpp
#include "codegen.hpp"

#include "ir.hpp"

#include "ir_opt.hpp"

#include "parser.hpp"

#include <fstream>

#include <iostream>

#include <sstream>

#include <string>


extern void outputDebugInfo(std::ostream &file, symbol::SymbolTable &table, const ir::IRCode &code);

void test_parse(const std::string &filename, const std::string &out_file, bool debug_info) {
    std::fstream file;
    file.open(filename, std::ios::in);
    if (!file.is_open()) {
        std::cerr << "ETL: Could not open: " << filename << ".\n";
        exit(EXIT_FAILURE);
    }
    std::ostringstream stream;
    stream << file.rdbuf() << " \n";
    file.close();
    scan::TString p(stream.str());
    std::ostringstream code;
    bool in_string = false;
    bool escaped = false;

    while (1) {
        auto c = p.getch();
        if (c.has_value()) {
            if (escaped) {
                code << *c;
                escaped = false;
            } else if (*c == '\\') {
                escaped = true;
                code << *c;
            } else if (*c == '"') {
                in_string = !in_string;
                code << *c;
            } else if (*c == '#' && !in_string) {
                do {
                    c = p.getch();
                } while (c.has_value() && *c != '\n');
            } else {
                code << *c;
            }
        } else
            break;
    }
    try {

        if (stream.str().length() > 0) {
            parse::Parser parser(new scan::Scanner(scan::TString(code.str())));
            if (parser.parse()) {
                auto rootAST = parser.getAST();
                if (rootAST) {
                    parse::IRGenerator irGen;
                    auto irContext = irGen.generateIR(rootAST);
                    ir::IROptimizer opt;
                    irContext.instructions = std::move(opt.optimize(irContext.instructions));
                    std::cout << "ETL: IR code: {\n";
                    for (const auto &instr : irContext.instructions) {
                        std::cout << "\t" << instr.toString() << "\n";
                    }
                    if (debug_info == true) {
                        std::fstream file;
                        file.open("debug.html", std::ios::out);
                        if (!file.is_open()) {
                            std::cerr << "Error could not open debug output file debug.html\n";
                            exit(EXIT_FAILURE);
                        }
                        outputDebugInfo(file, irContext.table, irContext.instructions);
                        file.close();
                    }
                    codegen::CodeEmitter emitter(irContext.table, irContext.functionLocalVarCount);
                    std::string text = emitter.emit(irContext.instructions);
                    std::fstream ofile;
                    ofile.open(out_file, std::ios::out);
                    ofile << text << "\n";
                    ofile.close();

                    std::cout << "}\n";
                    if (debug_info == true)
                        std::cout << "ETL: outputted debug info [debug.html]\n";

                    std::cout << "ETL: compiled [" << out_file << "]\n";
                    exit(EXIT_SUCCESS);
                }
            } else {
                std::cerr << "ETL: Parsing failed...\n";
                exit(EXIT_FAILURE);
            }
        } else {
            std::cerr << "ETL: Zero bytes to read..\n";
            exit(EXIT_FAILURE);
        }
    } catch (ir::IRException &e) {
        std::cerr << "ETL: IR Exception: " << e.why() << "\n";
        exit(EXIT_FAILURE);
    } catch (parse::ParseException &e) {
        std::cerr << "ETL: Parse Exception: " << e.why() << "\n";
    } catch (...) {
        std::cerr << "ETL: Unknown Exception\n";
        exit(EXIT_FAILURE);
    }
}