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

master
jing 4 weeks ago
parent d08b23276a
commit 66659524c8

@ -3,3 +3,27 @@
// - 表达式、语句、声明、函数、类型等节点
// - 支持后续阶段在节点上附加信息(类型、符号绑定、常量值等)
#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

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

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

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

@ -11,9 +11,11 @@
CLIOptions ParseCLI(int argc, char** argv) {
CLIOptions opt;
bool explicit_emit = false;
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) {
@ -31,6 +33,26 @@ CLIOptions ParseCLI(int argc, char** argv) {
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] == '-') {
throw std::runtime_error(std::string("未知参数: ") + arg +
"(使用 --help 查看用法)");
@ -46,5 +68,9 @@ CLIOptions ParseCLI(int argc, char** argv) {
if (opt.input.empty() && !opt.show_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;
}

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

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

Loading…
Cancel
Save