|
|
// 格式化错误并统一打印异常与帮助信息。
|
|
|
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
#include <ostream>
|
|
|
#include <string>
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
bool IsCLIError(const std::string_view msg) {
|
|
|
return HasErrorPrefix(msg, "cli");
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
void LogInfo(const std::string_view msg, std::ostream& os) {
|
|
|
os << "[info] " << msg << "\n";
|
|
|
}
|
|
|
|
|
|
void LogError(const std::string_view msg, std::ostream& os) {
|
|
|
os << "[error] " << msg << "\n";
|
|
|
}
|
|
|
|
|
|
std::string FormatError(const std::string_view stage,
|
|
|
const std::string_view msg) {
|
|
|
return "[" + std::string(stage) + "] " + std::string(msg);
|
|
|
}
|
|
|
|
|
|
std::string FormatErrorAt(const std::string_view stage, const std::size_t line,
|
|
|
const std::size_t column,
|
|
|
const std::string_view msg) {
|
|
|
return "[" + std::string(stage) + "] @" + std::to_string(line) + ":" +
|
|
|
std::to_string(column) + " - " + std::string(msg);
|
|
|
}
|
|
|
|
|
|
bool HasErrorPrefix(const std::string_view msg, const std::string_view stage) {
|
|
|
const std::string prefix = "[" + std::string(stage) + "]";
|
|
|
return msg.rfind(prefix, 0) == 0;
|
|
|
}
|
|
|
|
|
|
void PrintException(std::ostream& os, const std::exception& ex) {
|
|
|
LogError(ex.what(), os);
|
|
|
if (IsCLIError(ex.what())) {
|
|
|
os << "\n";
|
|
|
PrintHelp(os);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void PrintHelp(std::ostream& os) {
|
|
|
os << "SysY Compiler\n"
|
|
|
<< "\n"
|
|
|
<< "用法:\n"
|
|
|
<< " compiler [--help] [--emit-parse-tree] [--emit-ir] [--emit-asm] <input.sy>\n"
|
|
|
<< "\n"
|
|
|
<< "选项:\n"
|
|
|
<< " -h, --help 打印帮助信息并退出\n"
|
|
|
<< " --emit-parse-tree 仅在显式模式下启用语法树输出\n"
|
|
|
<< " --emit-ir 仅在显式模式下启用 IR 输出\n"
|
|
|
<< " --emit-asm 仅在显式模式下启用 AArch64 汇编输出\n"
|
|
|
<< "\n"
|
|
|
<< "说明:\n"
|
|
|
<< " - 默认输出 IR\n"
|
|
|
<< " - 若使用 --emit-parse-tree/--emit-ir/--emit-asm,则仅输出显式选择的阶段\n"
|
|
|
<< " - 可使用重定向写入文件:\n"
|
|
|
<< " compiler --emit-asm test/test_case/simple_add.sy > out.s\n";
|
|
|
}
|