summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-09-20 18:47:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-09-20 18:47:48 +0200
commit0804aa8543136f3e1585e0e59a14f9c331c0c448 (patch)
tree7ffaaf06f0627b13fe3f14868d19bdd277d98399
parentddb77e1407eeaf0f18390cb49d915ca50ac2b528 (diff)
Add name processor
Name processor is a separate pass over the semantics graph that assigns names to various constructs while making sure there are no name clashes.
-rw-r--r--cli/context.hxx15
-rw-r--r--cli/generator.cxx8
-rw-r--r--cli/makefile5
-rw-r--r--cli/name-processor.cxx154
-rw-r--r--cli/name-processor.hxx14
5 files changed, 194 insertions, 2 deletions
diff --git a/cli/context.hxx b/cli/context.hxx
index 4d88fe9..eb2e412 100644
--- a/cli/context.hxx
+++ b/cli/context.hxx
@@ -9,6 +9,7 @@
#include <map>
#include <string>
#include <ostream>
+#include <cstddef> // std::size_t
#include <cutl/shared-ptr.hxx>
@@ -20,6 +21,7 @@ using std::endl;
class context
{
public:
+ typedef std::size_t size_t;
typedef std::string string;
private:
@@ -46,6 +48,19 @@ public:
escape (string const&) const;
public:
+ static string const&
+ ename (semantics::nameable& n)
+ {
+ return n.context ().get<string> ("name");
+ }
+
+ static string const&
+ emember (semantics::nameable& n)
+ {
+ return n.context ().get<string> ("member");
+ }
+
+public:
context (std::ostream&,
semantics::cli_unit&);
diff --git a/cli/generator.cxx b/cli/generator.cxx
index c23f382..b864dfb 100644
--- a/cli/generator.cxx
+++ b/cli/generator.cxx
@@ -19,6 +19,7 @@
#include "context.hxx"
#include "generator.hxx"
+#include "name-processor.hxx"
using namespace std;
using namespace cutl;
@@ -99,6 +100,13 @@ generate (semantics::cli_unit& unit, path const& p)
cxx_path = dir / cxx_path;
}
+ // Process names.
+ //
+ {
+ context ctx (cerr, unit);
+ process_names (ctx);
+ }
+
fs::auto_removes auto_rm;
//
diff --git a/cli/makefile b/cli/makefile
index a6026a6..488d758 100644
--- a/cli/makefile
+++ b/cli/makefile
@@ -9,10 +9,11 @@ cxx_tun := cli.cxx lexer.cxx parser.cxx
cxx_tun += \
context.cxx \
-generator.cxx \
header.cxx \
inline.cxx \
-source.cxx
+source.cxx \
+generator.cxx \
+name-processor.cxx
cxx_tun += \
semantics/class.cxx \
diff --git a/cli/name-processor.cxx b/cli/name-processor.cxx
new file mode 100644
index 0000000..abeaae5
--- /dev/null
+++ b/cli/name-processor.cxx
@@ -0,0 +1,154 @@
+// file : cli/name-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <set>
+#include <sstream>
+
+#include "context.hxx"
+#include "name-processor.hxx"
+
+using namespace std;
+
+namespace
+{
+ typedef set<string> name_set;
+ typedef ::context context_base;
+
+ struct context: context_base
+ {
+ context (context_base& c): context_base (c) {}
+ context (context& c): context_base (c) {}
+
+ public:
+ string
+ find_name (string const& n, string const& suffix, name_set& set)
+ {
+ string name (escape (n + suffix));
+
+ for (size_t i (1); set.find (name) != set.end (); ++i)
+ {
+ ostringstream os;
+ os << i;
+ name = escape (n + os.str () + suffix);
+ }
+
+ set.insert (name);
+ return name;
+ }
+
+ string
+ find_name (string const& n, name_set& set)
+ {
+ return find_name (n, "", set);
+ }
+ };
+
+ struct primary_option: traversal::option, context
+ {
+ primary_option (context& c, name_set& set)
+ : context (c), set_ (set)
+ {
+ }
+
+ virtual void
+ traverse (type& o)
+ {
+ string n (o.name ()), name;
+
+ // Get rid of leading special characters, e.f., -, --, /, etc.
+ //
+ for (size_t i (0); i < n.size (); ++i)
+ {
+ if (isalpha (n[i]) || n[i] == '_')
+ {
+ name.assign (n.c_str (), i, n.size () - i);
+ break;
+ }
+ }
+
+ o.context ().set ("name", find_name (name, set_));
+ }
+
+ private:
+ name_set& set_;
+ };
+
+ struct secondary_option: traversal::option, context
+ {
+ secondary_option (context& c, name_set& set)
+ : context (c), set_ (set)
+ {
+ }
+
+ virtual void
+ traverse (type& o)
+ {
+ semantics::context& oc (o.context ());
+ string const& base (oc.get<string> ("name"));
+ oc.set ("member", find_name (base + "_", set_));
+ }
+
+ private:
+ name_set& set_;
+ };
+
+ struct class_: traversal::class_, context
+ {
+ class_ (context& c) : context (c) {}
+
+ virtual void
+ traverse (type& c)
+ {
+ semantics::context& cc (c.context ());
+
+ cc.set ("member-name-set", name_set ());
+ name_set& member_set (cc.get<name_set> ("member-name-set"));
+
+ member_set.insert (escape (c.name ()));
+
+ // First assign primary names.
+ //
+ {
+ primary_option option (*this, member_set);
+ traversal::names names (option);
+
+ class_::names (c, names);
+ }
+
+ // Then assign secondary names.
+ //
+ {
+ secondary_option option (*this, member_set);
+ traversal::names names (option);
+
+ class_::names (c, names);
+ }
+ }
+ };
+
+ void
+ process_names_ (context_base& c)
+ {
+ context ctx (c);
+
+ traversal::cli_unit unit;
+ traversal::names unit_names;
+ traversal::namespace_ ns;
+ traversal::names ns_names;
+
+ unit >> unit_names >> ns >> ns_names >> ns;
+
+ class_ cl (ctx);
+ ns_names >> cl;
+
+ unit.dispatch (ctx.unit);
+ }
+}
+
+void
+process_names (context_base& c)
+{
+ process_names_ (c);
+}
diff --git a/cli/name-processor.hxx b/cli/name-processor.hxx
new file mode 100644
index 0000000..13e25df
--- /dev/null
+++ b/cli/name-processor.hxx
@@ -0,0 +1,14 @@
+// file : cli/name-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_NAME_PROCESSOR_HXX
+#define CLI_NAME_PROCESSOR_HXX
+
+#include "context.hxx"
+
+void
+process_names (context&);
+
+#endif // CLI_NAME_PROCESSOR_HXX