diff options
Diffstat (limited to 'xsde/cxx/hybrid/aggregate-include.hxx')
-rw-r--r-- | xsde/cxx/hybrid/aggregate-include.hxx | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/xsde/cxx/hybrid/aggregate-include.hxx b/xsde/cxx/hybrid/aggregate-include.hxx new file mode 100644 index 0000000..9bd50bb --- /dev/null +++ b/xsde/cxx/hybrid/aggregate-include.hxx @@ -0,0 +1,223 @@ +// file : xsde/cxx/hybrid/aggregate-include.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_AGGREGATE_INCLUDE_HXX +#define CXX_HYBRID_AGGREGATE_INCLUDE_HXX + +#include <cult/containers/set.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/hybrid/elements.hxx> + +namespace CXX +{ + namespace Hybrid + { + // Parser/serializer implementation includes for additional + // schemas (polymorphic code). + // + + // For base types we only want member's types, but not the + // base itself. + // + struct BaseInclude: Traversal::Complex, Context + { + BaseInclude (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + }; + + struct TypeInclude: Traversal::Type, + Traversal::Complex, + Context + { + TypeInclude (Context& c) + : Context (c), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (types_.find (&t) != types_.end ()) + return; + + types_.insert (&t); + + if (polymorphic (t)) + collect (t); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (types_.find (&c) != types_.end ()) + return; + + types_.insert (&c); + + if (polymorphic (c)) + collect (c); + + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + + private: + virtual Void + collect (SemanticGraph::Type& t) + { + using SemanticGraph::Type; + + for (Type::BegetsIterator i (t.begets_begin ()); + i != t.begets_end (); + ++i) + { + Type& d (i->derived ()); + emit (d); + dispatch (d); + collect (d); + } + } + + virtual Void + emit (SemanticGraph::Type& t) + { + using SemanticGraph::Schema; + + Schema* s (&dynamic_cast<Schema&> (t.scope ().scope ())); + + // If this is not a top-level schema, get one that + // includes/import/sources this schema. Top-level schema + // is either not used by any other schema or is imported + // into a special schema that doesn't have a namespace. + // + for (;;) + { + if (!s->used ()) + break; + + SemanticGraph::Uses& u (*s->used_begin ()); + Schema& us (u.user ()); + + if (us.names_begin () == us.names_end ()) + break; + + s = &us; + } + + + if (s != &schema_root && schemas_.find (s) == schemas_.end ()) + { + schemas_.insert (s); + + SemanticGraph::Path path (s->used_begin ()->path ()); + + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.native_file_string (); + } + + String inc_path (hxx_expr->merge (path_str)); + os << "#include " << process_include_path (inc_path) << endl + << endl; + } + } + + private: + Cult::Containers::Set<SemanticGraph::Type*> types_; + Cult::Containers::Set<SemanticGraph::Schema*> schemas_; + + BaseInclude base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + struct AggregateInclude: Traversal::Type, + Traversal::Element, + Context + { + AggregateInclude (Context& c, Char const* key) + : Context (c), key_ (key), type_include_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (t.context ().count (key_)) + type_include_.dispatch (t); + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.context ().count (key_)) + type_include_.dispatch (e.type ()); + } + + private: + Char const* key_; + TypeInclude type_include_; + }; + } +} + +#endif // CXX_HYBRID_AGGREGATE_INCLUDE_HXX |