【发布时间】:2019-05-17 09:59:10
【问题描述】:
我的任务是构建一个编译器,对生成的抽象语法树进行词法分析、解析和分析,以确保类型匹配、避免重复声明等。
我们被指示构建一个符号表,其中包含每个范围的变量及其类型的映射。我选择了地图矢量。我更喜欢它而不是堆栈,因为我可以在任何范围内检查变量时对其进行迭代。
我为这个结构构造了 Push、Pop、Lookup 和 Insert 操作,如下所示,我的想法是在向量中保存对最新映射的引用并向其中添加变量。进入新范围时,会执行推送操作,在存储数组的向量中创建一个新映射。
当一个范围退出时,会执行 Pop 操作以删除向量末尾的映射并获取现在位于向量后面的前一个映射。
通过调试,我注意到该向量根本不包含地图详细信息,并且通过引用工作似乎没有做任何事情来更新应该包含此地图的向量。如何正确引用矢量内的地图并维护此结构?
符号表:
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();
}
【问题讨论】:
-
您有内存泄漏。您动态分配了一个新地图,但您从未释放它。
-
@Someprogrammerdude 在这种情况下会添加 delete _scopeVector.back() 工作吗?
-
不,不是您显示的当前代码。那是因为
_scopeVector.push_back(*_tempMap)也复制了地图!你需要delete tempMap(或者正如我在回答中建议的那样推送指针本身,在这种情况下你可以在Pop函数中删除它)。
标签: c++ compiler-construction semantic-analysis