【发布时间】:2018-12-20 07:57:08
【问题描述】:
我正在创建一个编译器,并且在语义分析阶段非常挣扎。我不确定如何处理符号表中的函数重载。我似乎找不到任何描述这个特定问题的资源。我认为必须在某处使用名称修饰,并且我很确定应该将 AST 中的类型转换为字符串。
只要每个声明具有不同的参数集,就可以在同一范围内声明多个同名函数。下面的 sn-p 是我的语言中的一个示例(它与 Swift 非常相似)。
func add(a: Int, b: Int) {
return a + b;
}
func add(a: Float, b: Float) {
return a + b;
}
我不知道如何在符号表中存储函数。这是我的符号表数据结构的一部分。
struct Symbol {};
struct Var final : Symbol {
std::string type;
};
using FuncParams = std::vector<std::string>;
struct Func final : Symbol {
std::string ret;
FuncParams params;
};
using Table = std::unordered_map<std::string, std::unique_ptr<Symbol>>;
struct Scope {
Table table;
Scope *parent = nullptr;
};
using Scopes = std::vector<std::unique_ptr<Scope>>;
我可以使用std::unordered_multimap 并将函数名称add 存储为键并将参数名称存储在符号对象中。我可以使用std::unordered_map 并将用参数add_Int_Int 修饰的函数名存储为键,并将参数的名称也存储在符号对象中。
另外,Symbol 应该是一个基类,还是应该将各种符号放在一个 Symbol 对象中?我见过很多使用enum 区分函数、变量和类型声明的示例,但函数存储返回类型和参数类型。我应该使用标记的联合吗?
我觉得有一种聪明而简单的方法可以解决这个问题,但我就是找不到。
更新:
我接受了@NeilButterworth 的建议,并使用未损坏的函数名称作为符号键,这似乎是要走的路(但我知道什么!)。对我的其他问题的回答或对此主题的一些建议将不胜感激。
【问题讨论】:
-
你知道C++是怎么做的吗?可能还有其他方法,但 C++ name mangling 相对简单。还有其他方法,并且可能有很多关于这个问题的研究论文(免费提供和付费)。
-
@Someprogrammerdude 你能详细说明一下吗?考虑这个函数
func f(n: Float) {}和这个调用:f(5)。如果我在调用站点的符号表中查找f_Int,我什么也找不到。我想查找f_Float,然后查找从Int到Float的转换。 -
您不希望在此处进行名称修改 - 在不考虑参数的情况下查找命名函数,然后在列表中查找与参数匹配或存在转换的函数
-
@NeilButterworth 我自己也开始得出这个结论。感谢您的意见!
标签: c++ data-structures compiler-construction