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.
nudt-compiler-cpp/include/sem/Sema.h

96 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 基于语法树的语义检查与名称绑定。
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include "SysYParser.h"
#include "ir/IR.h"
#define Sema_DEBUG 0
// 表达式信息结构
struct ExprInfo {
std::shared_ptr<ir::Type> type = nullptr;
bool is_lvalue = false;
bool is_const = false;
bool is_const_int = false; // 是否是整型常量
int const_int_value = 0;
float const_float_value = 0.0f;
antlr4::ParserRuleContext* node = nullptr; // 对应的语法树节点
};
// 语义分析上下文:存储分析过程中产生的信息
class SemanticContext {
public:
// ----- 变量使用绑定(使用 LValContext 而不是 VarContext-----
void BindVarUse(SysYParser::LValContext* use,
SysYParser::VarDefContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDefContext* ResolveVarUse(
const SysYParser::LValContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
void BindConstUse(SysYParser::LValContext* use, SysYParser::ConstDefContext* decl) {
const_uses_[use] = decl;
}
SysYParser::ConstDefContext* ResolveConstUse(const SysYParser::LValContext* use) const {
auto it = const_uses_.find(use);
return it == const_uses_.end() ? nullptr : it->second;
}
// ----- 表达式类型信息存储 -----
void SetExprType(antlr4::ParserRuleContext* node, const ExprInfo& info) {
ExprInfo copy = info;
copy.node = node;
expr_types_[node] = copy;
}
ExprInfo* GetExprType(antlr4::ParserRuleContext* node) {
auto it = expr_types_.find(node);
return it == expr_types_.end() ? nullptr : &it->second;
}
const ExprInfo* GetExprType(antlr4::ParserRuleContext* node) const {
auto it = expr_types_.find(node);
return it == expr_types_.end() ? nullptr : &it->second;
}
// ----- 隐式转换标记(供 IR 生成使用)-----
struct ConversionInfo {
antlr4::ParserRuleContext* node;
std::shared_ptr<ir::Type> from_type;
std::shared_ptr<ir::Type> to_type;
};
void AddConversion(antlr4::ParserRuleContext* node,
std::shared_ptr<ir::Type> from,
std::shared_ptr<ir::Type> to) {
conversions_.push_back({node, from, to});
}
const std::vector<ConversionInfo>& GetConversions() const { return conversions_; }
private:
// 变量使用映射 - 使用 LValContext 作为键
std::unordered_map<const SysYParser::LValContext*,
SysYParser::VarDefContext*> var_uses_;
// 表达式类型映射
std::unordered_map<antlr4::ParserRuleContext*, ExprInfo> expr_types_;
// 隐式转换列表
std::vector<ConversionInfo> conversions_;
std::unordered_map<const SysYParser::LValContext*, SysYParser::ConstDefContext*> const_uses_;
};
// 目前仅检查:
// - 变量先声明后使用
// - 局部变量不允许重复定义
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);