diff options
Diffstat (limited to 'libxsd-frontend/xsd-frontend/transformations/anonymous.cxx')
| -rw-r--r-- | libxsd-frontend/xsd-frontend/transformations/anonymous.cxx | 1016 | 
1 files changed, 1016 insertions, 0 deletions
| diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx new file mode 100644 index 0000000..1c42d98 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx @@ -0,0 +1,1016 @@ +// file      : xsd-frontend/transformations/anonymous.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/anonymous.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <iostream> +#include <sstream> +#include <typeinfo> + +using std::wcerr; +using std::endl; + +namespace XSDFrontend +{ +  namespace +  { +    using Transformations::AnonymousNameTranslator; + +    // +    // +    struct CompareMembers: Traversal::Element, +                           Traversal::Attribute, +                           Traversal::Any, +                           Traversal::AnyAttribute +    { +      CompareMembers (SemanticGraph::Nameable& m, bool& r) +          : member_ (m), result_ (r) +      { +      } + +      virtual void +      traverse (SemanticGraph::Element& x) +      { +        using SemanticGraph::Element; + +        Element& y (dynamic_cast<Element&> (member_)); + +        // Check cardinalities. +        // +        if (x.min () != y.min () || x.max () != y.max ()) +          return; + +        traverse_member (x); +      } + +      virtual void +      traverse (SemanticGraph::Attribute& x) +      { +        using SemanticGraph::Attribute; + +        Attribute& y (dynamic_cast<Attribute&> (member_)); + +        // Check cardinalities. +        // +        if (x.optional_p () != y.optional_p ()) +          return; + +        traverse_member (x); +      } + +      virtual void +      traverse_member (SemanticGraph::Member& x) +      { +        using SemanticGraph::Member; + +        Member& y (dynamic_cast<Member&> (member_)); + +        // Check name. +        // +        if (x.name () != y.name ()) +          return; + +        // Check namespace. +        // +        if (x.qualified_p () || y.qualified_p ()) +        { +          if (!x.qualified_p () || !y.qualified_p ()) +            return; + +          if (x.namespace_ ().name () != y.namespace_ ().name ()) +            return; +        } + +        // Check type. +        // +        // @@ What if types are anonymous and structurally equal? +        // +        if (&x.type () != &y.type ()) +          return; + +        // Check default/fixed values. +        // +        if (x.default_p () != y.default_p () || x.fixed_p () != y.fixed_p ()) +          return; + +        if (x.default_p () && x.value () != y.value ()) +          return; + +        result_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Any&) +      { +        //@@ TODO +      } + +      virtual void +      traverse (SemanticGraph::AnyAttribute&) +      { +        //@@ TODO +      } + +    private: +      SemanticGraph::Nameable& member_; +      bool& result_; +    }; + +    // Compare two types for structural equality. +    // +    struct CompareTypes: Traversal::List, +                         Traversal::Union, +                         Traversal::Enumeration, +                         Traversal::Complex +    { +      CompareTypes (SemanticGraph::Type& t, bool& r) +          : type_ (t), result_ (r) +      { +      } + + +      virtual void +      traverse (SemanticGraph::List&) +      { +        using SemanticGraph::List; + +        //List& y (dynamic_cast<List&> (type_)); +      } + +      virtual void +      traverse (SemanticGraph::Union& x) +      { +        using SemanticGraph::Union; + +        Union& y (dynamic_cast<Union&> (type_)); + +        Union::ArgumentedIterator ix (x.argumented_begin ()), +          iy (y.argumented_begin ()); + +        for (; ix != x.argumented_end () && iy != y.argumented_end (); +             ++ix, ++iy) +        { +          // @@ Anon structurally equivalent. +          // +          if (&iy->type () != &ix->type ()) +            return; +        } + +        result_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Enumeration& x) +      { +        using SemanticGraph::Enumeration; + +        Enumeration& y (dynamic_cast<Enumeration&> (type_)); + +        // Bases should be the same. +        // +        if (&x.inherits ().base () != &y.inherits ().base ()) +          return; + +        // Make sure facets match. +        // +        using SemanticGraph::Restricts; + +        Restricts& rx (dynamic_cast<Restricts&> (x.inherits ())); +        Restricts& ry (dynamic_cast<Restricts&> (y.inherits ())); + +        if (rx.facets () != ry.facets ()) +          return; + +        // Compare enumerators. +        // +        using SemanticGraph::Scope; + +        Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); +        for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) +        { +          if (ix->name () != iy->name ()) +            return; +        } + +        if (ix != x.names_end () || iy != y.names_end ()) +          return; + +        result_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Complex& x) +      { +        using SemanticGraph::Complex; + +        Complex& y (dynamic_cast<Complex&> (type_)); + +        // Check inheritance. +        // +        if (x.inherits_p () || y.inherits_p ()) +        { +          // They both must inherits. +          // +          if (!x.inherits_p () || !y.inherits_p ()) +            return; + +          // With the same kind of inheritance (restriction or extension). +          // +          if (typeid (x.inherits ()) != typeid (y.inherits ())) +            return; + +          // Bases should be the same. +          // +          // @@ What if bases are anonymous? +          // +          if (&x.inherits ().base () != &y.inherits ().base ()) +            return; + +          // If it is a restriction, make sure facets match. +          // +          using SemanticGraph::Restricts; + +          if (x.inherits ().is_a<Restricts> ()) +          { +            Restricts& rx (dynamic_cast<Restricts&> (x.inherits ())); +            Restricts& ry (dynamic_cast<Restricts&> (y.inherits ())); + +            if (rx.facets () != ry.facets ()) +              return; +          } +        } + +        // Check the member list. +        // +        // @@ Ignoring compositors at the moment. +        // +        using SemanticGraph::Scope; + +        Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); +        for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) +        { +          if (typeid (ix->named ()) != typeid (iy->named ())) +            return; + +          bool equal (false); +          CompareMembers t (iy->named (), equal); +          t.dispatch (ix->named ()); + +          if (!equal) +            return; +        } + +        if (ix != x.names_end () || iy != y.names_end ()) +          return; + +        result_ = true; +      } + +    private: +      SemanticGraph::Type& type_; +      bool& result_; +    }; + +    // +    // +    class Context +    { +    public: +      Context (SemanticGraph::Schema& schema_, +               SemanticGraph::Path const& file, +               AnonymousNameTranslator& trans_, +               bool du) +          : schema_path_ (file), +            ns_ (0), +            failed_ (false), +            trans (trans_), +            detect_unstable (du), +            schema (schema_), +            schema_path (schema_path_), +            ns (ns_), +            failed (failed_) +      { + +      } + +    protected: +      Context (Context& c) +          : trans (c.trans), +            detect_unstable (c.detect_unstable), +            schema (c.schema), +            schema_path (c.schema_path), +            ns (c.ns), +            failed (c.failed) +      { +      } + +    public: + +      bool +      structurally_equal (SemanticGraph::Type& x, SemanticGraph::Type& y) +      { +        if (typeid (x) != typeid (y)) +           return false; + +        bool r (false); +        CompareTypes t (y, r); +        t.dispatch (x); +        return r; +      } + +      struct UnstableConflict +      { +        UnstableConflict (SemanticGraph::Type& type) +            : type_ (type) +        { +        } + +        SemanticGraph::Type& +        type () const +        { +          return type_; +        } + +      private: +        SemanticGraph::Type& type_; +      }; + +      SemanticGraph::Type* +      conflict (String const& name) +      { +        using SemanticGraph::Type; +        using SemanticGraph::Schema; + +        if (Type* t1 = find (schema, name)) +        { +          // Check if this is a stable conflict. A conflict is unstable +          // if a conflicting type is visible from the root schema but +          // is not visible from the schema where the conflicting +          // element is defined. +          // +          if (detect_unstable) +          { +            Schema& s (dynamic_cast<Schema&> (ns->scope ())); + +            Type* t2 (find (s, name)); + +            if (t1 != t2) +              throw UnstableConflict (*t1); +          } + +          return t1; +        } + +        return 0; +      } + +      SemanticGraph::Type* +      find (SemanticGraph::Schema& schema, String const& name) +      { +        using SemanticGraph::Type; +        using SemanticGraph::Scope; +        using SemanticGraph::Namespace; + +        String ns_name (ns->name ()); + +        // Get all namespaces across include/import hierarchy with +        // our namespace name. +        // +        Scope::NamesIteratorPair nip (schema.find (ns_name)); + +        for (; nip.first != nip.second; ++nip.first) +        { +          Namespace& ns (dynamic_cast<Namespace&> (nip.first->named ())); + +          Scope::NamesIteratorPair types (ns.find (name)); + +          for (; types.first != types.second; ++types.first) +          { +            if (Type* t = dynamic_cast<Type*> (&types.first->named ())) +            { +              return t; +            } +          } +        } + +        return 0; +      } + +    public: +      SemanticGraph::Path +      path (SemanticGraph::Nameable& n) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Schema; +        using SemanticGraph::Uses; + +        Schema* schema (0); + +        for (Scope* s (dynamic_cast<Scope*> (&n) +                       ? dynamic_cast<Scope*> (&n) : &n.scope ());; +             s = &s->scope ()) +        { +          if ((schema = dynamic_cast<Schema*> (s))) +            break; +        } + +        if (!schema->used_p ()) +          return schema_path; + +        Uses& u (*schema->used_begin ()); +        return u.path (); +      } + +    public: +      String +      xpath (SemanticGraph::Nameable& n) +      { +        if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0) +          return L"<namespace-level>"; // There is a bug if you see this. + +        assert (n.named_p ()); + +        SemanticGraph::Scope& scope (n.scope ()); + +        if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0) +          return n.name (); + +        return xpath (scope) + L"/" + n.name (); +      } + +    private: +      SemanticGraph::Path const schema_path_; +      SemanticGraph::Namespace* ns_; +      bool failed_; + +    public: +      AnonymousNameTranslator& trans; +      bool detect_unstable; + +    public: +      SemanticGraph::Schema& schema; +      SemanticGraph::Path const& schema_path; +      SemanticGraph::Namespace*& ns; +      bool& failed; +    }; + + +    // 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 ("xsd-frontend-anonymous-seen")) +        { +          s.context ().set ("xsd-frontend-anonymous-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; + +    // Keep track which namespace we are in. +    // +    struct Namespace: Traversal::Namespace +    { +      Namespace (SemanticGraph::Namespace*& ns) +          : ns_ (ns) +      { +      } + +      void +      pre (SemanticGraph::Namespace& ns) +      { +        ns_ = &ns; +      } + +      void +      post (SemanticGraph::Namespace&) +      { +        ns_ = 0; +      } + +    private: +      SemanticGraph::Namespace*& ns_; +    }; + +    // +    // +    struct Type: Traversal::List, +                 Traversal::Union, +                 Traversal::Complex, +                 protected virtual Context +    { +      Type (Context& c) +          : Context (c) +      { +      } + +      virtual void +      traverse (SemanticGraph::List& l) +      { +        SemanticGraph::Type& t (l.argumented ().type ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            // Run the name through the translation service. +            // +            SemanticGraph::Path file (path (l)); +            file.normalize (); +            String file_str; + +            // Try to use the portable representation of the path. If that +            // fails, fall back to the native representation. +            // +            try +            { +              file_str = file.posix_string (); +            } +            catch (SemanticGraph::InvalidPath const&) +            { +              file_str = file.string (); +            } + +            String name ( +              trans.translate ( +                file_str, ns->name (), l.name () + L"_item", xpath (l))); + +            // Make sure the name is unique. +            // +            unsigned long n (1); +            String escaped (name); + +            while (conflict (escaped)) +            { +              std::wostringstream os; +              os << n++; +              escaped = name + os.str (); +            } + +            t.context ().set ("anonymous", true); +            schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": error: list type name '" << xpath (l) << "' " +                  << "creates an unstable conflict when used as a base " +                  << "for the item type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << l.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      virtual void +      traverse (SemanticGraph::Union& u) +      { +        String file_str; + +        for (SemanticGraph::Union::ArgumentedIterator i ( +               u.argumented_begin ()); i != u.argumented_end (); ++i) +        { +          SemanticGraph::Type& t (i->type ()); + +          if (!t.named_p () && +              !t.is_a<SemanticGraph::Fundamental::IdRef> () && +              !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +          { +            try +            { +              // Run the name through the translation service. +              // + +              if (!file_str) +              { +                SemanticGraph::Path file (path (u)); +                file.normalize (); + +                // Try to use the portable representation of the path. If +                // that fails, fall back to the native representation. +                // +                try +                { +                  file_str = file.posix_string (); +                } +                catch (SemanticGraph::InvalidPath const&) +                { +                  file_str = file.string (); +                } +              } + +              String name ( +                trans.translate ( +                  file_str, ns->name (), u.name () + L"_member", xpath (u))); + +              // Make sure the name is unique. +              // +              unsigned long n (1); +              String escaped (name); + +              while (conflict (escaped)) +              { +                std::wostringstream os; +                os << n++; +                escaped = name + os.str (); +              } + +              t.context ().set ("anonymous", true); +              schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +            } +            catch (UnstableConflict const& ex) +            { +              SemanticGraph::Type& t (ex.type ()); + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": error: union type name '" << xpath (u) << "' " +                    << "creates an unstable conflict when used as a base " +                    << "for the member type name" +                    << endl; + +              wcerr << t.file () << ":" << t.line () << ":" << t.column () +                    << ": info: conflicting type is defined here" << endl; + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": info: " +                    << "use --anonymous-regex to resolve this conflict" +                    << endl; + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": info: " +                    << "and don't forget to pass the same option when " +                    << "translating '" << u.file ().leaf () << "' and all " +                    << "the schemas that refer to it" << endl; + +              failed = true; +            } +          } +        } +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        if (!c.inherits_p ()) +          return; + +        SemanticGraph::Type& t (c.inherits ().base ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            // Run the name through the translation service. +            // +            SemanticGraph::Path file (path (c)); +            file.normalize (); +            String file_str; + +            // Try to use the portable representation of the path. If that +            // fails, fall back to the native representation. +            // +            try +            { +              file_str = file.posix_string (); +            } +            catch (SemanticGraph::InvalidPath const&) +            { +              file_str = file.string (); +            } + +            String name ( +              trans.translate ( +                file_str, ns->name (), c.name () + L"_base", xpath (c))); + +            // Make sure the name is unique. +            // +            unsigned long n (1); +            String escaped (name); + +            while (conflict (escaped)) +            { +              std::wostringstream os; +              os << n++; +              escaped = name + os.str (); +            } + +            t.context ().set ("anonymous", true); +            schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": error: simple type name '" << xpath (c) << "' " +                  << "creates an unstable conflict when used as a base " +                  << "for the base type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << c.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } +    }; + + +    // +    // +    struct Member: Traversal::Element, +                   Traversal::Attribute, +                   protected virtual Context +    { +      Member (Context& c) +          : Context (c) +      { +      } + +      virtual void +      traverse (SemanticGraph::Element& e) +      { +        SemanticGraph::Type& t (e.type ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            traverse_ (e); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": error: element name '" << xpath (e) << "' " +                  << "creates an unstable conflict when used as a type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << e.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      virtual void +      traverse (SemanticGraph::Attribute& a) +      { +        SemanticGraph::Type& t (a.type ()); + +        //@@ This IDREF stuff us really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            traverse_ (a); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": error: attribute name '" << xpath (a) << "' " +                  << "creates an unstable conflict when used as a type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << a.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      void +      traverse_ (SemanticGraph::Member& m) +      { +        using SemanticGraph::Type; + +        Type& t (m.type ()); + +        // Normally this will be the member which also "defined" the type. +        // However, in some cases of cyclic schema inclusion, this does +        // not happen. As a result we need an extra check that will make +        // sure we create the Names edge in the same Schema node as the +        // one which contains the member which initially defined this +        // type. See the cyclic-inclusion test for an example. +        // + +        // Find the first member that this type classifies. +        // +        for (Type::ClassifiesIterator i (t.classifies_begin ()); +             i != t.classifies_end (); ++i) +        { +          SemanticGraph::Instance& inst (i->instance ()); + +          if (inst.is_a<SemanticGraph::Member> ()) +          { +            // If it is the same member as the one we are traversing, +            // then continue. +            // +            if (&inst == &m) +              break; +            else +              return; +          } +        } + +        // Run the name through the translation service. +        // +        SemanticGraph::Path file (path (m)); +        file.normalize (); +        String file_str; + +        // Try to use the portable representation of the path. If that +        // fails, fall back to the native representation. +        // +        try +        { +          file_str = file.posix_string (); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          file_str = file.string (); +        } + +        String name ( +          trans.translate (file_str, ns->name (), m.name (), xpath (m))); + +        // Check if this name conflicts. +        // +        unsigned long n (1); +        String escaped (name); + +        while (SemanticGraph::Type* other = conflict (escaped)) +        { +          // First see if we should just use the other type. It should +          // also have been anonymous and structurally equal to our type. +          // +          if (other->context ().count ("anonymous")) +          { +            if (structurally_equal (t, *other)) +            { +              // Reset the elements that are classified by this type to point +              // to the other type. +              // +              for (Type::ClassifiesIterator i (t.classifies_begin ()); +                   i != t.classifies_end (); ++i) +              { +                schema.reset_right_node (*i, *other); +              } + +              //wcerr << "equal " << name << endl; +              return; +            } +            //else +              //wcerr << "unequal " << name << endl; +          } + +          std::wostringstream os; +          os << n++; +          escaped = name + os.str (); +        } + +        t.context ().set ("anonymous", true); +        schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +      } +    }; +  } + +  namespace Transformations +  { +    Anonymous:: +    Anonymous (AnonymousNameTranslator& trans) +        : trans_ (trans) +    { +    } + +    void Anonymous:: +    transform (SemanticGraph::Schema& s, +               SemanticGraph::Path const& f, +               bool duc) +    { +      Context ctx (s, f, trans_, duc); + +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Namespace ns (ctx.ns); +      Traversal::Names ns_names_member; +      Traversal::Names ns_names_type; + +      schema >> schema_names >> ns; +      ns >> ns_names_member; +      ns >> ns_names_type; + +      Type type (ctx); +      ns_names_type >> type; + +      Traversal::Scope scope; // Goes to both types and groups. +      Member member (ctx); + +      ns_names_member >> scope; +      ns_names_member >> member; + +      Traversal::Names names; + +      scope >> names >> member; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-anonymous-seen", true); + +      schema.dispatch (s); + +      if (ctx.failed) +        throw Failed (); +    } + +    AnonymousNameTranslator:: +    ~AnonymousNameTranslator () +    { +    } +  } +} | 
