CompilerSysY/include/scopetable.h
2023-05-24 20:40:45 +08:00

61 lines
1.6 KiB
C++

#pragma once
#include "common.h"
namespace CompSysY {
template <typename T_V>
class ScopeTable {
typedef std::map<std::string, T_V> ScopeTableEntry_t;
private:
std::vector<ScopeTableEntry_t> _scope_list;
bool _pre_enter = false; // use this for adding formal param to scope, which
// is also in the top block scope of a function
public:
// On init, there is already an empty scope
ScopeTable() {
_scope_list.push_back(ScopeTableEntry_t());
}
~ScopeTable() {}
void enter_scope(bool pre_enter = false) {
if (_pre_enter) {
_pre_enter = false;
sysy_assert(!pre_enter);
return;
}
if (pre_enter) _pre_enter = true;
_scope_list.push_back(ScopeTableEntry_t());
};
void leave_scope() {
if (_scope_list.size() <= 1) throw GrammarException("Unable to leave global scope");
_scope_list.pop_back();
};
void push_name(const std::string &name, const T_V &value) {
auto &current_scope = _scope_list.back();
if (current_scope.count(name)) throw GrammarException("Duplicate name in current scope");
current_scope[name] = value;
};
std::optional<T_V> get_name(const std::string &name) const {
for (int i = _scope_list.size() - 1; i >= 0; --i) {
if (_scope_list[i].count(name)) {
return {_scope_list[i].at(name)};
}
}
return {};
};
std::optional<T_V> get_name(const std::string &name, int level) const {
if (_scope_list[level].count(name)) {
return {_scope_list[level].at(name)};
}
return {};
};
int get_level() const {
return _scope_list.size() - 1;
}
};
} // namespace CompSysY