diff options
Diffstat (limited to 'xsde/cxx/hybrid/tree-name-processor.cxx')
-rw-r--r-- | xsde/cxx/hybrid/tree-name-processor.cxx | 1993 |
1 files changed, 1993 insertions, 0 deletions
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx new file mode 100644 index 0000000..c828250 --- /dev/null +++ b/xsde/cxx/hybrid/tree-name-processor.cxx @@ -0,0 +1,1993 @@ +// file : xsde/cxx/hybrid/tree-name-processor.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/elements.hxx> +#include <cxx/hybrid/tree-name-processor.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/set.hxx> +#include <cult/containers/map.hxx> + +#include <sstream> +#include <iostream> + +namespace CXX +{ + namespace Hybrid + { + namespace + { + // + // + typedef Cult::Containers::Set<String> NameSet; + Char const* member_set_key = "cxx-hybrid-name-processor-member-set"; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value<CLI::include_with_brackets> (), + ops.value<CLI::include_prefix> (), + "", // export symbol + ops.value<CLI::namespace_map> (), + ops.value<CLI::namespace_regex> (), + ops.value<CLI::namespace_regex_trace> (), + ops.value<CLI::include_regex> (), + ops.value<CLI::include_regex_trace> (), + ops.value<CLI::generate_inline> (), + ops.value<CLI::reserved_name> ()), + schema_path_ (file), + schema (root), + schema_path (schema_path_), + custom_data_map (custom_data_map_), + global_type_names (global_type_names_) + { + // Translate the type names with custom data. + // + { + typedef Cult::Containers::Vector<NarrowString> CustomData; + CustomData const& cd (ops.value<CLI::custom_data> ()); + + for (CustomData::ConstIterator i (cd.begin ()); + i != cd.end (); ++i) + { + String name (*i); + CustomDataMap* map (&custom_data_map); + String::size_type b (0), e; + + do + { + e = name.find (L"::", b); + String entry (name, b, e == String::npos ? e : e - b); + + Shptr<CustomDataMap>& p ((*map)[entry]); + + if (p == 0) + p = Shptr<CustomDataMap> (new CustomDataMap); + + b = e; + + if (b == String::npos) + { + // Last name. Add an empty string to indicate this. + // + (*p)[L""] = Shptr<CustomDataMap> (0); + break; + } + + map = p.get (); + b += 2; + + } while (true); + } + } + } + + protected: + Context (Context& c) + : CXX::Context (c), + schema (c.schema), + schema_path (c.schema_path), + custom_data_map (c.custom_data_map), + global_type_names (c.global_type_names) + { + } + + public: + Boolean + fixed_length (SemanticGraph::Type& t) + { + return t.context ().get<Boolean> ("fixed"); + } + + Boolean + fixed_length (SemanticGraph::Compositor& c) + { + return c.context ().get<Boolean> ("fixed"); + } + + Void + mark_variable (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* p (&c); + + while (true) + { + p->context ().set ("fixed", false); + + if (p->contained_compositor_p ()) + break; + + p = &p->contained_particle ().compositor (); + + if (!p->context ().get<Boolean> ("fixed")) + break; + } + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = Hybrid::Context::escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + public: + struct CustomDataMap: + Cult::Containers::Map<String, Shptr<CustomDataMap> > + { + }; + + private: + SemanticGraph::Path const schema_path_; + + CustomDataMap custom_data_map_; + Cult::Containers::Map<String, NameSet*> global_type_names_; + + public: + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + + CustomDataMap& custom_data_map; + Cult::Containers::Map<String, NameSet*>& global_type_names; + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& l) + { + if (!data_members_) + { + // Check if this type has custom data. + // + CustomDataMap::Iterator i (custom_data_map.find (l.name ())); + + if (i != custom_data_map.end () && + i->second->find (L"") != i->second->end ()) + { + SemanticGraph::Context& lc (l.context ()); + + // Use processed name. + // + String const& name (lc.get<String> ("name")); + + lc.set (member_set_key, NameSet ()); + NameSet& set (lc.get<NameSet> (member_set_key)); + set.insert (name); + + { + String name (find_name ("custom_data", set)); + + lc.set ("cd-name", name); + lc.set ("cd-sequence", find_name (name + L"_sequence", set)); + lc.set ("cd-iterator", find_name (name + L"_iterator", set)); + lc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", set)); + } + } + } + else + { + SemanticGraph::Context& lc (l.context ()); + + // Custom data. + // + if (lc.count ("cd-name")) + { + NameSet& set (lc.get<NameSet> (member_set_key)); + String const& base (lc.get<String> ("cd-name")); + lc.set ("cd-member", find_name (base + L"_", set)); + } + } + } + + private: + Boolean data_members_; + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& u) + { + SemanticGraph::Context& uc (u.context ()); + + if (!data_members_) + { + // Use processed name. + // + String const& name (uc.get<String> ("name")); + + uc.set (member_set_key, NameSet ()); + NameSet& set (uc.get<NameSet> (member_set_key)); + set.insert (name); + + uc.set ("value", find_name ("value", set)); + + // Check if this type has custom data. + // + CustomDataMap::Iterator i (custom_data_map.find (u.name ())); + + if (i != custom_data_map.end () && + i->second->find (L"") != i->second->end ()) + { + String name (find_name ("custom_data", set)); + + uc.set ("cd-name", name); + uc.set ("cd-sequence", find_name (name + L"_sequence", set)); + uc.set ("cd-iterator", find_name (name + L"_iterator", set)); + uc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", set)); + } + } + else + { + NameSet& set (uc.get<NameSet> (member_set_key)); + uc.set ("value-member", find_name ("value_", set)); + + // Custom data. + // + if (uc.count ("cd-name")) + { + String const& base (uc.get<String> ("cd-name")); + uc.set ("cd-member", find_name (base + L"_", set)); + } + } + } + + private: + Boolean data_members_; + }; + + // + // Primary names. + // + + struct PrimaryAttribute: Traversal::Attribute, Context + { + PrimaryAttribute (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + a.context ().set ("name", find_name (a.name (), set_)); + } + + private: + NameSet& set_; + }; + + struct PrimaryElement: Traversal::Element, Context + { + PrimaryElement (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + e.context ().set ("name", find_name (e.name (), set_)); + } + + private: + NameSet& set_; + }; + + struct PrimaryAll: Traversal::All, Context + { + PrimaryAll (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + a.context ().set ("name", find_name ("all", set_)); + else + All::contains (a); + } + + private: + NameSet& set_; + }; + + struct PrimaryChoice: Traversal::Choice, Context + { + PrimaryChoice (Context& c, NameSet& set, Boolean in_choice) + : Context (c), set_ (set), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // In case of choice assign primary name even if there is + // no nested class. It is used to derive names for arm + // functions. + // + c.context ().set ("name", find_name ("choice", set_)); + + if (!in_choice_ && c.max () == 1 && c.min () == 1) + Choice::contains (c); + } + + private: + NameSet& set_; + Boolean in_choice_; + }; + + struct PrimarySequence: Traversal::Sequence, Context + { + PrimarySequence (Context& c, NameSet& set, Boolean in_choice) + : Context (c), set_ (set), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + s.context ().set ("name", find_name ("sequence", set_)); + else + Sequence::contains (s); + } + + private: + NameSet& set_; + Boolean in_choice_; + }; + + // + // Secondary names. + // + + struct SecondaryAttribute: Traversal::Attribute, Context + { + SecondaryAttribute (Context& c, NameSet& set, Boolean data_members) + : Context (c), set_ (set), data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Context& ac (a.context ()); + + if (!data_members_) + { + if (a.optional ()) + ac.set ( + "present", + find_name (ac.get<String> ("name") + L"_present", set_)); + } + else + { + String const& base (ac.get<String> ("name")); + + if (a.optional ()) + { + if (fixed_length (a.type ())) + ac.set ("present-member", + find_name (ac.get<String> ("present") + L"_", set_)); + } + + ac.set ("member", find_name (base + L"_", set_)); + } + } + + private: + NameSet& set_; + Boolean data_members_; + }; + + struct SecondaryElement: Traversal::Element, Context + { + SecondaryElement (Context& c, NameSet& set, Boolean data_members) + : Context (c), set_ (set), data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!data_members_) + { + if (e.max () != 1) + { + String const& base (ec.get<String> ("name")); + + ec.set ("sequence", find_name (base + L"_sequence", set_)); + ec.set ("iterator", find_name (base + L"_iterator", set_)); + ec.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (e.min () == 0) + { + ec.set ( + "present", + find_name (ec.get<String> ("name") + L"_present", set_)); + } + } + else + { + String const& base (ec.get<String> ("name")); + + if (e.max () == 1 && e.min () == 0) + { + if (fixed_length (e.type ())) + ec.set ("present-member", + find_name (ec.get<String> ("present") + L"_", set_)); + } + + ec.set ("member", find_name (base + L"_", set_)); + } + } + + + private: + NameSet& set_; + Boolean data_members_; + }; + + struct SecondaryAll: Traversal::All, Context + { + SecondaryAll (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + SemanticGraph::Context& ac (a.context ()); + String const& base (ac.get<String> ("name")); + + if (!data_members_) + { + // Check if this type has custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + String type (find_name (base + L"_type", set_)); + ac.set ("type", type); + + // Handle the nested class. + // + { + ac.set (member_set_key, NameSet ()); + NameSet& name_set (ac.get<NameSet> (member_set_key)); + + name_set.insert (type); + + { + PrimaryElement element (*this, name_set); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + } + + { + SecondaryElement element (*this, name_set, false); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (a)) + mark_variable (a); + + String name (find_name ("custom_data", name_set)); + + ac.set ("cd-name", name); + + ac.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + ac.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + ac.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + ac.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (ac.get<NameSet> (member_set_key)); + + SecondaryElement element (*this, name_set, true); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + + // Custom data. + // + if (ac.count ("cd-name")) + { + String const& base (ac.get<String> ("cd-name")); + ac.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (fixed_length (a)) + ac.set ("present-member", + find_name (ac.get<String> ("present") + L"_", set_)); + + ac.set ("member", find_name (base + L"_", set_)); + } + } + else + All::contains (a); + } + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean data_members_; + }; + + struct ParticleTag: Traversal::Element, + Traversal::Any, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleTag (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& base (e.context ().get<String> ("name")); + e.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + a.context ().set ("tag", find_name (L"any", L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + String const& base (c.context ().get<String> ("name")); + c.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + String const& base (s.context ().get<String> ("name")); + s.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + private: + NameSet& set_; + }; + + struct SecondaryChoice: Traversal::Choice, Context + { + SecondaryChoice (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean in_choice, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + in_choice_ (in_choice), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Choice&); + + Void + traverse_nested (SemanticGraph::Choice&, NameSet&, CustomDataMap*); + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean in_choice_; + Boolean data_members_; + }; + + struct SecondarySequence: Traversal::Sequence, Context + { + SecondarySequence (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean in_choice, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + in_choice_ (in_choice), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Sequence&); + + Void + traverse_nested (SemanticGraph::Sequence&, NameSet&, CustomDataMap*); + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean in_choice_; + Boolean data_members_; + }; + + + Void SecondaryChoice:: + traverse (SemanticGraph::Choice& c) + { + SemanticGraph::Context& cc (c.context ()); + String const& base (cc.get<String> ("name")); + + // When choice is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + if (!data_members_) + { + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + // + // + String type (find_name (base + L"_type", set_)); + cc.set ("type", type); + + // Handle the nested class. + // + { + cc.set (member_set_key, NameSet ()); + NameSet& name_set (cc.get<NameSet> (member_set_key)); + + // Add both base and type names so that we get consistent + // naming for nested choices if any. + // + name_set.insert (base); + name_set.insert (type); + + traverse_nested (c, name_set, map); + + // Tags. + // + String arm (find_name (base + L"_arm", name_set)); + cc.set ("arm", arm); + cc.set ("arm-tag", find_name (arm + L"_tag", name_set)); + + { + UnsignedLong count (name_set.size ()); + + ParticleTag particle (*this, name_set); + Traversal::ContainsParticle contains (particle); + + Choice::contains (c, contains); + + count = name_set.size () - count; + cc.set ("arm-tag-count", count); + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (c)) + mark_variable (c); + + String name (find_name ("custom_data", name_set)); + + cc.set ("cd-name", name); + + cc.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + cc.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + cc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + if (c.max () != 1) + { + cc.set ("sequence", find_name (base + L"_sequence", set_)); + cc.set ("iterator", find_name (base + L"_iterator", set_)); + cc.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (c.min () == 0) + cc.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (cc.get<NameSet> (member_set_key)); + traverse_nested (c, name_set, 0); + + // Tags. + // + cc.set ("arm-member", + find_name (cc.get<String> ("arm") + L"_", name_set)); + cc.set ("member", find_name (base + L"_", name_set)); + + // Custom data. + // + if (cc.count ("cd-name")) + { + String const& base (cc.get<String> ("cd-name")); + cc.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (c.max () == 1 && c.min () == 0) + { + if (fixed_length (c)) + cc.set ("present-member", + find_name (cc.get<String> ("present") + L"_", set_)); + } + + cc.set ("member", find_name (base + L"_", set_)); + } + } + else + { + Choice::contains (c); + + if (!data_members_) + { + String arm (find_name (base + L"_arm", set_)); + cc.set ("arm", arm); + cc.set ("arm-tag", find_name (arm + L"_tag", set_)); + + { + UnsignedLong count (set_.size ()); + + ParticleTag particle (*this, set_); + Traversal::ContainsParticle contains (particle); + + Choice::contains (c, contains); + + count = set_.size () - count; + cc.set ("arm-tag-count", count); + } + } + else + { + cc.set ("arm-member", + find_name (cc.get<String> ("arm") + L"_", set_)); + cc.set ("member", find_name (base + L"_", set_)); + } + } + } + + Void SecondaryChoice:: + traverse_nested (SemanticGraph::Choice& c, + NameSet& name_set, + CustomDataMap* map) + { + if (!data_members_) + { + PrimaryElement element (*this, name_set); + PrimaryChoice choice_in_sequence (*this, name_set, false); + PrimarySequence sequence_in_sequence (*this, name_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, name_set, true); + PrimarySequence sequence_in_choice (*this, name_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Choice::contains (c, choice_contains_particle); + } + + SecondaryElement element (*this, name_set, data_members_); + SecondaryChoice choice_in_sequence ( + *this, name_set, map, false, data_members_); + SecondarySequence sequence_in_sequence ( + *this, name_set, map, false, data_members_); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, name_set, map, true, data_members_); + SecondarySequence sequence_in_choice ( + *this, name_set, map, true, data_members_); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Choice::contains (c, choice_contains_particle); + } + + Void SecondarySequence:: + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + SemanticGraph::Context& sc (s.context ()); + String const& base (sc.get<String> ("name")); + + if (!data_members_) + { + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + String type (find_name (base + L"_type", set_)); + sc.set ("type", type); + + // Handle the nested class. + // + { + sc.set (member_set_key, NameSet ()); + NameSet& name_set (sc.get<NameSet> (member_set_key)); + + // Add both base and type names so that we get consistent + // naming for nested sequences if any. + // + name_set.insert (base); + name_set.insert (type); + + traverse_nested (s, name_set, map); + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (s)) + mark_variable (s); + + String name (find_name ("custom_data", name_set)); + + sc.set ("cd-name", name); + + sc.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + sc.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + sc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + if (s.max () != 1) + { + sc.set ("sequence", find_name (base + L"_sequence", set_)); + sc.set ("iterator", find_name (base + L"_iterator", set_)); + sc.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (s.min () == 0) + sc.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (sc.get<NameSet> (member_set_key)); + traverse_nested (s, name_set, 0); + + // Custom data. + // + if (sc.count ("cd-name")) + { + String const& base (sc.get<String> ("cd-name")); + sc.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (s.max () == 1 && s.min () == 0) + { + if (fixed_length (s)) + sc.set ("present-member", + find_name (sc.get<String> ("present") + L"_", set_)); + } + + sc.set ("member", find_name (base + L"_", set_)); + } + } + else + Sequence::contains (s); + } + + Void SecondarySequence:: + traverse_nested (SemanticGraph::Sequence& s, + NameSet& name_set, + CustomDataMap* map) + { + if (!data_members_) + { + PrimaryElement element (*this, name_set); + PrimaryChoice choice_in_sequence (*this, name_set, false); + PrimarySequence sequence_in_sequence (*this, name_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, name_set, true); + PrimarySequence sequence_in_choice (*this, name_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Sequence::contains (s, sequence_contains_particle); + } + + SecondaryElement element (*this, name_set, data_members_); + SecondaryChoice choice_in_sequence ( + *this, name_set, map, false, data_members_); + SecondarySequence sequence_in_sequence ( + *this, name_set, map, false, data_members_); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, name_set, map, true, data_members_); + SecondarySequence sequence_in_choice ( + *this, name_set, map, true, data_members_); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Sequence::contains (s, sequence_contains_particle); + } + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& c) + { + if (data_members_) + assign_data (c); + else + assign_names (c); + } + + virtual Void + assign_names (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + { + CustomDataMap::Iterator i (custom_data_map.find (c.name ())); + if (i != custom_data_map.end ()) + map = i->second.get (); + } + + // Use processed name. + // + String const& name (cc.get<String> ("name")); + + cc.set (member_set_key, NameSet ()); + NameSet& member_set (cc.get<NameSet> (member_set_key)); + + member_set.insert (name); + + // Add our base's members to the initial list. + // + Boolean restriction (false); + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (b.is_a<SemanticGraph::Complex> ()) + { + SemanticGraph::Context& bc (b.context ()); + + if (!bc.count (member_set_key)) + dispatch (b); + + NameSet const& bset (bc.get<NameSet> (member_set_key)); + member_set.insert (bset.begin (), bset.end ()); + } + + // Inheritance by restriction from anyType is a special case. + // + restriction = c.inherits ().is_a<SemanticGraph::Restricts> () && + !b.is_a<SemanticGraph::AnyType> (); + } + + if (!restriction) + { + // First assign the "primary" names. + // + PrimaryAttribute pri_attribute (*this, member_set); + Traversal::Names pri_names (pri_attribute); + + Complex::names (c, pri_names); + + if (c.contains_compositor_p ()) + { + PrimaryElement element (*this, member_set); + PrimaryAll all (*this, member_set); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + PrimaryChoice choice_in_sequence (*this, member_set, false); + PrimarySequence sequence_in_sequence (*this, member_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, member_set, true); + PrimarySequence sequence_in_choice (*this, member_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + + // Assign "secondary" names. + // + SecondaryAttribute sec_attribute (*this, member_set, false); + Traversal::Names sec_names (sec_attribute); + + Complex::names (c, sec_names); + + if (c.contains_compositor_p ()) + { + SecondaryElement element (*this, member_set, false); + SecondaryAll all (*this, member_set, map, false); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + SecondaryChoice choice_in_sequence ( + *this, member_set, map, false, false); + SecondarySequence sequence_in_sequence ( + *this, member_set, map, false, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, member_set, map, true, false); + SecondarySequence sequence_in_choice ( + *this, member_set, map, true, false); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + String name (find_name ("custom_data", member_set)); + + cc.set ("cd-name", name); + + cc.set ("cd-sequence", + find_name (name + L"_sequence", member_set)); + + cc.set ("cd-iterator", + find_name (name + L"_iterator", member_set)); + + cc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", member_set)); + } + } + + virtual Void + assign_data (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a<SemanticGraph::Restricts> () && + !c.inherits ().base ().is_a<SemanticGraph::AnyType> (); + + NameSet& member_set (cc.get<NameSet> (member_set_key)); + + if (!restriction) + { + SecondaryAttribute sec_attribute (*this, member_set, true); + Traversal::Names sec_names (sec_attribute); + + Complex::names (c, sec_names); + + if (c.contains_compositor_p ()) + { + SecondaryElement element (*this, member_set, true); + SecondaryAll all (*this, member_set, 0, true); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + SecondaryChoice choice_in_sequence ( + *this, member_set, 0, false, true); + + SecondarySequence sequence_in_sequence ( + *this, member_set, 0, false, true); + + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, member_set, 0, true, true); + + SecondarySequence sequence_in_choice ( + *this, member_set, 0, true, true); + + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + } + + // Custom data. + // + if (cc.count ("cd-name")) + { + String const& base (cc.get<String> ("cd-name")); + cc.set ("cd-member", find_name (base + L"_", member_set)); + } + } + + private: + Boolean data_members_; + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + String name (find_name (t.name (), set_)); + t.context ().set ("name", name); + } + + private: + NameSet& set_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get<NameSet> ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + }; + + struct FundType : Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + + { + FundType (Context& c) + : Context (c) + { + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + set_name (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + set_name (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + set_name (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + set_name (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + set_name (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + set_name (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + set_name (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + set_name (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + set_name (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + set_name (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + set_name (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + set_name (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + set_name (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + set_name (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + set_name (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + set_name (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + set_name (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + set_name (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + set_name (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + set_name (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + set_name (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + set_name (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + set_name (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + set_name (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + set_name (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + set_name (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + set_name (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + set_name (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + set_name (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + set_name (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + set_name (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + set_name (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + set_name (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + set_name (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + set_name (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + set_name (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + set_name (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + set_name (t, "gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + set_name (t, "gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + set_name (t, "gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + set_name (t, "gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + set_name (t, "gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + set_name (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + set_name (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + set_name (t, "entities"); + } + + private: + Void + set_name (SemanticGraph::Type& t, String const& name) + { + SemanticGraph::Context& c (t.context ()); + c.set ("name", escape (name)); + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Imports::traverse (i); + } + } + }; + + // Go into implied schemas while making sure we don't process + // the same stuff more than once. + // + struct Implies: Traversal::Implies + { + virtual Void + traverse (SemanticGraph::Implies& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // Pass one - assign names to fundamental types. + // + { + Traversal::Schema schema; + Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Pass two - assign names to global types. This pass cannot + // be combined with pass three because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count ("cxx-hybrid-name-processor-seen")) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-hybrid-name-processor-seen", true); + + schema.dispatch (tu); + } + + // Pass three - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx, false); + Union union_ (ctx, false); + Complex complex (ctx, false); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + + // Pass four - assign names to data memeber. Here we aslo don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx, true); + Union union_ (ctx, true); + Complex complex (ctx, true); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + } + + Void TreeNameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} |