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.

70 lines
1.8 KiB

// 基于语法树的语义检查与名称绑定。
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include "SysYParser.h"
enum class SemanticType {
Void,
Int,
Float,
};
struct ScalarConstant {
SemanticType type = SemanticType::Int;
double number = 0.0;
};
struct ObjectBinding {
enum class DeclKind {
Var,
Const,
Param,
};
std::string name;
SemanticType type = SemanticType::Int;
DeclKind decl_kind = DeclKind::Var;
bool is_array_param = false;
std::vector<int> dimensions;
const SysYParser::VarDefContext* var_def = nullptr;
const SysYParser::ConstDefContext* const_def = nullptr;
const SysYParser::FuncFParamContext* func_param = nullptr;
bool has_const_value = false;
ScalarConstant const_value;
};
struct FunctionBinding {
std::string name;
SemanticType return_type = SemanticType::Int;
std::vector<ObjectBinding> params;
const SysYParser::FuncDefContext* func_def = nullptr;
bool is_builtin = false;
};
class SemanticContext {
public:
void BindObjectUse(const SysYParser::LValContext* use, ObjectBinding binding);
const ObjectBinding* ResolveObjectUse(
const SysYParser::LValContext* use) const;
void BindFunctionCall(const SysYParser::UnaryExpContext* call,
FunctionBinding binding);
const FunctionBinding* ResolveFunctionCall(
const SysYParser::UnaryExpContext* call) const;
void RegisterFunction(FunctionBinding binding);
const FunctionBinding* ResolveFunction(const std::string& name) const;
private:
std::unordered_map<const SysYParser::LValContext*, ObjectBinding> object_uses_;
std::unordered_map<const SysYParser::UnaryExpContext*, FunctionBinding>
function_calls_;
std::unordered_map<std::string, FunctionBinding> functions_;
};
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);