CompilerSysY/include/scopetable.h
2023-07-10 15:04:56 +08:00

74 lines
1.7 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