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.

87 lines
3.4 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 <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);