From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- xsd/cxx/tree/name-processor.cxx | 2100 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 2100 insertions(+) create mode 100644 xsd/cxx/tree/name-processor.cxx (limited to 'xsd/cxx/tree/name-processor.cxx') diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx new file mode 100644 index 0000000..456095f --- /dev/null +++ b/xsd/cxx/tree/name-processor.cxx @@ -0,0 +1,2100 @@ +// file : xsd/cxx/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 Tree + { + NameProcessor:: + NameProcessor () + { + // Dummy ctor, helps with long symbols on HP-UX. + } + + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + + + + + class Context: public Tree::Context + { + public: + struct Failed {}; + + Context (CLI::Options const& options, + Counts const& counts, + Boolean generate_xml_schema, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : Tree::Context (std::wcerr, + root, + options, + counts, + generate_xml_schema, + 0, + 0, + 0), + schema_path_ (file), + schema_path (schema_path_), + global_type_names (global_type_names_), + global_element_names (global_element_names_), + type_regex (type_regex_), + accessor_regex (accessor_regex_), + one_accessor_regex (one_accessor_regex_), + opt_accessor_regex (opt_accessor_regex_), + seq_accessor_regex (seq_accessor_regex_), + modifier_regex (modifier_regex_), + one_modifier_regex (one_modifier_regex_), + opt_modifier_regex (opt_modifier_regex_), + seq_modifier_regex (seq_modifier_regex_), + parser_regex (parser_regex_), + serializer_regex (serializer_regex_), + enumerator_regex (enumerator_regex_), + element_type_regex (element_type_regex_) + { + typedef Containers::Vector Vector; + + NarrowString tn (options.value ()); + NarrowString fn (options.value ()); + + + // Type name regex. + // + { + // Predefined rules. The most frequently used come last: global + // names, two components (,type), three components + // (,const,iterator), and one component (value in enum). + // + if (tn == "knr") + { + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/$1/"); + + /* + type_regex.push_back ("/([^,]+)/$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/[^ ]* (.+)/$1/"); + */ + } + else + { + // Upper camel case or Java. + // + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/\\u$1/"); + + /* + type_regex.push_back ("/([^,]+)/\\u$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/[^ ]* (.+)/\\u$1/"); + */ + + } + + compile_regex (options.value (), + type_regex, + "type"); + } + + // Accessor name regex. + // + { + // Predefined rules. The most frequently used come last: one + // component, three components (,default,value) and two + // component (dom,document). + // + if (fn == "knr") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + accessor_regex.push_back ("/([^,]+)/$1/"); + } + else if (fn == "lcc") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/\\l$1/"); + } + else + { + // Java: add get. + // + accessor_regex.push_back ("/([^,]+),([^,]+)/get\\u$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/get\\u$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/get\\u$1/"); + } + + compile_regex (options.value (), + accessor_regex, + "accessor"); + + compile_regex (options.value (), + one_accessor_regex, + "one accessor"); + + compile_regex (options.value (), + opt_accessor_regex, + "optional accessor"); + + compile_regex (options.value (), + seq_accessor_regex, + "sequence accessor"); + } + + + // Modifier name regex. + // + { + if (fn == "knr") + { + // any,attribute + // + modifier_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + } + else if (fn == "lcc") + { + modifier_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + modifier_regex.push_back ("/([^,]+)/\\l$1/"); + } + else + { + // Java: add set. + // + modifier_regex.push_back ("/([^,]+),([^,]+)/set\\u$1\\u$2/"); + modifier_regex.push_back ("/([^,]+)/set\\u$1/"); + } + + compile_regex (options.value (), + modifier_regex, + "modifier"); + + compile_regex (options.value (), + one_modifier_regex, + "one modifier"); + + compile_regex (options.value (), + opt_modifier_regex, + "optional modifier"); + + compile_regex (options.value (), + seq_modifier_regex, + "sequence modifier"); + } + + + // Parser name regex. + // + { + if (fn == "lcc") + { + parser_regex.push_back ("/(.+)/\\l$1/"); + } + else if (fn == "java") + { + // Java: add parse. + // + parser_regex.push_back ("/(.+)/parse\\u$1/"); + } + + compile_regex (options.value (), + parser_regex, + "parser"); + } + + // Serializer name regex. + // + { + if (fn == "lcc") + { + serializer_regex.push_back ("/(.+)/\\l$1/"); + } + else if (fn == "java") + { + // Java: add serialize. + // + serializer_regex.push_back ("/(.+)/serialize\\u$1/"); + } + + compile_regex (options.value (), + serializer_regex, + "serializer"); + } + + // Enumerator name regex. + // + { + compile_regex (options.value (), + enumerator_regex, + "enumerator"); + } + + // Element type regex. + // + compile_regex (options.value (), + element_type_regex, + "element_type"); + } + + protected: + Context (Context& c) + : Tree::Context (c), + schema_path (c.schema_path), + global_type_names (c.global_type_names), + global_element_names (c.global_element_names), + type_regex (c.type_regex), + accessor_regex (c.accessor_regex), + one_accessor_regex (c.one_accessor_regex), + opt_accessor_regex (c.opt_accessor_regex), + seq_accessor_regex (c.seq_accessor_regex), + modifier_regex (c.modifier_regex), + one_modifier_regex (c.one_modifier_regex), + opt_modifier_regex (c.opt_modifier_regex), + seq_modifier_regex (c.seq_modifier_regex), + parser_regex (c.parser_regex), + serializer_regex (c.serializer_regex), + enumerator_regex (c.enumerator_regex), + element_type_regex (c.element_type_regex) + { + } + + public: + typedef BackendElements::Regex::Expression Regex; + typedef BackendElements::Regex::Format RegexFormat; + typedef Cult::Containers::Vector RegexVector; + + String + process_regex (String const& name, + RegexVector const& rv, + String const& id) + { + Boolean trace (options.value ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::ConstReverseIterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& name, + RegexVector const& primary, + RegexVector const& backup, + String const& id) + { + Boolean trace (options.value ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::ConstReverseIterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::ConstReverseIterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& ns, + String const& name, + RegexVector const& rv, + String const& id) + { + String s (ns + L' ' + name); + Boolean trace (options.value ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::ConstReverseIterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& ns, + String const& name, + RegexVector const& primary, + RegexVector const& backup, + String const& id) + { + String s (ns + L' ' + name); + Boolean trace (options.value ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::ConstReverseIterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::ConstReverseIterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + public: + String + find_name (String const& base_name, + NameSet& set, + Boolean insert = true) + { + String name (base_name); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = base_name + os.str (); + } + + if (insert) + set.insert (name); + + return name; + } + + private: + Void + compile_regex (Containers::Vector const& sv, + RegexVector& rv, + String const& id) + { + typedef Containers::Vector Vector; + + for (Vector::ConstIterator i (sv.begin ()); i != sv.end (); ++i) + { + try + { + rv.push_back (Regex (*i)); + } + catch (RegexFormat const& e) + { + os << "error: invalid " << id << " name regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } + } + + private: + SemanticGraph::Path const schema_path_; + + Cult::Containers::Map global_type_names_; + Cult::Containers::Map global_element_names_; + + RegexVector type_regex_; + RegexVector accessor_regex_; + RegexVector one_accessor_regex_; + RegexVector opt_accessor_regex_; + RegexVector seq_accessor_regex_; + RegexVector modifier_regex_; + RegexVector one_modifier_regex_; + RegexVector opt_modifier_regex_; + RegexVector seq_modifier_regex_; + RegexVector parser_regex_; + RegexVector serializer_regex_; + RegexVector enumerator_regex_; + RegexVector element_type_regex_; + + public: + SemanticGraph::Path const& schema_path; + + Cult::Containers::Map& global_type_names; + Cult::Containers::Map& global_element_names; + + RegexVector& type_regex; + RegexVector& accessor_regex; + RegexVector& one_accessor_regex; + RegexVector& opt_accessor_regex; + RegexVector& seq_accessor_regex; + RegexVector& modifier_regex; + RegexVector& one_modifier_regex; + RegexVector& opt_modifier_regex; + RegexVector& seq_modifier_regex; + RegexVector& parser_regex; + RegexVector& serializer_regex; + RegexVector& enumerator_regex; + RegexVector& element_type_regex; + }; + + // + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (Type& e) + { + // Process the name with enumerator name regex. + // + String name ( + process_regex (e.name (), enumerator_regex, L"enumerator")); + + // Escape and unclash. + // + name = find_name (escape (name), set_); + e.context ().set ("name", name); + } + + private: + NameSet& set_; + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + // Use processed name. + // + String name (e.context ().get ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (e, name) && !name) + return; + + NameSet enum_set; + enum_set.insert (name); + + Enumerator enumerator (*this, enum_set); + Traversal::Names names (enumerator); + + Traversal::Enumeration::names (e, names); + + // Assign name to the value type. First process the name + // with type name regex. + // + String value_name ( + escape (process_regex ("value", type_regex, L"type"))); + e.context ().set ("value", find_name (value_name, enum_set)); + } + }; + + // + // + struct PrimaryMember: Traversal::Member, Context + { + PrimaryMember (Context& c, NameSet& name_set, NameSet& stem_set) + : Context (c), name_set_ (name_set), stem_set_ (stem_set) + { + } + + virtual Void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + String stem (find_name (m.name (), stem_set_)); + + m.context ().set ("stem", stem); + m.context ().set ("name", + find_name (escape (stem), name_set_, false)); + } + + private: + NameSet& name_set_; + NameSet& stem_set_; + }; + + // + // + struct DerivedMember: Traversal::Member, Context + { + DerivedMember (Context& c, NameSet& name_set) + : Context (c), name_set_ (name_set) + { + } + + virtual Void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + UnsignedLong max (Tree::Context::max (m)); + UnsignedLong min (Tree::Context::min (m)); + + String const& s (m.context ().get ("stem")); + String const& b (m.context ().get ("name")); + + Boolean def_attr (m.default_ () && + m.is_a () && + !Tree::Context::is_qname (m.type ())); + + // Accessors/modifiers. Note that we postpone inserting the + // names into the name_set to avoid over-escaping. + // + String an, mn; + + if (max != 1) + { + an = find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + name_set_, + false); + } + else if (min == 0 && !def_attr) + { + an = find_name ( + escape (process_regex (s, + opt_accessor_regex, + accessor_regex, + L"optional accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + opt_modifier_regex, + modifier_regex, + L"optional modifier")), + name_set_, + false); + } + else + { + an = find_name ( + escape (process_regex (s, + one_accessor_regex, + accessor_regex, + L"one accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_, + false); + } + + m.context ().set ("aname", an); + m.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + + // Types. + // + m.context ().set ( + "type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "traits", + find_name ( + escape (process_regex (s + L",traits", type_regex, L"type")), + name_set_)); + + if (max != 1) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + } + else if (min == 0 && !def_attr) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",optional", type_regex, L"type")), + name_set_)); + } + + // Data member. + // + m.context ().set ("member", find_name (b + L"_", name_set_)); + + // Default value. + // + if (m.default_ () && !Tree::Context::is_qname (m.type ())) + { + Boolean simple (true); + + if (m.is_a ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + String an ( + escape ( + process_regex ( + s + L",default,value", accessor_regex, L"accessor"))); + + m.context ().set ( "default-value", find_name (an, name_set_)); + + m.context ().set ( + "default-value-member", + find_name (b + L"_default_value_", name_set_)); + } + } + } + + private: + NameSet& name_set_; + }; + + + // + // + struct Any: Traversal::Any, Traversal::AnyAttribute, Context + { + Any (Context& c, + NameSet& name_set, + NameSet& stem_set, + Boolean& has_wildcard) + : Context (c), + name_set_ (name_set), + stem_set_ (stem_set), + has_wildcard_ (has_wildcard) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong max (Tree::Context::max (a)); + UnsignedLong min (Tree::Context::min (a)); + + String s (find_name (L"any", stem_set_)); + + String b (find_name (escape (s), name_set_, false)); + a.context ().set ("name", b); + + // Accessors/modifiers. Note that we postpone inserting the + // names into the name_set to avoid over-escaping. + // + String an, mn; + + if (max != 1) + { + an = find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + name_set_, + false); + } + else if (min == 0) + { + an = find_name ( + escape (process_regex (s, + opt_accessor_regex, + accessor_regex, + L"optional accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + opt_modifier_regex, + modifier_regex, + L"optional modifier")), + name_set_, + false); + } + else + { + an = find_name ( + escape (process_regex (s, + one_accessor_regex, + accessor_regex, + L"one accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_, + false); + } + + a.context ().set ("aname", an); + a.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Types + // + if (max != 1) + { + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + } + else if (min == 0) + { + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",optional", type_regex, L"type")), + name_set_)); + } + + // Data member. + // + a.context ().set ("member", find_name (b + L"_", name_set_)); + + if (!has_wildcard_) + has_wildcard_ = true; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String s (find_name (L"any,attribute", stem_set_)); + + String b (find_name (escape (s), name_set_, false)); + a.context ().set ("name", b); + + // Accessors/modifiers. Note that we postpone inserting the + // names into the name_set to avoid over-escaping. + // + String an ( + find_name ( + escape (process_regex (s, accessor_regex, L"accessor")), + name_set_, + false)); + + String mn ( + find_name ( + escape (process_regex (s, modifier_regex, L"modifier")), + name_set_, + false)); + + a.context ().set ("aname", an); + a.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Types + // + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",set", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + + // Data member. + // + a.context ().set ("member", find_name (b + L"_", name_set_)); + + if (!has_wildcard_) + has_wildcard_ = true; + } + + private: + NameSet& name_set_; + NameSet& stem_set_; + Boolean& has_wildcard_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // Use processed name. + // + String name (cc.get ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (c, name) && !name) + return; + + // We leave this set around to allow other mappings to use + // this information. + // + cc.set ("cxx-tree-name-processor-stem-set", NameSet ()); + cc.set ("cxx-tree-name-processor-member-set", NameSet ()); + + NameSet& stem_set ( + cc.get ("cxx-tree-name-processor-stem-set")); + + NameSet& member_set ( + cc.get ("cxx-tree-name-processor-member-set")); + + stem_set.insert (c.name ()); + member_set.insert (name); + + // Add our base's stems and members to the initial list. + // + if (c.inherits_p ()) + { + // @@ What if this types name is the same as one of base's + // members? + // + SemanticGraph::Type& base (c.inherits ().base ()); + + if (base.is_a ()) + { + if (!base.context ().count ( + "cxx-tree-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_stem_set ( + base.context ().get ( + "cxx-tree-name-processor-stem-set")); + + stem_set.insert (base_stem_set.begin (), base_stem_set.end ()); + + NameSet const& base_member_set ( + base.context ().get ( + "cxx-tree-name-processor-member-set")); + + member_set.insert (base_member_set.begin (), + base_member_set.end ()); + } + } + + // First assign the "primary" names. + // + { + PrimaryMember member (*this, member_set, stem_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Derived names for members. + // + { + DerivedMember member (*this, member_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Names for wildcards. + // + if (options.value ()) + { + Boolean has_wildcard (false); + Any any (*this, member_set, stem_set, has_wildcard); + Traversal::Names names (any); + Complex::names (c, names); + + // Assign names for dom_document. + // + if (has_wildcard) + { + // Check if we already have dom_document down inheritance + // hierarchy. + // + for (SemanticGraph::Complex* p (&c); p->inherits_p ();) + { + if (SemanticGraph::Complex* base = + dynamic_cast ( + &p->inherits ().base ())) + { + if (base->context ().count ("dom-document")) + { + c.context ().set ( + "dom-document", + base->context ().get ("dom-document")); + break; + } + + p = base; + } + else + break; + } + + // If not, set up the names. + // + if (!c.context ().count ("dom-document")) + { + String stem (find_name (L"dom,document", stem_set)); + + String an ( + escape ( + process_regex (stem, accessor_regex, L"accessor"))); + + c.context ().set ("dom-document", find_name (an, member_set)); + + c.context ().set ( + "dom-document-member", + find_name (escape (stem + L"_"), member_set)); + } + } + } + } + }; + + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + // Process the name with type name regex. + // + String name (process_regex ( + namespace_ (t).name (), + t.name (), + type_regex, + L"type")); + + // Escape and unclash. + // + name = find_name (escape (name), set_); + t.context ().set ("name", name); + + // Also add renamed name if any. + // + if (renamed_type (t, name) && name) + set_.insert (name); + } + + private: + NameSet& set_; + }; + + + // + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c, + NameSet const& type_set, + NameSet& element_set) + : GlobalElementBase (c), + Context (c), + type_set_ (type_set), + element_set_ (element_set) + { + } + + virtual Void + traverse (Type& e) + { + // First we need to figure out if we need to process this + // global element. + // + if (!generate_p (e)) + return; + + if (options.value ()) + { + SemanticGraph::Context& ec (e.context ()); + + String name; + + if (doc_root_p (e)) + { + name = find_name ( + escape ( + process_regex ( + namespace_ (e).name (), + e.name (), + element_type_regex, + type_regex, + L"element type"))); + + // Assign inner names. + // + NameSet set; + set.insert (name); + + ec.set ( + "type", + Context::find_name ( + escape (process_regex (L"value,type", type_regex, L"type")), + set)); + + ec.set ( + "traits", + Context::find_name ( + escape (process_regex (L"value,traits", type_regex, L"type")), + set)); + + String an = Context::find_name ( + escape (process_regex ("value", + one_accessor_regex, + accessor_regex, + L"one accessor")), + set, + false); + + String mn = Context::find_name ( + escape (process_regex ("value", + one_modifier_regex, + modifier_regex, + L"one modifier")), + set, + false); + + ec.set ("aname", an); + ec.set ("mname", mn); + + set.insert (an); + + if (an != mn) + set.insert (mn); + + // Assign name() and namespace_() names. + // + ec.set ( + "element-name", + Context::find_name ( + escape ( + process_regex ("name", accessor_regex, L"modifier")), + set)); + + ec.set ( + "element-ns", + Context::find_name ( + escape ( + process_regex ("namespace", accessor_regex, L"modifier")), + set)); + + // Data members. + // + ec.set ("member", Context::find_name ("value_", set)); + ec.set ("element-name-member", + Context::find_name ("name_", set)); + ec.set ("element-ns-member", + Context::find_name ("namespace__", set)); + } + else + name = find_name (escape (e.name ())); + + ec.set ("name", name); + element_set_.insert (name); + } + else + { + // Make sure the name is unique among global elements and + // does not collide with a global type name. + // + String base (find_name (escape (e.name ()))); + e.context ().set ("name", base); + + String n (e.name ()); + + // Assign the parsing function name. + // + String p; + + if (!options.value () && doc_root_p (e)) + { + p = find_name ( + escape ( + process_regex (n, parser_regex, L"parsing function"))); + + e.context ().set ("parser", p); + } + + // Assign the serialization function name. + // + String s; + + if (options.value () && + doc_root_p (e)) + { + s = find_name ( + escape ( + process_regex ( + n, serializer_regex, L"serialization function"))); + + e.context ().set ("serializer", s); + } + + // Add the names to the set only after processing parsing and + // serialization function names so that we do not over-escape + // them. + // + element_set_.insert (base); + + if (p && p != base) + element_set_.insert (p); + + if (s && s != base && s != p) + element_set_.insert (s); + } + } + + private: + String + find_name (String const& name) + { + String r (name); + + // If we are conflicting with a type name let's first try to + // simply append an underscore and only resort to ugly names + // like name1, etc., if this fails. + // + if (type_set_.find (r) != type_set_.end ()) + r += L"_"; + + for (UnsignedLong i (1); + element_set_.find (r) != element_set_.end () || + type_set_.find (r) != type_set_.end (); ++i) + { + std::wostringstream os; + os << i; + r = name + os.str (); + } + + return r; + } + + private: + NameSet const& type_set_; + NameSet& element_set_; + }; + + struct NamespacePassOne: Traversal::Namespace, Context + { + NamespacePassOne (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + NameSet& type_set (global_type_names[ns.name ()]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + Traversal::Namespace::names (ns); + } + }; + + + struct NamespacePassThree: Traversal::Namespace, Context + { + NamespacePassThree (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + String const& name (ns.name ()); + + NameSet const& type_set (global_type_names[name]); + NameSet& element_set (global_element_names[name]); + + GlobalElement element (*this, type_set, element_set); + Traversal::Names names (element); + + Traversal::Namespace::names (ns, names); + } + }; + + + struct FundamentalNamespace : Traversal::Namespace, + + 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::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::QName, + + 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 + { + FundamentalNamespace (Context& c) + : Context (c) + { + *this >> names_ >> *this; + } + + Void + process_name (SemanticGraph::Type& t, String const& name) + { + String r ( + process_regex ( + namespace_ (t).name (), name, type_regex, L"type")); + + t.context ().set ("name", escape (r)); + } + + Void + process_name (SemanticGraph::Namespace& n, + String const& name, + Char const* key) + { + String r (process_regex (name, type_regex, L"type")); + n.context ().set (key, escape (r)); + } + + // anyType and anySimpleType + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + process_name (t, "type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + process_name (t, "simple,type"); + } + + // Integrals. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + process_name (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + process_name (t, "unsigned,byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + process_name (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + process_name (t, "unsigned,short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + process_name (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + process_name (t, "unsigned,int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + process_name (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + process_name (t, "unsigned,long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + process_name (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + process_name (t, "non,positive,integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + process_name (t, "non,negative,integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + process_name (t, "positive,integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + process_name (t, "negative,integer"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + process_name (t, "boolean"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + process_name (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + process_name (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + process_name (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + process_name (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + process_name (t, "normalized,string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + process_name (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + process_name (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + process_name (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + process_name (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + process_name (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + process_name (t, "language"); + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + process_name (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + process_name (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + process_name (t, "idrefs"); + } + + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + process_name (t, "uri"); + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + process_name (t, "qname"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + process_name (t, "base64,binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + process_name (t, "hex,binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + process_name (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + process_name (t, "date,time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + process_name (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + process_name (t, "gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + process_name (t, "gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + process_name (t, "gmonth,day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + process_name (t, "gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + process_name (t, "gyear,month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + process_name (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + process_name (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + process_name (t, "entities"); + } + + virtual Void + post (SemanticGraph::Namespace& n) + { + // Assign names to extra stuff in the XML Schema namespace. + // + process_name (n, "container", "container"); + process_name (n, "buffer", "buffer"); + process_name (n, "time,zone", "time-zone"); + + if (options.value ()) + process_name (n, "element,type", "element-type"); + + if (options.value ()) + process_name (n, "element,map", "element-map"); + + if (options.value ()) + { + process_name (n, "namespace,info", "namespace-info"); + process_name (n, "namespace,infomap", "namespace-infomap"); + process_name (n, "list,stream", "list-stream"); + process_name (n, "as,double", "as-double"); + process_name (n, "as,decimal", "as-decimal"); + process_name (n, "facet", "facet"); + } + + if (!options.value ().empty ()) + { + process_name (n, "ostream", "ostream"); + } + + if (!options.value ().empty ()) + { + process_name (n, "istream", "istream"); + } + + process_name (n, "flags", "flags"); + process_name (n, "properties", "properties"); + + NarrowString fn (options.value ()); + + if (fn == "knr") + n.context ().set ("tree-node-key", String ("tree_node_key")); + else + n.context ().set ("tree-node-key", String ("treeNodeKey")); + + process_name (n, "exception", "exception"); + process_name (n, "parsing", "parsing"); + process_name (n, "expected,element", "expected-element"); + process_name (n, "unexpected,element", "unexpected-element"); + process_name (n, "expected,attribute", "expected-attribute"); + process_name (n, "unexpected,enumerator", "unexpected-enumerator"); + process_name (n, "expected,text,content", "expected-text-content"); + process_name (n, "no,type,info", "no-type-info"); + process_name (n, "no,element,info", "no-element-info"); + process_name (n, "not,derived", "not-derived"); + process_name (n, "duplicate,id", "duplicate-id"); + process_name (n, "serialization", "serialization"); + process_name (n, "no,namespace,mapping", "no-namespace-mapping"); + process_name (n, "no,prefix,mapping", "no-prefix-mapping"); + process_name (n, "xsi,already,in,use", "xsi-already-in-use"); + process_name (n, "bounds", "bounds"); + + process_name (n, "severity", "severity"); + process_name (n, "error", "error"); + process_name (n, "diagnostics", "diagnostics"); + + if (!options.value () || + options.value ()) + { + process_name (n, "error,handler", "error-handler"); + } + + Namespace::post (n); + } + + private: + Traversal::Names names_; + }; + + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct UsesPassOne: Traversal::Uses + { + virtual Void + traverse (Type& u) + { + SemanticGraph::Schema& s (u.schema ()); + + if (!s.context ().count ("cxx-tree-name-processor-pass-1")) + { + s.context ().set ("cxx-tree-name-processor-pass-1", true); + Traversal::Uses::traverse (u); + } + } + }; + + struct UsesPassThree: Traversal::Uses + { + virtual Void + traverse (Type& u) + { + SemanticGraph::Schema& s (u.schema ()); + + if (!s.context ().count ("cxx-tree-name-processor-pass-3")) + { + s.context ().set ("cxx-tree-name-processor-pass-3", true); + Traversal::Uses::traverse (u); + } + } + }; + + // 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-tree-name-processor-seen")) + { + s.context ().set ("cxx-tree-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + Boolean + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + try + { + Counts counts; + Context ctx (ops, counts, false, tu, file); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema xs_schema; + Traversal::Names xs_schema_names; + FundamentalNamespace xs_ns (ctx); + + xs_schema >> xs_schema_names >> xs_ns; + + xs_schema.dispatch (tu); + } + else + { + + // Pass one - assign names to global types. This pass cannot + // be combined with pass two 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-tree-name-processor-pass-1")) + { + Traversal::Schema schema; + Traversal::Schema xs_schema; + UsesPassOne uses; + Implies implies; + + schema >> uses >> schema; + schema >> implies >> xs_schema; + + Traversal::Names schema_names; + Traversal::Names xs_schema_names; + NamespacePassOne ns (ctx); + FundamentalNamespace xs_ns (ctx); + + schema >> schema_names >> ns; + xs_schema >> xs_schema_names >> xs_ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-tree-name-processor-pass-1", true); + + schema.dispatch (tu); + } + + // Pass two - 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; + + Complex complex (ctx); + Traversal::Enumeration enumeration; // Avoid fallback on complex. + + ns_names >> complex; + ns_names >> enumeration; + + schema.dispatch (tu); + } + + // Pass three - assign names to global elements as well as + // inside enums. 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-tree-name-processor-pass-3")) + { + Traversal::Schema schema; + UsesPassThree uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + NamespacePassThree ns (ctx); + Traversal::Namespace ns_enum; + + schema >> schema_names; + + schema_names >> ns; + schema_names >> ns_enum; + + Traversal::Names ns_names; + Enumeration enumeration (ctx); + + ns_enum >> ns_names >> enumeration; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-tree-name-processor-pass-3", true); + + schema.dispatch (tu); + } + } + } + catch (Context::Failed const&) + { + // Diagnostics has already been issued. + // + return false; + } + + return true; + } + } + + Boolean NameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + return process_impl (ops, tu, file); + } + } +} -- cgit v1.1