File: Synopsis/SymbolLookup/Scope.hh
  1//
  2// Copyright (C) 2004 Stefan Seefeld
  3// All rights reserved.
  4// Licensed to the public under the terms of the GNU LGPL (>= 2),
  5// see the file COPYING for details.
  6//
  7#ifndef Synopsis_SymbolLookup_Scope_hh_
  8#define Synopsis_SymbolLookup_Scope_hh_
  9
 10#include <Synopsis/SymbolLookup/Symbol.hh>
 11#include <map>
 12#include <set>
 13
 14namespace Synopsis
 15{
 16namespace SymbolLookup
 17{
 18struct TypeError : std::exception
 19{
 20  TypeError(PTree::Encoding const &n, PTree::Encoding const &t)
 21    : name(n), type(t) {}
 22  virtual ~TypeError() throw() {}
 23  virtual char const * what() const throw() { return "TypeError";}
 24  PTree::Encoding name;
 25  PTree::Encoding type;
 26};
 27
 28struct Undefined : std::exception
 29{
 30  Undefined(PTree::Encoding const &n, PTree::Node const *ref = 0)
 31    : name(n), ptree(ref) {}
 32  virtual ~Undefined() throw() {}
 33  virtual char const * what() const throw() { return "Undefined";}
 34  PTree::Encoding     name;
 35  PTree::Node const * ptree;
 36};
 37
 38struct MultiplyDefined : std::exception
 39{
 40  MultiplyDefined(PTree::Encoding const &n,
 41		  PTree::Node const *decl,
 42		  PTree::Node const *orig)
 43    : name(n), declaration(decl), original(orig) {}
 44  virtual ~MultiplyDefined() throw() {}
 45  virtual char const * what() const throw() { return "MultiplyDefined";}
 46  PTree::Encoding name;
 47  PTree::Node const * declaration;
 48  PTree::Node const * original;
 49};
 50
 51class InternalError : public std::exception
 52{
 53public:
 54  InternalError(std::string const &what) : my_what(what) {}
 55  virtual ~InternalError() throw() {}
 56  virtual char const * what() const throw() { return my_what.c_str();}
 57private:
 58  std::string my_what;
 59};
 60
 61typedef std::set<Symbol const *> SymbolSet;
 62
 63class ScopeVisitor;
 64
 65//. A Scope contains symbol definitions.
 66class Scope
 67{
 68protected:
 69  //. SymbolTable provides a mapping from (encoded) names to Symbols declared
 70  //. in this scope.
 71  typedef std::multimap<PTree::Encoding, Symbol const *> SymbolTable;
 72  //. ScopeTable provides a mapping from scope nodes to Scopes,
 73  //. which can be used to traverse the scope tree in parallel with
 74  //. the associated parse tree. As this traversal is also done
 75  //. during the parsing, the scopes can not be const.
 76  typedef std::map<PTree::Node const *, Scope *> ScopeTable;
 77
 78public:
 79  typedef SymbolTable::const_iterator symbol_iterator;
 80  typedef ScopeTable::const_iterator scope_iterator;
 81
 82  typedef unsigned int LookupContext;
 83  static LookupContext const DEFAULT = 0x0;
 84  static LookupContext const SCOPE = 0x1; // lookup a scope, see [basic.lookup.qual]
 85  static LookupContext const USING = 0x2; // lookup in the context of a using directive
 86  static LookupContext const ELABORATE = 0x4; // elaborate name lookup
 87  static LookupContext const DECLARATION = 0x8; // see 3.4.3.2/6 [namespace.qual]
 88
 89  Scope() : my_refcount(1) {}
 90  Scope *ref() { ++my_refcount; return this;}
 91  Scope const *ref() const { ++my_refcount; return this;}
 92  void unref() const { if (!--my_refcount) delete this;}
 93
 94  virtual Scope const *outer_scope() const = 0;
 95  Scope const *global_scope() const;
 96
 97  virtual void accept(ScopeVisitor *v) = 0;
 98
 99  symbol_iterator symbols_begin() const { return my_symbols.begin();}
100  symbol_iterator symbols_end() const { return my_symbols.end();}
101
102  scope_iterator scopes_begin() const { return my_scopes.begin();}
103  scope_iterator scopes_end() const { return my_scopes.end();}
104
105  //. declare the given symbol in the local scope 
106  //. using the given encoded name.
107  void declare(PTree::Encoding const &name, Symbol const *symbol);
108
109  //. declare a nested scope
110  void declare_scope(PTree::Node const *, Scope *);
111
112  //. declare a 'using' directive.
113  //. The default implementation raises an exception,
114  //. as it is only well-formed when the current scope
115  //. is a function scope or a namespace.
116  virtual void use(PTree::UsingDirective const *);
117
118  //. find a nested scope by declaration
119  Scope *find_scope(PTree::Node const *) const;
120  //. find a nested scope by symbol.
121  //. The encoded name is provided for diagnostic purposes only.
122  Scope *find_scope(PTree::Encoding const &, Symbol const *) const;
123  //. Remove the given nested scope from the scope.
124  void remove_scope(PTree::Node const*);
125  //. find a nested scope by name
126  //Scope *find_scope(PTree::Encoding const &) const;
127
128  //. find the encoded name declared in this scope and 
129  //. return a set of matching symbols.
130  SymbolSet find(PTree::Encoding const &, LookupContext) const throw();
131  //. Remove the given symbol from the scope.
132  //. s shall not be used after its removal.
133  void remove(Symbol const *s);
134
135  //. look up the encoded name and return a set of matching symbols.
136  SymbolSet lookup(PTree::Encoding const &, LookupContext = DEFAULT) const;
137
138  virtual SymbolSet unqualified_lookup(PTree::Encoding const &,
139				       LookupContext = DEFAULT) const = 0;
140  virtual SymbolSet qualified_lookup(PTree::Encoding const &,
141				     LookupContext = DEFAULT) const;
142
143protected:
144
145  //. Scopes are ref counted, and thus are deleted only by 'unref()'
146  virtual ~Scope();
147
148  SymbolTable    my_symbols;
149  ScopeTable     my_scopes;
150  mutable size_t my_refcount;
151};
152
153inline void Scope::declare_scope(PTree::Node const *node, Scope *scope)
154{
155  my_scopes[node] = scope->ref();
156}
157
158inline Scope *Scope::find_scope(PTree::Node const *node) const
159{
160  ScopeTable::const_iterator i = my_scopes.find(node);
161  return i == my_scopes.end() ? 0 : i->second;
162}
163
164inline Scope const *Scope::global_scope() const
165{
166  Scope const *scope = this;
167  while (Scope const *outer = scope->outer_scope())
168    scope = outer;
169  return scope;
170}
171
172}
173}
174
175#endif