// 将 parse tree 转换为 AST。 #include "frontend/AstBuilder.h" #include #include #include #include #include #include "SysYBaseVisitor.h" #include "SysYParser.h" #include "ast/AstNodes.h" #include "antlr4-runtime.h" namespace { using ast::BinaryExpr; using ast::BinaryOp; using ast::Block; using ast::CompUnit; using ast::FuncDef; using ast::NumberExpr; using ast::ReturnStmt; using ast::VarDecl; using ast::VarExpr; template T Take(std::any&& value) { if (auto* ptr = std::any_cast(&value)) { return std::move(*ptr); } throw std::runtime_error("AST 构建失败:类型不匹配"); } class Builder : public SysYBaseVisitor { public: std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override { auto func = Take>(visit(ctx->funcDef())); return std::make_shared(std::move(func)); } std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override { auto body = Take>(visit(ctx->block())); return std::make_shared("main", std::move(body)); } std::any visitBlock(SysYParser::BlockContext* ctx) override { auto block = std::make_shared(); for (auto stmtCtx : ctx->stmt()) { if (stmtCtx->varDecl()) { block->varDecls.emplace_back( Take>(visit(stmtCtx->varDecl()))); } else if (stmtCtx->returnStmt()) { block->stmts.emplace_back( Take>(visit(stmtCtx->returnStmt()))); } } return block; } std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override { std::shared_ptr init; if (ctx->exp()) { init = Take>(visit(ctx->exp())); } return std::make_shared(ctx->Ident()->getText(), std::move(init)); } std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override { auto expr = Take>(visit(ctx->exp())); return std::make_shared(std::move(expr)); } std::any visitExp(SysYParser::ExpContext* ctx) override { return visit(ctx->addExp()); } std::any visitAddExp(SysYParser::AddExpContext* ctx) override { auto node = Take>(visit(ctx->primary(0))); for (size_t i = 1; i < ctx->primary().size(); ++i) { auto rhs = Take>(visit(ctx->primary(i))); auto opToken = ctx->AddOp(i - 1); BinaryOp op = BinaryOp::Add; if (opToken->getText() == "-") op = BinaryOp::Sub; node = std::make_shared(op, std::move(node), std::move(rhs)); } return node; } std::any visitPrimary(SysYParser::PrimaryContext* ctx) override { if (ctx->Number()) { std::shared_ptr expr = std::make_shared(std::stoi(ctx->Number()->getText())); return expr; } if (ctx->Ident()) { std::shared_ptr expr = std::make_shared(ctx->Ident()->getText()); return expr; } return visit(ctx->exp()); } }; } // namespace std::shared_ptr BuildAst(antlr4::tree::ParseTree* tree) { if (!tree) { throw std::runtime_error("parse tree 为空"); } Builder visitor; auto result = visitor.visit(tree); return Take>(std::move(result)); }