/***** * table.h * Andy Hammerlindl 2002/06/18 * * Table used to bind symbols to vars and types in a namespace. *****/ #ifndef TABLE_H #define TABLE_H #include #include #include "symbol.h" #include "common.h" namespace sym { template class table; template std::ostream& operator<< (std::ostream& out, const table& t); template class table { protected: typedef mem::multimap scope_t; typedef typename scope_t::iterator scope_iterator; typedef mem::list scopes_t; typedef mem::list name_t; typedef typename name_t::iterator name_iterator; typedef mem::map names_t; typedef typename names_t::iterator names_iterator; scopes_t scopes; names_t names; void remove(symbol key); public : table(); void enter(symbol key, B value); B look(symbol key); // Allows scoping and overloading of symbols of the same name void beginScope(); void endScope(); // Copies all bindings in the top scope to the scope underneath it, and // removes the the top scope. void collapseScope(); // Adds to l, all names prefixed by start. void completions(mem::list& l, string start); friend std::ostream& operator<< (std::ostream& out, const table& t); }; template inline table::table() { beginScope(); } template inline void table::enter(symbol key, B value) { scopes.front().insert(std::make_pair(key,value)); names[key].push_front(value); } template inline B table::look(symbol key) { if (!names[key].empty()) return names[key].front(); return 0; } template inline void table::beginScope() { scopes.push_front(scope_t()); } template inline void table::remove(symbol key) { if (!names[key].empty()) names[key].pop_front(); } template inline void table::endScope() { scope_t &scope = scopes.front(); for (scope_iterator p = scope.begin(); p != scope.end(); ++p) remove(p->first); scopes.pop_front(); } template inline void table::collapseScope() { scope_t scope = scopes.front(); scopes.pop_front(); scopes.front().insert(scope.begin(), scope.end()); } // Returns true if start is a prefix for name; eg, mac is a prefix of machine. inline bool prefix(string start, string name) { return equal(start.begin(), start.end(), name.begin()); } template inline void table::completions(mem::list& l, string start) { for (names_iterator p = names.begin(); p != names.end(); ++p) if (prefix(start, p->first) && !p->second.empty()) l.push_back(p->first); } } // namespace sym #endif