aboutsummaryrefslogtreecommitdiff
path: root/xsd/processing
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-09-17 07:15:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-09-17 07:15:29 +0200
commitf0510d2f90467de8e8f260b47d79a9baaf9bef17 (patch)
tree0b9929946f06a9cbe9b9e8f2a7600dae4e048f79 /xsd/processing
Start tracking XSD with git
Diffstat (limited to 'xsd/processing')
-rw-r--r--xsd/processing/cardinality/processor.cxx407
-rw-r--r--xsd/processing/cardinality/processor.hxx32
-rw-r--r--xsd/processing/inheritance/processor.cxx474
-rw-r--r--xsd/processing/inheritance/processor.hxx32
4 files changed, 945 insertions, 0 deletions
diff --git a/xsd/processing/cardinality/processor.cxx b/xsd/processing/cardinality/processor.cxx
new file mode 100644
index 0000000..fae30f6
--- /dev/null
+++ b/xsd/processing/cardinality/processor.cxx
@@ -0,0 +1,407 @@
+// file : processing/cardinality/processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <processing/cardinality/processor.hxx>
+
+#include <elements.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace Processing
+{
+ using namespace Cult;
+
+ namespace SemanticGraph = XSDFrontend::SemanticGraph;
+ namespace Traversal = XSDFrontend::Traversal;
+
+ typedef WideString String;
+
+ namespace Cardinality
+ {
+ namespace
+ {
+ //
+ //
+ struct ElementInfo
+ {
+ ElementInfo ()
+ : min (0), max (0), e_ (0)
+ {
+ }
+
+ ElementInfo (SemanticGraph::Element& e)
+ : min (1), max (1), e_ (&e)
+ {
+ }
+
+ ElementInfo (SemanticGraph::Element& e,
+ UnsignedLong min_, UnsignedLong max_)
+ : min (min_), max (max_), e_ (&e)
+ {
+ }
+
+ SemanticGraph::Element&
+ element ()
+ {
+ assert (e_ != 0);
+ return *e_;
+ }
+
+ public:
+ UnsignedLong min, max;
+
+ private:
+ SemanticGraph::Element* e_;
+ };
+
+ typedef Cult::Containers::Map<String, ElementInfo> ElementInfoMap;
+
+ //
+ //
+ struct AnyInfo
+ {
+ AnyInfo ()
+ : min (0), max (0), a_ (0)
+ {
+ }
+
+ AnyInfo (SemanticGraph::Any& a)
+ : min (1), max (1), a_ (&a)
+ {
+ }
+
+ AnyInfo (SemanticGraph::Any& a,
+ UnsignedLong min_, UnsignedLong max_)
+ : min (min_), max (max_), a_ (&a)
+ {
+ }
+
+ SemanticGraph::Any&
+ any ()
+ {
+ assert (a_ != 0);
+ return *a_;
+ }
+
+ public:
+ UnsignedLong min, max;
+
+ private:
+ SemanticGraph::Any* a_;
+ };
+
+ typedef Cult::Containers::Map<String, AnyInfo> AnyInfoMap;
+
+ //
+ //
+ struct Particle: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Traversal::Element,
+ Traversal::Any
+ {
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ traverse_sequence (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ // Go over all particles we contain and add them to the map.
+ //
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ Particle t;
+ t.dispatch (ci->particle ());
+
+ // Handle elements.
+ //
+ if (ci == c.contains_begin ())
+ el_map = t.el_map; // First arm.
+ else
+ {
+ // For elements that are in the map but not in this
+ // arm of choice, we need to set min to 0 while for
+ // those that are we need to choose minimum between
+ // the two for min and maximum for max.
+ //
+ for (ElementInfoMap::Iterator i (el_map.begin ());
+ i != el_map.end (); ++i)
+ {
+ String const& name (i->first);
+ ElementInfo& ei (i->second);
+
+ ElementInfoMap::Iterator j (t.el_map.find (name));
+
+ if (j == t.el_map.end ())
+ ei.min = 0;
+ else
+ {
+ ei.min = j->second.min < ei.min ? j->second.min : ei.min;
+ ei.max = j->second.max > ei.max ? j->second.max : ei.max;
+ }
+ }
+
+ // Now elements that are in this arm of choice but are
+ // not in the map, we need to add to the map and set their
+ // min to 0.
+ //
+ for (ElementInfoMap::Iterator i (t.el_map.begin ());
+ i != t.el_map.end (); ++i)
+ {
+ String const& name (i->first);
+ ElementInfo& ei (i->second);
+
+ ElementInfoMap::Iterator j (el_map.find (name));
+
+ if (j == el_map.end ())
+ el_map[name] = ElementInfo (ei.element (), 0, ei.max);
+ }
+ }
+
+ // Handle wildcards. Since each wildcard is treated as unique,
+ // we need to copy them from each arm of choice and set min to
+ // 0.
+ //
+ for (AnyInfoMap::Iterator i (t.any_map.begin ());
+ i != t.any_map.end (); ++i)
+ {
+ String const& name (i->first);
+ AnyInfo& ai (i->second);
+
+ assert (any_map.find (name) == any_map.end ());
+
+ any_map[name] = AnyInfo (ai.any (), 0, ai.max);
+ }
+ }
+
+ // Choice's min and max.
+ //
+ UnsignedLong cmin (c.min ()), cmax (c.max ());
+
+ // Iterate over elements and wildcards in the maps and multiply
+ // their cardinality by cmin and cmax.
+ //
+ for (ElementInfoMap::Iterator i (el_map.begin ());
+ i != el_map.end (); ++i)
+ {
+ i->second.min *= cmin;
+ i->second.max *= cmax;
+ }
+
+ for (AnyInfoMap::Iterator i (any_map.begin ());
+ i != any_map.end (); ++i)
+ {
+ i->second.min *= cmin; // Not really necessary since min == 0.
+ i->second.max *= cmax;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ traverse_sequence (s);
+ }
+
+ Void
+ traverse_sequence (SemanticGraph::Compositor& c)
+ {
+ using SemanticGraph::Compositor;
+
+ // Sequence's min and max.
+ //
+ UnsignedLong smin (c.min ()), smax (c.max ());
+
+ // Go over all particles we contain and add them to the map.
+ //
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ Particle t;
+ t.dispatch (ci->particle ());
+
+ // Handle elements.
+ //
+ for (ElementInfoMap::Iterator i (t.el_map.begin ());
+ i != t.el_map.end (); ++i)
+ {
+ String const& name (i->first);
+ ElementInfo& ei (i->second);
+ UnsignedLong min (ei.min * smin);
+ UnsignedLong max (ei.max * smax);
+ ElementInfoMap::Iterator j (el_map.find (name));
+
+ if (j != el_map.end ())
+ {
+ // Add i's cardinality to j
+ //
+ j->second.min += min;
+ j->second.max = (j->second.max == 0 || max == 0) ?
+ 0 : (j->second.max + max);
+ }
+ else
+ el_map[name] = ElementInfo (ei.element (), min, max);
+ }
+
+ // Handle wildcards.
+ //
+ for (AnyInfoMap::Iterator i (t.any_map.begin ());
+ i != t.any_map.end (); ++i)
+ {
+ String const& name (i->first);
+ AnyInfo& ai (i->second);
+ UnsignedLong min (ai.min * smin);
+ UnsignedLong max (ai.max * smax);
+
+ assert (any_map.find (name) == any_map.end ());
+
+ any_map[name] = AnyInfo (ai.any (), min, max);
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::ContainsParticle& cp (e.contained_particle ());
+
+ String name (e.qualified ()
+ ? e.namespace_ ().name () + L" " + e.name ()
+ : e.name ());
+
+ el_map[name] = ElementInfo (e, cp.min (), cp.max ());
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ SemanticGraph::ContainsParticle& cp (a.contained_particle ());
+
+ any_map[a.name ()] = AnyInfo (a, cp.min (), cp.max ());
+ }
+
+ public:
+ AnyInfoMap any_map;
+ ElementInfoMap el_map;
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex
+ {
+ virtual Void
+ traverse (Type& c)
+ {
+ if (c.contains_compositor_p ())
+ {
+ Particle t;
+ t.dispatch (c.contains_compositor ().compositor ());
+
+ for (ElementInfoMap::Iterator i (t.el_map.begin ());
+ i != t.el_map.end (); ++i)
+ {
+ ElementInfo& ei (i->second);
+ FrontendElements::Context& ctx (ei.element ().context ());
+
+ ctx.set ("min", ei.min);
+ ctx.set ("max", ei.max);
+ }
+
+ for (AnyInfoMap::Iterator i (t.any_map.begin ());
+ i != t.any_map.end (); ++i)
+ {
+ AnyInfo& ai (i->second);
+ FrontendElements::Context& ctx (ai.any ().context ());
+
+ ctx.set ("min", ai.min);
+ ctx.set ("max", ai.max);
+ }
+ }
+
+ // Traverse attributes and anonymous types (via elements).
+ //
+ Complex::names (c);
+ }
+ };
+
+
+ //
+ //
+ struct Attribute: Traversal::Attribute
+ {
+ virtual Void
+ traverse (Type& a)
+ {
+ FrontendElements::Context& ctx (a.context ());
+
+ ctx.set ("min", a.optional () ? 0UL : 1UL);
+ ctx.set ("max", 1UL);
+ }
+ };
+
+ // Go into implied/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Uses
+ {
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Schema& s (u.schema ());
+
+ if (!s.context ().count ("processing-cardinality-seen"))
+ {
+ s.context ().set ("processing-cardinality-seen", true);
+ Traversal::Uses::traverse (u);
+ }
+ }
+ };
+ }
+
+ Void Processor::
+ process (SemanticGraph::Schema& tu, SemanticGraph::Path const&)
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ Complex complex_type;
+ AnonymousBase anonymous (complex_type);
+
+ ns_names >> complex_type;
+ ns_names >> anonymous;
+
+ Attribute attribute;
+ Traversal::Names names;
+
+ complex_type >> names;
+
+ names >> attribute;
+ names >> anonymous;
+
+ // Some twisted schemas do recusive inclusions.
+ //
+ tu.context ().set ("processing-cardinality-seen", true);
+
+ schema.dispatch (tu);
+ }
+ }
+}
diff --git a/xsd/processing/cardinality/processor.hxx b/xsd/processing/cardinality/processor.hxx
new file mode 100644
index 0000000..feed41a
--- /dev/null
+++ b/xsd/processing/cardinality/processor.hxx
@@ -0,0 +1,32 @@
+// file : processing/cardinality/processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef PROCESSING_CARDINALITY_PROCESSOR_HXX
+#define PROCESSING_CARDINALITY_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+namespace Processing
+{
+ namespace Cardinality
+ {
+ using namespace Cult::Types;
+
+ class Processor
+ {
+ public:
+ struct Failed {};
+
+ Void
+ process (XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // PROCESSING_CARDINALITY_PROCESSOR_HXX
diff --git a/xsd/processing/inheritance/processor.cxx b/xsd/processing/inheritance/processor.cxx
new file mode 100644
index 0000000..dbc9237
--- /dev/null
+++ b/xsd/processing/inheritance/processor.cxx
@@ -0,0 +1,474 @@
+// file : processing/inheritance/processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <processing/inheritance/processor.hxx>
+
+#include <elements.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <iostream>
+using std::wcerr;
+using std::endl;
+
+namespace Processing
+{
+ using namespace Cult;
+
+ namespace SemanticGraph = XSDFrontend::SemanticGraph;
+ namespace Traversal = XSDFrontend::Traversal;
+
+ typedef WideString String;
+
+ namespace Inheritance
+ {
+ namespace
+ {
+ struct Dep
+ {
+ Dep (SemanticGraph::Type& t,
+ SemanticGraph::Member* m = 0,
+ String const& xpath = L"")
+ : type (t), member (m), member_xpath (xpath)
+ {
+ }
+
+ SemanticGraph::Type& type;
+ SemanticGraph::Member* member; // Member if type is anonymous.
+ String member_xpath;
+ };
+
+ inline Boolean
+ operator< (Dep const& a, Dep const& b)
+ {
+ return &a.type < &b.type;
+ }
+
+ typedef Containers::Set<Dep> DepSet;
+ typedef Containers::Set<SemanticGraph::Type*> TypeSet;
+
+
+ String
+ xpath (SemanticGraph::Nameable& n)
+ {
+ if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0)
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ if (n.named ())
+ {
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0)
+ return n.name ();
+
+ return xpath (scope) + L"/" + n.name ();
+ }
+ else
+ {
+ return L"(anonymous type for " +
+ n.context ().get<String> ("instance-name") + L")";
+ }
+ }
+
+
+ // Calculate the list of dependencies for this complex
+ // type.
+ //
+ struct ComplexType: Traversal::Complex,
+ Traversal::Member
+ {
+ ComplexType (DepSet& dep_set)
+ : dep_set_ (dep_set), last_ (0)
+ {
+ *this >> names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Complex;
+
+ if (c.inherits_p ())
+ dep_set_.insert (Dep (c.inherits ().base (), last_, last_xpath_));
+
+ types_seen_.insert (&c);
+
+ // Go after anonymous types.
+ //
+ names (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ SemanticGraph::Type& t (m.type ());
+
+ if (!t.named () && types_seen_.find (&t) == types_seen_.end ())
+ {
+ FrontendElements::Context& ctx (t.context ());
+
+ last_xpath_ = xpath (m);
+
+ String prev_xpath;
+
+ if (ctx.count ("instance-name"))
+ prev_xpath = ctx.get<String> ("instance-name");
+
+ ctx.set ("instance-name", last_xpath_);
+
+ last_ = &m;
+ dispatch (t);
+
+ if (prev_xpath)
+ ctx.set ("instance-name", prev_xpath);
+ else
+ ctx.remove ("instance-name");
+ }
+ }
+
+ private:
+ DepSet& dep_set_;
+ TypeSet types_seen_;
+
+ SemanticGraph::Member* last_;
+ String last_xpath_;
+
+ Traversal::Names names_;
+ };
+
+
+ //
+ //
+ template <typename N, typename A>
+ struct NodeArgs
+ {
+ NodeArgs (N& node, A arg)
+ : node_ (node), arg_ (arg)
+ {
+ }
+
+ operator N& () const
+ {
+ return node_;
+ }
+
+ template <typename E>
+ Void
+ add_edge_left (E& e)
+ {
+ node_.add_edge_left (e, arg_);
+ }
+
+ template <typename E>
+ Void
+ add_edge_right (E& e)
+ {
+ node_.add_edge_right (e, arg_);
+ }
+
+ private:
+ N& node_;
+ A arg_;
+ };
+
+
+ //
+ //
+ struct Global: Traversal::Type,
+ Traversal::Complex,
+ Traversal::Element
+ {
+ Global (SemanticGraph::Schema& root,
+ SemanticGraph::Schema& schema,
+ Boolean& failed)
+ : root_ (root), schema_ (schema), failed_ (failed)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (t.named ())
+ types_seen_.insert (&t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ check_dep (c, c);
+ types_seen_.insert (&c);
+ };
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (!t.named ())
+ {
+ t.context ().set ("instance-name", xpath (e));
+ check_dep (e, t);
+ t.context ().remove ("instance-name");
+ }
+ };
+
+ private:
+ Void
+ check_dep (SemanticGraph::Nameable& global,
+ SemanticGraph::Type& type)
+ {
+ using SemanticGraph::Type;
+ using SemanticGraph::Scope;
+ using SemanticGraph::Names;
+ using SemanticGraph::Schema;
+
+ DepSet prereqs;
+
+ // Calculate our prerequisistes.
+ //
+ {
+ ComplexType complex (prereqs);
+ complex.dispatch (type);
+ }
+
+ for (DepSet::ConstIterator i (prereqs.begin ());
+ i != prereqs.end (); ++i)
+ {
+ Dep const& dep (*i);
+ Type& t (dep.type);
+
+ // We won't be able to generate compilable code in case of a
+ // dependency on ourselves (e.g., a member element with
+ // anonymous type that inherits from us).
+ //
+ if (&t == &type)
+ {
+ assert (dep.member != 0);
+
+ SemanticGraph::Member& m (*dep.member);
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << " error: nested anonymous type for '"
+ << dep.member_xpath << "' cyclicly inherits from '"
+ << t.name () << "'" << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << " error: unable to generate valid code for such "
+ << "cyclic inheritance" << endl;
+
+ wcerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << " info: '" << m.name () << "' element is declared here"
+ << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": info: consider explicitly naming this type "
+ << "or remove the --preserve-anonymous option"
+ << endl;
+
+ failed_ = true;
+ continue;
+ }
+
+ if (types_seen_.find (&t) == types_seen_.end ())
+ {
+ Scope& scope (t.scope ());
+ Schema& schema (dynamic_cast<Schema&> (scope.scope ()));
+
+ // Don't worry about types that are in included/imported
+ // schemas.
+ //
+ if (&schema != &schema_ && !sources_p (schema_, schema))
+ continue;
+
+ if (t.context ().count ("seen"))
+ {
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << " error: nested anonymous type in '" << t.name ()
+ << "' or '" << type.name () << "' inherits from one of "
+ << "these types and makes them mutually dependant"
+ << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << " error: unable to generate valid code for such "
+ << "cyclic dependency" << endl;
+
+ wcerr << type.file () << ":" << type.line () << ":"
+ << type.column () << " info: '" << type.name ()
+ << "' type is defined here"
+ << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": info: consider explicitly naming the anonymous "
+ << "type or remove the --preserve-anonymous option"
+ << endl;
+
+ failed_ = true;
+ continue;
+ }
+
+
+ //wcerr << "type '" << t.name () << "' needs to be moved " <<
+ // "before " << (global.is_a<Type> () ? "type" : "element") <<
+ // " '" << global.name () << "'" << endl;
+
+
+ // Delete current Names edge.
+ //
+ String name (t.name ());
+ {
+ Names& n (t.named_ ());
+ root_.delete_edge (scope, t, n);
+ }
+
+ // Insert a new Names edge before global.
+ //
+ {
+ // Convert to the insert-after call.
+ //
+ Scope::NamesIterator i (scope.find (global.named_ ()));
+
+ if (i == scope.names_begin ())
+ i = scope.names_end ();
+ else
+ --i;
+
+ NodeArgs<Scope, Scope::NamesIterator> na (scope, i);
+ root_.new_edge<Names> (na, t, name);
+ }
+
+ // Recursively process the moved type.
+ //
+ global.context ().set ("seen", true);
+ dispatch (t);
+ global.context ().remove ("seen");
+ }
+ }
+ }
+
+ private:
+ // Return true if root sources s.
+ //
+ Boolean
+ sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s)
+ {
+ using SemanticGraph::Schema;
+ using SemanticGraph::Sources;
+
+ for (Schema::UsesIterator i (root.uses_begin ());
+ i != root.uses_end (); ++i)
+ {
+ if (i->is_a<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ SemanticGraph::Schema& root_;
+ SemanticGraph::Schema& schema_;
+ TypeSet types_seen_;
+ Boolean& failed_;
+ };
+
+
+ // Go into included/imported schemas while making sure we don't
+ // process the same stuff more than once.
+ //
+ struct Uses: Traversal::Includes, Traversal::Imports
+ {
+ Uses (SemanticGraph::Schema& root, Boolean& failed)
+ : root_ (root), failed_ (failed)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ traverse (i.schema ());
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ traverse (i.schema ());
+ }
+
+ private:
+ Void
+ traverse (SemanticGraph::Schema& s)
+ {
+ if (!s.context ().count ("processing-inheritance-seen"))
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+ schema >> *this;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ Global global (root_, s, failed_);
+
+ ns_names >> global;
+
+ s.context ().set ("processing-inheritance-seen", true);
+ schema.dispatch (s);
+ }
+ }
+
+ private:
+ SemanticGraph::Schema& root_;
+ Boolean& failed_;
+ };
+ }
+
+ Void Processor::
+ process (SemanticGraph::Schema& tu, SemanticGraph::Path const&)
+ {
+ Boolean failed (false);
+
+ // We need to process include/imported schemas since other
+ // parts of the process, for example, name processors can
+ // rely on the order of types in the schema.
+ //
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Uses uses (tu, failed);
+
+ schema >> sources >> schema;
+ schema >> uses;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ Global global (tu, tu, failed);
+
+ ns_names >> global;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("processing-inheritance-seen", true);
+
+ schema.dispatch (tu);
+
+ if (failed)
+ throw Failed ();
+ }
+ }
+}
diff --git a/xsd/processing/inheritance/processor.hxx b/xsd/processing/inheritance/processor.hxx
new file mode 100644
index 0000000..ee0743d
--- /dev/null
+++ b/xsd/processing/inheritance/processor.hxx
@@ -0,0 +1,32 @@
+// file : processing/inheritance/processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef PROCESSING_INHERITANCE_PROCESSOR_HXX
+#define PROCESSING_INHERITANCE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+namespace Processing
+{
+ namespace Inheritance
+ {
+ using namespace Cult::Types;
+
+ class Processor
+ {
+ public:
+ struct Failed {};
+
+ Void
+ process (XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // PROCESSING_INHERITANCE_PROCESSOR_HXX