diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 | 
| commit | aad5ad9bf0c02aa4e79bc6b7d6c934612fff4026 (patch) | |
| tree | 9cc224b059f248a6229ab0dcdc64eb4a73fa9800 /xsd/processing | |
| parent | c1034fc5e99197f507caf450aa15bc178698b26e (diff) | |
New upstream version 4.2.0upstream/4.2.0upstream
Diffstat (limited to 'xsd/processing')
| -rw-r--r-- | xsd/processing/cardinality/processor.cxx | 407 | ||||
| -rw-r--r-- | xsd/processing/cardinality/processor.hxx | 28 | ||||
| -rw-r--r-- | xsd/processing/inheritance/processor.cxx | 492 | ||||
| -rw-r--r-- | xsd/processing/inheritance/processor.hxx | 28 | 
4 files changed, 955 insertions, 0 deletions
| diff --git a/xsd/processing/cardinality/processor.cxx b/xsd/processing/cardinality/processor.cxx new file mode 100644 index 0000000..c8c5dc5 --- /dev/null +++ b/xsd/processing/cardinality/processor.cxx @@ -0,0 +1,407 @@ +// file      : xsd/processing/cardinality/processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/elements.hxx> + +#include <xsd/processing/cardinality/processor.hxx> + +using namespace std; + +namespace Processing +{ +  namespace SemanticGraph = XSDFrontend::SemanticGraph; +  namespace Traversal = XSDFrontend::Traversal; + +  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, size_t min_, size_t max_) +            : min (min_), max (max_), e_ (&e) +        { +        } + +        SemanticGraph::Element& +        element () +        { +          assert (e_ != 0); +          return *e_; +        } + +      public: +        size_t min, max; + +      private: +        SemanticGraph::Element* e_; +      }; + +      typedef 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, size_t min_, size_t max_) +            : min (min_), max (max_), a_ (&a) +        { +        } + +        SemanticGraph::Any& +        any () +        { +          assert (a_ != 0); +          return *a_; +        } + +      public: +        size_t min, max; + +      private: +        SemanticGraph::Any* a_; +      }; + +      typedef 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; + +                  // Unbounded is encoded as 0. +                  // +                  if (j->second.max == 0 || ei.max == 0) +                    ei.max = 0; +                  else +                    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. +          // +          size_t 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. +          // +          size_t 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); +              size_t min (ei.min * smin); +              size_t 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); +              size_t min (ai.min * smin); +              size_t 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_p () +                       ? 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); +              SemanticGraph::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); +              SemanticGraph::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) +        { +          SemanticGraph::Context& ctx (a.context ()); + +          ctx.set ("min", size_t (a.optional_p () ? 0 : 1)); +          ctx.set ("max", size_t (1)); +        } +      }; + +      // 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..93a85fb --- /dev/null +++ b/xsd/processing/cardinality/processor.hxx @@ -0,0 +1,28 @@ +// file      : xsd/processing/cardinality/processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX +#define XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/types.hxx> + +namespace Processing +{ +  namespace Cardinality +  { +    class Processor +    { +    public: +      struct Failed {}; + +      void +      process (XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX diff --git a/xsd/processing/inheritance/processor.cxx b/xsd/processing/inheritance/processor.cxx new file mode 100644 index 0000000..6c0e40e --- /dev/null +++ b/xsd/processing/inheritance/processor.cxx @@ -0,0 +1,492 @@ +// file      : xsd/processing/inheritance/processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <iostream> + +#include <xsd/processing/inheritance/processor.hxx> + +#include <xsd/elements.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace Processing +{ +  namespace SemanticGraph = XSDFrontend::SemanticGraph; +  namespace Traversal = XSDFrontend::Traversal; + +  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 bool +      operator< (Dep const& a, Dep const& b) +      { +        return &a.type < &b.type; +      } + +      typedef set<Dep> DepSet; +      typedef 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_p ()) +        { +          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_p () && types_seen_.find (&t) == types_seen_.end ()) +          { +            SemanticGraph::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, +                bool& failed) +            : root_ (root), schema_ (schema), failed_ (failed) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (t.named_p ()) +            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_p ()) +          { +            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::const_iterator i (prereqs.begin ()); +               i != prereqs.end (); ++i) +          { +            Dep const& dep (*i); +            Type& t (dep.type); + +            // Ignore IDREF templates. +            // +            if (!t.named_p () && +                (t.is_a<SemanticGraph::Fundamental::IdRef> () || +                 t.is_a<SemanticGraph::Fundamental::IdRefs> ())) +              continue; + +            // 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. +              // +              { +                // t.scope () and global.scope () can be different in +                // case of the chameleon inclusion. +                // +                Scope& scope (global.scope ()); + +                // 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. +        // +        bool +        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_; +        bool& failed_; +      }; + + +      // Sources traverser that goes into each schema only once. +      // +      struct Sources: Traversal::Sources +      { +        virtual void +        traverse (SemanticGraph::Sources& s) +        { +          if (schemas_.insert (&s.schema ()).second) +            Traversal::Sources::traverse (s); +        } + +      private: +        set<SemanticGraph::Schema*> schemas_; +      }; + +      // 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, bool& 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; +            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_; +        bool& failed_; +      }; +    } + +    void Processor:: +    process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) +    { +      bool 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; +      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..2a70e02 --- /dev/null +++ b/xsd/processing/inheritance/processor.hxx @@ -0,0 +1,28 @@ +// file      : xsd/processing/inheritance/processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX +#define XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/types.hxx> + +namespace Processing +{ +  namespace Inheritance +  { +    class Processor +    { +    public: +      struct Failed {}; + +      void +      process (XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX | 
