summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-05-11 12:07:56 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-05-11 12:07:56 +0200
commit5a2e172ce1f2d823bf0957602662bbab0c0dcd0b (patch)
treef3645c87168542ec8c5f753e944e9382091ac22e /cli
parentd4274a0d8bd3bb210b8085332f4c827486ede2f3 (diff)
Move lookup to semantic graph from parser
Diffstat (limited to 'cli')
-rw-r--r--cli/parser.cxx107
-rw-r--r--cli/parser.hxx19
-rw-r--r--cli/semantics/unit.hxx21
-rw-r--r--cli/semantics/unit.txx109
4 files changed, 131 insertions, 125 deletions
diff --git a/cli/parser.cxx b/cli/parser.cxx
index 55090d4..3f9b19c 100644
--- a/cli/parser.cxx
+++ b/cli/parser.cxx
@@ -488,7 +488,7 @@ class_def ()
else
ns = scope_->fq_name ();
- if (class_* b = lookup<class_> (ns, name))
+ if (class_* b = cur_->lookup<class_> (ns, name))
root_->new_edge<inherits> (*n, *b);
else
{
@@ -1289,108 +1289,3 @@ fundamental_type (token& t, string& r)
return true;
}
-
-template <typename T>
-T* parser::
-lookup (string const& ss, string const& name, cli_unit* unit, bool outer)
-{
- if (unit == 0)
- unit = cur_;
-
- // Resolve the starting scope in this unit, if any.
- //
- string::size_type b (0), e;
- scope* s (0);
-
- do
- {
- e = ss.find ("::", b);
- string n (ss, b, e == string::npos ? e : e - b);
-
- if (n.empty ())
- s = unit;
- else
- {
- scope::names_iterator_pair ip (s->find (n));
-
- for (s = 0; ip.first != ip.second; ++ip.first)
- if (s = dynamic_cast<scope*> (&ip.first->named ()))
- break;
-
- if (s == 0)
- break; // No such scope in this unit.
- }
-
- b = e;
-
- if (b == string::npos)
- break;
-
- b += 2;
- } while (true);
-
- // If we have the starting scope, then try to resolve the name in it.
- //
- if (s != 0)
- {
- b = 0;
-
- do
- {
- e = name.find ("::", b);
- string n (name, b, e == string::npos ? e : e - b);
-
- scope::names_iterator_pair ip (s->find (n));
-
- // If this is the last name, then see if we have the desired type.
- //
- if (e == string::npos)
- {
- for (; ip.first != ip.second; ++ip.first)
- if (T* r = dynamic_cast<T*> (&ip.first->named ()))
- return r;
- }
- // Otherwise, this should be a scope.
- //
- else
- {
- for (s = 0; ip.first != ip.second; ++ip.first)
- if (s = dynamic_cast<scope*> (&ip.first->named ()))
- break;
-
- if (s == 0)
- break; // No such inner scope.
- }
-
- b = e;
-
- if (b == string::npos)
- break;
-
- b += 2;
- } while (true);
- }
-
- // If we are here, then that means the lookup didn't find anything in
- // this unit. The next step is to examine all the included units.
- //
- for (cli_unit::includes_iterator i (unit->includes_begin ());
- i != unit->includes_end ();
- ++i)
- {
- if (cli_includes* ci = dynamic_cast<cli_includes*> (&*i))
- if (T* r = lookup<T> (ss, name, &ci->includee (), false))
- return r;
- }
-
- // If we still haven't found anything, then the next step is to search
- // one-outer scope, unless it is the global namespace.
- //
- if (outer && !ss.empty ())
- {
- string n (ss, 0, ss.rfind ("::"));
- return lookup<T> (n, name, unit, true);
- }
-
- return 0;
-}
diff --git a/cli/parser.hxx b/cli/parser.hxx
index f7f6d68..29f4b22 100644
--- a/cli/parser.hxx
+++ b/cli/parser.hxx
@@ -61,25 +61,6 @@ private:
void
recover (token& t);
- // Lookup a name in the specified starting scope. Empty scope denotes
- // the global namespace. Starting scope should be a fully-qualified
- // name while name can be qualified but should not be fully-qualified
- // (to lookup a fully-qualified name use the global namespace as the
- // starting scope).
- //
- // If starting unit is not specified, the lookup is performed in the
- // current unit. It then continues in all the units that the starting
- // unit includes, transitively.
- //
- // The outer flag specifies whether to search the outer scopes.
- //
- template <typename T>
- T*
- lookup (std::string const& scope,
- std::string const& name,
- semantics::cli_unit* unit = 0,
- bool outer = true);
-
private:
paths const include_paths_;
diff --git a/cli/semantics/unit.hxx b/cli/semantics/unit.hxx
index f20ba82..cd4198b 100644
--- a/cli/semantics/unit.hxx
+++ b/cli/semantics/unit.hxx
@@ -8,6 +8,7 @@
#include <map>
#include <vector>
+#include <string>
#include <semantics/elements.hxx>
#include <semantics/namespace.hxx>
@@ -139,6 +140,24 @@ namespace semantics
typedef std::vector<includes*> includes_list;
public:
+ // Lookup a name in the specified starting scope. Empty scope denotes
+ // the global namespace. Starting scope should be a fully-qualified
+ // name while name can be qualified but should not be fully-qualified
+ // (to lookup a fully-qualified name use the global namespace as the
+ // starting scope).
+ //
+ // The lookup starts in this unit and continues in all the units that
+ // this unit includes, transitively.
+ //
+ // The outer flag specifies whether to search the outer scopes.
+ //
+ template <typename T>
+ T*
+ lookup (std::string const& scope,
+ std::string const& name,
+ bool outer = true);
+
+ public:
typedef
pointer_iterator<includes_list::const_iterator>
includes_iterator;
@@ -286,4 +305,6 @@ namespace semantics
};
}
+#include <semantics/unit.txx>
+
#endif // CLI_SEMANTICS_UNIT_HXX
diff --git a/cli/semantics/unit.txx b/cli/semantics/unit.txx
new file mode 100644
index 0000000..f884e18
--- /dev/null
+++ b/cli/semantics/unit.txx
@@ -0,0 +1,109 @@
+// file : cli/semantics/unit.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace semantics
+{
+ template <typename T>
+ T* cli_unit::
+ lookup (std::string const& ss, std::string const& name, bool outer)
+ {
+ using std::string;
+
+ // Resolve the starting scope in this unit, if any.
+ //
+ string::size_type b (0), e;
+ scope* s (0);
+
+ do
+ {
+ e = ss.find ("::", b);
+ string n (ss, b, e == string::npos ? e : e - b);
+
+ if (n.empty ())
+ s = this;
+ else
+ {
+ scope::names_iterator_pair ip (s->find (n));
+
+ for (s = 0; ip.first != ip.second; ++ip.first)
+ if (s = dynamic_cast<scope*> (&ip.first->named ()))
+ break;
+
+ if (s == 0)
+ break; // No such scope in this unit.
+ }
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+ } while (true);
+
+ // If we have the starting scope, then try to resolve the name in it.
+ //
+ if (s != 0)
+ {
+ b = 0;
+
+ do
+ {
+ e = name.find ("::", b);
+ string n (name, b, e == string::npos ? e : e - b);
+
+ scope::names_iterator_pair ip (s->find (n));
+
+ // If this is the last name, then see if we have the desired type.
+ //
+ if (e == string::npos)
+ {
+ for (; ip.first != ip.second; ++ip.first)
+ if (T* r = dynamic_cast<T*> (&ip.first->named ()))
+ return r;
+ }
+ // Otherwise, this should be a scope.
+ //
+ else
+ {
+ for (s = 0; ip.first != ip.second; ++ip.first)
+ if (s = dynamic_cast<scope*> (&ip.first->named ()))
+ break;
+
+ if (s == 0)
+ break; // No such inner scope.
+ }
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+ } while (true);
+ }
+
+ // If we are here, then that means the lookup didn't find anything in
+ // this unit. The next step is to examine all the included units.
+ //
+ for (includes_iterator i (includes_begin ()); i != includes_end (); ++i)
+ {
+ if (cli_includes* ci = dynamic_cast<cli_includes*> (&*i))
+ if (T* r = ci->includee ().lookup<T> (ss, name, false))
+ return r;
+ }
+
+ // If we still haven't found anything, then the next step is to search
+ // one-outer scope, unless it is the global namespace.
+ //
+ if (outer && !ss.empty ())
+ {
+ string n (ss, 0, ss.rfind ("::"));
+ return lookup<T> (n, name, true);
+ }
+
+ return 0;
+ }
+}