// file : xsde/cxx/hybrid/tree-name-processor.cxx // author : Boris Kolpackov // copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include #include #include #include #include #include #include namespace CXX { namespace Hybrid { namespace { // // typedef Cult::Containers::Set 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 (), ops.value (), "", // export symbol ops.value (), ops.value (), ops.value (), ops.value (), ops.value (), ops.value (), ops.value ()), 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 CustomData; CustomData const& cd (ops.value ()); 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& p ((*map)[entry]); if (p == 0) p = Shptr (new CustomDataMap); b = e; if (b == String::npos) { // Last name. Add an empty string to indicate this. // (*p)[L""] = Shptr (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 ("fixed"); } Boolean fixed_length (SemanticGraph::Compositor& c) { return c.context ().get ("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 ("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 > { }; private: SemanticGraph::Path const schema_path_; CustomDataMap custom_data_map_; Cult::Containers::Map global_type_names_; public: SemanticGraph::Schema& schema; SemanticGraph::Path const& schema_path; CustomDataMap& custom_data_map; Cult::Containers::Map& 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 ("name")); lc.set (member_set_key, NameSet ()); NameSet& set (lc.get (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 (member_set_key)); String const& base (lc.get ("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 ("name")); uc.set (member_set_key, NameSet ()); NameSet& set (uc.get (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 (member_set_key)); uc.set ("value-member", find_name ("value_", set)); // Custom data. // if (uc.count ("cd-name")) { String const& base (uc.get ("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 ("name") + L"_present", set_)); } else { String const& base (ac.get ("name")); if (a.optional ()) { if (fixed_length (a.type ())) ac.set ("present-member", find_name (ac.get ("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 ("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 ("name") + L"_present", set_)); } } else { String const& base (ec.get ("name")); if (e.max () == 1 && e.min () == 0) { if (fixed_length (e.type ())) ec.set ("present-member", find_name (ec.get ("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 ("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 (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 (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 ("cd-name")); ac.set ("cd-member", find_name (base + L"_", name_set)); } } if (fixed_length (a)) ac.set ("present-member", find_name (ac.get ("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 ("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 ("name")); c.context ().set ("tag", find_name (base, L"_tag", set_)); } virtual Void traverse (SemanticGraph::Sequence& s) { String const& base (s.context ().get ("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 ("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 (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 (member_set_key)); traverse_nested (c, name_set, 0); // Tags. // cc.set ("arm-member", find_name (cc.get ("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 ("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 ("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 ("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 ("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 (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 (member_set_key)); traverse_nested (s, name_set, 0); // Custom data. // if (sc.count ("cd-name")) { String const& base (sc.get ("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 ("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 ("name")); cc.set (member_set_key, NameSet ()); NameSet& member_set (cc.get (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::Context& bc (b.context ()); if (!bc.count (member_set_key)) dispatch (b); NameSet const& bset (bc.get (member_set_key)); member_set.insert (bset.begin (), bset.end ()); } // Inheritance by restriction from anyType is a special case. // restriction = c.inherits ().is_a () && !b.is_a (); } 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 () && !c.inherits ().base ().is_a (); NameSet& member_set (cc.get (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 ("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 ("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); } } }