#pragma once #include "common.h" namespace antlrSysY { template class ScopeTable { typedef std::map ScopeTableEntry_t; private: std::vector _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 ¤t_scope = _scope_list.back(); if (current_scope.count(name)) throw GrammarException("Duplicate name in current scope"); current_scope[name] = value; }; std::optional 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 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 antlrSysY