|
|
#pragma once
|
|
|
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
#include <unordered_map>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
|
|
|
enum class SymbolKind { Object, Function };
|
|
|
|
|
|
struct ConstantData {
|
|
|
// 语义阶段只需要覆盖 SysY 的两种可常量求值基础标量。
|
|
|
enum class Kind { Int, Float };
|
|
|
|
|
|
Kind kind = Kind::Int;
|
|
|
int int_value = 0;
|
|
|
float float_value = 0.0f;
|
|
|
|
|
|
static ConstantData FromInt(int value);
|
|
|
static ConstantData FromFloat(float value);
|
|
|
|
|
|
bool IsInt() const { return kind == Kind::Int; }
|
|
|
bool IsFloat() const { return kind == Kind::Float; }
|
|
|
// 以 SysY 的隐式转换规则读取常量值;调用方应先结合 kind/type 做约束检查。
|
|
|
int AsInt() const;
|
|
|
float AsFloat() const;
|
|
|
ConstantData CastTo(const std::shared_ptr<ir::Type>& dst_type) const;
|
|
|
std::shared_ptr<ir::Type> GetType() const;
|
|
|
};
|
|
|
|
|
|
struct SymbolInfo {
|
|
|
// 统一记录对象和函数的语义信息。对于对象,type 可能是标量、数组或“数组形参
|
|
|
// 退化后的指针”;对于函数,type 为 FunctionType。
|
|
|
std::string name;
|
|
|
SymbolKind kind = SymbolKind::Object;
|
|
|
std::shared_ptr<ir::Type> type;
|
|
|
bool is_const = false;
|
|
|
bool is_global = false;
|
|
|
bool is_parameter = false;
|
|
|
bool is_array_parameter = false;
|
|
|
bool is_builtin = false;
|
|
|
|
|
|
SysYParser::ConstDefContext* const_def = nullptr;
|
|
|
SysYParser::VarDefContext* var_def = nullptr;
|
|
|
SysYParser::FuncDefContext* func_def = nullptr;
|
|
|
|
|
|
bool has_const_value = false;
|
|
|
ConstantData const_value{};
|
|
|
};
|
|
|
|
|
|
class SemanticContext {
|
|
|
public:
|
|
|
// Sema 会把所有需要跨阶段复用的信息都绑定回语法树节点:
|
|
|
// 1. 定义/引用对应的符号
|
|
|
// 2. 表达式推导出的 IR 类型
|
|
|
// 这些结果后续由 IRGen 直接读取,而无需再次做名字解析。
|
|
|
SymbolInfo* CreateSymbol(SymbolInfo symbol);
|
|
|
|
|
|
void BindConstDef(SysYParser::ConstDefContext* node, const SymbolInfo* symbol);
|
|
|
void BindVarDef(SysYParser::VarDefContext* node, const SymbolInfo* symbol);
|
|
|
void BindFuncDef(SysYParser::FuncDefContext* node, const SymbolInfo* symbol);
|
|
|
void BindLVal(SysYParser::LValContext* node, const SymbolInfo* symbol);
|
|
|
void BindCall(SysYParser::UnaryExpContext* node, const SymbolInfo* symbol);
|
|
|
void SetExprType(const void* node, std::shared_ptr<ir::Type> type);
|
|
|
|
|
|
const SymbolInfo* ResolveConstDef(const SysYParser::ConstDefContext* node) const;
|
|
|
const SymbolInfo* ResolveVarDef(const SysYParser::VarDefContext* node) const;
|
|
|
const SymbolInfo* ResolveFuncDef(const SysYParser::FuncDefContext* node) const;
|
|
|
const SymbolInfo* ResolveLVal(const SysYParser::LValContext* node) const;
|
|
|
const SymbolInfo* ResolveCall(const SysYParser::UnaryExpContext* node) const;
|
|
|
std::shared_ptr<ir::Type> ResolveExprType(const void* node) const;
|
|
|
|
|
|
private:
|
|
|
std::vector<std::unique_ptr<SymbolInfo>> owned_symbols_;
|
|
|
std::unordered_map<const SysYParser::ConstDefContext*, const SymbolInfo*> const_defs_;
|
|
|
std::unordered_map<const SysYParser::VarDefContext*, const SymbolInfo*> var_defs_;
|
|
|
std::unordered_map<const SysYParser::FuncDefContext*, const SymbolInfo*> func_defs_;
|
|
|
std::unordered_map<const SysYParser::LValContext*, const SymbolInfo*> lvals_;
|
|
|
std::unordered_map<const SysYParser::UnaryExpContext*, const SymbolInfo*> calls_;
|
|
|
std::unordered_map<const void*, std::shared_ptr<ir::Type>> expr_types_;
|
|
|
};
|
|
|
|
|
|
// 对整个编译单元执行语义检查,并返回可供 IRGen 复用的语义绑定结果。
|
|
|
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
|