// file : xsd/cxx/elements.hxx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #ifndef CXX_ELEMENTS_HXX #define CXX_ELEMENTS_HXX #include #include #include #include #include #include #include #include #include namespace CXX { using std::endl; typedef WideString String; // On some platforms std::toupper can be something other than a // function with C++ linkage. // wchar_t upcase (wchar_t c); // Exceptions. // struct NoNamespaceMapping { NoNamespaceMapping (SemanticGraph::Path const& file, UnsignedLong line, UnsignedLong column, String const& ns) : file_ (file), line_ (line), column_ (column), ns_ (ns) { } SemanticGraph::Path const& file () const { return file_; } UnsignedLong line () const { return line_; } UnsignedLong column () const { return column_; } String const& ns () const { return ns_; } private: SemanticGraph::Path file_; UnsignedLong line_; UnsignedLong column_; String ns_; }; struct InvalidNamespaceMapping { InvalidNamespaceMapping (String const& mapping, String const& reason) : mapping_ (mapping), reason_ (reason) { } String const& mapping () const { return mapping_; } String const& reason () const { return reason_; } private: String mapping_; String reason_; }; // // class Context { public: typedef BackendElements::Regex::Pattern RegexPat; typedef BackendElements::Regex::Expression Regex; typedef Cult::Containers::Vector RegexMapping; typedef Cult::Containers::Map MapMapping; typedef Cult::Containers::Map MappingCache; typedef Cult::Containers::Map ReservedNameMap; typedef Cult::Containers::Set KeywordSet; public: Context (std::wostream& o, SemanticGraph::Schema& root, NarrowString const& char_type__, Boolean include_with_brackets__, NarrowString const& include_prefix__, NarrowString const& esymbol, Containers::Vector const& nsm, Containers::Vector const& nsr, Boolean trace_namespace_regex_, Containers::Vector const& include_regex, Boolean trace_include_regex_, Boolean inline_, Containers::Vector const& reserved_name); protected: Context (Context& c) : os (c.os), schema_root (c.schema_root), char_type (c.char_type), L (c.L), string_type (c.string_type), include_with_brackets (c.include_with_brackets), include_prefix (c.include_prefix), type_exp (c.type_exp), inst_exp (c.inst_exp), inl (c.inl), ns_mapping_cache (c.ns_mapping_cache), xs_ns_ (c.xs_ns_), cxx_id_expr (c.cxx_id_expr), trace_namespace_regex (c.trace_namespace_regex), nsr_mapping (c.nsr_mapping), nsm_mapping (c.nsm_mapping), include_mapping (c.include_mapping), trace_include_regex (c.trace_include_regex), reserved_name_map (c.reserved_name_map), keyword_set (c.keyword_set) { } Context (Context& c, std::wostream& o) : os (o), schema_root (c.schema_root), char_type (c.char_type), L (c.L), string_type (c.string_type), include_with_brackets (c.include_with_brackets), include_prefix (c.include_prefix), type_exp (c.type_exp), inst_exp (c.inst_exp), inl (c.inl), ns_mapping_cache (c.ns_mapping_cache), xs_ns_ (c.xs_ns_), cxx_id_expr (c.cxx_id_expr), trace_namespace_regex (c.trace_namespace_regex), nsr_mapping (c.nsr_mapping), nsm_mapping (c.nsm_mapping), include_mapping (c.include_mapping), trace_include_regex (c.trace_include_regex), reserved_name_map (c.reserved_name_map), keyword_set (c.keyword_set) { } public: static String unclash (String const& name, String const& new_name) { return name == new_name ? (new_name + L'_') : new_name; } public: // Return UTF-32 character starting at this position. Position is // advanced by 1 if this Unicode character takes more than one // underlying character. // static UnsignedLong unicode_char (String const& str, Size& pos); static UnsignedLong unicode_char (WideChar const*& p); // Escape C++ keywords and illegal characters. // String escape (String const&); // Create a string literal so that it can be used in C++ source // code. It includes "". // String strlit (String const&); // Escape the string so that it can be used in C++ comment. // String comment (String const&); // Translate XML namespace name to a C++ identifier. // String ns_name (SemanticGraph::Namespace&); // XML Schema namespace. // SemanticGraph::Namespace& xs_ns (); // C++ namespace for XML Schema. // String xs_ns_name (); // // SemanticGraph::Namespace& namespace_ (SemanticGraph::Nameable& n); // Original XML namespace name. // String xml_ns_name (SemanticGraph::Nameable& ns); // Fully-qualified C++ name. // String fq_name (SemanticGraph::Nameable& n, Char const* name_key = "name"); public: static SemanticGraph::Type& ultimate_base (SemanticGraph::Complex&); public: String process_include_path (String const&) const; public: static Boolean skip (SemanticGraph::Member& m) { // "Subsequent" local element. // return !m.scope ().is_a () && m.context ().count ("min") == 0; } static UnsignedLong min (SemanticGraph::Member const& m) { return m.context ().get ("min"); } static UnsignedLong min (SemanticGraph::Any const& a) { return a.context ().get ("min"); } static UnsignedLong max (SemanticGraph::Member const& m) { return m.context ().get ("max"); } static UnsignedLong max (SemanticGraph::Any const& a) { return a.context ().get ("max"); } public: // Get escaped name. // static String const& ename (SemanticGraph::Nameable const& n) { return n.context ().get ("name"); } public: std::wostream& os; SemanticGraph::Schema& schema_root; String& char_type; String& L; // string literal prefix String& string_type; Boolean& include_with_brackets; String& include_prefix; String& type_exp; String& inst_exp; String& inl; public: MappingCache& ns_mapping_cache; private: SemanticGraph::Namespace* xs_ns_; String char_type_; String L_; String string_type_; Boolean include_with_brackets_; String include_prefix_; String type_exp_; String inst_exp_; String inl_; private: RegexPat const cxx_id_expr_; RegexPat const& cxx_id_expr; Boolean trace_namespace_regex; RegexMapping nsr_mapping_; MapMapping nsm_mapping_; RegexMapping const& nsr_mapping; MapMapping const& nsm_mapping; MappingCache ns_mapping_cache_; RegexMapping include_mapping_; RegexMapping const& include_mapping; Boolean trace_include_regex; ReservedNameMap const& reserved_name_map; ReservedNameMap reserved_name_map_; KeywordSet const& keyword_set; KeywordSet keyword_set_; }; inline UnsignedLong Context:: unicode_char (String const& str, Size& pos) { if (sizeof (WideChar) == 4) { return str[pos]; } else if (sizeof (WideChar) == 2) { WideChar x (str[pos]); if (x < 0xD800 || x > 0xDBFF) return x; else return ((x - 0xD800) << 10) + (str[++pos] - 0xDC00) + 0x10000; } else return 0; } inline UnsignedLong Context:: unicode_char (WideChar const*& p) { if (sizeof (WideChar) == 4) { return *p; } else if (sizeof (WideChar) == 2) { WideChar x (*p); if (x < 0xD800 || x > 0xDBFF) return x; else return ((x - 0xD800) << 10) + (*(++p) - 0xDC00) + 0x10000; } else return 0; } // Usual namespace mapping. // struct Namespace : Traversal::Namespace { struct ScopeTracker { // First scope name if always empty (global scope). The last flag // signals the last scope. // virtual Void enter (Type&, String const& name, Boolean last) = 0; virtual Void leave () = 0; }; Namespace (Context& c) : ctx_ (c), st_ (0) { } Namespace (Context& c, ScopeTracker& st) : ctx_ (c), st_ (&st) { } virtual Void pre (Type&); virtual Void post (Type&); private: Context& ctx_; ScopeTracker* st_; }; // // template struct Has : X { Has (Boolean& result) : result_ (result) { } virtual Void traverse (typename X::Type&) { result_ = true; } private: Boolean& result_; }; // Checks if scope 'Y' names any of 'X' // template Boolean has (Y& y) { using SemanticGraph::Scope; Boolean result (false); Has t (result); for (Scope::NamesIterator i (y.names_begin ()), e (y.names_end ()); !result && i != e; ++i) t.dispatch (i->named ()); return result; } // Checks if the compositor has any particle of 'X' // template Boolean has_particle (SemanticGraph::Compositor& y) { using SemanticGraph::Compositor; Boolean result (false); Has t (result); for (Compositor::ContainsIterator i (y.contains_begin ()), e (y.contains_end ()); !result && i != e; ++i) { SemanticGraph::Particle& p (i->particle ()); t.dispatch (p); if (!result && p.is_a ()) result = has_particle (dynamic_cast (p)); } return result; } // Specialization for Complex // template Boolean has_particle (SemanticGraph::Complex& c) { return c.contains_compositor_p () && has_particle (c.contains_compositor ().compositor ()); } // Fundamental type mapping helper. // struct Fundamental : Traversal::Fundamental::Type, Traversal::Fundamental::String, Traversal::Fundamental::NormalizedString, Traversal::Fundamental::Token, Traversal::Fundamental::Name, Traversal::Fundamental::NameToken, Traversal::Fundamental::NCName, Traversal::Fundamental::Id, Traversal::Fundamental::IdRef { virtual Void fundamental_type (SemanticGraph::Fundamental::Type& t) = 0; virtual Void fundamental_template (SemanticGraph::Fundamental::Type& t) = 0; virtual Void traverse (SemanticGraph::Fundamental::Type& t) { fundamental_type (t); } virtual Void traverse (SemanticGraph::Fundamental::String& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::NormalizedString& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::Token& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::Name& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::NameToken& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::NCName& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::Id& t) { fundamental_template (t); } virtual Void traverse (SemanticGraph::Fundamental::IdRef& t) { fundamental_template (t); } }; } #endif // CXX_TREE_ELEMENTS_HXX