summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/table.h
blob: 38427f90b06ed20f234fa662b00cd92d2fc4f7be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*****
 * 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 <cassert>
#include <utility>

#include "symbol.h"
#include "common.h"

namespace sym {

template <class B>
class table;

template <class B>
std::ostream& operator<< (std::ostream& out, const table<B>& t);

template <class B>
class table {
protected:
  typedef mem::multimap<symbol CONST,B> scope_t;
  typedef typename scope_t::iterator scope_iterator;
  typedef mem::list<scope_t> scopes_t;
  typedef mem::list<B> name_t;
  typedef typename name_t::iterator name_iterator;
  typedef mem::map<symbol CONST,name_t> 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<symbol >& l, string start);

  friend std::ostream& operator<< <B> (std::ostream& out, const table& t);
};

template <class B>
inline table<B>::table()
{
  beginScope();
}

template <class B>
inline void table<B>::enter(symbol key, B value)
{
  scopes.front().insert(std::make_pair(key,value));
  names[key].push_front(value);
}

template <class B>
inline B table<B>::look(symbol key)
{
  if (!names[key].empty())
    return names[key].front();
  return 0;
}

template <class B>
inline void table<B>::beginScope()
{
  scopes.push_front(scope_t());
}

template <class B>
inline void table<B>::remove(symbol key)
{
  if (!names[key].empty())
    names[key].pop_front();
}

template <class B>
inline void table<B>::endScope()
{
  scope_t &scope = scopes.front();
  for (scope_iterator p = scope.begin(); p != scope.end(); ++p)
    remove(p->first);
  scopes.pop_front();
}

template <class B>
inline void table<B>::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 <class B>
inline void table<B>::completions(mem::list<symbol>& 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