forked from NUDT-compiler/nudt-compiler-cpp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
5.7 KiB
225 lines
5.7 KiB
#include "sem/Sema.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
namespace {
|
|
|
|
SymbolType ParseType(const std::string& text) {
|
|
if (text == "int") {
|
|
return SymbolType::TYPE_INT;
|
|
}
|
|
if (text == "float") {
|
|
return SymbolType::TYPE_FLOAT;
|
|
}
|
|
if (text == "void") {
|
|
return SymbolType::TYPE_VOID;
|
|
}
|
|
return SymbolType::TYPE_UNKNOWN;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::any SemaVisitor::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitDecl(SysYParser::DeclContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitConstDef(SysYParser::ConstDefContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitConstInitValue(SysYParser::ConstInitValueContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitVarDecl(SysYParser::VarDeclContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitVarDef(SysYParser::VarDefContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitInitValue(SysYParser::InitValueContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitFuncDef(SysYParser::FuncDefContext* ctx) {
|
|
SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
|
|
if (ctx && ctx->funcType()) {
|
|
ret_type = ParseType(ctx->funcType()->getText());
|
|
}
|
|
|
|
ir_ctx_.SetCurrentFuncReturnType(ret_type);
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitFuncType(SysYParser::FuncTypeContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitFuncFParams(SysYParser::FuncFParamsContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitFuncFParam(SysYParser::FuncFParamContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
|
ir_ctx_.EnterScope();
|
|
std::any result = visitChildren(ctx);
|
|
ir_ctx_.LeaveScope();
|
|
return result;
|
|
}
|
|
|
|
std::any SemaVisitor::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitStmt(SysYParser::StmtContext* ctx) {
|
|
if (!ctx) {
|
|
return {};
|
|
}
|
|
|
|
if (ctx->WHILE()) {
|
|
ir_ctx_.EnterLoop();
|
|
std::any result = visitChildren(ctx);
|
|
ir_ctx_.ExitLoop();
|
|
return result;
|
|
}
|
|
|
|
if (ctx->BREAK() && !ir_ctx_.InLoop()) {
|
|
ir_ctx_.RecordError(
|
|
ErrorMsg("break 只能出现在循环语句中", ctx->getStart()->getLine(),
|
|
ctx->getStart()->getCharPositionInLine() + 1));
|
|
}
|
|
|
|
if (ctx->CONTINUE() && !ir_ctx_.InLoop()) {
|
|
ir_ctx_.RecordError(
|
|
ErrorMsg("continue 只能出现在循环语句中", ctx->getStart()->getLine(),
|
|
ctx->getStart()->getCharPositionInLine() + 1));
|
|
}
|
|
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
|
|
if (!ctx) {
|
|
return {};
|
|
}
|
|
|
|
if (ctx->exp() && ir_ctx_.GetCurrentFuncReturnType() == SymbolType::TYPE_VOID) {
|
|
ir_ctx_.RecordError(
|
|
ErrorMsg("void 函数不应返回表达式", ctx->getStart()->getLine(),
|
|
ctx->getStart()->getCharPositionInLine() + 1));
|
|
}
|
|
|
|
if (!ctx->exp() &&
|
|
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_VOID &&
|
|
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_UNKNOWN) {
|
|
ir_ctx_.RecordError(
|
|
ErrorMsg("非 void 函数 return 必须带表达式", ctx->getStart()->getLine(),
|
|
ctx->getStart()->getCharPositionInLine() + 1));
|
|
}
|
|
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitExp(SysYParser::ExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitCond(SysYParser::CondContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitLValue(SysYParser::LValueContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) {
|
|
if (!ctx) {
|
|
return {};
|
|
}
|
|
|
|
if (ctx->ILITERAL()) {
|
|
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
|
|
ir_ctx_.SetConstVal(ctx, std::any(0L));
|
|
} else if (ctx->FLITERAL()) {
|
|
ir_ctx_.SetType(ctx, SymbolType::TYPE_FLOAT);
|
|
ir_ctx_.SetConstVal(ctx, std::any(0.0));
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::any SemaVisitor::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitUnaryOp(SysYParser::UnaryOpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitMulExp(SysYParser::MulExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitAddExp(SysYParser::AddExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitRelExp(SysYParser::RelExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitEqExp(SysYParser::EqExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitLAndExp(SysYParser::LAndExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitLOrExp(SysYParser::LOrExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
std::any SemaVisitor::visitConstExp(SysYParser::ConstExpContext* ctx) {
|
|
return visitChildren(ctx);
|
|
}
|
|
|
|
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx) {
|
|
if (!ctx) {
|
|
throw std::invalid_argument("CompUnitContext is null");
|
|
}
|
|
SemaVisitor visitor(ir_ctx);
|
|
visitor.visit(ctx);
|
|
}
|
|
|
|
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
|
|
IRGenContext ctx;
|
|
RunSemanticAnalysis(&comp_unit, ctx);
|
|
return SemanticContext();
|
|
}
|