我的任务是构造一个编译器,对最终的抽象语法树进行词法分析,解析和分析,以确保类型匹配,避免重复声明等。
已指示我们构造一个符号表,其中包含每个范围的变量及其类型的映射。我选择了地图矢量。我宁愿选择它而不是堆栈,因为在检查任何作用域的变量时都可以对其进行迭代。
我为此结构构造了Push,Pop,Lookup和Insert操作,如下所示,我的想法是在向量中保留对最新映射的引用并向其中添加变量。输入新的作用域后,将执行推入操作,以在向量中创建一个新映射,以在其中存储数组。
退出范围时,将执行弹出操作以删除矢量末端的地图,并获取现在位于矢量背面的先前的地图。
通过调试,我已经注意到向量只是不保存任何地图详细信息,并且通过引用进行工作似乎对更新应该保存此地图的向量没有任何作用。如何正确引用向量内部的地图并保持这种结构?
符号表:
struct SymbolTable {
// Stack defining scopes holding identifier / type details
std::vector<std::map<std::string,std::string>> _scopeVector;
// Tracks current working stack
std::map<std::string,std::string> _currentMap;
SymbolTable() = default;
void Push() {
std::map<std::string,std::string> *_tempMap;
_tempMap = new std::map<std::string,std::string>();
_scopeVector.push_back(*_tempMap);
_currentMap = _scopeVector.back();
}
void Insert(std::string p_name, std::string p_type) {
_currentMap.insert(std::make_pair(p_name,p_type));
}
// Returns type if found, empty if not
std::string Lookup (std::string p_name) {
for (int i = 0; i < _scopeVector.size(); i++) {
if (_scopeVector[i].find(p_name) == _scopeVector[i].end()) {
// No match yet
} else {
return _scopeVector[i].find(p_name)->first; // return var name
}
}
std::cerr << "Type name " << p_name << " not found in all of stack" << std::endl;
return "";
}
void Pop () {
_scopeVector.pop_back();
_currentMap = _scopeVector.back();
}
};
SymbolTable *ST;
用于建立符号表的类构造函数:
SemanticAnalysisVisitor() {
ST = new SymbolTable();
ST->Push();
}
答案 0 :(得分:1)
关于您的问题(我认为),声明
_currentMap = _scopeVector.back();
从向量复制 地图。
_currentMap
将始终是单独且不同的地图,与向量中的任何内容完全无关。
似乎您想使用引用,但这在这种情况下是不可能的(除非您进行重新设计)。
您可以通过具有指向映射的(智能)指针的向量,并使_currentMap
成为(智能)指针,来解决此问题(以及我在评论中提到的内存泄漏)。