From 0804aa8543136f3e1585e0e59a14f9c331c0c448 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 20 Sep 2009 18:47:48 +0200 Subject: 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. --- cli/context.hxx | 15 +++++ cli/generator.cxx | 8 +++ cli/makefile | 5 +- cli/name-processor.cxx | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ cli/name-processor.hxx | 14 +++++ 5 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 cli/name-processor.cxx create mode 100644 cli/name-processor.hxx 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 #include #include +#include // std::size_t #include @@ -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 ("name"); + } + + static string const& + emember (semantics::nameable& n) + { + return n.context ().get ("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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include +#include + +#include "context.hxx" +#include "name-processor.hxx" + +using namespace std; + +namespace +{ + typedef set 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 ("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 ("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 +// 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 -- cgit v1.1