// file : xsde/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 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; public: Context (std::wostream& o, SemanticGraph::Schema& root, Char const* name_key, 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), ename_key (c.ename_key), 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) { } Context (Context& c, std::wostream& o) : os (o), schema_root (c.schema_root), ename_key (c.ename_key), 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) { } 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&) 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&) const; // 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 = 0) const; public: static SemanticGraph::Type& ultimate_base (SemanticGraph::Complex&); public: String process_include_path (String const&) const; public: static Boolean anonymous (SemanticGraph::Type& t) { return t.context ().count ("anonymous"); } // Restriction correspondance. // public: static SemanticGraph::Element* correspondent (SemanticGraph::Element& r); static SemanticGraph::Any* correspondent (SemanticGraph::Any& r); static SemanticGraph::Compositor* correspondent (SemanticGraph::Compositor& r); public: // Get escaped name. // String const& ename (SemanticGraph::Nameable const& n) const { return n.context ().get (ename_key.c_str ()); } public: std::wostream& os; SemanticGraph::Schema& schema_root; NarrowString const& ename_key; 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_; NarrowString const ename_key_; 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_; }; 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 { virtual ~ScopeTracker () {} virtual Void enter (String const&) = 0; virtual Void leave () = 0; }; Namespace (Context& c, ScopeTracker* st = 0) : ctx_ (c), st_ (st) { } 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); } }; // // struct Includes : Traversal::Imports, Traversal::Includes { typedef BackendElements::Regex::Expression Regex; Includes (Context& c, Regex const& expr) : ctx_ (c), expr_ (expr) { } virtual Void traverse (SemanticGraph::Imports& i) { traverse (i.path ()); } virtual Void traverse (SemanticGraph::Includes& i) { traverse (i.path ()); } Void traverse (SemanticGraph::Path const&); private: Context& ctx_; Regex expr_; }; } #endif // CXX_TREE_ELEMENTS_HXX