compiler-go/main.cpp

142 lines
4.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <antlr4-runtime.h>
#include "Public/Public.h"
#include "ICG/GoTo3code.h"
#include "GoParser.h"
#include "GoLexer.h"
#include "GoParserListener.h"
#include "GoParserBaseListener.h"
#include "TCG/Translator.h"
#include <iostream>
#include <vector>
#include <string>
#include <filesystem>
#include <optional>
#include <memory>
using namespace std;
bool ends_with(const std::string& str, const std::string& suffix) {
if (str.length() < suffix.length()) {
return false;
}
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
}
void init_log(const std::string& log_file_name, const std::string& log_path) {
system(("mkdir -p " + log_path).c_str());
google::InitGoogleLogging(log_file_name.c_str());
google::SetLogDestination(google::GLOG_INFO, (log_path + "/").c_str());
google::InstallFailureSignalHandler(); // Capture signals
FLAGS_log_prefix = false; // Log prefixes
FLAGS_colorlogtostderr = true; // Color logs in stderr
FLAGS_alsologtostderr = true; // Log to console
FLAGS_logbufsecs = 0; // Disable log buffering
}
struct CmdParam {
std::vector<std::string> input;
std::string output;
std::string output_3code = "3code.txt";
std::string output_asm = "out.asm";
std::string output_bin = "out.bin";
std::string log_path = "./log";
std::string log_file_name;
};
std::optional<std::string> parse_option(const std::string& option, int& i, int argc, char* argv[]) {
if (i + 1 < argc) {
return argv[++i];
}
std::cerr << "Option " << option << " requires a value." << std::endl;
exit(EXIT_FAILURE);
}
CmdParam read_cmd_param(int argc, char* argv[]) {
CmdParam cmd_param;
cmd_param.log_file_name = argv[0];
for (int i = 1; i < argc; ++i) {
std::string argv_i = argv[i];
if (argv_i[0] == '-') {
if (argv_i.length() == 1) {
std::cerr << "Invalid option." << std::endl;
exit(EXIT_FAILURE);
}
if (auto value = parse_option(argv_i, i, argc, argv)) {
if (argv_i == "-o" || argv_i == "--output") {
cmd_param.output = *value;
} else if (argv_i == "-l" || argv_i == "--log") {
cmd_param.log_path = *value;
} else {
std::cerr << "Unknown parameter " << argv_i << std::endl;
exit(EXIT_FAILURE);
}
}
} else {
cmd_param.input.emplace_back(argv[i]);
}
}
if (cmd_param.input.empty()) {
std::cerr << "No input .go files provided." << std::endl;
exit(EXIT_FAILURE);
}
for (const auto& input_file : cmd_param.input) {
std::string base_name = std::filesystem::path(input_file).stem().string();
if (ends_with(base_name, ".go")) {
base_name = base_name.substr(0, base_name.length() - 3);
}
cmd_param.output = base_name;
std::filesystem::create_directories(cmd_param.output);
}
return cmd_param;
}
int main(int argc, char* argv[]) {
try
{
CmdParam cmd_param = read_cmd_param(argc, argv);
init_log(cmd_param.log_file_name, cmd_param.log_path);
const string& filename = cmd_param.input.front();
LOG(INFO) << "Starting translation for file: " << filename;
antlr4::ANTLRFileStream file;
file.loadFromFile(filename);
antlr4::ANTLRInputStream inputStream(file.toString());
LOG(INFO) << "Starting lexical analysis.";
GoLexer lexer(&inputStream);
antlr4::CommonTokenStream tokens(&lexer);
LOG(INFO) << "Starting syntax analysis.";
GoParser parser(&tokens);
// 遍历AST自定义生成三地址代码
GoTo3code listener;
antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, parser.sourceFile());
std::string path_3code = cmd_param.output + "/" + cmd_param.output_3code;
listener.Go23file_(path_3code);
// 三地址转汇编
LOG(INFO) << "Translating three-address code to assembly.";
auto tac_file = make_shared<TACFile>(std::move(listener.TACBlocks));
Translator translator(tac_file, listener.globalScope);
translator.Translate();
std::string path_asm = cmd_param.output + "/" + cmd_param.output_asm;
translator.OutputFile(path_asm);
LOG(INFO) << "Translation completed successfully.";
return 0;
}
catch(...)
{
LOG(ERROR) << "Translation completed unsuccessfully.";
return -1;
}
}