feat(frontend): 命令行添加IR和AST选择输出

This commit is contained in:
jing
2026-02-28 23:40:05 +08:00
parent d08b23276a
commit 66659524c8
7 changed files with 75 additions and 16 deletions

View File

@@ -3,3 +3,27 @@
// - 表达式、语句、声明、函数、类型等节点 // - 表达式、语句、声明、函数、类型等节点
// - 支持后续阶段在节点上附加信息(类型、符号绑定、常量值等) // - 支持后续阶段在节点上附加信息(类型、符号绑定、常量值等)
#include "ast/AstNodes.h" #include "ast/AstNodes.h"
#include <utility>
namespace ast {
NumberExpr::NumberExpr(int v) : value(v) {}
VarExpr::VarExpr(std::string n) : name(std::move(n)) {}
BinaryExpr::BinaryExpr(BinaryOp op, std::shared_ptr<Expr> lhs,
std::shared_ptr<Expr> rhs)
: op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {}
ReturnStmt::ReturnStmt(std::shared_ptr<Expr> v) : value(std::move(v)) {}
VarDecl::VarDecl(std::string n, std::shared_ptr<Expr> i)
: name(std::move(n)), init(std::move(i)) {}
FuncDef::FuncDef(std::string n, std::shared_ptr<Block> b)
: name(std::move(n)), body(std::move(b)) {}
CompUnit::CompUnit(std::shared_ptr<FuncDef> f) : func(std::move(f)) {}
} // namespace ast

View File

@@ -16,20 +16,19 @@ struct Expr {
struct NumberExpr : Expr { struct NumberExpr : Expr {
int value{}; int value{};
explicit NumberExpr(int v) : value(v) {} explicit NumberExpr(int v);
}; };
struct VarExpr : Expr { struct VarExpr : Expr {
std::string name; std::string name;
explicit VarExpr(std::string n) : name(std::move(n)) {} explicit VarExpr(std::string n);
}; };
struct BinaryExpr : Expr { struct BinaryExpr : Expr {
BinaryOp op; BinaryOp op;
std::shared_ptr<Expr> lhs; std::shared_ptr<Expr> lhs;
std::shared_ptr<Expr> rhs; std::shared_ptr<Expr> rhs;
BinaryExpr(BinaryOp op, std::shared_ptr<Expr> lhs, std::shared_ptr<Expr> rhs) BinaryExpr(BinaryOp op, std::shared_ptr<Expr> lhs, std::shared_ptr<Expr> rhs);
: op(op), lhs(std::move(lhs)), rhs(std::move(rhs)) {}
}; };
struct Stmt { struct Stmt {
@@ -38,14 +37,13 @@ struct Stmt {
struct ReturnStmt : Stmt { struct ReturnStmt : Stmt {
std::shared_ptr<Expr> value; std::shared_ptr<Expr> value;
explicit ReturnStmt(std::shared_ptr<Expr> v) : value(std::move(v)) {} explicit ReturnStmt(std::shared_ptr<Expr> v);
}; };
struct VarDecl { struct VarDecl {
std::string name; std::string name;
std::shared_ptr<Expr> init; // nullptr if no initializer std::shared_ptr<Expr> init; // nullptr if no initializer
VarDecl(std::string n, std::shared_ptr<Expr> i) VarDecl(std::string n, std::shared_ptr<Expr> i);
: name(std::move(n)), init(std::move(i)) {}
}; };
struct Block { struct Block {
@@ -56,13 +54,12 @@ struct Block {
struct FuncDef { struct FuncDef {
std::string name; std::string name;
std::shared_ptr<Block> body; std::shared_ptr<Block> body;
FuncDef(std::string n, std::shared_ptr<Block> b) FuncDef(std::string n, std::shared_ptr<Block> b);
: name(std::move(n)), body(std::move(b)) {}
}; };
struct CompUnit { struct CompUnit {
std::shared_ptr<FuncDef> func; std::shared_ptr<FuncDef> func;
explicit CompUnit(std::shared_ptr<FuncDef> f) : func(std::move(f)) {} explicit CompUnit(std::shared_ptr<FuncDef> f);
}; };
// 调试打印 // 调试打印

View File

@@ -60,6 +60,7 @@ void PrintAST(const CompUnit& cu) {
PrintLine(0, "CompUnit"); PrintLine(0, "CompUnit");
if (!cu.func) { if (!cu.func) {
PrintLine(1, "<empty>"); PrintLine(1, "<empty>");
std::cout << "\n";
return; return;
} }
@@ -86,6 +87,7 @@ void PrintAST(const CompUnit& cu) {
PrintLine(3, "UnknownStmt"); PrintLine(3, "UnknownStmt");
} }
} }
std::cout << "\n";
} }
namespace { namespace {

View File

@@ -21,7 +21,9 @@ int main(int argc, char** argv) {
} }
auto antlr = ParseFileWithAntlr(opts.input); auto antlr = ParseFileWithAntlr(opts.input);
auto ast = BuildAst(antlr.tree); auto ast = BuildAst(antlr.tree);
ast::PrintAST(*ast); // 调试 AST if (opts.emit_ast) {
ast::PrintAST(*ast); // 调试 AST
}
if (!opts.ast_dot_output.empty()) { if (!opts.ast_dot_output.empty()) {
std::ofstream dot_out(opts.ast_dot_output); std::ofstream dot_out(opts.ast_dot_output);
if (!dot_out) { if (!dot_out) {
@@ -34,8 +36,10 @@ int main(int argc, char** argv) {
// 同学们可以在 irgen/ 目录下按提示自行完善或替换实现。 // 同学们可以在 irgen/ 目录下按提示自行完善或替换实现。
auto module = GenerateIR(*ast); auto module = GenerateIR(*ast);
ir::IRPrinter printer; if (opts.emit_ir) {
printer.Print(*module); ir::IRPrinter printer;
printer.Print(*module);
}
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
std::cerr << "error: " << ex.what() << "\n"; std::cerr << "error: " << ex.what() << "\n";
return 1; return 1;

View File

@@ -11,9 +11,11 @@
CLIOptions ParseCLI(int argc, char** argv) { CLIOptions ParseCLI(int argc, char** argv) {
CLIOptions opt; CLIOptions opt;
bool explicit_emit = false;
if (argc <= 1) { if (argc <= 1) {
throw std::runtime_error("用法: compiler [--help] [--ast-dot <file.dot>] <input.sy>"); throw std::runtime_error(
"用法: compiler [--help] [--emit-ast] [--emit-ir] [--ast-dot <file.dot>] <input.sy>");
} }
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
@@ -31,6 +33,26 @@ CLIOptions ParseCLI(int argc, char** argv) {
continue; continue;
} }
if (std::strcmp(arg, "--emit-ast") == 0) {
if (!explicit_emit) {
opt.emit_ast = false;
opt.emit_ir = false;
explicit_emit = true;
}
opt.emit_ast = true;
continue;
}
if (std::strcmp(arg, "--emit-ir") == 0) {
if (!explicit_emit) {
opt.emit_ast = false;
opt.emit_ir = false;
explicit_emit = true;
}
opt.emit_ir = true;
continue;
}
if (arg[0] == '-') { if (arg[0] == '-') {
throw std::runtime_error(std::string("未知参数: ") + arg + throw std::runtime_error(std::string("未知参数: ") + arg +
"(使用 --help 查看用法)"); "(使用 --help 查看用法)");
@@ -46,5 +68,9 @@ CLIOptions ParseCLI(int argc, char** argv) {
if (opt.input.empty() && !opt.show_help) { if (opt.input.empty() && !opt.show_help) {
throw std::runtime_error("缺少输入文件:请提供 <input.sy>(使用 --help 查看用法)"); throw std::runtime_error("缺少输入文件:请提供 <input.sy>(使用 --help 查看用法)");
} }
if (!opt.emit_ast && !opt.emit_ir && opt.ast_dot_output.empty()) {
throw std::runtime_error(
"未选择任何输出:请使用 --emit-ast 或 --emit-ir或使用 --ast-dot 导出图)");
}
return opt; return opt;
} }

View File

@@ -6,6 +6,8 @@
struct CLIOptions { struct CLIOptions {
std::string input; std::string input;
std::string ast_dot_output; std::string ast_dot_output;
bool emit_ast = true;
bool emit_ir = true;
bool show_help = false; bool show_help = false;
}; };

View File

@@ -10,13 +10,17 @@ void PrintHelp(std::ostream& os) {
os << "SysY Compiler (课程实验最小可运行示例)\n" os << "SysY Compiler (课程实验最小可运行示例)\n"
<< "\n" << "\n"
<< "用法:\n" << "用法:\n"
<< " compiler [--help] [--ast-dot <file.dot>] <input.sy>\n" << " compiler [--help] [--emit-ast] [--emit-ir] [--ast-dot <file.dot>] <input.sy>\n"
<< "\n" << "\n"
<< "选项:\n" << "选项:\n"
<< " -h, --help 打印帮助信息并退出\n" << " -h, --help 打印帮助信息并退出\n"
<< " --emit-ast 仅在显式模式下启用 AST 文本输出\n"
<< " --emit-ir 仅在显式模式下启用 IR 输出\n"
<< " --ast-dot <path> 导出 AST Graphviz DOT 到指定文件\n" << " --ast-dot <path> 导出 AST Graphviz DOT 到指定文件\n"
<< "\n" << "\n"
<< "说明:\n" << "说明:\n"
<< " - 当前默认将 IR 输出到标准输出,可使用重定向写入文件:\n" << " - 默认同时输出 AST 与 IR\n"
<< " - 若使用 --emit-ast/--emit-ir则仅输出显式选择的阶段\n"
<< " - 可使用重定向写入文件:\n"
<< " compiler test/test_case/simple_add.sy > out.ll\n"; << " compiler test/test_case/simple_add.sy > out.ll\n";
} }