diff options
Diffstat (limited to 'libxsd-frontend/xsd-frontend')
91 files changed, 16926 insertions, 0 deletions
diff --git a/libxsd-frontend/xsd-frontend/generators/dependencies.cxx b/libxsd-frontend/xsd-frontend/generators/dependencies.cxx new file mode 100644 index 0000000..55e7ae8 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/generators/dependencies.cxx @@ -0,0 +1,70 @@ +// file      : xsd-frontend/generators/dependencies.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <xsd-frontend/generators/dependencies.hxx> + +namespace XSDFrontend +{ +  typedef std::vector<SemanticGraph::Path> Paths; + +  namespace +  { +    // Go into included/imported (but not implied) schemas while making +    // sure we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Uses +    { +      Uses (Paths& p): paths_ (p) {} + +      virtual void +      traverse (Type& u) +      { +        if (u.is_a<SemanticGraph::Implies> ()) +          return; + +        SemanticGraph::Schema& s (u.schema ()); + +        if (!s.context ().count ("xsd-frontend-dependencies-seen")) +        { +          s.context ().set ("xsd-frontend-dependencies-seen", true); + +          // While the edge contains the exact path that was found in the +          // schema, the schema node itself has the reative to the including +          // or importing schema path, which is what we want. +          // +          paths_.push_back (s.file ()); +          Traversal::Uses::traverse (u); +        } +      } + +    private: +      Paths& paths_; +    }; +  } + +  namespace Generators +  { +    Paths Dependencies:: +    generate (SemanticGraph::Schema& s, SemanticGraph::Path const& p) +    { +      Paths r; +      r.push_back (p); + +      Traversal::Schema schema; +      Uses uses (r); + +      schema >> uses >> schema; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-dependencies-seen", true); + +      schema.dispatch (s); +      return r; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/generators/dependencies.hxx b/libxsd-frontend/xsd-frontend/generators/dependencies.hxx new file mode 100644 index 0000000..5a7624f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/generators/dependencies.hxx @@ -0,0 +1,32 @@ +// file      : xsd-frontend/generators/dependencies.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_GENERATORS_DEPENDENCIES_HXX +#define XSD_FRONTEND_GENERATORS_DEPENDENCIES_HXX + +#include <vector> + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Generators +  { +    // Return the list of included/imported schema paths (transitively and +    // including the main schema file) which can then be used to produce +    // make dependencies, etc. +    // +    class Dependencies +    { +    public: +      std::vector<SemanticGraph::Path> +      generate (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_GENERATORS_DEPENDENCIES_HXX diff --git a/libxsd-frontend/xsd-frontend/makefile b/libxsd-frontend/xsd-frontend/makefile new file mode 100644 index 0000000..4dbffcd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/makefile @@ -0,0 +1,117 @@ +# file      : xsd-frontend/makefile +# copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +cxx_tun := semantic-graph/annotation.cxx      \ +           semantic-graph/any.cxx             \ +           semantic-graph/any-attribute.cxx   \ +           semantic-graph/attribute.cxx       \ +           semantic-graph/attribute-group.cxx \ +           semantic-graph/complex.cxx         \ +           semantic-graph/compositors.cxx     \ +           semantic-graph/element.cxx         \ +           semantic-graph/element-group.cxx   \ +           semantic-graph/elements.cxx        \ +           semantic-graph/enumeration.cxx     \ +           semantic-graph/fundamental.cxx     \ +           semantic-graph/list.cxx            \ +           semantic-graph/namespace.cxx       \ +           semantic-graph/particle.cxx        \ +           semantic-graph/schema.cxx          \ +           semantic-graph/union.cxx + +cxx_tun += traversal/attribute.cxx       \ +           traversal/attribute-group.cxx \ +           traversal/complex.cxx         \ +           traversal/compositors.cxx     \ +           traversal/element.cxx         \ +           traversal/element-group.cxx   \ +           traversal/elements.cxx        \ +           traversal/enumeration.cxx     \ +           traversal/fundamental.cxx     \ +           traversal/list.cxx            \ +           traversal/namespace.cxx       \ +           traversal/particle.cxx        \ +           traversal/schema.cxx          \ +           traversal/union.cxx + +cxx_tun += transformations/anonymous.cxx       \ +           transformations/enum-synthesis.cxx  \ +           transformations/restriction.cxx     \ +           transformations/schema-per-type.cxx \ +           transformations/simplifier.cxx + +cxx_tun += generators/dependencies.cxx + +cxx_tun += types.cxx parser.cxx schema-dom-parser.cxx + + +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od  := $(cxx_obj:.o=.o.d) +m4_cxx  := $(out_base)/semantic-graph/fundamental.hxx \ +  $(out_base)/semantic-graph/fundamental.cxx + +xsd_frontend.l             := $(out_base)/xsd-frontend.l +xsd_frontend.l.cpp-options := $(out_base)/xsd-frontend.l.cpp-options + +clean   := $(out_base)/.clean + +$(call import,\ +  $(scf_root)/import/libxerces-c/stub.make,\ +  l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + +$(call import,\ +  $(scf_root)/import/libcutl/stub.make,\ +  l: cutl.l,cpp-options: cutl.l.cpp-options) + +# What to build. +# +$(xsd_frontend.l): $(cxx_obj) $(cutl.l) $(xerces_c.l) + +$(xsd_frontend.l.cpp-options): prefix := xsd-frontend/ $(out_root)/ +$(xsd_frontend.l.cpp-options): value := -I$(src_root) -I$(out_root) +$(xsd_frontend.l.cpp-options): $(cutl.l.cpp-options) + +#@@ This can be further optimized since only parser depends on xerces. +# +$(cxx_obj) $(cxx_od): $(xsd_frontend.l.cpp-options) $(xerces_c.l.cpp-options) + +$(m4_cxx): $(src_base)/semantic-graph/fundamental.m4 +$(m4_cxx): m4_options := -I $(src_base)/semantic-graph + +$(call include-dep,$(cxx_od)) + +# Alias for default target. +# +$(out_base)/: $(xsd_frontend.l) + +# Clean +# +$(clean): $(xsd_frontend.l).o.clean     \ +  $(xsd_frontend.l.cpp-options).clean   \ +  $(addsuffix .cxx.clean,$(cxx_obj))    \ +  $(addsuffix .cxx.clean,$(cxx_od)) + +ifneq ($(libxsd_frontend_clean_gen),n) +$(clean): $(addsuffix .m4.clean,$(m4_cxx)) +endif + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(xsd_frontend.l): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := semantic-graph/fundamental.hxx semantic-graph/fundamental.cxx +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/o-l.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/m4/m4.make) diff --git a/libxsd-frontend/xsd-frontend/parser.cxx b/libxsd-frontend/xsd-frontend/parser.cxx new file mode 100644 index 0000000..6b582ab --- /dev/null +++ b/libxsd-frontend/xsd-frontend/parser.cxx @@ -0,0 +1,5164 @@ +// file      : xsd-frontend/parser.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> +#include <stack> +#include <vector> +#include <iostream> +#include <sstream> + +#include <cutl/compiler/type-id.hxx> + +#include <xsd-frontend/version.hxx> // Check Xerces-C++ version. +#include <xsd-frontend/xml.hxx> +#include <xsd-frontend/parser.hxx> +#include <xsd-frontend/schema-dom-parser.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +//@@ Do i need this? +// +#include <xercesc/dom/DOM.hpp> + +#include <xercesc/sax/ErrorHandler.hpp> +#include <xercesc/sax/SAXParseException.hpp> + +#include <xercesc/sax2/SAX2XMLReader.hpp> +#include <xercesc/sax2/XMLReaderFactory.hpp> + +#include <xercesc/util/XMLUniDefs.hpp> +#include <xercesc/util/XMLString.hpp> +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/util/BinInputStream.hpp> +#include <xercesc/util/BinFileInputStream.hpp> + +#include <xercesc/validators/common/Grammar.hpp> + +#include <xercesc/sax/InputSource.hpp> +#include <xercesc/framework/LocalFileInputSource.hpp> +#include <xercesc/framework/Wrapper4InputSource.hpp> + +using namespace std; + +using cutl::compiler::type_id; + +namespace XSDFrontend +{ +  namespace Xerces = XML::Xerces; +  using namespace SemanticGraph; + +  //@@ Port to tracing facility. +  // +  bool trace_ = false; + +  String const xsd = L"http://www.w3.org/2001/XMLSchema"; +  String const xse = L"http://www.codesynthesis.com/xmlns/xml-schema-extension"; + +  namespace +  { +    // +    // Exceptions. +    // + +    struct NotNamespace +    { +      NotNamespace (String const& ns) +          : ns_ (ns) +      { +      } + +      String const& +      ns () const +      { +        return ns_; +      } + +    private: +      String ns_; +    }; + +    struct NotName +    { +      NotName (String const& ns, String const& name) +          : ns_ (ns), name_ (name) +      { +      } + +      String const& +      ns () const +      { +        return ns_; +      } + +      String const& +      name () const +      { +        return name_; +      } + +    private: +      String ns_; +      String name_; +    }; + +    // Trim leading and trailing whitespaces. +    // +    template <typename C> +    StringTemplate<C> +    trim (StringTemplate<C> const& s) +    { +      typedef StringTemplate<C> String; + +      size_t size (s.size ()); + +      if (size == 0) +        return s; + +      C const* f (s.c_str ()); +      C const* l (f + size); + +      C const* of (f); + +      while (f < l && +             (*f == C (0x20) || *f == C (0x0A) || +              *f == C (0x0D) || *f == C (0x09))) +        ++f; + +      --l; + +      C const* ol (l); + +      while (l > f && +             (*l == C (0x20) || *l == C (0x0A) || +              *l == C (0x0D) || *l == C (0x09))) +        --l; + +      if (f != of || l != ol) +        return f <= l ? String (f, l - f + 1) : String (); +      else +        return s; +    } + +    // Name cache. We only support maximum two nodes with the same +    // name in the cache (e.g., element and type). For (rare) cases +    // where there is three or more names, there will be a cache miss. +    // +    struct CacheNodes +    { +      CacheNodes () : first (0), second (0) {} + +      Nameable* first; +      Nameable* second; +    }; + +    typedef std::map<String, CacheNodes> NodeMap; +    typedef std::map<String, NodeMap> NamespaceMap; +    typedef std::vector<SemanticGraph::Member*> DefaultValues; + +    template <typename X> +    X& +    resolve (String const& ns_name, +             String const& uq_name, +             Schema& s_, +             NamespaceMap& cache) +    { +      // First check the cache. +      // +      NamespaceMap::iterator i (cache.find (ns_name)); + +      if (i != cache.end ()) +      { +        NodeMap::iterator j (i->second.find (uq_name)); + +        if (j != i->second.end ()) +        { +          X* x; + +          if ((x = dynamic_cast<X*> (j->second.first)) || +              (x = dynamic_cast<X*> (j->second.second))) +              return *x; +        } +      } + +      Scope::NamesIteratorPair nss (s_.find (ns_name)); + +      if (nss.first == nss.second) +        throw NotNamespace (ns_name); + +      for (; nss.first != nss.second; ++nss.first) +      { +        Namespace& ns (dynamic_cast<Namespace&> (nss.first->named ())); + +        Scope::NamesIteratorPair types (ns.find (uq_name)); + +        for (; types.first != types.second; ++types.first) +        { +          if (X* x = dynamic_cast<X*> (&types.first->named ())) +          { +            if (trace_) +              wcout << "successfully resolved '" << ns_name << '#' << uq_name +                    << "'" << endl; + +            // Add to the cache if there are free slots. +            // +            NodeMap& m (i != cache.end () ? i->second : cache[ns_name]); +            CacheNodes& n (m[uq_name]); + +            if (n.first == 0) +              n.first = x; +            else if (n.second == 0) +              n.second = x; + +            return *x; +          } +        } +      } + +      throw NotName (ns_name, uq_name); +    } + +    // +    // +    typedef std::map<String, String> Facets; + +    void +    copy_facets (Restricts& r, Facets const& f) +    { +      for (Facets::const_iterator i (f.begin ()), e (f.end ()); i != e; ++i) +        r.facet_insert (i->first, i->second); +    } + +    // +    // +    struct UnionMemberType +    { +      UnionMemberType (String const& ns, String const& uq) +          : ns_name (ns), uq_name (uq) +      { +      } + +      String ns_name; +      String uq_name; +    }; + +    typedef std::vector<UnionMemberType> UnionMemberTypes; + +    // +    // +    struct ElementGroupRef +    { +      ElementGroupRef (String const& uq_name_, String const& ns_name_, +                       unsigned long min_, unsigned long max_, +                       Compositor& compositor, Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_), +            min (min_), max (max_) +      { +        contains_pos  = compositor.contains_end (); +        if (compositor.contains_begin () != contains_pos) +          --contains_pos; + +        names_pos = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      ElementGroupRef (String const& uq_name_, String const& ns_name_, +                       unsigned long min_, unsigned long max_, +                       Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_), +            min (min_), max (max_) +      { +        names_pos  = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      String uq_name; +      String ns_name; +      unsigned long min, max; +      Compositor::ContainsIterator contains_pos; +      Scope::NamesIterator names_pos; +    }; + +    typedef std::vector<ElementGroupRef> ElementGroupRefs; + +    // +    // +    struct AttributeGroupRef +    { +      AttributeGroupRef (String const& uq_name_, +                         String const& ns_name_, +                         Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_) +      { +        names_pos = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      String uq_name; +      String ns_name; +      Scope::NamesIterator names_pos; +    }; + +    typedef std::vector<AttributeGroupRef> AttributeGroupRefs; + + +    // +    // +    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 Resolver : Traversal::Element, +                      Traversal::Attribute, +                      Traversal::Fundamental::IdRef, +                      Traversal::Fundamental::IdRefs, +                      Traversal::List, +                      Traversal::Union, +                      Traversal::Complex, +                      Traversal::Enumeration, +                      Traversal::ElementGroup, +                      Traversal::AttributeGroup, +                      Traversal::Compositor +    { +      Resolver (Schema& s, +                bool& valid, +                NamespaceMap& cache, +                DefaultValues& default_values) +          : s_ (s), +            valid_ (valid), +            cache_ (cache), +            default_values_ (default_values) +      { +        *this >> contains_compositor >> *this; +      } + +      void +      traverse (SemanticGraph::Attribute& a) +      { +        // Avoid traversing attribute more than once. +        // +        if (!a.context ().count ("attribute-traversed")) +        { +          a.context ().set ("attribute-traversed", true); +          SemanticGraph::Member& m (a); +          resolve_member (m); +        } +      } + +      void +      traverse (SemanticGraph::Element& e) +      { +        resolve_element (e); +      } + +      void +      resolve_element (SemanticGraph::Element& e) +      { +        // Avoid resolving element more than once. +        // +        if (e.context ().count ("element-resolved")) +          return; + +        e.context ().set ("element-resolved", true); + +        { +          SemanticGraph::Member& m (e); +          resolve_member (m); +        } + +        if (e.context ().count ("substitution-ns-name")) +        { +          String ns_name (e.context ().get<String> ("substitution-ns-name")); +          String uq_name (e.context ().get<String> ("substitution-uq-name")); + +          e.context ().remove ("substitution-ns-name"); +          e.context ().remove ("substitution-uq-name"); + +          try +          { +            SemanticGraph::Element& root ( +              resolve<SemanticGraph::Element> (ns_name, uq_name, s_, cache_)); + +            s_.new_edge<Substitutes> (e, root); + +            // See if we need to derive the type of this element from the +            // one it substitutes. +            // +            if (!e.typed_p ()) +            { +              resolve_member (root); // Make sure the type is resolved. +              s_.new_edge<Belongs> (e, root.type ()); +            } +          } +          catch (NotNamespace const& ex) +          { +            if (valid_) +            { +              wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                    << endl; +              abort (); +            } +          } +          catch (NotName const& ex) +          { +            if (valid_) +            { +              wcerr << "ice: unable to resolve name '" << ex.name () +                    << "' inside namespace '" << ex.ns () << "'" <<endl; +              abort (); +            } +          } +        } +      } + +      void +      resolve_member (SemanticGraph::Member& m) +      { +        using SemanticGraph::Member; +        using SemanticGraph::Element; +        using SemanticGraph::Attribute; + +        try +        { +          String ns_name; +          String uq_name; + +          if (m.context ().count ("type-ns-name")) +          { +            ns_name = m.context ().get<String> ("type-ns-name"); +            uq_name = m.context ().get<String> ("type-uq-name"); + +            m.context ().remove ("type-ns-name"); +            m.context ().remove ("type-uq-name"); +            m.context ().remove ("edge-type-id"); + +            s_.new_edge<Belongs> ( +              m, resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_)); +          } +          else if (m.context ().count ("instance-ns-name")) +          { +            ns_name = m.context ().get<String> ("instance-ns-name"); +            uq_name = m.context ().get<String> ("instance-uq-name"); + +            m.context ().remove ("instance-ns-name"); +            m.context ().remove ("instance-uq-name"); + +            // Resolve the name to the same type. It is legal to have +            // an element and an attribute with the same name. +            // +            Member& ref ( +              m.is_a<Element> () +              ? static_cast<Member&> ( +                  resolve<Element> (ns_name, uq_name, s_, cache_)) +              : static_cast<Member&> ( +                  resolve<Attribute> (ns_name, uq_name, s_, cache_))); + +            // Make sure the referenced member is fully resolved. +            // @@ Substitutes edge won't be resolved. +            // +            resolve_member (ref); + + +            // Substitution group info. We have to test for both resolved +            // and unresolved cases since we don't know whether it was +            // resolved or not. +            // +            if (ref.is_a<Element> ()) +            { +              Element& m_e (dynamic_cast<Element&> (m)); +              Element& ref_e (dynamic_cast<Element&> (ref)); + +              if (ref_e.substitutes_p ()) +              { +                s_.new_edge<Substitutes> (m_e, ref_e.substitutes ().root ()); +              } +              else if (ref_e.context ().count ("substitution-ns-name")) +              { +                m_e.context ().set ( +                  "substitution-ns-name", +                  ref_e.context ().get<String> ("substitution-ns-name")); + +                m_e.context ().set ( +                  "substitution-uq-name", +                  ref_e.context ().get<String> ("substitution-uq-name")); +              } +            } + +            // +            // +            s_.new_edge<BelongsToNamespace> (m, ref.namespace_ ()); + +            // Transfer default and fixed values if we haven't already +            // gotten them. +            // +            if (!m.default_p ()) +            { +              if (ref.fixed_p ()) +                m.fixed (ref.value ()); +              else if (ref.default_p ()) +              { +                // Default value applies only if the attribute is optional. +                // +                if (Attribute* a = dynamic_cast<Attribute*> (&m)) +                { +                  if (a->optional_p ()) +                    m.default_ (ref.value ()); +                } +                else +                  m.default_ (ref.value ()); +              } + +              if (m.default_p ()) +              { +                m.context ().set ( +                  "dom-node", +                  ref.context ().get<Xerces::DOMElement*> ("dom-node")); +                default_values_.push_back (&m); +              } +            } + +            // Transfer annotation if we haven't already gotten it. +            // +            if (!m.annotated_p () && ref.annotated_p ()) +              s_.new_edge<Annotates> (ref.annotation (), m); + +            // Type info. Can be missing for a substitution group member. +            // +            if (ref.typed_p ()) +              s_.new_edge<Belongs> (m, ref.type ()); +          } +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve name '" << ex.name () +                  << "' inside namespace '" << ex.ns () << "'" <<endl; +            abort (); +          } +        } +      } + +      void +      traverse (SemanticGraph::Fundamental::IdRef& i) +      { +        ref_type (i); +      } + +      void +      traverse (SemanticGraph::Fundamental::IdRefs& i) +      { +        ref_type (i); +      } + +      void +      ref_type (SemanticGraph::Specialization& s) +      { +        if (s.context ().count ("type-ns-name")) +        { +          String ns_name (s.context ().get<String> ("type-ns-name")); +          String uq_name (s.context ().get<String> ("type-uq-name")); + +          s.context ().remove ("type-ns-name"); +          s.context ().remove ("type-uq-name"); +          s.context ().remove ("edge-type-id"); + +          try +          { +            s_.new_edge<Arguments> ( +              resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_), s); +          } +          catch (NotName const& ex) +          { +            wcerr << s.file () << ":" << s.line () << ":" << s.column () << ": " +                  << "error: unable to resolve type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } +      } + +      void +      traverse (SemanticGraph::List& l) +      { +        if (l.context ().count ("type-ns-name")) +        { +          String ns_name (l.context ().get<String> ("type-ns-name")); +          String uq_name (l.context ().get<String> ("type-uq-name")); + +          l.context ().remove ("type-ns-name"); +          l.context ().remove ("type-uq-name"); +          l.context ().remove ("edge-type-id"); + +          try +          { +            s_.new_edge<Arguments> ( +              resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_), l); +          } +          catch (NotName const& ex) +          { +            wcerr << l.file () << ":" << l.line () << ":" << l.column () << ": " +                  << "error: unable to resolve item type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        Traversal::List::traverse (l); +      } + +      void +      traverse (SemanticGraph::Union& u) +      { +        using SemanticGraph::Union; + +        if (u.context ().count ("union-member-types")) +        { +          UnionMemberTypes const& m ( +            u.context ().get<UnionMemberTypes> ("union-member-types")); + +          // Process it backwards so that we can just insert each +          // edge in the front. +          // +          for (UnionMemberTypes::const_reverse_iterator i (m.rbegin ()); +               i != m.rend (); i++) +          { +            try +            { +              NodeArgs<Union, Union::ArgumentedIterator> na ( +                u, u.argumented_begin ()); + +              s_.new_edge<Arguments> ( +                resolve<SemanticGraph::Type> ( +                  i->ns_name, i->uq_name, s_, cache_), na); +            } +            catch (NotName const& ex) +            { +              wcerr << u.file () << ":" << u.line () << ":" << u.column () << ": " +                    << "error: unable to resolve item type '" << i->uq_name << "' " +                    << "in namespace '" << i->ns_name << "'" << endl; + +              valid_ = false; +            } +          } + +          u.context ().remove ("union-member-types"); +        } + +        Traversal::Union::traverse (u); +      } + +      void +      traverse (SemanticGraph::Complex& c) +      { +        // Avoid traversing complex type more than once. +        // +        if (c.context ().count ("complex-type-resolved")) +          return; + +        c.context ().set ("complex-type-resolved", true); + +        // Resolve base type if any. +        // +        if (c.context ().count ("type-ns-name")) +        { +          String ns_name (c.context ().get<String> ("type-ns-name")); +          String uq_name (c.context ().get<String> ("type-uq-name")); +          type_id edge_id (c.context ().get<type_id> ("edge-type-id")); + +          c.context ().remove ("type-ns-name"); +          c.context ().remove ("type-uq-name"); +          c.context ().remove ("edge-type-id"); + +          try +          { +            if (edge_id == typeid (Extends)) +            { +              s_.new_edge<Extends> ( +                c, resolve<SemanticGraph::Type> ( +                  ns_name, uq_name, s_, cache_)); +            } +            else if (edge_id == typeid (Restricts)) +            { +              Restricts& r ( +                s_.new_edge<Restricts> ( +                  c, resolve<SemanticGraph::Type> ( +                    ns_name, uq_name, s_, cache_))); + +              if (c.context ().count ("facets")) +              { +                Facets const& f (c.context ().get<Facets> ("facets")); +                copy_facets (r, f); +                c.context ().remove ("facets"); +              } +            } +            else +              assert (false); +          } +          catch (NotName const& ex) +          { +            wcerr << c.file () << ":" << c.line () << ":" << c.column () << ": " +                  << "error: unable to resolve base type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        // Resolve attribute-group-refs. Do it before element-group-refs +        // so that if the scope was empty they end up at the end. +        // +        if (c.context ().count ("attribute-group-refs")) +        { +          AttributeGroupRefs& refs ( +            c.context ().get<AttributeGroupRefs> ("attribute-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (AttributeGroupRefs::reverse_iterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            clone_attribute_group_content (*i, c); +          } + +          c.context ().remove ("attribute-group-refs"); +        } + +        // Resolve element-group-ref if any. +        // +        if (c.context ().count ("element-group-ref")) +        { +          using SemanticGraph::Compositor; + +          ElementGroupRef& ref ( +            c.context ().get<ElementGroupRef> ("element-group-ref")); + +          Compositor* comp (clone_element_group_content (c, ref)); + +          // Create ContainsCompositor edge. +          // +          if (comp) +            s_.new_edge<ContainsCompositor> (c, *comp, ref.min, ref.max); + +          c.context ().remove ("element-group-ref"); +        } + +        Traversal::Complex::traverse (c); +      } + +      void +      traverse (SemanticGraph::Enumeration& e) +      { +        // Resolve base type if any. +        // +        if (e.context ().count ("type-ns-name")) +        { +          String ns_name (e.context ().get<String> ("type-ns-name")); +          String uq_name (e.context ().get<String> ("type-uq-name")); + +          e.context ().remove ("type-ns-name"); +          e.context ().remove ("type-uq-name"); +          e.context ().remove ("edge-type-id"); + +          try +          { +            Restricts& r ( +              s_.new_edge<Restricts> ( +                e, resolve<SemanticGraph::Type> ( +                  ns_name, uq_name, s_, cache_))); + +            if (e.context ().count ("facets")) +            { +              Facets const& f (e.context ().get<Facets> ("facets")); +              copy_facets (r, f); +              e.context ().remove ("facets"); +            } +          } +          catch (NotName const& ex) +          { +            wcerr << e.file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: unable to resolve base type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        Traversal::Enumeration::traverse (e); +      } + +      void +      traverse (SemanticGraph::ElementGroup& g) +      { +        // Avoid traversing groups more than once. +        // +        if (!g.context ().count ("element-group-traversed")) +        { +          g.context ().set ("element-group-traversed", true); +          Traversal::ElementGroup::traverse (g); + +          // Note that setting element-group-resolved after traversing +          // the group allows for a recursive shallow resolution using +          // resolve_element_group. +          // +          g.context ().set ("element-group-resolved", true); +        } +      } + +      // We need a "shallow" resolve to break possible recursing: +      // group->element->complexType->group. +      // +      void +      resolve_element_group (SemanticGraph::ElementGroup& g) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Element; + +        // Avoid resolving groups more than once. +        // +        if (!g.context ().count ("element-group-resolved")) +        { +          g.context ().set ("element-group-resolved", true); + +          for (Scope::NamesIterator i (g.names_begin ()); +               i != g.names_end (); ++i) +          { +            if (Element* e = dynamic_cast<Element*> (&i->named ())) +              resolve_element (*e); +          } + +          traverse (g.contains_compositor ().compositor ()); +        } +      } + +      void +      traverse (SemanticGraph::AttributeGroup& g) +      { +        // Avoid traversing groups more than once. +        // +        if (g.context ().count ("attribute-group-resolved")) +          return; + +        g.context ().set ("attribute-group-resolved", true); + +        // Resolve attribute-group-refs. +        // +        if (g.context ().count ("attribute-group-refs")) +        { +          AttributeGroupRefs& refs ( +            g.context ().get<AttributeGroupRefs> ("attribute-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (AttributeGroupRefs::reverse_iterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            clone_attribute_group_content (*i, g); +          } + +          g.context ().remove ("attribute-group-refs"); +        } + +        Traversal::AttributeGroup::traverse (g); +      } + +      void +      traverse (SemanticGraph::Compositor& c) +      { +        using SemanticGraph::Compositor; + +        // Resolve element-group-refs if any. +        // +        if (c.context ().count ("element-group-refs")) +        { +          using SemanticGraph::Scope; + +          ElementGroupRefs& refs ( +            c.context ().get<ElementGroupRefs> ("element-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (ElementGroupRefs::reverse_iterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            // Find our scope. +            // +            Compositor* j (&c); + +            while(!j->contained_compositor_p ()) +              j = &j->contained_particle ().compositor (); + +            Compositor* comp ( +              clone_element_group_content ( +                dynamic_cast<Scope&> (j->contained_compositor ().container ()), +                *i)); + +            // Create ContainsParticle edge. +            // +            if (comp) +            { +              NodeArgs<Compositor, Compositor::ContainsIterator> na ( +                c, i->contains_pos); +              s_.new_edge<ContainsParticle> (na, *comp, i->min, i->max); +            } +          } + +          c.context ().remove ("element-group-refs"); +        } + +        // Traverse recursively but only particles that are compositors. +        // This way we won't trigger anonymous type traversal (via member) +        // and therefore can call this functions from resolve_element_group +        // to completely resolve a group. +        // +        for (Compositor::ContainsIterator i (c.contains_begin ()), +               e (c.contains_end ()); i != e; ++i) +        { +          SemanticGraph::Particle& p (i->particle ()); + +          if (p.is_a<Compositor> ()) +            dispatch (p); +        } + +        // Traversal::Compositor::traverse (c); +      } + +      SemanticGraph::Compositor* +      clone_element_group_content (SemanticGraph::Scope& s, +                                   ElementGroupRef const& ref) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Compositor; +        using SemanticGraph::ElementGroup; + +        try +        { +          ElementGroup& g ( +            resolve<ElementGroup> (ref.ns_name, ref.uq_name, s_, cache_)); + +          // Make sure the group and all its content are fully resolved. +          // +          resolve_element_group (g); + +          Scope::NamesIterator pos (ref.names_pos); +          Compositor& root (g.contains_compositor ().compositor ()); +          Compositor& copy (clone_compositor (root, s, pos)); + +          return © +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve name '" << ex.name () +                  << "' inside namespace '" << ex.ns () << "'" << endl; +            abort (); +          } +        } + +        return 0; +      } + +      SemanticGraph::Compositor& +      clone_compositor (SemanticGraph::Compositor& c, +                        SemanticGraph::Scope& scope, +                        SemanticGraph::Scope::NamesIterator& pos) +      { +        using SemanticGraph::Any; +        using SemanticGraph::Element; +        using SemanticGraph::Particle; +        using SemanticGraph::Compositor; + +        Compositor* tmp (0); + +        if (c.is_a<All> ()) +          tmp = &s_.new_node<All> (c.file (), c.line (), c.column ()); +        else if (c.is_a<Choice> ()) +          tmp = &s_.new_node<Choice> (c.file (), c.line (), c.column ()); +        else if (c.is_a<Sequence> ()) +          tmp = &s_.new_node<Sequence> (c.file (), c.line (), c.column ()); +        else +          assert (false); + +        Compositor& copy (*tmp); + +        // Copy annotation. +        // +        if (c.annotated_p ()) +          s_.new_edge<Annotates> (c.annotation (), copy); + +        for (Compositor::ContainsIterator i (c.contains_begin ()); +             i != c.contains_end (); ++i) +        { +          Particle& p (i->particle ()); + +          if (p.is_a<Compositor> ()) +          { +            Compositor& c (dynamic_cast<Compositor&> (p)); +            Compositor& cc (clone_compositor (c, scope, pos)); + +            s_.new_edge<ContainsParticle> (copy, cc, i->min (), i->max ()); +          } +          else if (p.is_a<Element> ()) +          { +            Element& e (dynamic_cast<Element&> (p)); +            Element& ec (clone_element (e)); + +            s_.new_edge<ContainsParticle> (copy, ec, i->min (), i->max ()); + +            NodeArgs<Scope, Scope::NamesIterator> na (scope, pos); +            s_.new_edge<Names> (na, ec, e.name ()); +            ++pos; +          } +          else if (p.is_a<Any> ()) +          { +            Any& a (dynamic_cast<Any&> (p)); +            Any& ac ( +              s_.new_node<Any> (a.file (), a.line (), a.column (), +                                a.namespace_begin (), a.namespace_end ())); + +            ac.prototype (a); + +            s_.new_edge<ContainsParticle> (copy, ac, i->min (), i->max ()); + +            // Transfer annotation. +            // +            if (a.annotated_p ()) +              s_.new_edge<Annotates> (a.annotation (), ac); + +            // Any has no name so we have to come up with a fake one in +            // order to put it into the scope. Note that we cannot reuse +            // the name from the prototype. + +            unsigned long count; +            SemanticGraph::Context& ctx (scope.context ()); + +            if (!ctx.count ("any-name-count")) +            { +              count = 0; +              ctx.set ("any-name-count", count); +            } +            else +              count = ++(ctx.get<unsigned long> ("any-name-count")); + +            std::basic_ostringstream<wchar_t> os; +            os << "any #" << count; + +            NodeArgs<Scope, Scope::NamesIterator> na (scope, pos); +            s_.new_edge<Names> (na, ac, os.str ()); +            ++pos; +          } +          else +            assert (false); +        } + +        return copy; +      } + +      // Clone a fully-resolved element. Note that it cannot be used as +      // is to clone ref'ed element (default/fixed value, etc). +      // +      SemanticGraph::Element& +      clone_element (SemanticGraph::Element& e) +      { +        using SemanticGraph::Element; + +        Element& copy ( +        s_.new_node<Element> ( +          e.file (), e.line (), e.column (), e.global_p (), e.qualified_p ())); + +        if (e.qualified_p ()) +          s_.new_edge<BelongsToNamespace> (copy, e.namespace_ ()); + +        // Transfer default and fixed values. +        // +        if (e.fixed_p ()) +          copy.fixed (e.value ()); +        else if (e.default_p ()) +          copy.default_ (e.value ()); + +        if (copy.default_p ()) +        { +          copy.context ().set ( +            "dom-node", +            e.context ().get<Xerces::DOMElement*> ("dom-node")); +          default_values_.push_back (©); +        } + +        // Transfer annotation. +        // +        if (e.annotated_p ()) +          s_.new_edge<Annotates> (e.annotation (), copy); + +        // Belongs edge. +        // +        if (e.typed_p ()) +          s_.new_edge<Belongs> (copy, e.type ()); +        else +          assert (!valid_); + +        // Substitutes edge. +        // +        if (e.substitutes_p ()) +          s_.new_edge<Substitutes> (copy, e.substitutes ().root ()); + +        return copy; +      } + +      void +      clone_attribute_group_content (AttributeGroupRef& ref, +                                     SemanticGraph::Scope& s) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Attribute; +        using SemanticGraph::AttributeGroup; + +        try +        { +          AttributeGroup& g ( +            resolve<AttributeGroup> (ref.ns_name, ref.uq_name, s_, cache_)); + +          // Make sure the group and all its content are fully resolved. +          // +          traverse (g); + +          Scope::NamesIterator pos (ref.names_pos); + +          for (Scope::NamesIterator i (g.names_begin ()); +               i != g.names_end (); ++i) +          { +            if (Attribute* p = dynamic_cast<Attribute*> (&i->named ())) +            { +              Attribute& a ( +                s_.new_node<Attribute> (p->file (), +                                        p->line (), +                                        p->column (), +                                        p->optional_p (), +                                        p->global_p (), +                                        p->qualified_p ())); + +              NodeArgs<Scope, Scope::NamesIterator> na (s, pos); +              s_.new_edge<Names> (na, a, p->name ()); +              ++pos; + +              if (p->qualified_p ()) +                s_.new_edge<BelongsToNamespace> (a, p->namespace_ ()); + +              // Transfer default and fixed values if any. +              // +              if (p->fixed_p ()) +                a.fixed (p->value ()); +              else if (p->default_p ()) +                a.default_ (p->value ()); + +              if (a.default_p ()) +              { +                a.context ().set ( +                  "dom-node", +                  p->context ().get<Xerces::DOMElement*> ("dom-node")); +                default_values_.push_back (&a); +              } + +              // Transfer annotation. +              // +              if (p->annotated_p ()) +                s_.new_edge<Annotates> (p->annotation (), a); + +              // Belongs edge. +              // +              if (p->typed_p ()) +                s_.new_edge<Belongs> (a, p->type ()); +              else +                assert (!valid_); +            } +            else if ( +              AnyAttribute* p = dynamic_cast<AnyAttribute*> (&i->named ())) +            { +              AnyAttribute& any ( +                s_.new_node<AnyAttribute> (p->file (), +                                           p->line (), +                                           p->column (), +                                           p->namespace_begin (), +                                           p->namespace_end ())); + +              any.prototype (*p); + +              // Transfer annotation. +              // +              if (p->annotated_p ()) +                s_.new_edge<Annotates> (p->annotation (), any); + +              // AnyAttribute has no name so we have to come up with a fake +              // one in order to put it into the scope. Note that we cannot +              // reuse the name from the attribute group. + +              unsigned long count; +              SemanticGraph::Context& ctx (s.context ()); + +              if (!ctx.count ("any-attribute-name-count")) +              { +                count = 0; +                ctx.set ("any-attribute-name-count", count); +              } +              else +                count = ++(ctx.get<unsigned long> ("any-attribute-name-count")); + +              std::basic_ostringstream<wchar_t> os; +              os << "any-attribute #" << count; + +              NodeArgs<Scope, Scope::NamesIterator> na (s, pos); +              s_.new_edge<Names> (na, any, os.str ()); +              ++pos; +            } +          } +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve attribute group name '" +                  << ex.name () << "' inside namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +      } + +    private: +      Schema& s_; +      bool& valid_; +      NamespaceMap& cache_; +      DefaultValues& default_values_; + +    private: +      //Traversal::ContainsParticle contains_particle; +      Traversal::ContainsCompositor contains_compositor; +    }; +  } + +  // Parser::Impl +  // + +  class Parser::Impl +  { +    Impl (Impl const&); +    Impl& operator= (Impl const&); + +  public: +    ~Impl (); + +    Impl (bool proper_restriction, +          bool multiple_imports, +          bool full_schema_check, +          LocationTranslator*, +          const WarningSet*); + +    auto_ptr<Schema> +    parse (Path const&); + +    auto_ptr<Schema> +    parse (Paths const&); + +    auto_ptr<Schema> +    xml_schema (Path const&); + +  private: +    void +    fill_xml_schema (Schema&, Path const&); + +  private: +    XML::AutoPtr<Xerces::DOMDocument> +    dom (SemanticGraph::Path const&, bool validate); + +    void +    schema (XML::Element const&); + +    SemanticGraph::Annotation* +    annotation (bool process); + +    void +    import (XML::Element const&); + +    void +    include (XML::Element const&); + +    void +    element_group (XML::Element const&, bool in_compositor); + +    SemanticGraph::Type* +    simple_type (XML::Element const&); + +    SemanticGraph::Type* +    list (XML::Element const& l, XML::Element const& type); + +    SemanticGraph::Type* +    union_ (XML::Element const& u, XML::Element const& type); + +    SemanticGraph::Type* +    restriction (XML::Element const& r, XML::Element const& type); + +    void +    enumeration (XML::Element const&); + +    SemanticGraph::Type* +    complex_type (XML::Element const&); + +    All* +    all (XML::Element const&); + +    Choice* +    choice (XML::Element const&, bool in_compositor); + +    Sequence* +    sequence (XML::Element const&, bool in_compositor); + +    void +    simple_content (XML::Element const&); + +    void +    complex_content (XML::Element const&, Complex&); + +    void +    simple_content_extension (XML::Element const&); + +    void +    simple_content_restriction (XML::Element const&); + +    void +    complex_content_extension (XML::Element const&, Complex&); + +    void +    complex_content_restriction (XML::Element const&, Complex&); + +    void +    element (XML::Element const&, bool global); + +    void +    attribute (XML::Element const&, bool global); + +    void +    attribute_group (XML::Element const&); + +    void +    any (XML::Element const&); + +    void +    any_attribute (XML::Element const&); + +  private: +    bool +    is_disabled (char const* warning) +    { +      return disabled_warnings_all_ || +        (disabled_warnings_ && +         disabled_warnings_->find (warning) != disabled_warnings_->end ()); +    } + +  private: +    bool +    more () const +    { +      iterator const& it (iteration_state_.top ()); + +      return it.l_->getLength () > it.i_; +    } + +    XML::Element +    next () +    { +      iterator& it (iteration_state_.top ()); + +      return XML::Element ( +        dynamic_cast<Xerces::DOMElement*> (it.l_->item (it.i_++))); +    } + +    void +    prev () +    { +      iterator& it (iteration_state_.top ()); + +      if (it.i_) +        --it.i_; +    } + +    void +    push (XML::Element const& e) +    { +      iteration_state_.push (e.dom_element ()); +    } + +    void +    pop () +    { +      iteration_state_.pop (); +    } + +  private: +    void +    push_scope (SemanticGraph::Scope& s) +    { +      scope_stack_.push (&s); +    } + +    void +    pop_scope () +    { +      scope_stack_.pop (); +    } + +    SemanticGraph::Scope& +    scope () const +    { +      return *(scope_stack_.top ()); +    } + +  private: +    void +    push_compositor (SemanticGraph::Compositor& c) +    { +      compositor_stack_.push (&c); +    } + +    void +    pop_compositor () +    { +      assert (!compositor_stack_.empty ()); +      compositor_stack_.pop (); +    } + +    SemanticGraph::Compositor& +    compositor () const +    { +      assert (!compositor_stack_.empty ()); +      return *(compositor_stack_.top ()); +    } + +  private: +    static unsigned long const unbounded = ~static_cast<unsigned long> (0); + +    unsigned long +    parse_min (String const& m) +    { +      if (m.empty ()) +        return 1; + +      unsigned long v; +      std::basic_istringstream<wchar_t> is (m); + +      is >> v; +      return v; +    } + +    unsigned long +    parse_max (String const& m) +    { +      if (m.empty ()) +        return 1; + +      if (m == L"unbounded") +        return unbounded; + +      unsigned long v; +      std::basic_istringstream<wchar_t> is (m); + +      is >> v; +      return v; +    } + +  private: +    SemanticGraph::Namespace& +    cur_ns () const +    { +      // Here I am using the fact that each Schema Names only one +      // Namespace. +      // +      return dynamic_cast<Namespace&> (cur_->names_begin ()->named ()); +    } + +  private: +    String +    unqualified_name (String const& n) +    { +      return XML::uq_name (n); +    } + +    String +    namespace_name (XML::Element const& e, String const& n) +    { +      try +      { +        String p (XML::prefix (n)); + +        // If we are currently handling a chameleon-included schema then +        // the empty prefix is logically translated into acquired target +        // namespace. +        // +        if (cur_chameleon_ && p.empty ()) +          return cur_ns ().name (); + +        // We have to try to resolve even the empty prefix since it can +        // be assigned to a namespace (which takes precedence over names +        // without a namespace). +        // +        return XML::ns_name (e.dom_element (), p); +      } +      catch (XML::NoMapping const& ex) +      { +        if (ex.prefix ().empty ()) +          return String (); +        else +          throw; +      } +    } + +    SemanticGraph::Type& +    ultimate_base (SemanticGraph::Type& t) +    { +      using namespace SemanticGraph; + +      Complex* c = dynamic_cast<Complex*> (&t); + +      if (c != 0 && c->inherits_p ()) +      { +        Type* b (&c->inherits ().base ()); + +        while (true) +        { +          Complex* cb (dynamic_cast<Complex*> (b)); + +          if (cb != 0 && cb->inherits_p ()) +          { +            b = &cb->inherits ().base (); +            continue; +          } + +          break; +        } + +        return *b; +      } +      else +        return t; +    } + +  private: +    template <typename Edge, typename Node> +    Edge* +    set_type (String const& type, XML::Element const& e, Node& node); + +  private: +    XML::PtrVector<Xerces::DOMDocument>* dom_docs_; + +    struct iterator +    { +      iterator (Xerces::DOMElement* e) +          : l_ (e->getChildNodes ()), i_ (0) +      { +      } + +      Xerces::DOMNodeList* l_; +      size_t i_; +    }; + +    std::stack<iterator> iteration_state_; +    SemanticGraph::Schema* s_;   // root schema file +    SemanticGraph::Schema* cur_; // current schema file +    bool cur_chameleon_;      // whethere cur_ is chameleon + +    SemanticGraph::Schema* xml_schema_; // XML Schema file +    SemanticGraph::Path xml_schema_path_; + +    // +    // +    std::stack<SemanticGraph::Scope*> scope_stack_; + +    // +    // +    std::stack<SemanticGraph::Compositor*> compositor_stack_; + + +    // Map of absolute file path and namespace pair to a Schema node. +    // +    struct SchemaId +    { +      SchemaId (SemanticGraph::Path const& path, String const& ns) +          : path_ (path), ns_ (ns) +      { +      } + + +      friend bool +      operator< (SchemaId const& x, SchemaId const& y) +      { +        return x.path_ < y.path_ || (x.path_ == y.path_ && x.ns_ < y.ns_); +      } + +    private: +      SemanticGraph::Path path_; +      String ns_; +    }; + + +    typedef std::map<SchemaId, SemanticGraph::Schema*> SchemaMap; +    SchemaMap schema_map_; + +    // Path stack for diagnostic. +    // +    struct PathPair +    { +      PathPair (SemanticGraph::Path const& r, SemanticGraph::Path const& a) +          : rel (r), abs (a) +      { +      } + +      SemanticGraph::Path rel, abs; +    }; + +    std::stack<PathPair> file_stack_; + +    SemanticGraph::Path const& +    file () +    { +      return file_stack_.top ().rel; +    } + +    SemanticGraph::Path const& +    abs_file () +    { +      return file_stack_.top ().abs; +    } + +    // Members with default/fixed values (needed for QName handling). +    // +    DefaultValues default_values_; + +  private: +    bool qualify_attribute_; +    bool qualify_element_; + +    bool valid_; + +    bool proper_restriction_; +    bool multiple_imports_; +    bool full_schema_check_; +    LocationTranslator* loc_translator_; +    const WarningSet* disabled_warnings_; +    bool disabled_warnings_all_; + +    NamespaceMap* cache_; +  }; + + +  Parser::Impl:: +  Impl (bool proper_restriction, +        bool multiple_imports, +        bool full_schema_check, +        LocationTranslator* t, +        const WarningSet* dw) +      : s_ (0), +        cur_ (0), +        cur_chameleon_ (false), +        xml_schema_path_ ("XMLSchema.xsd"), +        qualify_attribute_ (false), +        qualify_element_ (false), +        proper_restriction_ (proper_restriction), +        multiple_imports_ (multiple_imports), +        full_schema_check_ (full_schema_check), +        loc_translator_ (t), +        disabled_warnings_ (dw), +        disabled_warnings_all_ (false) +  { +    if (dw && dw->find ("all") != dw->end ()) +      disabled_warnings_all_ = true; + +    // Initialize the Xerces-C++ runtime. +    // +    Xerces::XMLPlatformUtils::Initialize (); +  } + +  Parser::Impl:: +  ~Impl () +  { +    // Terminate the Xerces-C++ runtime. +    // +    Xerces::XMLPlatformUtils::Terminate (); +  } + +  template<typename T> T& +  add_type (Schema& s, Namespace& ns, String name) +  { +    Path path ("XMLSchema.xsd"); +    T& node (s.new_node<T> (path, 0, 0)); +    s.new_edge<Names> (ns, node, name); + +    return node; +  } + +  void Parser::Impl:: +  fill_xml_schema (Schema& s, Path const& path) +  { +    Namespace& ns (s.new_node<Namespace> (path, 1, 1)); +    s.new_edge<Names> (s, ns, xsd); + +    // anyType and & anySimpleType +    // +    AnyType& any_type ( +      add_type<AnyType>                       (s, ns, L"anyType")); +    add_type<AnySimpleType>                   (s, ns, L"anySimpleType"); + +    // Integers. +    // +    add_type<Fundamental::Byte>               (s, ns, L"byte"); +    add_type<Fundamental::UnsignedByte>       (s, ns, L"unsignedByte"); +    add_type<Fundamental::Short>              (s, ns, L"short"); +    add_type<Fundamental::UnsignedShort>      (s, ns, L"unsignedShort"); +    add_type<Fundamental::Int>                (s, ns, L"int"); +    add_type<Fundamental::UnsignedInt>        (s, ns, L"unsignedInt"); +    add_type<Fundamental::Long>               (s, ns, L"long"); +    add_type<Fundamental::UnsignedLong>       (s, ns, L"unsignedLong"); +    add_type<Fundamental::Integer>            (s, ns, L"integer"); +    add_type<Fundamental::NonPositiveInteger> (s, ns, L"nonPositiveInteger"); +    add_type<Fundamental::NonNegativeInteger> (s, ns, L"nonNegativeInteger"); +    add_type<Fundamental::PositiveInteger>    (s, ns, L"positiveInteger"); +    add_type<Fundamental::NegativeInteger>    (s, ns, L"negativeInteger"); + +    // Boolean. +    // +    add_type<Fundamental::Boolean>            (s, ns, L"boolean"); + +    // Floats. +    // +    add_type<Fundamental::Float>              (s, ns, L"float"); +    add_type<Fundamental::Double>             (s, ns, L"double"); +    add_type<Fundamental::Decimal>            (s, ns, L"decimal"); + +    // Strings +    // +    add_type<Fundamental::String>             (s, ns, L"string"); +    add_type<Fundamental::NormalizedString>   (s, ns, L"normalizedString"); +    add_type<Fundamental::Token>              (s, ns, L"token"); +    add_type<Fundamental::Name>               (s, ns, L"Name"); +    add_type<Fundamental::NameToken>          (s, ns, L"NMTOKEN"); +    add_type<Fundamental::NameTokens>         (s, ns, L"NMTOKENS"); +    add_type<Fundamental::NCName>             (s, ns, L"NCName"); +    add_type<Fundamental::Language>           (s, ns, L"language"); + +    // ID/IDREF. +    // +    add_type<Fundamental::Id>                 (s, ns, L"ID"); + +    Fundamental::IdRef& id_ref ( +      s.new_node<Fundamental::IdRef> (path, 0, 0)); +    s.new_edge<Names> (ns, id_ref, L"IDREF"); +    s.new_edge<Arguments> (any_type, id_ref); + +    Fundamental::IdRefs& id_refs ( +      s.new_node<Fundamental::IdRefs> (path, 0, 0)); +    s.new_edge<Names> (ns, id_refs, L"IDREFS"); +    s.new_edge<Arguments> (any_type, id_refs); + +    // URI. +    // +    add_type<Fundamental::AnyURI>             (s, ns, L"anyURI"); + +    // Qualified name. +    // +    add_type<Fundamental::QName>              (s, ns, L"QName"); + +    // Binary. +    // +    add_type<Fundamental::Base64Binary>       (s, ns, L"base64Binary"); +    add_type<Fundamental::HexBinary>          (s, ns, L"hexBinary"); + +    // Date/time. +    // +    add_type<Fundamental::Date>               (s, ns, L"date"); +    add_type<Fundamental::DateTime>           (s, ns, L"dateTime"); +    add_type<Fundamental::Duration>           (s, ns, L"duration"); +    add_type<Fundamental::Day>                (s, ns, L"gDay"); +    add_type<Fundamental::Month>              (s, ns, L"gMonth"); +    add_type<Fundamental::MonthDay>           (s, ns, L"gMonthDay"); +    add_type<Fundamental::Year>               (s, ns, L"gYear"); +    add_type<Fundamental::YearMonth>          (s, ns, L"gYearMonth"); +    add_type<Fundamental::Time>               (s, ns, L"time"); + +    // Entity. +    // +    add_type<Fundamental::Entity>             (s, ns, L"ENTITY"); +    add_type<Fundamental::Entities>           (s, ns, L"ENTITIES"); + +    // Notation. +    // +    add_type<Fundamental::Notation>           (s, ns, L"NOTATION"); +  } + + +  auto_ptr<Schema> Parser::Impl:: +  xml_schema (Path const& tu) +  { +    valid_ = true; + +    auto_ptr<Schema> rs (new Schema (tu, 1, 1)); +    fill_xml_schema (*rs, tu); + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } +  auto_ptr<Schema> Parser::Impl:: +  parse (Path const& tu) +  { +    valid_ = true; +    schema_map_.clear (); +    default_values_.clear (); + +    XML::PtrVector<Xerces::DOMDocument> dom_docs; +    dom_docs_ = &dom_docs; + +    NamespaceMap cache; +    cache_ = &cache; + +    XML::AutoPtr<Xerces::DOMDocument> d (dom (tu, true)); + +    if (!d) +      throw InvalidSchema (); + +    XML::Element root (d->getDocumentElement ()); +    String ns (trim (root["targetNamespace"])); + +    if (trace_) +      wcout << "target namespace: " << ns << endl; + +    auto_ptr<Schema> rs (new Schema (tu, root.line (), root.column ())); + +    // Implied schema with fundamental types. +    // +    xml_schema_ = &rs->new_node<Schema> (xml_schema_path_, 1, 1); +    rs->new_edge<Implies> (*rs, *xml_schema_, xml_schema_path_); + +    fill_xml_schema (*xml_schema_, xml_schema_path_); + +    // Parse. +    // +    { +      // Enter the file into schema_map_. Do normalize() before +      // complete() to avoid hitting system path limits with '..' +      // directories. +      // +      Path abs_path (tu); +      abs_path.normalize ().complete (); +      schema_map_[SchemaId (abs_path, ns)] = rs.get (); +      rs->context ().set ("absolute-path", abs_path); + +      s_ = cur_ = rs.get (); +      { +        file_stack_.push (PathPair (tu, abs_path)); + +        { +          push_scope ( +            s_->new_node<Namespace> ( +              file (), root.line (), root.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (root); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      s_ = cur_ = 0; +    } + +    dom_docs_->push_back (d); + +    // Second pass to resolve forward references to types, elements, +    // attributes and groups. +    // +    if (valid_) +    { +      Traversal::Schema schema; + +      struct Uses: Traversal::Uses +      { +        virtual void +        traverse (Type& u) +        { +          Schema& s (u.schema ()); + +          if (!s.context ().count ("schema-resolved")) +          { +            s.context ().set ("schema-resolved", true); +            Traversal::Uses::traverse (u); +          } +        } +      } uses; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> uses >> schema; +      schema >> schema_names >> ns >> ns_names; + +      Resolver resolver (*rs, valid_, *cache_, default_values_); + +      struct AnonymousMember: Traversal::Attribute, +                              Traversal::Element, +                              Traversal::Member +      { +        AnonymousMember (Traversal::NodeDispatcher& d) +        { +          belongs_.node_traverser (d); +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          traverse_member (a); +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          traverse_member (e); +        } + +        void +        traverse_member (SemanticGraph::Member& m) +        { +          if (m.typed_p () && +              !m.type ().named_p () && +              !m.type ().context ().count ("seen")) +          { +            m.type().context ().set ("seen", true); + +            Traversal::Member::belongs (m, belongs_); + +            m.type ().context ().remove ("seen"); +          } +        } + +      private: +        Traversal::Belongs belongs_; +      } anonymous_member (resolver); + +      struct AnonymousBase: Traversal::Type +      { +        AnonymousBase (Traversal::NodeDispatcher& d) +            : base_ (d) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (!t.named_p ()) +            base_.dispatch (t); +        } + +      private: +        Traversal::NodeDispatcher& base_; +      } anonymous_base (resolver); + +      ns_names >> resolver; +      ns_names >> anonymous_member; + +      Traversal::Names names; +      Traversal::Inherits inherits; +      Traversal::Argumented argumented; +      resolver >> names >> resolver; +      names >> anonymous_member; +      resolver >> inherits >> anonymous_base; +      resolver >> argumented >> anonymous_base; + +      if (trace_) +        wcout << "starting resolution pass" << endl; + +      schema.dispatch (*rs); +    } + +    // Resolve default/fixed values of QName type. +    // +    if (valid_) +    { +      for (DefaultValues::const_iterator i (default_values_.begin ()), +             e (default_values_.end ()); i != e; ++i) +      { +        SemanticGraph::Member& m (**i); +        SemanticGraph::Type& t (m.type ()); +        SemanticGraph::Context& c (m.context ()); + +        if (ultimate_base (t).is_a<SemanticGraph::Fundamental::QName> ()) +        { +          String v (m.value ()); +          Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("dom-node")); + +          try +          { +            // We have to try to resolve even the empty prefix since it can +            // be assigned to a namespace (which takes precedence over names +            // without a namespace). +            // +            String ns (XML::ns_name (e, XML::prefix (v))); + +            if (m.fixed_p ()) +              m.fixed (ns + L'#' + v); +            else +              m.default_ (ns + L'#' + v); +          } +          catch (XML::NoMapping const& ex) +          { +            if (!ex.prefix ().empty ()) +            { +              wcerr << m.file () << ":" << m.line () << ":" << m.column () +                    << ": error: unable to resolve namespace for prefix '" +                    <<  ex.prefix () << "'" << endl; + +              valid_ = false; +            } +          } +        } + +        c.remove ("dom-node"); +      } +    } + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } + +  auto_ptr<Schema> Parser::Impl:: +  parse (Paths const& paths) +  { +    valid_ = true; +    schema_map_.clear (); +    default_values_.clear (); + +    XML::PtrVector<Xerces::DOMDocument> dom_docs; +    dom_docs_ = &dom_docs; + +    NamespaceMap cache; +    cache_ = &cache; + +    auto_ptr<Schema> rs (new Schema (Path (), 0, 0)); + +    // Implied schema with fundamental types. +    // +    xml_schema_ = &rs->new_node<Schema> (xml_schema_path_, 1, 1); +    rs->new_edge<Implies> (*rs, *xml_schema_, xml_schema_path_); + +    fill_xml_schema (*xml_schema_, xml_schema_path_); + +    // Parse individual schemas. +    // +    s_ = rs.get (); + +    for (Paths::const_iterator i (paths.begin ()); i != paths.end (); ++i) +    { +      Path const& tu (*i); +      XML::AutoPtr<Xerces::DOMDocument> d (dom (tu, true)); + +      if (!d) +        throw InvalidSchema (); + +      XML::Element root (d->getDocumentElement ()); +      String ns (trim (root["targetNamespace"])); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      // Check if we already have this schema. Do normalize() before +      // complete() to avoid hitting system path limits with '..' +      // directories. +      // +      Path abs_path (tu); +      abs_path.normalize ().complete (); +      SchemaId schema_id (abs_path, ns); + +      if (schema_map_.find (schema_id) != schema_map_.end ()) +        continue; + +      Schema& s (s_->new_node<Schema> (tu, root.line (), root.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); +      s_->new_edge<Imports> (*s_, s, tu); + +      // Enter the file into schema_map_. +      // +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      cur_ = &s; + +      { +        file_stack_.push (PathPair (tu, abs_path)); + +        { +          push_scope ( +            s_->new_node<Namespace> ( +              file (), root.line (), root.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (root); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_ = 0; + +      dom_docs_->push_back (d); + +      if (!valid_) +        break; +    } + +    s_ = 0; + +    // Second pass to resolve forward references to types, elements, +    // attributes and groups. +    // +    if (valid_) +    { +      Traversal::Schema schema; + +      struct Uses: Traversal::Uses +      { +        virtual void +        traverse (Type& u) +        { +          Schema& s (u.schema ()); + +          if (!s.context ().count ("schema-resolved")) +          { +            s.context ().set ("schema-resolved", true); +            Traversal::Uses::traverse (u); +          } +        } +      } uses; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> uses >> schema; +      schema >> schema_names >> ns >> ns_names; + +      Resolver resolver (*rs, valid_, *cache_, default_values_); + +      struct AnonymousMember: Traversal::Attribute, +                              Traversal::Element, +                              Traversal::Member +      { +        AnonymousMember (Traversal::NodeDispatcher& d) +        { +          belongs_.node_traverser (d); +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          traverse_member (a); +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          traverse_member (e); +        } + +        virtual void +        traverse_member (SemanticGraph::Member& m) +        { +          if (m.typed_p () && +              !m.type ().named_p () && +              !m.type ().context ().count ("seen")) +          { +            m.type().context ().set ("seen", true); + +            Traversal::Member::belongs (m, belongs_); + +            m.type ().context ().remove ("seen"); +          } +        } + +      private: +        Traversal::Belongs belongs_; +      } anonymous_member (resolver); + +      struct AnonymousBase: Traversal::Type +      { +        AnonymousBase (Traversal::NodeDispatcher& d) +            : base_ (d) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (!t.named_p ()) +            base_.dispatch (t); +        } + +      private: +        Traversal::NodeDispatcher& base_; +      } anonymous_base (resolver); + +      ns_names >> resolver; +      ns_names >> anonymous_member; + +      Traversal::Names names; +      Traversal::Inherits inherits; +      Traversal::Argumented argumented; +      resolver >> names >> resolver; +      names >> anonymous_member; +      resolver >> inherits >> anonymous_base; +      resolver >> argumented >> anonymous_base; + +      if (trace_) +        wcout << "starting resolution pass" << endl; + +      schema.dispatch (*rs); +    } + +    // Resolve default/fixed values of QName type. +    // +    if (valid_) +    { +      for (DefaultValues::const_iterator i (default_values_.begin ()), +             e (default_values_.end ()); i != e; ++i) +      { +        SemanticGraph::Member& m (**i); +        SemanticGraph::Type& t (m.type ()); +        SemanticGraph::Context& c (m.context ()); + +        if (ultimate_base (t).is_a<SemanticGraph::Fundamental::QName> ()) +        { +          String v (m.value ()); +          Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("dom-node")); + +          try +          { +            // We have to try to resolve even the empty prefix since it can +            // be assigned to a namespace (which takes precedence over names +            // without a namespace). +            // +            String ns (XML::ns_name (e, XML::prefix (v))); + +            if (m.fixed_p ()) +              m.fixed (ns + L'#' + v); +            else +              m.default_ (ns + L'#' + v); +          } +          catch (XML::NoMapping const& ex) +          { +            if (!ex.prefix ().empty ()) +            { +              wcerr << m.file () << ":" << m.line () << ":" << m.column () +                    << ": error: unable to resolve namespace for prefix '" +                    <<  ex.prefix () << "'" << endl; + +              valid_ = false; +            } +          } +        } + +        c.remove ("dom-node"); +      } +    } + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } + +  void Parser::Impl:: +  schema (XML::Element const& s) +  { +    bool old_qa (qualify_attribute_); +    bool old_qe (qualify_element_); + +    if (String af = trim (s["attributeFormDefault"])) +      qualify_attribute_ = af == L"qualified"; +    else +      qualify_attribute_ = false; + +    if (String ef = trim (s["elementFormDefault"])) +      qualify_element_ = ef == L"qualified"; +    else +      qualify_element_ = false; + +    push (s); + +    // Parse leading annotation if any and add it as an annotation for +    // this schema. +    // +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, *cur_); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      if (name == L"import")         import (e);               else +      if (name == L"include")        include (e);              else +      if (name == L"element")        element (e, true);        else +      if (name == L"attribute")      attribute (e, true);      else +      if (name == L"simpleType")     simple_type (e);          else +      if (name == L"annotation");                              else +      if (name == L"complexType")    complex_type (e);         else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected top-level element: '" << name << "'" +              << endl; + +        valid_ = false; +      } +    } + +    pop (); + +    qualify_attribute_ = old_qa; +    qualify_element_ = old_qe; +  } + +  void Parser::Impl:: +  import (XML::Element const& i) +  { +    NarrowString loc ( +      trim ( +        XML::transcode_to_narrow ( +          i.dom_element ()->getAttribute ( +            XML::XMLChString ("schemaLocation").c_str ())))); + +    if (loc_translator_) +      loc = loc_translator_->translate (loc); + +    String ins (trim (i["namespace"])); + +    // Ignore empty <import>. +    // +    if (!loc && !ins) +      return; + +    Path path, rel_path, abs_path; +    try +    { +      path = Path (loc); + +      if (path.absolute ()) +      { +        abs_path = rel_path = path; +        abs_path.normalize (); +      } +      else +      { +        // Do normalize() before complete() to avoid hitting system path +        // limits with '..' directories. +        // +        abs_path = rel_path = file ().directory () / path; +        abs_path.normalize ().complete (); +      } +    } +    catch (InvalidPath const&) +    { +      wcerr << file () << ":" << i.line () << ":" << i.column () << ": " +            << "error: '" << loc.c_str () << "' is not a valid " +            << "filesystem path" << endl; + +      valid_ = false; +      return; +    } + +    SchemaId schema_id (abs_path, ins); + +    if (schema_map_.find (schema_id) != schema_map_.end ()) +    { +      s_->new_edge<Imports> (*cur_, *schema_map_[schema_id], path); +      return; +    } + +    if (trace_) +      wcout << "importing " << rel_path << endl; + +    if (XML::AutoPtr<Xerces::DOMDocument> d  = dom (abs_path, false)) +    { +      XML::Element r (d->getDocumentElement ()); +      String ns (trim (r["targetNamespace"])); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      Schema& s (s_->new_node<Schema> (rel_path, r.line (), r.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); +      s_->new_edge<Imports> (*cur_, s, path); + +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      Schema* old_cur (cur_); +      bool old_cur_chameleon (cur_chameleon_); +      cur_ = &s; +      cur_chameleon_ = false; + +      { +        file_stack_.push (PathPair (rel_path, abs_path)); + +        { +          push_scope ( +            s_->new_node<Namespace> (file (), r.line (), r.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (r); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_chameleon_ = old_cur_chameleon; +      cur_ = old_cur; + +      dom_docs_->push_back (d); +    } +  } + +  void Parser::Impl:: +  include (XML::Element const& i) +  { +    NarrowString loc ( +      trim ( +        XML::transcode_to_narrow ( +          i.dom_element ()->getAttribute ( +            XML::XMLChString ("schemaLocation").c_str ())))); + +    if (loc_translator_) +      loc = loc_translator_->translate (loc); + +    Path path, rel_path, abs_path; +    try +    { +      path = Path (loc); + +      if (path.absolute ()) +      { +        abs_path = rel_path = path; +        abs_path.normalize (); +      } +      else +      { +        // Do normalize() before complete() to avoid hitting system path +        // limits with '..' directories. +        // +        abs_path = rel_path = file ().directory () / path; +        abs_path.normalize ().complete (); +      } +    } +    catch (InvalidPath const&) +    { +      wcerr << file () << ":" << i.line () << ":" << i.column () << ": " +            << "error: '" << loc.c_str () << "' is not a valid " +            << "filesystem path" << endl; + +      valid_ = false; +      return; +    } + +    // Included schema should have the same namespace as ours. +    // +    SchemaId schema_id (abs_path, cur_ns ().name ()); + +    if (schema_map_.find (schema_id) != schema_map_.end ()) +    { +      Schema& s (*schema_map_[schema_id]); + +      // Chemeleon inclusion results in a new Schema node for every +      // namespace. As a result, such a Schema node can only be +      // Source'ed. I use this property to decide which edge to use. +      // + +      if (s.used_p () && s.used_begin ()->is_a<Sources> ()) +        s_->new_edge<Sources> (*cur_, s, path); +      else +        s_->new_edge<Includes> (*cur_, s, path); + +      return; +    } + +    if (trace_) +      wcout << "including " << rel_path << endl; + +    if (XML::AutoPtr<Xerces::DOMDocument> d  = dom (abs_path, false)) +    { +      XML::Element r (d->getDocumentElement ()); +      String ns (trim (r["targetNamespace"])), cur_ns; + +      Schema& s (s_->new_node<Schema> (rel_path, r.line (), r.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); + +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      bool chameleon (false); + +      if (ns.empty () && !(cur_ns = (cur_->names_begin ())->name ()).empty ()) +      { +        // Chameleon. +        // +        ns = cur_ns; +        s_->new_edge<Sources> (*cur_, s, path); +        chameleon = true; + +        if (trace_) +          wcout << "handling chameleon schema" << endl; +      } +      else +        s_->new_edge<Includes> (*cur_, s, path); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      Schema* old_cur (cur_); +      bool old_cur_chameleon (cur_chameleon_); +      cur_ = &s; +      cur_chameleon_ = chameleon; + +      { +        file_stack_.push (PathPair (rel_path, abs_path)); + +        { +          push_scope ( +            s_->new_node<Namespace> (file (), r.line (), r.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (r); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_chameleon_ = old_cur_chameleon; +      cur_ = old_cur; + +      dom_docs_->push_back (d); +    } +  } + +  void Parser::Impl:: +  element_group (XML::Element const& g, bool in_compositor) +  { +    if (String name = trim (g["name"])) +    { +      ElementGroup& group ( +        s_->new_node<ElementGroup> (file (), g.line (), g.column ())); + +      s_->new_edge<Names> (scope (), group, name); + +      push_scope (group); +      push (g); + +      annotation (false); + +      XML::Element e (next ()); + +      name = e.name (); + +      if (trace_) +        wcout << name << endl; + +      Compositor* c (0); + +      if (name == L"all")      c = all (e);             else +      if (name == L"choice")   c = choice (e, false);   else +      if (name == L"sequence") c = sequence (e, false); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'all', 'choice' or 'sequence' " +              << "instead of '" << name << "'" << endl; + +        valid_ = false; +      } + +      // Group's immediate compositor always has cardinality 1,1. +      // +      if (c) +        s_->new_edge<ContainsCompositor> (group, *c, 1, 1); + +      pop (); +      pop_scope (); +    } +    else if (String ref = trim (g["ref"])) +    { +      if (trace_) +        wcout << "element-group-ref " << ref << endl; + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (g, ref)); + +        // In order to avoid code duplication we are going to let the +        // resolver handle this case. +        // +        if (trace_) +          wcout << "deferring resolution of group name '" << uq_name +                << "' inside namespace '" << ns_name << "'" +                << " until later" << endl; + +        if (in_compositor) +        { +          Compositor& c (compositor ()); + +          unsigned long min (parse_min (trim (g["minOccurs"]))); +          unsigned long max (parse_max (trim (g["maxOccurs"]))); + +          ElementGroupRef ref ( +            uq_name, ns_name, +            min, +            max == unbounded ? 0 : max, +            c, +            scope ()); + +          if (!c.context ().count ("element-group-refs")) +            c.context ().set ("element-group-refs", ElementGroupRefs ()); + +          c.context ().get<ElementGroupRefs> ( +            "element-group-refs").push_back (ref); +        } +        else +        { +          // This is a group-ref directly in complexType. +          // + +          Scope& s (scope ()); + +          unsigned long min (parse_min (trim (g["minOccurs"]))); +          unsigned long max (parse_max (trim (g["maxOccurs"]))); + +          ElementGroupRef ref ( +            uq_name, ns_name, min, max == unbounded ? 0 : max, s); + +          s.context ().set ("element-group-ref", ref); +        } +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; + +          abort (); +        } +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +              << "error: unable to resolve namespace prefix '" << ex.prefix () +              << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +            << "error: 'name' or 'ref' attribute is missing in group " +            << "declaration" << endl; + +      valid_ = false; + +      return; +    } +  } + +  //@@ Need RAII for push/pop. +  // + +  Type* Parser::Impl:: +  simple_type (XML::Element const& t) +  { +    Type* r (0); + +    push (t); + +    Annotation* a (annotation (true)); + +    XML::Element e (next ()); + +    String name (e.name ()); + +    if (name == L"list") r = list (e, t); else +    if (name == L"union") r = union_ (e, t); else +    if (name == L"restriction") r = restriction (e, t); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'list', 'union', or 'restriction' " +            << "instead of '" << name << "'" << endl; + +      valid_ = false; +    } + +    if (r != 0 && a != 0) +      s_->new_edge<Annotates> (*a, *r); + +    pop (); + +    return r; +  } + +  SemanticGraph::Type* Parser::Impl:: +  list (XML::Element const& l, XML::Element const& t) +  { +    if (trace_) +      wcout << "list" << endl; + +    List& node (s_->new_node<List> (file (), t.line (), t.column ())); + +    if (String item_type = trim (l["itemType"])) +    { +      if (trace_) +        wcout << "item type: " << fq_name (l, item_type) << endl; + +      set_type<Arguments> (item_type, l, node); +    } +    else +    { +      // Anonymous list item type. +      // +      push (l); + +      annotation (false); + +      if (more ()) +      { +        XML::Element e (next ()); + +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        Type* t (0); + +        if (name == L"simpleType")  t = simple_type (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } + +        if (t) +          s_->new_edge<Arguments> (*t, node); +      } +      else +      { +        wcerr << file () << ":" << l.line () << ":" << l.column () << ": " +              << "error: expected 'itemType' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      pop (); +    } + +    if (String name = trim (t["name"])) +      s_->new_edge<Names> (scope (), node, name); + +    return &node; +  } + +  namespace +  { +    // +    // List parsing utility functions. +    // + +    // Find first non-space character. +    // +    size_t +    find_ns (const wchar_t* s, size_t size, size_t pos) +    { +      while (pos < size && +             (s[pos] == 0x20 || // space +              s[pos] == 0x0D || // carriage return +              s[pos] == 0x09 || // tab +              s[pos] == 0x0A)) +        ++pos; + +      return pos < size ? pos : String::npos; +    } + +    // Find first space character. +    // +    size_t +    find_s (const wchar_t* s, size_t size, size_t pos) +    { +      while (pos < size && +             s[pos] != 0x20 && // space +             s[pos] != 0x0D && // carriage return +             s[pos] != 0x09 && // tab +             s[pos] != 0x0A) +        ++pos; + +      return pos < size ? pos : String::npos; +    } +  } + +  SemanticGraph::Type* Parser::Impl:: +  union_ (XML::Element const& u, XML::Element const& t) +  { +    if (trace_) +      wcout << "union" << endl; + +    Union& node (s_->new_node<Union> (file (), t.line (), t.column ())); + +    bool has_members (false); + +    if (String members = trim (u["memberTypes"])) +    { +      // Don't bother trying to resolve member types at this point +      // since the order is important so we would have to insert +      // the late resolutions into specific places. It is simpler +      // to just do the whole resolution later. +      // +      const wchar_t* data (members.c_str ()); +      size_t size (members.size ()); + +      UnionMemberTypes* m (0); + +      // Traverse the type list while logically collapsing spaces. +      // +      for (size_t i (find_ns (data, size, 0)); i != String::npos;) +      { +        String s; +        size_t j (find_s (data, size, i)); + +        if (j != String::npos) +        { +          s = String (data + i, j - i); +          i = find_ns (data, size, j); +        } +        else +        { +          // Last item. +          // +          s = String (data + i, size - i); +          i = String::npos; +        } + +        if (trace_) +          wcout << "member type: " << fq_name (u, s) << endl; + +        if (m == 0) +        { +          node.context ().set ("union-member-types", UnionMemberTypes ()); +          m = &node.context ().get<UnionMemberTypes> ("union-member-types"); +        } + +        try +        { +          m->push_back ( +            UnionMemberType ( +              namespace_name (u, s), unqualified_name (s))); +        } +        catch (XML::NoMapping const& ex) +        { +          wcerr << file () << ":" << u.line () << ":" << u.column () << ": " +                << "error: unable to resolve namespace prefix " +                << "'" << ex.prefix () << "' in '" << s << "'" << endl; + +          valid_ = false; +        } +      } + +      has_members = (m != 0); +    } + +    // Handle anonymous members. +    // +    push (u); + +    annotation (false); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      Type* t (0); + +      if (name == L"simpleType")  t = simple_type (e);  else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'simpleType' instead of " +              << "'" << e.name () << "'" << endl; + +        valid_ = false; +      } + +      if (t) +        s_->new_edge<Arguments> (*t, node); +    } + +    pop (); + +    if (node.argumented_begin () == node.argumented_end () && !has_members) +    { +      wcerr << file () << ":" << u.line () << ":" << u.column () << ": " +            << "error: expected 'memberTypes' attribute or 'simpleType' " +            << "nested element" << endl; + +      valid_ = false; +    } + +    if (String name = trim (t["name"])) +      s_->new_edge<Names> (scope (), node, name); + +    return &node; +  } + +  Type* Parser::Impl:: +  restriction (XML::Element const& r, XML::Element const& t) +  { +    String base (trim (r["base"])); +    Type* base_type (0); + +    if (base) +    { +      if (trace_) +        wcout << "restriction base: " << fq_name (r, base) << endl; +    } + +    Type* rv (0); + +    push (r); + +    annotation (false); + +    bool enum_ (false); + +    if (!base) +    { +      // Anonymous base type. +      // +      if (more ()) +      { +        XML::Element e (next ()); + +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"simpleType")  base_type = simple_type (e); else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } +      } +      else +      { +        wcerr << file () << ":" << r.line () << ":" << r.column () << ": " +              << "error: expected 'base' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      if (!valid_) +      { +        pop (); +        return 0; +      } +    } + +    Facets facets; +    Restricts* restricts (0); +    String pattern; + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"enumeration") +      { +        // Enumeration +        // +        if (enum_) +          enumeration (e); +        else +        { +          // First +          // +          enum_ = true; + +          Enumeration& node ( +            s_->new_node<Enumeration> (file (), t.line (), t.column ())); + +          if (base_type) +            restricts = &s_->new_edge<Restricts> (node, *base_type); +          else +            restricts = set_type<Restricts> (base, r, node); + +          if (String name = trim (t["name"])) +            s_->new_edge<Names> (scope (), static_cast<Nameable&> (node), name); + +          rv = &node; +          push_scope (node); +          enumeration (e); +        } +      } +      else if (name == L"minExclusive" || +               name == L"minInclusive" || +               name == L"maxExclusive" || +               name == L"maxInclusive" || +               name == L"totalDigits" || +               name == L"fractionDigits" || +               name == L"length" || +               name == L"minLength" || +               name == L"maxLength" || +               name == L"whiteSpace") +      { +        facets[name] = trim (e["value"]); +      } +      else if (name == L"pattern") +      { +        if (pattern) +          pattern += L'|'; + +        pattern += e["value"]; +      } +      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "' in " +              << "simple type restriction" << endl; + +        valid_ = false; +      } +    } + +    if (pattern) +      facets[L"pattern"] = pattern; + +    if (enum_) +      pop_scope (); +    else +    { +      Complex& node (s_->new_node<Complex> (file (), t.line (), t.column ())); + +      if (base_type) +        restricts = &s_->new_edge<Restricts> (node, *base_type); +      else +        restricts = set_type<Restricts> (base, r, node); + +      if (String name = trim (t["name"])) +        s_->new_edge<Names> (scope (), node, name); + +      rv = &node; +    } + +    if (!facets.empty ()) +    { +      if (restricts) +        copy_facets (*restricts, facets); +      else +        rv->context ().set ("facets", facets); +    } + +    pop (); + +    return rv; +  } + +  void Parser::Impl:: +  enumeration (XML::Element const& e) +  { +    String value (e["value"]); + +    if (trace_) +      wcout << "enumeration value: " << value << endl; + +    push (e); +    Annotation* a (annotation (true)); +    pop (); + +    Enumerator& node ( +      s_->new_node<Enumerator> (file (), e.line (), e.column ())); + +    s_->new_edge<Names> (scope (), node, value); +    s_->new_edge<Belongs> (node, dynamic_cast<Type&>(scope ())); + +    if (a != 0) +      s_->new_edge<Annotates> (*a, node); + +  } + +  Type* Parser::Impl:: +  complex_type (XML::Element const& t) +  { +    Type* r (0); + +    Complex& node (s_->new_node<Complex> (file (), t.line (), t.column ())); + +    if (String m = trim (t["mixed"])) +      node.mixed_p (m == L"true" || m == L"1"); + +    if (String name = trim (t["name"])) +      s_->new_edge<Names> (scope (), node, name); + +    r = &node; + +    push_scope (node); +    push (t); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    if (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      if (name == L"simpleContent")  simple_content (e);        else +      if (name == L"complexContent") complex_content (e, node); else +      { +        Compositor* c (0); + +        if (name == L"all")            c = all (e);              else +        if (name == L"choice")         c = choice (e, false);    else +        if (name == L"sequence")       c = sequence (e, false);  else +        if (name == L"attribute")      attribute (e, false);     else +        if (name == L"anyAttribute")   any_attribute (e);        else +        if (name == L"group")          element_group (e, false); else +        if (name == L"attributeGroup") attribute_group (e);      else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: unexpected element '" << name << "'" << endl; + +          valid_ = false; +        } + +        if (c) +        { +          unsigned long min (parse_min (trim (e["minOccurs"]))); +          unsigned long max (parse_max (trim (e["maxOccurs"]))); + +          if (!(min == 0 && max == 0)) +            s_->new_edge<ContainsCompositor> ( +              node, *c, min, max == unbounded ? 0 : max); +        } + +        while (more ()) +        { +          XML::Element e (next ()); +          String name (e.name ()); + +          if (name == L"attribute")      attribute (e, false); else +          if (name == L"anyAttribute")   any_attribute (e);    else +          if (name == L"attributeGroup") attribute_group (e);  else +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: expected 'attribute', 'anyAttribute', or " +                  << "'attributeGroup' instead of '" << name << "'" << endl; + +            valid_ = false; +          } +        } +      } +    } + +    pop (); +    pop_scope (); + +    return r; +  } + +  All* Parser::Impl:: +  all (XML::Element const& a) +  { +    // 'all' cannot be nested inside 'choice' or 'sequence', nor +    //  can it contain any of those. The only valid  cardinality +    //  values for 'all' are min=0,1 and max=1. +    // +    All& node (s_->new_node<All> (file (), a.line (), a.column ())); + +    push_compositor (node); +    push (a); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"element") element (e, false); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'element' " +              << "instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  Choice* Parser::Impl:: +  choice (XML::Element const& c, bool in_compositor) +  { +    Choice& node (s_->new_node<Choice> (file (), c.line (), c.column ())); + +    if (in_compositor) +    { +      unsigned long min (parse_min (trim (c["minOccurs"]))); +      unsigned long max (parse_max (trim (c["maxOccurs"]))); + +      if (!(min == 0 && max == 0)) +        s_->new_edge<ContainsParticle> ( +          compositor (), node, min, max == unbounded ? 0 : max); +    } + +    push_compositor (node); +    push (c); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"any")      any (e);                 else +      if (name == L"choice")   choice (e, true);        else +      if (name == L"element")  element (e, false);      else +      if (name == L"sequence") sequence (e, true);      else +      if (name == L"group")    element_group (e, true); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'any', 'group', 'choice', 'sequence', " +              << "or 'element' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  Sequence* Parser::Impl:: +  sequence (XML::Element const& s, bool in_compositor) +  { +    Sequence& node (s_->new_node<Sequence> (file (), s.line (), s.column ())); + +    if (in_compositor) +    { +      unsigned long min (parse_min (trim (s["minOccurs"]))); +      unsigned long max (parse_max (trim (s["maxOccurs"]))); + +      if (!(min == 0 && max == 0)) +        s_->new_edge<ContainsParticle> ( +          compositor (), node, min, max == unbounded ? 0 : max); +    } + +    push_compositor (node); +    push (s); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"any")      any (e);                 else +      if (name == L"choice")   choice (e, true);        else +      if (name == L"element")  element (e, false);      else +      if (name == L"sequence") sequence (e, true);      else +      if (name == L"group")    element_group (e, true); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'any', 'group', 'choice', 'sequence', " +              << "or 'element' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  void Parser::Impl:: +  simple_content (XML::Element const& c) +  { +    push (c); + +    annotation (false); + +    XML::Element e (next ()); +    String name (e.name ()); + +    if (name == L"extension")   simple_content_extension (e);   else +    if (name == L"restriction") simple_content_restriction (e); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'extension' or 'restriction' instead of " +            << "'" << name << "'" << endl; + +      valid_ = false; +    } + +    pop (); +  } + +  void Parser::Impl:: +  complex_content (XML::Element const& c, Complex& type) +  { +    if (String m = trim (c["mixed"])) +      type.mixed_p (m == L"true" || m == L"1"); + +    push (c); + +    annotation (false); + +    XML::Element e (next ()); +    String name (e.name ()); + +    if (name == L"extension")   complex_content_extension (e, type);   else +    if (name == L"restriction") complex_content_restriction (e, type); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'extension' or 'restriction' instead of " +            << "'" << name << "'" << endl; + +      valid_ = false; +    } + +    pop (); +  } + +  void Parser::Impl:: +  simple_content_extension (XML::Element const& e) +  { +    if (trace_) +      wcout << "extension base: " << fq_name (e, e["base"]) << endl; + +    set_type<Extends> (trim (e["base"]), e, dynamic_cast<Complex&> (scope ())); + +    push (e); + +    annotation (false); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"attribute")      attribute (e, false); else +      if (name == L"anyAttribute")   any_attribute (e);    else +      if (name == L"attributeGroup") attribute_group (e);  else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'attribute', 'anyAttribute', or " +              << "'attributeGroup' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +  } + +  void Parser::Impl:: +  simple_content_restriction (XML::Element const& r) +  { +    String base (trim (r["base"])); + +    if (trace_ && base) +      wcout << "restriction base: " << fq_name (r, base) << endl; + +    push (r); +    annotation (false); + +    if (!base) +    { +      // Anonymous base type. +      // +      if (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"simpleType") simple_type (e); else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } +      } +      else +      { +        wcerr << file () << ":" << r.line () << ":" << r.column () << ": " +              << "error: expected 'base' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      if (!valid_) +      { +        pop (); +        return; +      } +    } + +    Facets facets; +    String pattern; + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"simpleType") +      { +        // This is a "superimposed" restriction where the base +        // content is restricted by specifying another simple +        // type. The attributes are restricted in the ussual +        // way. So in effect we have kind of two base classes. +        // I guess the way to handle this one day would be to +        // copy all the facets from the base-to-this-type +        // part of the hierarchy (will need to "know" facets +        // for the built-in type restrictions as well). For +        // now just ignore it. +        // +      } +      else if (name == L"enumeration") +      { +        // Right now our sementic graph cannot represent enumerations +        // with attributes so we are going to ignore enumerators for +        // now. +        // +      } +      else if (name == L"minExclusive" || +               name == L"minInclusive" || +               name == L"maxExclusive" || +               name == L"maxInclusive" || +               name == L"totalDigits" || +               name == L"fractionDigits" || +               name == L"length" || +               name == L"minLength" || +               name == L"maxLength" || +               name == L"whiteSpace") +      { +        facets[name] = trim (e["value"]); +      } +      else if (name == L"pattern") +      { +        if (pattern) +          pattern += L'|'; + +        pattern += e["value"]; +      } +      else if (name == L"attribute") +      { +        if (proper_restriction_) +          attribute (e, false); +      } +      else if (name == L"anyAttribute") +      { +        if (proper_restriction_) +          any_attribute (e); +      } +      else if (name == L"attributeGroup") +      { +        if (proper_restriction_) +          attribute_group (e); +      } +      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "' in " +              << "simple content restriction" << endl; + +        valid_ = false; +      } +    } + +    if (pattern) +      facets[L"pattern"] = pattern; + +    Complex& type (dynamic_cast<Complex&> (scope ())); +    Restricts* restricts = set_type<Restricts> (base, r, type); + +    if (!facets.empty ()) +    { +      if (restricts) +        copy_facets (*restricts, facets); +      else +        type.context ().set ("facets", facets); +    } + +    pop (); +  } + +  void Parser::Impl:: +  complex_content_extension (XML::Element const& e, Complex& type) +  { +    if (trace_) +      wcout << "extension base: " << fq_name (e, e["base"]) << endl; + +    set_type<Extends> (trim (e["base"]), e, dynamic_cast<Complex&> (scope ())); + +    push (e); + +    annotation (false); + +    if (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); +      Compositor* c (0); + +      if (name == L"all")            c = all (e);              else +      if (name == L"choice")         c = choice (e, false);    else +      if (name == L"sequence")       c = sequence (e, false);  else +      if (name == L"attribute")      attribute (e, false);     else +      if (name == L"anyAttribute")   any_attribute (e);        else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "'" << endl; + +        valid_ = false; +      } + +      if (c) +      { +        unsigned long min (parse_min (trim (e["minOccurs"]))); +        unsigned long max (parse_max (trim (e["maxOccurs"]))); + +        if (!(min == 0 && max == 0)) +          s_->new_edge<ContainsCompositor> ( +            type, *c, min, max == unbounded ? 0 : max); +      } + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } +    } + +    pop (); +  } + +  void Parser::Impl:: +  complex_content_restriction (XML::Element const& e, Complex& type) +  { +    if (trace_) +      wcout << "restriction base: " << fq_name (e, e["base"]) << endl; + +    set_type<Restricts> ( +      trim (e["base"]), +      e, +      dynamic_cast<Complex&> (scope ())); + +    // @@ +    // For now we simply skip the contents unless the base is anyType +    // (or a trivial alias thereof). Checking for the trivial alias +    // is further complicated by the fact that it might not be defined +    // at this stage (forward inheritnace) so we will ignore that case +    // as well for now. +    // +    if (!proper_restriction_) +    { +      String base (trim (e["base"])); +      String uq_name (unqualified_name (base)); +      String ns_name (namespace_name (e, base)); + +      if (ns_name != xsd || uq_name != L"anyType") +        return; +    } + +    push (e); + +    annotation (false); + +    if (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); +      Compositor* c (0); + +      if (name == L"all")            c = all (e);              else +      if (name == L"choice")         c = choice (e, false);    else +      if (name == L"sequence")       c = sequence (e, false);  else +      if (name == L"attribute")      attribute (e, false);     else +      if (name == L"anyAttribute")   any_attribute (e);        else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "'" << endl; + +        valid_ = false; +      } + +      if (c) +      { +        unsigned long min (parse_min (trim (e["minOccurs"]))); +        unsigned long max (parse_max (trim (e["maxOccurs"]))); + +        if (!(min == 0 && max == 0)) +          s_->new_edge<ContainsCompositor> ( +            type, *c, min, max == unbounded ? 0 : max); +      } + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } +    } + +    pop (); +  } + +  void Parser::Impl:: +  element (XML::Element const& e, bool global) +  { +    bool qualified (global ? true : qualify_element_); + +    if (String form = trim (e["form"])) +      qualified = form == L"qualified"; + +    if (trace_) +      wcout << "element qualified: " << qualified << endl; + +    if (String name = trim (e["name"])) +    { +      if (trace_) +        wcout << "element name '" << name << "'" << endl; + +      Element& node ( +        s_->new_node<Element> ( +          file (), e.line (), e.column (), global, qualified)); + +      if (!global) +      { +        unsigned long min (parse_min (trim (e["minOccurs"]))); +        unsigned long max (parse_max (trim (e["maxOccurs"]))); + +        if (!(min == 0 && max == 0)) +        { +          s_->new_edge<Names> (scope (), node, name); + +          s_->new_edge<ContainsParticle> ( +            compositor (), node, min, max == unbounded ? 0 : max); +        } +      } +      else +        s_->new_edge<Names> (scope (), node, name); + +      if (qualified) +        s_->new_edge<BelongsToNamespace> (node, cur_ns ()); + +      // Default and fixed values are mutually exclusive. +      // +      if (e.attribute_p ("fixed")) +        node.fixed (e.attribute ("fixed")); +      else if (e.attribute_p ("default")) +        node.default_ (e.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", e.dom_element ()); +        default_values_.push_back (&node); +      } + +      bool subst (false); +      if (global) +      { +        if (String sg = trim (e["substitutionGroup"])) +        { +          if (trace_) +            wcout << "substitutes " << sg << endl; + +          subst = true; + +          try +          { +            String uq_name (unqualified_name (sg)); +            String ns_name (namespace_name (e, sg)); + +            node.context ().set ("substitution-ns-name", ns_name); +            node.context ().set ("substitution-uq-name", uq_name); +          } +          catch (XML::NoMapping const& ex) +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: unable to resolve namespace prefix '" +                  << ex.prefix () << "' in '" << sg << "'" << endl; + +            valid_ = false; +          } +        } +      } + +      if (String type = trim (e["type"])) +      { +        if (trace_) +          wcout << "element type " << fq_name (e, type) << endl; + +        set_type<Belongs> (type, e, node); + +        // Parse annotation. +        // +        push (e); + +        if (Annotation* a = annotation (true)) +          s_->new_edge<Annotates> (*a, node); + +        pop (); +      } +      else +      { +        // Looks like an anonymous type. +        // +        push (e); + +        if (Annotation* a = annotation (true)) +          s_->new_edge<Annotates> (*a, node); + +        if (more ()) +        { +          XML::Element e (next ()); + +          String name (e.name ()); + +          if (trace_) +            wcout << name << endl; + +          Type* t (0); + +          if (name == L"simpleType")  t = simple_type (e);  else +          if (name == L"complexType") t = complex_type (e); else +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: expected 'simpleType' or 'complexType' " +                  << "instead of '" << e.name () << "'" << endl; + +            valid_ = false; +          } + +          if (t) +            s_->new_edge<Belongs> (node, *t); +        } +        // By default the type is anyType unless this element is a +        // member of a substitution group, in which case it has the +        // same type as the element it substiutes. +        // +        else if (!subst) +        { +          if (!is_disabled ("F001")) +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "warning F001: element '" << name << "' is implicitly " +                  << "of anyType" << endl; + +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "info: did you forget to specify 'type' attribute?" +                  << endl; +          } + +          String prefix (ns_prefix (e, xsd)); +          type =  prefix + (prefix.empty () ? L"" : L":") + L"anyType"; + +          set_type<Belongs> (type, e, node); +        } + +        pop (); +      } +    } +    else if (String ref = trim (e["ref"])) +    { +      Element& node ( +        s_->new_node<Element> ( +          file (), e.line (), e.column (), true, true)); + +      unsigned long min (parse_min (trim (e["minOccurs"]))); +      unsigned long max (parse_max (trim (e["maxOccurs"]))); + +      // Default and fixed values are mutually exclusive. +      // +      if (e.attribute_p ("fixed")) +        node.fixed (e.attribute ("fixed")); +      else if (e.attribute_p ("default")) +        node.default_ (e.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", e.dom_element ()); +        default_values_.push_back (&node); +      } + +      // Parse annotation. +      // +      push (e); + +      if (Annotation* a = annotation (true)) +        s_->new_edge<Annotates> (*a, node); + +      pop (); + +      if (!(min == 0 && max == 0)) +      { +        // Ref can only be in compositor. +        // +        s_->new_edge<ContainsParticle> ( +          compositor (), node, min, max == unbounded ? 0 : max); + +        // Try to resolve the prototype. +        // +        try +        { +          String uq_name (unqualified_name (ref)); +          String ns_name (namespace_name (e, ref)); + +          s_->new_edge<Names> (scope (), node, uq_name); + +          Element& prot (resolve<Element> (ns_name, uq_name, *s_, *cache_)); +          s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); + +          // Copy substitution group information if any. +          // +          if (prot.context ().count ("substitution-ns-name")) +          { +            node.context ().set ( +              "substitution-ns-name", +              prot.context ().get<String> ("substitution-ns-name")); + +            node.context ().set ( +              "substitution-uq-name", +              prot.context ().get<String> ("substitution-uq-name")); +          } + +          // Transfer default and fixed values if the ref declaration hasn't +          // defined its own. +          // +          if (!node.default_p ()) +          { +            if (prot.fixed_p ()) +              node.fixed (prot.value ()); +            else if (prot.default_p ()) +              node.default_ (prot.value ()); + +            if (node.default_p ()) +            { +              node.context ().set ( +                "dom-node", +                prot.context ().get<Xerces::DOMElement*> ("dom-node")); +              default_values_.push_back (&node); +            } +          } + +          // Transfer annotation if the ref declaration hasn't defined its own. +          // +          if (!node.annotated_p () && prot.annotated_p ()) +            s_->new_edge<Annotates> (prot.annotation (), node); + +          // Set type information. +          // +          if (prot.typed_p ()) +          { +            s_->new_edge<Belongs> (node, prot.type ()); +          } +          else if (prot.context ().count ("type-ns-name")) +          { +            String ns_name (prot.context ().get<String> ("type-ns-name")); +            String uq_name (prot.context ().get<String> ("type-uq-name")); + +            node.context ().set ("type-ns-name", ns_name); +            node.context ().set ("type-uq-name", uq_name); +            node.context ().set ("edge-type-id", type_id (typeid (Belongs))); + +            if (trace_) +              wcout << "element '" << ref << "' is not typed" << endl +                    << "deferring resolution until later" << endl; +          } +          else +          { +            // This could be a recursive reference to an element who's +            // (anonymous) type is being defined. We are going to let +            // resolver sort out this case. +            // +            node.context ().set ("instance-ns-name", ns_name); +            node.context ().set ("instance-uq-name", uq_name); + +            if (trace_) +              wcout << "looks like a recursive reference to an element '" +                    << ns_name << "#" << uq_name << "' which is being " +                    << "defined" << endl +                    << "deferring resolution until later" << endl; +          } +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; + +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          node.context ().set ("instance-ns-name", ex.ns ()); +          node.context ().set ("instance-uq-name", ex.name ()); + +          if (trace_) +            wcout << "unable to resolve name '" << ex.name () +                  << "' inside namespace '" << ex.ns () << "'" << endl +                  << "deferring resolution until later" << endl; +        } +        catch (XML::NoMapping const& ex) +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: unable to resolve namespace prefix '" +                << ex.prefix () << "' in '" << ref << "'" << endl; + +          valid_ = false; +        } +      } +    } +    else +    { +      if (valid_) +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: 'name' or 'ref' attribute is missing in element " +              << "declaration" << endl; +      } +    } +  } + +  SemanticGraph::Annotation* Parser::Impl:: +  annotation (bool process) +  { +    Annotation* r (0); + +    if (more ()) +    { +      XML::Element e (next ()); + +      if (e.name () == L"annotation") +      { +        if (process) +        { +          push (e); + +          while (more ()) +          { +            XML::Element doc (next ()); + +            if (doc.name () == L"documentation") +            { +              using Xerces::DOMNode; +              using Xerces::DOMText; +              using Xerces::DOMElement; + +              // Use first non-structured (text only) documentation element. +              // +              String text; +              bool struc (false); +              DOMElement* de (doc.dom_element()); + +              for (DOMNode* n (de->getFirstChild ()); +                   n != 0 && !struc; +                   n = n->getNextSibling ()) +              { +                switch (n->getNodeType ()) +                { +                case DOMNode::TEXT_NODE: +                case DOMNode::CDATA_SECTION_NODE: +                  { +                    DOMText* t (static_cast<DOMText*> (n)); +                    text += XML::transcode (t->getData ()); +                    break; +                  } +                case DOMNode::ELEMENT_NODE: +                  { +                    struc = true; +                    break; +                  } +                default: +                  break; // ignore +                } +              } + +              if (struc) +                continue; + +              r = &s_->new_node<Annotation> ( +                file (), e.line (), e.column (), text); +              break; +            } +          } + +          pop (); +        } +      } +      else +        prev (); +    } + +    return r; +  } + + +  void Parser::Impl:: +  attribute (XML::Element const& a, bool global) +  { +    bool optional (true); + +    String use (trim (a["use"])); + +    if (use == L"prohibited") +      return; +    else if (use == L"required") +      optional = false; + +    bool qualified (global ? true : qualify_attribute_); + +    if (String form = trim (a["form"])) +      qualified = form == L"qualified"; + +    if (String name = trim (a["name"])) +    { +      if (trace_) +        wcout << "attribute '" << name << "'" << endl; + +      Attribute& node ( +        s_->new_node<Attribute> ( +          file (), a.line (), a.column (), optional, global, qualified)); + +      s_->new_edge<Names> (scope (), node, name); + +      if (qualified) +        s_->new_edge<BelongsToNamespace> (node, cur_ns ()); + + +      // Default and fixed values are mutually exclusive. +      // +      if (a.attribute_p ("fixed")) +        node.fixed (a.attribute ("fixed")); +      else if (a.attribute_p ("default")) +        node.default_ (a.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", a.dom_element ()); +        default_values_.push_back (&node); +      } + +      if (String type = trim (a["type"])) +      { +        if (trace_) +          wcout << "attribute type: '" << fq_name (a, type) << "'" << endl; + +        set_type<Belongs> (type, a, node); + +        // Parse annotation. +        // +        push (a); + +        if (Annotation* ann = annotation (true)) +          s_->new_edge<Annotates> (*ann, node); + +        pop (); +      } +      else +      { +        // Looks like an anonymous type. +        // +        push (a); + +        if (Annotation* ann = annotation (true)) +          s_->new_edge<Annotates> (*ann, node); + +        if (more ()) +        { +          XML::Element e (next ()); + +          String name (e.name ()); + +          if (trace_) +            wcout << name << endl; + +          Type* t (0); + +          if (name == L"simpleType") t = simple_type (e); else +          { +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "error: expected 'simpleType' instead of '" << e.name () +                  << "'" << endl; + +            valid_ = false; +          } + +          if (t) +            s_->new_edge<Belongs> (node, *t); +        } +        else +        { +          if (!is_disabled ("F002")) +          { +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "warning F002: attribute '" << name << "' is implicitly " +                  << "of anySimpleType" << endl; + +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "info: did you forget to specify 'type' attribute?" +                  << endl; +          } + +          // anySimpleType +          // +          String prefix (ns_prefix (a, xsd)); +          type =  prefix + (prefix.empty () ? L"" : L":") + L"anySimpleType"; + +          set_type<Belongs> (type, a, node); +        } + +        pop (); +      } +    } +    else if (String ref = trim (a["ref"])) +    { +      Attribute& node ( +        s_->new_node<Attribute> ( +          file (), a.line (), a.column (), optional, true, true)); + + +      // Default and fixed values are mutually exclusive. +      // +      if (a.attribute_p ("fixed")) +        node.fixed (a.attribute ("fixed")); +      else if (a.attribute_p ("default")) +        node.default_ (a.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", a.dom_element ()); +        default_values_.push_back (&node); +      } + +      // Parse annotation. +      // +      push (a); + +      if (Annotation* ann = annotation (true)) +        s_->new_edge<Annotates> (*ann, node); + +      pop (); + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (a, ref)); + +        s_->new_edge<Names> (scope (), node, uq_name); + +        Attribute& prot (resolve<Attribute> (ns_name, uq_name, *s_, *cache_)); +        s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); + +        // Transfer default and fixed values if the ref declaration hasn't +        // defined its own. +        // +        if (!node.default_p ()) +        { +          // Default value applies only if this attribute is optional. +          // +          if (prot.fixed_p ()) +            node.fixed (prot.value ()); +          else if (optional && prot.default_p ()) +            node.default_ (prot.value ()); + +          if (node.default_p ()) +          { +            node.context ().set ( +              "dom-node", +              prot.context ().get<Xerces::DOMElement*> ("dom-node")); +            default_values_.push_back (&node); +          } +        } + +        // Transfer annotation if the ref declaration hasn't defined its own. +        // +        if (!node.annotated_p () && prot.annotated_p ()) +          s_->new_edge<Annotates> (prot.annotation (), node); + +        // Set type. +        // +        if (prot.typed_p ()) +        { +          s_->new_edge<Belongs> (node, prot.type ()); +        } +        else if (prot.context ().count ("type-ns-name")) +        { +          String ns_name (prot.context ().get<String> ("type-ns-name")); +          String uq_name (prot.context ().get<String> ("type-uq-name")); + +          node.context ().set ("type-ns-name", ns_name); +          node.context ().set ("type-uq-name", uq_name); +          node.context ().set ("edge-type-id", type_id (typeid (Belongs))); + +          if (trace_) +            wcout << "attribute '" << ref << "' is not typed" << endl +                  << "deferring resolution until later" << endl; +        } +        else +        { +          // This could be a recursive reference to an attribute who's +          // (anonymous) type is being defined. We are going to let +          // resolver sort out this case. +          // +          node.context ().set ("instance-ns-name", ns_name); +          node.context ().set ("instance-uq-name", uq_name); + +          if (trace_) +            wcout << "looks like a recursive reference to an attribute '" +                  << ns_name << "#" << uq_name << "' which is being " +                  << "defined" << endl +                  << "deferring resolution until later" << endl; +        } +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; +          abort (); +        } +      } +      catch (NotName const& ex) +      { +        node.context ().set ("instance-ns-name", ex.ns ()); +        node.context ().set ("instance-uq-name", ex.name ()); + +        if (trace_) +          wcout << "unable to resolve name '" << ex.name () +                << "' inside namespace '" << ex.ns () << "'" << endl +                << "deferring resolution until later" << endl; +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +              << "error: unable to resolve namespace prefix '" +              << ex.prefix () << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      if (valid_) +      { +        wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +              << "error: 'name' or 'ref' attribute is missing in attribute " +              << "declaration" << endl; +      } +    } +  } + +  void Parser::Impl:: +  attribute_group (XML::Element const& g) +  { +    if (String name = trim (g["name"])) +    { +      // Global definition. +      // +      if (trace_) +        wcout << "attributeGroup '" << name << "'" << endl; + +      AttributeGroup& group ( +        s_->new_node<AttributeGroup> (file (), g.line (), g.column ())); +      s_->new_edge<Names> (scope (), group, name); + +      push_scope (group); +      push (g); + +      annotation (false); + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } + +      pop (); +      pop_scope (); +    } +    else if (String ref = trim (g["ref"])) +    { +      if (trace_) +        wcout << "attribute-group-ref " << ref << endl; + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (g, ref)); + +        // In order to avoid code duplication we are going to let the +        // resolver handle this case. +        // +        if (trace_) +          wcout << "deferring resolution of group name '" << uq_name +                << "' inside namespace '" << ns_name << "'" +                << " until later" << endl; + +        Scope& s (scope ()); +        AttributeGroupRef ref (uq_name, ns_name, s); + +        if (!s.context ().count ("attribute-group-refs")) +          s.context ().set ("attribute-group-refs", AttributeGroupRefs ()); + +        s.context ().get<AttributeGroupRefs> ( +          "attribute-group-refs").push_back (ref); +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; +          abort (); +        } +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +              << "error: unable to resolve namespace prefix '" +              << ex.prefix () << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +            << "error: 'name' or 'ref' attribute is missing in " +            << "attributeGroup declaration" << endl; + +      valid_ = false; +      return; +    } +  } + +  void Parser::Impl:: +  any (XML::Element const& a) +  { +    if (trace_) +      wcout << "any" << endl; + +    String namespaces (trim (a["namespace"])); + +    if (!namespaces) +      namespaces = L"##any"; + +    Any& any ( +      s_->new_node<Any> (file (), a.line (), a.column (), namespaces)); + +    unsigned long min (parse_min (trim (a["minOccurs"]))); +    unsigned long max (parse_max (trim (a["maxOccurs"]))); + +    // Parse annotation. +    // +    push (a); + +    if (Annotation* ann = annotation (true)) +      s_->new_edge<Annotates> (*ann, any); + +    pop (); + +    if (!(min == 0 && max == 0)) +    { +      s_->new_edge<ContainsParticle> ( +        compositor (), any, min, max == unbounded ? 0 : max); + +      // Any has no name so we have to come up with a fake one in order to +      // put it into the scope. +      // +      unsigned long count; +      SemanticGraph::Context& ctx (scope ().context ()); + +      if (!ctx.count ("any-name-count")) +      { +        count = 0; +        ctx.set ("any-name-count", count); +      } +      else +        count = ++(ctx.get<unsigned long> ("any-name-count")); + +      std::basic_ostringstream<wchar_t> os; +      os << "any #" << count; + +      s_->new_edge<Names> (scope (), any, os.str ()); +    } +  } + +  void Parser::Impl:: +  any_attribute (XML::Element const& a) +  { +    if (trace_) +      wcout << "anyAttribute" << endl; + +    String namespaces (trim (a["namespace"])); + +    if (!namespaces) +      namespaces = L"##any"; + +    AnyAttribute& any ( +      s_->new_node<AnyAttribute> ( +        file (), a.line (), a.column (), namespaces)); + +    // Parse annotation. +    // +    push (a); + +    if (Annotation* ann = annotation (true)) +      s_->new_edge<Annotates> (*ann, any); + +    pop (); + +    // AnyAttribute has no name so we have to come up with a fake one +    // in order to put it into the scope. +    // + +    unsigned long count; +    SemanticGraph::Context& ctx (scope ().context ()); + +    if (!ctx.count ("any-attribute-name-count")) +    { +      count = 0; +      ctx.set ("any-attribute-name-count", count); +    } +    else +      count = ++(ctx.get<unsigned long> ("any-attribute-name-count")); + +    std::basic_ostringstream<wchar_t> os; +    os << "any-attribute #" << count; + +    s_->new_edge<Names> (scope (), any, os.str ()); +  } + +  // Some specializations to get edge orientations right. +  // + +  template <typename Edge, typename Node> +  struct Orientation +  { +    static Edge& +    set_edge (Schema& s, Node& node, Type& type) +    { +      // By default it is node->edge +      // +      return s.template new_edge<Edge> (node, type); +    } +  }; + +  template <typename Node> +  struct Orientation<Arguments, Node> +  { +    static Arguments& +    set_edge (Schema& s, Node& node, Type& type) +    { +      // For Arguments it is type->node. +      // +      return s.template new_edge<Arguments> (type, node); +    } +  }; + +  template <typename Edge, typename Node> +  Edge* Parser::Impl:: +  set_type (String const& type, XML::Element const& e, Node& node) +  { +    Edge* r (0); + +    try +    { +      String uq_name (unqualified_name (type)); +      String ns_name (namespace_name (e, type)); + +      Type& t (resolve<Type> (ns_name, uq_name, *s_, *cache_)); + +      // See if it is an IDREF specialization. +      // +      if (ns_name == xsd && (uq_name == L"IDREF" || uq_name == L"IDREFS")) +      { +        // See if we've got 'xse:refType' attribute. +        // +        if (String ref_type = trim (e.attribute (xse, "refType"))) +        { +          if (trace_) +            wcout << "found refType attribute '" << ref_type << "'" << endl; + +          //@@ It is a bit wasteful to create a new spcialization for +          //   each refType. Instead we could lookup the target type +          //   and then navigate through Arguments edges to see if this +          //   type already arguments specialization that we are intersted +          //   in. But for now I will simplify the logic by creating a new +          //   specialization every time. +          // + +          Specialization* spec (0); + +          if (uq_name == L"IDREF") +            spec = &s_->new_node<Fundamental::IdRef> ( +              file (), e.line (), e.column ()); +          else +            spec = &s_->new_node<Fundamental::IdRefs> ( +              file (), e.line (), e.column ()); + +          r = &Orientation<Edge, Node>::set_edge (*s_, node, *spec); + +          set_type<Arguments> (ref_type, e, *spec); +        } +        else +          r = &Orientation<Edge, Node>::set_edge (*s_, node, t); +      } +      else +        r = &Orientation<Edge, Node>::set_edge (*s_, node, t); +    } +    catch (NotNamespace const& ex) +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: unable to resolve namespace '" << ex.ns () << "'" +            << endl; + +      valid_ = false; + +    } +    catch (NotName const& ex) +    { +      node.context ().set ("type-ns-name", ex.ns ()); +      node.context ().set ("type-uq-name", ex.name ()); +      node.context ().set ("edge-type-id", type_id (typeid (Edge))); + +      if (trace_) +        wcout << "unable to resolve name '" << ex.name () +              << "' inside namespace '" << ex.ns () << "'" << endl +              << "deferring resolution until later" << endl; +    } +    catch (XML::NoMapping const& ex) +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: unable to resolve namespace prefix " +            << "'" << ex.prefix () << "' in '" << type << "'" << endl; + +      valid_ = false; +    } + +    return r; +  } + +  // Xerces has a provision to associate a public id with input streams +  // that can later be used in diagnostics. Unfortunately, it doesn't +  // work. So we will have to keep our own track. +  // +  struct Context +  { +    Context () {} + +    // File map for diagnostic. +    // +    Path const& +    file (Path const& abs) const +    { +      FileMap::const_iterator i (file_map_.find (abs)); + +      if (i != file_map_.end ()) +      { +        return i->second; +      } +      else +      { +        return abs; +      } +    } + +    void +    map_file (Path const& abs, Path const& rel) +    { +      file_map_[abs] = rel; +    } + +  private: +    Context (Context const&); +    Context& operator= (Context const&); + +  private: +    typedef std::map<Path, Path> FileMap; +    FileMap file_map_; +  }; + +  // +  // +  class ErrorHandler : public  Xerces::DOMErrorHandler +  { +  public: +    ErrorHandler (bool& valid, XSDFrontend::Context const& ctx) +        : valid_ (valid), +          ctx_ (ctx) +    { +    } + +    virtual bool +    handleError (Xerces::DOMError const& e) +    { +      // Xerces likes to say "Fatal error encountered during schema scan". +      // We don't need this junk. +      // +      if (!valid_ +          && e.getLocation ()->getLineNumber () == 0 +          && e.getLocation ()->getColumnNumber () == 0) +        return true; + + +      XSDFrontend::SemanticGraph::Path abs_path ( +        XML::transcode_to_narrow (e.getLocation ()->getURI ())); + +      XSDFrontend::SemanticGraph::Path rel_path (ctx_.file (abs_path)); + +      wcerr << rel_path << ':' +            << e.getLocation ()->getLineNumber () << ':' +            << e.getLocation ()->getColumnNumber () << ": "; + +      switch (e.getSeverity ()) +      { +      case Xerces::DOMError::DOM_SEVERITY_WARNING: +        { +          wcerr << "warning: "; +          break; +        } +      default: +        { +          wcerr << "error: "; +          valid_ = false; +          break; +        } +      } + +      wcerr << e.getMessage () << endl; + +      return true; +    } + +  private: +    bool& valid_; +    XSDFrontend::Context const& ctx_; +  }; + + +  // Failed to open resource. +  // +  struct Open {}; + +  class InputSource: public Xerces::InputSource +  { +  public: +    InputSource ( +      Path const& abs, +      Path const& rel, +      Path const& base, +      XSDFrontend::Context const& ctx, +      Xerces::MemoryManager* mm = Xerces::XMLPlatformUtils::fgMemoryManager) +        : Xerces::InputSource (mm), +          abs_ (abs), +          rel_ (rel), +          base_ (base), +          ctx_ (ctx) +    { +      setSystemId (XML::XMLChString (String (abs_.string ())).c_str ()); +    } + +    virtual Xerces::BinInputStream* +    makeStream () const +    { +      using namespace Xerces; + +      BinFileInputStream* is ( +        new (getMemoryManager ()) +        BinFileInputStream (getSystemId (), getMemoryManager ())); + +      if (!is->getIsOpen ()) +      { +        delete is; + +        wcerr << ctx_.file (base_) << ": error: " +              << "'" << rel_ << "': unable to open in read mode" +              << endl; + +        throw Open (); +      } + +      return is; +    } + +  private: +    Path abs_; +    Path rel_; +    Path base_; +    XSDFrontend::Context const& ctx_; +  }; + + +  class EntityResolver: public Xerces::XMemory, +                        public Xerces::DOMLSResourceResolver +  { +  public: +    EntityResolver (XSDFrontend::Context& ctx, LocationTranslator* t) +        : ctx_ (ctx), loc_translator_ (t) +    { +    } + +    virtual Xerces::DOMLSInput* +    resolveResource(XMLCh const* const, +                    XMLCh const* const, +                    XMLCh const* const /*pub_id*/, +                    XMLCh const* const prv_id, +                    XMLCh const* const base_uri) +    { +      /* +      XMLCh empty[1]; +      empty[0] = 0; + +      wcerr << "resolve entity:" << endl +            << "  pub_id " << (pub_id ? pub_id : empty) << endl +            << "  prv_id " << (prv_id ? prv_id : empty) << endl +            << "     uri " << (base_uri ? base_uri : empty) << endl; +      */ + +      // base_uri should be a valid path by now. +      // +      Path base (XML::transcode_to_narrow (base_uri)); + +      if (prv_id == 0) +      { +        //@@ How can I get the line/column numbers for this? +        // +        wcerr << ctx_.file (base) << ": error: " +              << "unable to guess which schema to open" +              << endl; + +        wcerr << ctx_.file (base) << ": info: " +              << "did you forget to specify schemaLocation for import/include?" +              << endl; + +        throw Open (); +      } + +      NarrowString path_str (XML::transcode_to_narrow (prv_id)); + +      if (loc_translator_) +        path_str = loc_translator_->translate (path_str); + +      try +      { +        Path path (path_str); +        Path base_dir (base.directory ()); + +        Path abs_path, rel_path; + +        if (path.absolute ()) +        { +          abs_path = rel_path = path; +        } +        else +        { +          abs_path = base_dir / path; +          rel_path = ctx_.file (base).directory () / path; +        } + +        abs_path.normalize (); + +        ctx_.map_file (abs_path, rel_path); + +        using namespace Xerces; + +        InputSource* is ( +          new (XMLPlatformUtils::fgMemoryManager) +          InputSource (abs_path, rel_path, base, ctx_)); + +        // Note that I can't use XMLPlatformUtils::fgMemoryManager here +        // since Wrapper4InputSource is-not-an XMemory. +        // +        return new Wrapper4InputSource (is); +      } +      catch (InvalidPath const&) +      { +        wcerr << ctx_.file (base) << ": error: " +              << "'" << path_str.c_str () << "' is not a valid filesystem path" +              << endl; +        throw; +      } + +      // Will never reach. +      // +      return 0; +    } + +  private: +    XSDFrontend::Context& ctx_; +    LocationTranslator* loc_translator_; +  }; + + +  XML::AutoPtr<Xerces::DOMDocument> Parser::Impl:: +  dom (Path const& tu, bool validate) +  { +    using namespace Xerces; + +    try +    { +      XSDFrontend::Context ctx; + +      // Do normalize() before complete() to avoid hitting system path +      // limits with '..' directories. +      // +      Path abs_path (tu); +      abs_path.normalize ().complete (); +      ctx.map_file (abs_path, tu); + +      InputSource input_source (abs_path, tu, abs_path, ctx); + +      // First validate the schema with Xerces. +      // +      if (validate) +      { +        // Instantiate the DOM parser. +        // +        XMLCh const gLS[] = {chLatin_L, chLatin_S, chNull }; + +        // Get an implementation of the Load-Store (LS) interface. +        // +        DOMImplementationLS* impl ( +          static_cast<DOMImplementationLS*> ( +            DOMImplementationRegistry::getDOMImplementation (gLS))); + +        // Create a DOMBuilder. +        // +        XML::AutoPtr<DOMLSParser> parser ( +          impl->createLSParser (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + +        DOMConfiguration* conf (parser->getDomConfig ()); + +        conf->setParameter (XMLUni::fgDOMComments, false); +        conf->setParameter (XMLUni::fgDOMDatatypeNormalization, true); +        conf->setParameter (XMLUni::fgDOMEntities, false); +        conf->setParameter (XMLUni::fgDOMNamespaces, true); +        conf->setParameter (XMLUni::fgDOMValidate, true); +        conf->setParameter (XMLUni::fgDOMElementContentWhitespace, false); +        conf->setParameter (XMLUni::fgXercesSchema, true); + +        // Xerces-C++ 3.1.0 is the first version with working multi import +        // support. +        // +#if _XERCES_VERSION >= 30100 +        conf->setParameter (XMLUni::fgXercesHandleMultipleImports, multiple_imports_); +#endif + +        conf->setParameter (XMLUni::fgXercesSchemaFullChecking, full_schema_check_); +        conf->setParameter (XMLUni::fgXercesValidationErrorAsFatal, true); + +        ErrorHandler eh (valid_, ctx); +        conf->setParameter (XMLUni::fgDOMErrorHandler, &eh); + +        EntityResolver er (ctx, loc_translator_); +        conf->setParameter (XMLUni::fgDOMResourceResolver, &er); + +        Wrapper4InputSource wrap (&input_source, false); +        parser->loadGrammar (&wrap, Grammar::SchemaGrammarType); +      } + +      if (!valid_) +        return XML::AutoPtr<DOMDocument> (0); + +      // Now do our own parsing. +      // +      std::auto_ptr<XML::SchemaDOMParser> xsd_parser ( +        new (XMLPlatformUtils::fgMemoryManager) XML::SchemaDOMParser ()); + +      xsd_parser->parse (input_source); + +      XML::AutoPtr<DOMDocument> doc (xsd_parser->adoptDocument()); + +      return doc; +    } +    catch (Xerces::XMLException const& e) +    { +      wcerr << tu << ": ice: Xerces::XMLException: " << e.getMessage () +            << endl; + +      abort (); +    } +    catch (Xerces::DOMException const& e) +    { +      size_t const size = 2047; +      XMLCh text[size + 1]; + +      wcerr << tu << ": ice: Xerces::DOMException: "; + +      if (DOMImplementation::loadDOMExceptionMsg (e.code, text, size)) +        wcerr << text << endl; +      else +        wcerr << "no message available, error code: " << e.code << endl; + +      abort (); +    } +    catch (InvalidPath const&) +    { +      // Diagnostics has already been issued. +      // +      valid_ = false; +    } +    catch (Open const&) +    { +      // Diagnostics has already been issued. +      // +      valid_ = false; +    } + +    return XML::AutoPtr<DOMDocument> (0); +  } + +  // LocationTranslator +  // +  LocationTranslator:: +  ~LocationTranslator () +  { +  } + +  // Parser +  // +  Parser:: +  ~Parser () +  { +  } + +  Parser:: +  Parser (bool proper_restriction, +          bool multiple_imports, +          bool full_schema_check) +      : impl_ (new Impl (proper_restriction, +                         multiple_imports, +                         full_schema_check, +                         0, +                         0)) +  { +  } + +  Parser:: +  Parser (bool proper_restriction, +          bool multiple_imports, +          bool full_schema_check, +          LocationTranslator& t, +          const WarningSet& d) +      : impl_ (new Impl (proper_restriction, +                         multiple_imports, +                         full_schema_check, +                         &t, +                         &d)) +  { +  } + +  auto_ptr<SemanticGraph::Schema> Parser:: +  parse (SemanticGraph::Path const& path) +  { +    return impl_->parse (path); +  } + +  auto_ptr<SemanticGraph::Schema> Parser:: +  parse (SemanticGraph::Paths const& paths) +  { +    return impl_->parse (paths); +  } + +  auto_ptr<SemanticGraph::Schema> Parser:: +  xml_schema (SemanticGraph::Path const& path) +  { +    return impl_->xml_schema (path); +  } +} diff --git a/libxsd-frontend/xsd-frontend/parser.hxx b/libxsd-frontend/xsd-frontend/parser.hxx new file mode 100644 index 0000000..746aa97 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/parser.hxx @@ -0,0 +1,78 @@ +// file      : xsd-frontend/parser.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_PARSER_HXX +#define XSD_FRONTEND_PARSER_HXX + +#include <set> +#include <memory> // std::auto_ptr + +#include <xsd-frontend/types.hxx> +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  struct InvalidSchema {}; + +  class LocationTranslator +  { +  public: +    virtual +    ~LocationTranslator (); + +    virtual NarrowString +    translate (NarrowString const& location) = 0; +  }; + +  // Set of disabled warning IDs. Special ID "all" disables all +  // warnings. +  // +  typedef std::set<NarrowString> WarningSet; + +  class Parser +  { +  public: +    ~Parser (); + +    Parser (bool proper_restriction, +            bool multiple_imports, +            bool full_schema_check); + +    Parser (bool proper_restriction, +            bool multiple_imports, +            bool full_schema_check, +            LocationTranslator&, +            const WarningSet& disabled); + +  private: +    Parser (Parser const&); +    Parser& operator= (Parser const&); + +  public: +    // Parse a schema file. Throws InvalidSchema in case of a failure. +    // +    std::auto_ptr<SemanticGraph::Schema> +    parse (SemanticGraph::Path const&); + +    // Parse a number of schema files all into one semantic graph. +    // Each schema file is imported from an unnamed root translation +    // unit. Throws InvalidSchema in case of a failure. +    // +    std::auto_ptr<SemanticGraph::Schema> +    parse (SemanticGraph::Paths const&); + +    // Returns a schema graph that corresponds to the XML Schema +    // namespace with built-in type definitions. The path is fake +    // and is only used as a lable. +    // +    std::auto_ptr<SemanticGraph::Schema> +    xml_schema (SemanticGraph::Path const&); + +  private: +    class Impl; +    std::auto_ptr<Impl> impl_; +  }; +} + +#endif  // XSD_FRONTEND_PARSER_HXX diff --git a/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx b/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx new file mode 100644 index 0000000..73a0f83 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx @@ -0,0 +1,173 @@ +// file      : xsd-frontend/schema-dom-parser.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/schema-dom-parser.hxx> + +#include <xercesc/dom/DOMDocument.hpp> +#include <xercesc/dom/DOMElement.hpp> +#include <xercesc/dom/DOMAttr.hpp> +#include <xercesc/dom/DOMText.hpp> + +#include <xercesc/framework/XMLValidityCodes.hpp> +#include <xercesc/validators/schema/SchemaSymbols.hpp> + +#include <xercesc/util/XMLString.hpp> + +#include <xercesc/internal/XMLScanner.hpp> +#include <xercesc/internal/ElemStack.hpp> + +namespace XSDFrontend +{ +  namespace XML +  { +    using namespace Xerces; + +    const XMLCh line_key[2] = {chLatin_l, chNull}; +    const XMLCh column_key[2] = {chLatin_c, chNull}; + +    SchemaDOMParser:: +    SchemaDOMParser (MemoryManager* mgr) +        : XercesDOMParser(0, mgr, 0), +          depth_ (-1), +          ann_depth_ (-1), +          inner_ann_depth_ (-1) +    { +      error_reporter_.setErrorReporter (this); +      setValidationScheme (XercesDOMParser::Val_Never); +      setDoNamespaces (true); +    } + +    void SchemaDOMParser:: +    startElement (const XMLElementDecl& decl, +                  const unsigned int url_id, +                  const XMLCh* const prefix, +                  const RefVectorOf<XMLAttr>& attributes, +                  const XMLSize_t attr_count, +                  const bool empty, +                  const bool root) +    { +      depth_++; + +      if (ann_depth_ == -1) +      { +        if (XMLString::equals(decl.getBaseName(), +                              SchemaSymbols::fgELT_ANNOTATION) && +            XMLString::equals(getURIText(url_id), +                              SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) +        { +          ann_depth_ = depth_; +        } +      } +      else if (depth_ == ann_depth_ + 1) +      { +        inner_ann_depth_ = depth_; +      } + +      XercesDOMParser::startElement ( +        decl, url_id, prefix, attributes, attr_count, false, root); + +      // Set the line/column info. +      // +      ReaderMgr::LastExtEntityInfo info; +      ((ReaderMgr*) fScanner->getLocator())->getLastExtEntityInfo(info); + +      unsigned long l (static_cast<unsigned long> (info.lineNumber)); +      unsigned long c (static_cast<unsigned long> (info.colNumber)); + +      fCurrentNode->setUserData (line_key, reinterpret_cast<void*> (l), 0); +      fCurrentNode->setUserData (column_key, reinterpret_cast<void*> (c), 0); + +      // If an empty element, call the endElement() now. +      // +      if (empty) +        endElement (decl, url_id, root, prefix); +    } + +    void SchemaDOMParser:: +    endElement (const XMLElementDecl& decl, +                const unsigned int url_id, +                const bool root, +                const XMLCh* const prefix) +    { +      if(ann_depth_ > -1) +      { +        if (inner_ann_depth_ == depth_) +        { +          inner_ann_depth_ = -1; +        } +        else if (ann_depth_ == depth_) +        { +          ann_depth_ = -1; +        } +      } + +      depth_--; + +      XercesDOMParser::endElement (decl, url_id, root, prefix); +    } + +    void SchemaDOMParser:: +    docCharacters (const XMLCh* const s, +                   const XMLSize_t length, +                   const bool cdata) +    { +      // Ignore chars outside of content. +      // +      if (!fWithinElement) +        return; + +      if (inner_ann_depth_ == -1) +      { +        if (!((ReaderMgr*) fScanner->getReaderMgr())->getCurrentReader()-> +            isAllSpaces(s, length)) +        { +          ReaderMgr::LastExtEntityInfo lastInfo; +          fScanner->getReaderMgr()->getLastExtEntityInfo(lastInfo); +          locator_.setValues(lastInfo.systemId, lastInfo.publicId, +                             lastInfo.lineNumber, lastInfo.colNumber); +          error_reporter_.emitError(XMLValid::NonWSContent, +                                    XMLUni::fgValidityDomain, +                                    &locator_); +        } +      } +      else +      { +        // When it's within either of the 2 annotation sub-elements, +        // characters are allowed and we need to store them. +        // +        XercesDOMParser::docCharacters (s, length, cdata); +      } +    } + +    void SchemaDOMParser:: +    docComment (const XMLCh* const) +    { +      // We don't want any comments. +    } + +    void SchemaDOMParser:: +    startEntityReference (const XMLEntityDecl&) +    { +    } + +    void SchemaDOMParser:: +    endEntityReference (const XMLEntityDecl&) +    { +    } + +    void SchemaDOMParser:: +    ignorableWhitespace (const XMLCh* const s, +                         const XMLSize_t length, +                         const bool cdata) +    { +      // Ignore chars before the root element. +      // +      if (!fWithinElement || !fIncludeIgnorableWhitespace) +        return; + +      if (ann_depth_ > -1) +        XercesDOMParser::ignorableWhitespace (s, length, cdata); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx b/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx new file mode 100644 index 0000000..344065a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx @@ -0,0 +1,82 @@ +// file      : xsd-frontend/schema-dom-parser.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX +#define XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX + +#include <xercesc/parsers/XercesDOMParser.hpp> + +#include <xercesc/dom/DOMElement.hpp> + +#include <xercesc/validators/schema/XSDLocator.hpp> +#include <xercesc/validators/schema/XSDErrorReporter.hpp> + +#include <xsd-frontend/version.hxx> // Check Xerces-C++ version. + +namespace XSDFrontend +{ +  namespace XML +  { +    namespace Xerces = xercesc; + +    extern const XMLCh line_key[2]; +    extern const XMLCh column_key[2]; + +    class SchemaDOMParser: public Xerces::XercesDOMParser +    { +    public : +      SchemaDOMParser ( +        Xerces::MemoryManager* = Xerces::XMLPlatformUtils::fgMemoryManager); + +      // Callbacks. +      // +      virtual void +      startElement (const Xerces::XMLElementDecl&, +                    const unsigned int url_id, +                    const XMLCh* const prefix, +                    const Xerces::RefVectorOf<Xerces::XMLAttr>& attributes, +                    const XMLSize_t attribute_count, +                    const bool empty, +                    const bool root); + +      virtual void +      endElement (const Xerces::XMLElementDecl&, +                  const unsigned int url_id, +                  const bool root, +                  const XMLCh* const prefix); + +      virtual void +      docCharacters (const XMLCh* const, +                     const XMLSize_t length, +                     const bool cdata); + +      virtual void +      docComment (const XMLCh* const); + +      virtual void +      startEntityReference (const Xerces::XMLEntityDecl&); + +      virtual void +      endEntityReference (const Xerces::XMLEntityDecl&); + +      virtual void +      ignorableWhitespace (const XMLCh* const, +                           const XMLSize_t length, +                           const bool cdata); +    private: +      SchemaDOMParser (SchemaDOMParser const&); +      SchemaDOMParser& +      operator=(SchemaDOMParser const&); + +    private: +      int depth_; +      int ann_depth_; +      int inner_ann_depth_; +      Xerces::XSDLocator locator_; +      Xerces::XSDErrorReporter error_reporter_; +    }; +  } +} + +#endif // XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph.hxx b/libxsd-frontend/xsd-frontend/semantic-graph.hxx new file mode 100644 index 0000000..36d42c3 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph.hxx @@ -0,0 +1,26 @@ +// file      : xsd-frontend/semantic-graph.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_HXX + +#include <xsd-frontend/semantic-graph/annotation.hxx> +#include <xsd-frontend/semantic-graph/any.hxx> +#include <xsd-frontend/semantic-graph/any-attribute.hxx> +#include <xsd-frontend/semantic-graph/attribute.hxx> +#include <xsd-frontend/semantic-graph/attribute-group.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> +#include <xsd-frontend/semantic-graph/element.hxx> +#include <xsd-frontend/semantic-graph/element-group.hxx> +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/enumeration.hxx> +#include <xsd-frontend/semantic-graph/fundamental.hxx> +#include <xsd-frontend/semantic-graph/list.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> +#include <xsd-frontend/semantic-graph/schema.hxx> +#include <xsd-frontend/semantic-graph/union.hxx> + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx new file mode 100644 index 0000000..17a0f03 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx @@ -0,0 +1,45 @@ +// file      : xsd-frontend/semantic-graph/annotation.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/annotation.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    using compiler::type_info; + +    // Annotates +    // +    namespace +    { +      struct AnnotatesInit +      { +        AnnotatesInit () +        { +          type_info ti (typeid (Annotates)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } annotates_init_; +    } + +    // Annotation +    // +    namespace +    { +      struct AnnotationInit +      { +        AnnotationInit () +        { +          type_info ti (typeid (Annotation)); +          ti.add_base (typeid (Node)); +          insert (ti); +        } +      } annotation_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx new file mode 100644 index 0000000..0464f4f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx @@ -0,0 +1,75 @@ +// file      : xsd-frontend/semantic-graph/annotation.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class Annotation; + +    class Annotates: public virtual Edge +    { +    public: +      Annotation& +      annotation () +      { +        return *annotation_; +      } + +    public: +      Annotates (): annotation_ (0) {} + +      void +      set_left_node (Annotation& a) +      { +        annotation_ = &a; +      } + +      void +      set_right_node (Node&) {} + +      void +      set_right_node (Edge&) {} + +    private: +      Annotation* annotation_; +    }; + +    // +    // +    class Annotation: public virtual Node +    { +    public: +      String const& +      documentation () const +      { +        return documentation_; +      } + +    public: +      Annotation (Path const& file, +                  unsigned long line, +                  unsigned long column, +                  String const& documentation) +          : Node (file, line, column), documentation_ (documentation) +      { +      } + +      void +      add_edge_left (Annotates&) {} + +    private: +      String documentation_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx new file mode 100644 index 0000000..19b9df2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx @@ -0,0 +1,111 @@ +// file      : xsd-frontend/semantic-graph/any-attribute.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/any-attribute.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    AnyAttribute:: +    AnyAttribute (Path const& file, +                  unsigned long line, +                  unsigned long column, +                  String const& namespaces) +        : Node (file, line, column), +          prototype_ (0) +    { +      // Not sure if the separator is just space or any white-space +      // chararcter. +      // + +      for (size_t i (0), j (namespaces.find (L' '));;) +      { +        if (j != String::npos) +        { +          namespaces_.push_back (String (namespaces, i, j - i)); + +          i = j + 1; +          j = namespaces.find (L' ', i); +        } +        else +        { +          // Last element. +          // +          namespaces_.push_back (String (namespaces, i)); +          break; +        } +      } +    } + +    AnyAttribute:: +    AnyAttribute (Path const& file, +                  unsigned long line, +                  unsigned long column, +                  NamespaceIterator begin, +                  NamespaceIterator end) +        : Node (file, line, column), +          prototype_ (0) +    { +      for (; begin != end; ++begin) +        namespaces_.push_back (*begin); +    } + +    namespace +    { +      Namespace& +      namespace_ (Nameable& n) +      { +        // The basic idea goes like this: go up Names edges until you +        // reach Namespace. There are, however, anonymous types which +        // need special handling. In the case of an anonymous type we +        // will go up the first Belongs edge (because the first edge +        // is where the type was defined. +        // + +        if (n.named_p ()) +        { +          Scope& s (n.scope ()); +          Namespace* ns (dynamic_cast<Namespace*> (&n)); + +          return ns ? *ns : namespace_ (s); +        } +        else +        { +          Type& t (dynamic_cast<Type&> (n)); +          Belongs& b (*t.classifies_begin ()); + +          return namespace_ (b.instance ()); +        } +      } +    } + +    Namespace& AnyAttribute:: +    definition_namespace () +    { +      if (prototype_p ()) +        return prototype ().definition_namespace (); + +      return namespace_ (scope ()); +    } + +    namespace +    { +      using compiler::type_info; + +      struct AnyAttributeInit +      { +        AnyAttributeInit () +        { +          type_info ti (typeid (AnyAttribute)); +          ti.add_base (typeid (Nameable)); +          insert (ti); +        } +      } any_attribute_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx new file mode 100644 index 0000000..bb3d761 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx @@ -0,0 +1,80 @@ +// file      : xsd-frontend/semantic-graph/any-attribute.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX + +#include <vector> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class AnyAttribute: public virtual Nameable +    { +      typedef std::vector<String> Namespaces; + +    public: +      typedef Namespaces::const_iterator NamespaceIterator; + +      NamespaceIterator +      namespace_begin () const +      { +        return namespaces_.begin (); +      } + +      NamespaceIterator +      namespace_end () const +      { +        return namespaces_.end (); +      } + +    public: +      bool +      prototype_p () +      { +        return prototype_ != 0; +      } + +      AnyAttribute& +      prototype () +      { +        assert (prototype_ != 0); +        return *prototype_; +      } + +      void +      prototype (AnyAttribute& a) +      { +        assert (prototype_ == 0); +        prototype_ = &a; +      } + +    public: +      Namespace& +      definition_namespace (); + +    public: +      AnyAttribute (Path const& file, +                    unsigned long line, +                    unsigned long column, +                    String const& namespaces); + +      AnyAttribute (Path const& file, +                    unsigned long line, +                    unsigned long column, +                    NamespaceIterator begin, +                    NamespaceIterator end); + +    private: +      AnyAttribute* prototype_; +      Namespaces namespaces_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx new file mode 100644 index 0000000..c8ebc93 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx @@ -0,0 +1,122 @@ +// file      : xsd-frontend/semantic-graph/any.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/any.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    Any:: +    Any (Path const& file, +         unsigned long line, +         unsigned long column, +         String const& namespaces) +        : Node (file, line, column), +          prototype_ (0) +    { +      // Not sure if the separator is just space or any white-space +      // chararcter. +      // + +      for (size_t i (0), j (namespaces.find (L' '));;) +      { +        if (j != String::npos) +        { +          namespaces_.push_back (String (namespaces, i, j - i)); + +          i = j + 1; +          j = namespaces.find (L' ', i); +        } +        else +        { +          // Last element. +          // +          namespaces_.push_back (String (namespaces, i)); +          break; +        } +      } +    } + +    Any:: +    Any (Path const& file, +         unsigned long line, +         unsigned long column, +         NamespaceIterator begin, +         NamespaceIterator end) +        : Node (file, line, column), +          prototype_ (0) +    { +      for (; begin != end; ++begin) +        namespaces_.push_back (*begin); +    } + +    namespace +    { +      Namespace& +      namespace_ (Nameable& n) +      { +        // The basic idea goes like this: go up Names edges until you +        // reach Namespace. There are, however, anonymous types which +        // need special handling. In the case of an anonymous type we +        // will go up the first Belongs edge (because the first edge +        // is where the type was defined. +        // + +        if (n.named_p ()) +        { +          Scope& s (n.scope ()); +          Namespace* ns (dynamic_cast<Namespace*> (&n)); + +          return ns ? *ns : namespace_ (s); +        } +        else +        { +          Type& t (dynamic_cast<Type&> (n)); +          Belongs& b (*t.classifies_begin ()); + +          return namespace_ (b.instance ()); +        } +      } +    } + +    Namespace& Any:: +    definition_namespace () +    { +      if (prototype_p ()) +        return prototype ().definition_namespace (); + +      // Get to our scope. +      // +      Compositor* c (&contained_particle ().compositor ()); + +      while(!c->contained_compositor_p ()) +        c = &c->contained_particle ().compositor (); + +      Scope& scope ( +        dynamic_cast<Scope&> (c->contained_compositor ().container ())); + +      return namespace_ (scope); +    } + +    namespace +    { +      using compiler::type_info; + +      struct AnyInit +      { +        AnyInit () +        { +          type_info ti (typeid (Any)); +          ti.add_base (typeid (Nameable)); +          ti.add_base (typeid (Particle)); +          insert (ti); +        } +      } any_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx new file mode 100644 index 0000000..8e42762 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx @@ -0,0 +1,85 @@ +// file      : xsd-frontend/semantic-graph/any.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX + +#include <vector> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Any: public virtual Nameable, +               public virtual Particle +    { +      typedef std::vector<String> Namespaces; + +    public: +      typedef Namespaces::const_iterator NamespaceIterator; + +      NamespaceIterator +      namespace_begin () const +      { +        return namespaces_.begin (); +      } + +      NamespaceIterator +      namespace_end () const +      { +        return namespaces_.end (); +      } + +    public: +      bool +      prototype_p () +      { +        return prototype_ != 0; +      } + +      Any& +      prototype () +      { +        assert (prototype_ != 0); +        return *prototype_; +      } + +      void +      prototype (Any& a) +      { +        assert (prototype_ == 0); +        prototype_ = &a; +      } + +    public: +      Namespace& +      definition_namespace (); + +    public: +      Any (Path const& file, +           unsigned long line, +           unsigned long column, +           String const& namespaces); + +      Any (Path const& file, +           unsigned long line, +           unsigned long column, +           NamespaceIterator begin, +           NamespaceIterator end); + +      using Nameable::add_edge_right; +      using Particle::add_edge_right; + +    private: +      Any* prototype_; +      Namespaces namespaces_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx new file mode 100644 index 0000000..f61fa39 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx @@ -0,0 +1,34 @@ +// file      : xsd-frontend/semantic-graph/attribute-group.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    AttributeGroup:: +    AttributeGroup (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct AttributeGroupInit +      { +        AttributeGroupInit () +        { +          type_info ti (typeid (AttributeGroup)); +          ti.add_base (typeid (Scope)); +          insert (ti); +        } +      } attribute_group_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx new file mode 100644 index 0000000..62a1f81 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx @@ -0,0 +1,24 @@ +// file      : xsd-frontend/semantic-graph/attribute-group.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class AttributeGroup: public virtual Scope +    { +    public: +      AttributeGroup (Path const& file, +                      unsigned long line, +                      unsigned long column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx new file mode 100644 index 0000000..624b16a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx @@ -0,0 +1,41 @@ +// file      : xsd-frontend/semantic-graph/attribute.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/attribute.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    Attribute:: +    Attribute (Path const& file, +               unsigned long line, +               unsigned long column, +               bool optional, +               bool global, +               bool qualified) +        : Node (file, line, column), +          Member (global, qualified), +          optional_ (optional) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct AttributeInit +      { +        AttributeInit () +        { +          type_info ti (typeid (Attribute)); +          ti.add_base (typeid (Member)); +          insert (ti); +        } +      } attribute_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx new file mode 100644 index 0000000..9d9b0fb --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx @@ -0,0 +1,36 @@ +// file      : xsd-frontend/semantic-graph/attribute.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Attribute: public virtual Member +    { +    public: +      bool +      optional_p () const +      { +        return optional_; +      } + +    public: +      Attribute (Path const& file, +                 unsigned long line, +                 unsigned long column, +                 bool optional, +                 bool global, +                 bool qualified); +    private: +      bool optional_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx new file mode 100644 index 0000000..8433a0e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx @@ -0,0 +1,42 @@ +// file      : xsd-frontend/semantic-graph/complex.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    Complex:: +    Complex () +        : mixed_ (false), contains_compositor_ (0) +    { +    } + +    Complex:: +    Complex (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column), +          mixed_ (false), contains_compositor_ (0) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct ComplexInit +      { +        ComplexInit () +        { +          type_info ti (typeid (Complex)); +          ti.add_base (typeid (Type)); +          ti.add_base (typeid (Scope)); +          insert (ti); +        } +      } complex_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx new file mode 100644 index 0000000..ac47810 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx @@ -0,0 +1,87 @@ +// file      : xsd-frontend/semantic-graph/complex.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Complex: public virtual Type, public virtual Scope +    { +    public: +      bool +      mixed_p () const +      { +        if (mixed_) +          return true; + +        // If we have empty content, then we have the same content +        // type as our base. +        // +        if (!contains_compositor_p () && inherits_p ()) +        { +          if (Complex* b = dynamic_cast<Complex*> (&inherits ().base ())) +            return b->mixed_p (); +        } + +        return false; +      } + +    public: +      bool +      contains_compositor_p () const +      { +        return contains_compositor_ != 0; +      } + +      ContainsCompositor& +      contains_compositor () +      { +        assert (contains_compositor_ != 0); +        return *contains_compositor_; +      } + +    public: +      void +      mixed_p (bool m) +      { +        mixed_ = m; +      } + +    public: +      Complex (Path const& file, unsigned long line, unsigned long column); + +      void +      add_edge_left (ContainsCompositor& e) +      { +        contains_compositor_ = &e; +      } + +      void +      remove_edge_left (ContainsCompositor& e) +      { +        assert (contains_compositor_ == &e); +        contains_compositor_ = 0; +      } + +      using Type::add_edge_right; +      using Type::add_edge_left; +      using Scope::add_edge_left; + +    protected: +      Complex (); // For virtual inheritance (Enumeration). + +    private: +      bool mixed_; +      ContainsCompositor* contains_compositor_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx new file mode 100644 index 0000000..dd65e56 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx @@ -0,0 +1,100 @@ +// file      : xsd-frontend/semantic-graph/compositor.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // ContainsCompositor +    // +    ContainsCompositor:: +    ContainsCompositor (unsigned long min, unsigned long max) +        : compositor_ (0), container_ (0), min_ (min), max_ (max) +    { +    } + +    // All +    // +    All:: +    All (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    // Choice +    // +    Choice:: +    Choice (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    // Sequence +    // +    Sequence:: +    Sequence (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct ContainsCompositorInit +      { +        ContainsCompositorInit () +        { +          type_info ti (typeid (ContainsCompositor)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } contains_compositor_init_; + +      struct CompositorInit +      { +        CompositorInit () +        { +          type_info ti (typeid (Compositor)); +          ti.add_base (typeid (Particle)); +          insert (ti); +        } +      } compositor_init_; + +      struct AllInit +      { +        AllInit () +        { +          type_info ti (typeid (All)); +          ti.add_base (typeid (Compositor)); +          insert (ti); +        } +      } all_init_; + +      struct ChoiceInit +      { +        ChoiceInit () +        { +          type_info ti (typeid (Choice)); +          ti.add_base (typeid (Compositor)); +          insert (ti); +        } +      } choice_init_; + +      struct SequenceInit +      { +        SequenceInit () +        { +          type_info ti (typeid (Sequence)); +          ti.add_base (typeid (Compositor)); +          insert (ti); +        } +      } sequence_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx new file mode 100644 index 0000000..3573c24 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx @@ -0,0 +1,234 @@ +// file      : xsd-frontend/semantic-graph/compositors.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX + +#include <list> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class ContainsCompositor: public virtual Edge +    { +    public: +      Compositor& +      compositor () const +      { +        return *compositor_; +      } + +      Node& +      container () const +      { +        return *container_; +      } + +    public: +      unsigned long +      min () const +      { +        return min_; +      } + +      unsigned long +      max () const +      { +        return max_; +      } + +    public: +      ContainsCompositor (unsigned long min, unsigned long max); + +      void +      set_left_node (Node& n) +      { +        container_ = &n; +      } + +      void +      set_right_node (Compositor& n) +      { +        compositor_ = &n; +      } + +      void +      clear_left_node (Node& n) +      { +        assert (container_ == &n); +        container_ = 0; +      } + +      void +      clear_right_node (Compositor& n) +      { +        assert (compositor_ == &n); +        compositor_ = 0; +      } + +    private: +      Compositor* compositor_; +      Node* container_; +      unsigned long min_, max_; +    }; + +    // +    // +    class Compositor: public virtual Particle +    { +      typedef std::list<ContainsParticle*> ContainsList; + +    public: +      typedef pointer_iterator<ContainsList::iterator> ContainsIterator; +      typedef +      pointer_iterator<ContainsList::const_iterator> +      ContainsConstIterator; + +      ContainsIterator +      contains_begin () +      { +        return contains_.begin (); +      } + +      ContainsIterator +      contains_end () +      { +        return contains_.end (); +      } + +      ContainsConstIterator +      contains_begin () const +      { +        return contains_.begin (); +      } + +      ContainsConstIterator +      contains_end () const +      { +        return contains_.end (); +      } + +    public: +      bool +      contained_compositor_p () +      { +        return contained_compositor_ != 0; +      } + +      ContainsCompositor& +      contained_compositor () +      { +        assert (contained_compositor_ != 0); +        return *contained_compositor_; +      } + +    public: +      unsigned long +      min () const +      { +        if (contained_compositor_ != 0) +          return contained_compositor_->min (); +        else +          return Particle::min (); +      } + +      unsigned long +      max () const +      { +        if (contained_compositor_ != 0) +          return contained_compositor_->max (); +        else +          return Particle::max (); +      } + +    public: +      Compositor (): contained_compositor_ (0) {} + +      void +      add_edge_left (ContainsParticle& e) +      { +        contains_.push_back (&e); +      } + +      void +      add_edge_left (ContainsParticle& e, ContainsIterator const& after) +      { +        if (after.base () == contains_.end ()) +          contains_.push_front (&e); +        else +        { +          ContainsList::iterator i (after.base ()); +          contains_.insert (++i, &e); +        } +      } + +      void +      remove_edge_left (ContainsParticle& e) +      { +        for (ContainsList::iterator i (contains_.begin ()); +             i != contains_.end (); ++i) +        { +          if (*i == &e) +          { +            contains_.erase (i); +            break; +          } +        } +      } + +      void +      add_edge_right (ContainsCompositor& e) +      { +        contained_compositor_ = &e; +      } + +      void +      remove_edge_right (ContainsCompositor& e) +      { +        assert (contained_compositor_ == &e); +        contained_compositor_ = 0; +      } + +      using Node::add_edge_right; +      using Particle::add_edge_right; +      using Particle::remove_edge_right; + +    private: +      ContainsList contains_; +      ContainsCompositor* contained_compositor_; +    }; + +    // +    // +    class All: public virtual Compositor +    { +    public: +      All (Path const& file, unsigned long line, unsigned long column); +    }; + +    // +    // +    class Choice: public virtual Compositor +    { +    public: +      Choice (Path const& file, unsigned long line, unsigned long column); +    }; + +    // +    // +    class Sequence: public virtual Compositor +    { +    public: +      Sequence (Path const& file, unsigned long line, unsigned long column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx new file mode 100644 index 0000000..a02d751 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx @@ -0,0 +1,34 @@ +// file      : xsd-frontend/semantic-graph/element-group.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/element-group.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    ElementGroup:: +    ElementGroup (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column), contains_compositor_ (0) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct ElementGroupInit +      { +        ElementGroupInit () +        { +          type_info ti (typeid (ElementGroup)); +          ti.add_base (typeid (Scope)); +          insert (ti); +        } +      } element_group_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx new file mode 100644 index 0000000..ee7772c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx @@ -0,0 +1,42 @@ +// file      : xsd-frontend/semantic-graph/element-group.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class ElementGroup: public virtual Scope +    { +    public: +      ContainsCompositor& +      contains_compositor () +      { +        assert (contains_compositor_ != 0); +        return *contains_compositor_; +      } + +    public: +      ElementGroup (Path const& file, unsigned long line, unsigned long column); + +      void +      add_edge_left (ContainsCompositor& e) +      { +        contains_compositor_ = &e; +      } + +      using Scope::add_edge_left; + +    private: +      ContainsCompositor* contains_compositor_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx new file mode 100644 index 0000000..fb7d3a7 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx @@ -0,0 +1,53 @@ +// file      : xsd-frontend/semantic-graph/element.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/element.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // Element +    // +    Element:: +    Element (Path const& file, +             unsigned long line, +             unsigned long column, +             bool global, +             bool qualified) +        : Node (file, line, column), +          Member (global, qualified), +          substitutes_ (0) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct SubstitutesInit +      { +        SubstitutesInit () +        { +          type_info ti (typeid (Substitutes)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } substitutes_init_; + +      struct ElementInit +      { +        ElementInit () +        { +          type_info ti (typeid (Element)); +          ti.add_base (typeid (Member)); +          ti.add_base (typeid (Particle)); +          insert (ti); +        } +      } element_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx new file mode 100644 index 0000000..0af164e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx @@ -0,0 +1,94 @@ +// file      : xsd-frontend/semantic-graph/element.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Element; + +    class Substitutes: public virtual Edge +    { +    public: +      Element& +      substitution () const +      { +        return *substitution_; +      } + +      Element& +      root () const +      { +        return *root_; +      } + +    public: +      void +      set_left_node (Element& n) +      { +        substitution_ = &n; +      } + +      void +      set_right_node (Element& n) +      { +        root_ = &n; +      } + +    private: +      Element* root_; +      Element* substitution_; +    }; + + +    class Element: public virtual Member, +                   public virtual Particle +    { +    public: +      bool +      substitutes_p () const +      { +        return substitutes_ != 0; +      } + +      Substitutes& +      substitutes () const +      { +        assert (substitutes_ != 0); +        return *substitutes_; +      } + +    public: +      Element (Path const& file, +               unsigned long line, +               unsigned long column, +               bool global, +               bool qualified); + +      void +      add_edge_left (Substitutes& e) +      { +        substitutes_ = &e; +      } + +      void +      add_edge_right (Substitutes&) {} + +      using Member::add_edge_left; +      using Member::add_edge_right; +      using Particle::add_edge_right; + +    private: +      Substitutes* substitutes_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx new file mode 100644 index 0000000..fa48a9a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx @@ -0,0 +1,299 @@ +// file      : xsd-frontend/semantic-graph/elements.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <algorithm> + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/annotation.hxx> + +using namespace std; + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // Node +    // +    Annotation& Node:: +    annotation () +    { +      return annotates_->annotation (); +    } + +    // Type +    // +    void Type:: +    remove_edge_left (Arguments& a) +    { +      ArgumentsSet::iterator i (arguments_.find (&a)); +      assert (i != arguments_.end ()); +      arguments_.erase (i); +    } + +    // Specialization +    // +    void Specialization:: +    remove_edge_right (Arguments& a) +    { +      // The number of entries should be small so linear search will do. +      // +      Argumented::iterator i ( +        std::find (argumented_.begin (), argumented_.end (), &a)); + +      assert (i != argumented_.end ()); +      argumented_.erase (i); +    } + +    using compiler::type_info; + +    namespace +    { +      // Edge +      // +      struct EdgeInit +      { +        EdgeInit () +        { +          type_info ti (typeid (Edge)); +          insert (ti); +        } +      } edge_init_; + +      // Node +      // +      struct NodeInit +      { +        NodeInit () +        { +          type_info ti (typeid (Node)); +          insert (ti); +        } +      } node_init_; + +      // Names +      // +      struct NamesInit +      { +        NamesInit () +        { +          type_info ti (typeid (Names)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } names_init_; + +      // Nameable +      // +      struct NameableInit +      { +        NameableInit () +        { +          type_info ti (typeid (Nameable)); +          ti.add_base (typeid (Node)); +          insert (ti); +        } +      } nameable_init_; + +      // Scope +      // +      struct ScopeInit +      { +        ScopeInit () +        { +          type_info ti (typeid (Scope)); +          ti.add_base (typeid (Nameable)); +          insert (ti); +        } +      } scope_init_; + +      // Type +      // +      struct TypeInit +      { +        TypeInit () +        { +          type_info ti (typeid (Type)); +          ti.add_base (typeid (Nameable)); +          insert (ti); +        } +      } type_init_; + +      // Instance +      // +      struct InstanceInit +      { +        InstanceInit () +        { +          type_info ti (typeid (Instance)); +          ti.add_base (typeid (Nameable)); +          insert (ti); +        } +      } instance_init_; + +      // Belongs +      // +      struct BelongsInit +      { +        BelongsInit () +        { +          type_info ti (typeid (Belongs)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } belongs_init_; + +      // Inherits +      // +      struct InheritsInit +      { +        InheritsInit () +        { +          type_info ti (typeid (Inherits)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } inherits_init_; + +      // Extends +      // +      struct ExtendsInit +      { +        ExtendsInit () +        { +          type_info ti (typeid (Extends)); +          ti.add_base (typeid (Inherits)); +          insert (ti); +        } +      } extends_init_; + +      // Restricts +      // +      struct RestrictsInit +      { +        RestrictsInit () +        { +          type_info ti (typeid (Restricts)); +          ti.add_base (typeid (Inherits)); +          insert (ti); +        } +      } restricts_init_; + +      // BelongsToNamespace +      // +      struct BelongsToNamespaceInit +      { +        BelongsToNamespaceInit () +        { +          type_info ti (typeid (BelongsToNamespace)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } belongs_to_namespace_init_; + +      // Member +      // +      struct MemberInit +      { +        MemberInit () +        { +          type_info ti (typeid (Member)); +          ti.add_base (typeid (Instance)); +          insert (ti); +        } +      } member_init_; + +      // Specialization +      // +      struct SpecializationInit +      { +        SpecializationInit () +        { +          type_info ti (typeid (Specialization)); +          ti.add_base (typeid (Type)); +          insert (ti); +        } +      } specialization_init_; + +      // Arguments +      // +      struct ArgumentsInit +      { +        ArgumentsInit () +        { +          type_info ti (typeid (Arguments)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } arguments_init_; + +      /* +      // Contains +      // +      struct ContainsInit +      { +        ContainsInit () +        { +          type_info ti (typeid (Contains)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } contains_init_; + +      // Container +      // +      struct ContainerInit +      { +        ContainerInit () +        { +          type_info ti (typeid (Container)); +          ti.add_base (typeid (Node)); +          insert (ti); +        } +      } container_init_; +      */ + +      // AnyType +      // +      struct AnyTypeInit +      { +        AnyTypeInit () +        { +          type_info ti (typeid (AnyType)); +          ti.add_base (typeid (SemanticGraph::Type)); +            insert (ti); +        } +      } any_type_init_; + +      // AnySimpleType +      // +      struct AnySimpleTypeInit +      { +        AnySimpleTypeInit () +        { +          type_info ti (typeid (AnySimpleType)); +          ti.add_base (typeid (Type)); +            insert (ti); +        } +      } any_simple_type_init_; +    } + +    // Instance +    // +    Type& Instance:: +    type () const +    { +      return belongs ().type (); +    } +  } +} + +// Path +// +std::wostream& +operator<< (std::wostream& os, XSDFrontend::SemanticGraph::Path const& path) +{ +  return os << path.string ().c_str (); +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx new file mode 100644 index 0000000..98fb180 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx @@ -0,0 +1,997 @@ +// file      : xsd-frontend/semantic-graph/elements.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX + +#include <set> +#include <map> +#include <list> +#include <vector> +#include <iosfwd> +#include <utility> // std::pair +#include <cstdlib> // abort +#include <cassert> + +#include <cutl/container/graph.hxx> +#include <cutl/container/pointer-iterator.hxx> +#include <cutl/compiler/context.hxx> +#include <cutl/fs/path.hxx> + +#include <xsd-frontend/types.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    using namespace cutl; + +    using container::pointer_iterator; + +    // +    // +    typedef fs::path Path; +    typedef fs::invalid_path InvalidPath; +    typedef std::vector<Path> Paths; + +    typedef compiler::context Context; + +    // +    // +    class Node; +    class Edge; + +    // +    // +    class Annotates; +    class Annotation; + +    // +    // +    class Edge +    { +    public: +      Context& +      context () const +      { +        return context_; +      } + +      virtual +      ~Edge () +      { +      } + +    public: +      template <typename X> +      bool +      is_a () const +      { +        return dynamic_cast<X const*> (this) != 0; +      } + +    private: +      mutable Context context_; +    }; + +    inline bool +    operator== (Edge const& x, Edge const& y) +    { +      return &x == &y; +    } + + +    // +    // +    class Node +    { +    public: +      Context& +      context () const +      { +        return context_; +      } + +    public: +      Path const& +      file () const +      { +        return file_; +      } + +      unsigned long +      line () const +      { +        return line_; +      } + +      unsigned long +      column () const +      { +        return column_; +      } + +    public: +      bool +      annotated_p () const +      { +        return annotates_ != 0; +      } + +      Annotates& +      annotated () const +      { +        return *annotates_; +      } + +      Annotation& +      annotation (); + +    public: +      template <typename X> +      bool +      is_a () const +      { +        return dynamic_cast<X const*> (this) != 0; +      } + +    public: +      virtual +      ~Node () {} + +      Node (Path const& file, unsigned long line, unsigned long column) +          : annotates_ (0), file_ (file), line_ (line), column_ (column) +      { +      } + +      void +      add_edge_right (Annotates& a) +      { +        annotates_ = &a; +      } + +    protected: +      Node () // For virtual inheritance. +      { +        abort (); // Told you so! +      } + +    private: +      mutable Context context_; +      Annotates* annotates_; +      Path file_; +      unsigned long line_; +      unsigned long column_; +    }; + +    inline bool +    operator== (Node const& x, Node const& y) +    { +      return &x == &y; +    } + +    // +    // +    typedef container::graph<Node, Edge> graph; + +    // +    // +    typedef String Name; + + +    // +    // +    class Scope; +    class Nameable; + + +    // +    // +    class Names: public virtual Edge +    { +    public: +      Name +      name () const +      { +        return name_; +      } + +      Scope& +      scope () const +      { +        return *scope_; +      } + +      Nameable& +      named () const +      { +        return *named_; +      } + +    public: +      Names (Name const& name): name_ (name) {} + +      void +      set_left_node (Scope& n) +      { +        scope_ = &n; +      } + +      void +      set_right_node (Nameable& n) +      { +        named_ = &n; +      } + +      void +      clear_left_node (Scope& n) +      { +        assert (scope_ == &n); +        scope_ = 0; +      } + +      void +      clear_right_node (Nameable& n) +      { +        assert (named_ == &n); +        named_ = 0; +      } + +    private: +      Scope* scope_; +      Nameable* named_; +      Name name_; +    }; + + +    class Nameable: public virtual Node +    { +    public: +      bool +      named_p () const +      { +        return named_ != 0; +      } + +      Name +      name () const +      { +        assert (named_p ()); +        return named_->name (); +      } + +      Scope& +      scope () +      { +        assert (named_p ()); +        return named_->scope (); +      } + +      Names& +      named () +      { +        assert (named_p ()); +        return *named_; +      } + +    public: +      Nameable (): named_ (0) {} + +      void +      add_edge_right (Names& e) +      { +        named_ = &e; +      } + +      void +      remove_edge_right (Names& e) +      { +        assert (named_ == &e); +        named_ = 0; +      } + +      using Node::add_edge_right; + +    private: +      Names* named_; +    }; + +    // +    // +    typedef std::set<Nameable*> Nameables; + +    // +    // +    class Scope: public virtual Nameable +    { +    protected: +      typedef std::list<Names*> NamesList; +      typedef std::map<Names*, NamesList::iterator> ListIteratorMap; +      typedef std::map<Name, NamesList> NamesMap; + +    public: +      typedef pointer_iterator<NamesList::iterator> NamesIterator; +      typedef pointer_iterator<NamesList::const_iterator> NamesConstIterator; + +      typedef +      std::pair<NamesConstIterator, NamesConstIterator> +      NamesIteratorPair; + +      NamesIterator +      names_begin () +      { +        return names_.begin (); +      } + +      NamesIterator +      names_end () +      { +        return names_.end (); +      } + +      NamesConstIterator +      names_begin () const +      { +        return names_.begin (); +      } + +      NamesConstIterator +      names_end () const +      { +        return names_.end (); +      } + +      virtual NamesIteratorPair +      find (Name const& name) const +      { +        NamesMap::const_iterator i (names_map_.find (name)); + +        if (i == names_map_.end ()) +          return NamesIteratorPair (names_.end (), names_.end ()); +        else +          return NamesIteratorPair (i->second.begin (), i->second.end ()); +      } + +      NamesIterator +      find (Names& e) +      { +        ListIteratorMap::iterator i (iterator_map_.find (&e)); +        return i != iterator_map_.end () ? i->second : names_.end (); +      } + +    public: +      Scope (Path const& file, unsigned long line, unsigned long column) +          : Node (file, line, column) +      { +      } + +      void +      add_edge_left (Names& e) +      { +        NamesList::iterator i (names_.insert (names_.end (), &e)); +        iterator_map_[&e] = i; +        names_map_[e.name ()].push_back (&e); +      } + +      void +      remove_edge_left (Names& e) +      { +        ListIteratorMap::iterator i (iterator_map_.find (&e)); +        assert (i != iterator_map_.end ()); + +        names_.erase (i->second); +        iterator_map_.erase (i); + +        NamesMap::iterator j (names_map_.find (e.name ())); + +        for (NamesList::iterator i (j->second.begin ()); +             i != j->second.end (); ++i) +        { +          if (*i == &e) +            i = j->second.erase (i); +        } +      } + +      void +      add_edge_left (Names& e, NamesIterator const& after) +      { +        NamesList::iterator i; + +        if (after.base () == names_.end ()) +          i = names_.insert (names_.begin (), &e); +        else +        { +          NamesList::iterator j (after.base ()); +          i = names_.insert (++j, &e); +        } + +        iterator_map_[&e] = i; +        names_map_[e.name ()].push_back (&e); +      } + +      using Nameable::add_edge_right; + +    protected: +      Scope () {} + +    private: +      NamesList names_; +      ListIteratorMap iterator_map_; +      NamesMap names_map_; +    }; + + +    // +    // +    class Belongs; +    class Inherits; +    class Arguments; + +    class Type: public virtual Nameable +    { +    protected: +      typedef std::vector<Belongs*> Classifies; +      typedef std::vector<Inherits*> Begets; +      typedef std::set<Arguments*> ArgumentsSet; + +    public: +      typedef pointer_iterator<Classifies::const_iterator> ClassifiesIterator; + +      ClassifiesIterator +      classifies_begin () const +      { +        return classifies_.begin (); +      } + +      ClassifiesIterator +      classifies_end () const +      { +        return classifies_.end (); +      } + +      // +      // +      bool +      inherits_p () const +      { +        return inherits_ != 0; +      } + +      Inherits& +      inherits () const +      { +        assert (inherits_ != 0); +        return *inherits_; +      } + +      // +      // +      typedef pointer_iterator<Begets::const_iterator> BegetsIterator; + +      BegetsIterator +      begets_begin () const +      { +        return begets_.begin (); +      } + +      BegetsIterator +      begets_end () const +      { +        return begets_.end (); +      } + +      // +      // +      typedef pointer_iterator<ArgumentsSet::const_iterator> ArgumentsIterator; + +      ArgumentsIterator +      arguments_begin () const +      { +        return arguments_.begin (); +      } + +      ArgumentsIterator +      arguments_end () const +      { +        return arguments_.end (); +      } + +    public: +      Type (): inherits_ (0) {} + +      void +      add_edge_right (Belongs& e) +      { +        classifies_.push_back (&e); +      } + +      void +      add_edge_right (Inherits& e) +      { +        begets_.push_back (&e); +      } + +      using Nameable::add_edge_right; + +      void +      add_edge_left (Arguments& a) +      { +        arguments_.insert (&a); +      } + +      void +      remove_edge_left (Arguments&); + +      void +      add_edge_left (Inherits& e) +      { +        inherits_ = &e; +      } + +    private: +      Inherits* inherits_; +      Begets begets_; +      Classifies classifies_; +      ArgumentsSet arguments_; +    }; + +    class Instance: public virtual Nameable +    { +    public: +      Belongs& +      belongs () const +      { +        return *belongs_; +      } + +      Type& +      type () const; + +      bool +      typed_p () const +      { +        return belongs_ != 0; +      } + +    public: +      Instance (): belongs_ (0) {} + +      void +      add_edge_left (Belongs& e) +      { +        belongs_ = &e; +      } + +    private: +      Belongs* belongs_; +    }; + + +    class Belongs: public virtual Edge +    { +    public: +      Instance& +      instance () const +      { +        return *instance_; +      } + +      Type& +      type () const +      { +        return *type_; +      } + +    public: +      void +      set_left_node (Instance& n) +      { +        instance_ = &n; +      } + +      void +      set_right_node (Type& n) +      { +        type_ = &n; +      } + +    private: +      Instance* instance_; +      Type* type_; +    }; + + +    // +    // +    class Inherits: public virtual Edge +    { +    public: +      Type& +      base () const +      { +        return *base_; +      } + +      Type& +      derived () const +      { +        return *derived_; +      } + +    public: +      void +      set_left_node (Type& n) +      { +        derived_ = &n; +      } + +      void +      set_right_node (Type& n) +      { +        base_ = &n; +      } + +    private: +      Type* base_; +      Type* derived_; +    }; + +    class Extends: public virtual Inherits +    { +    }; + +    class Restricts: public virtual Inherits +    { +    public: +      typedef std::map<String, String> Facets; +      typedef Facets::iterator FacetIterator; + +      bool +      facet_empty () +      { +        return facets_.empty (); +      } + +      FacetIterator +      facet_begin () +      { +        return facets_.begin (); +      } + +      FacetIterator +      facet_end () +      { +        return facets_.end (); +      } + +      FacetIterator +      facet_find (String const& name) +      { +        return facets_.find (name); +      } + +      void +      facet_insert (String const& name, String const& value) +      { +        facets_[name] = value; +      } + +      Facets const& +      facets () const +      { +        return facets_; +      } + +    protected: +      Facets facets_; +    }; + + +    // +    // +    class Member; +    class Namespace; + +    class BelongsToNamespace: public virtual Edge +    { +    public: +      Member& +      member () const +      { +        assert (member_ != 0); +        return *member_; +      } + +      Namespace& +      namespace_ () const +      { +        assert (namespace__ != 0); +        return *namespace__; +      } + +    public: +      BelongsToNamespace (): member_ (0), namespace__ (0) {} + +      void +      set_left_node (Member& n) +      { +        member_ = &n; +      } + +      void +      set_right_node (Namespace& n) +      { +        namespace__ = &n; +      } + +    private: +      Member* member_; +      Namespace* namespace__; +    }; + +    // +    // +    class Member: public virtual Instance +    { +    public: +      // Member is global either if it is defined outside any type +      // or it is a ref="" of a global member. +      // +      bool +      global_p () const +      { +        return global_; +      } + +      bool +      qualified_p () const +      { +        return qualified_; +      } + +      // Note that only qualified members belong to a namespace. +      // +      Namespace& +      namespace_ () const +      { +        assert (belongs_to_namespace_ != 0); +        return belongs_to_namespace_->namespace_ (); +      } + + +      // Default and fixed value API. Note that the fixed value semantics +      // is a superset of the default value semantics. As such setting the +      // fixed value appears as if the default value was also set. +      // +      bool +      default_p () const +      { +        return value_type_ != ValueType::none; +      } + +      bool +      fixed_p () const +      { +        return value_type_ == ValueType::fixed; +      } + +      struct NoValue {}; + +      String +      value () const +      { +        if (value_type_ != ValueType::none) +          return value_; +        else +          throw NoValue (); +      } + +      // +      // +      void +      default_ (String const& v) +      { +        value_ = v; +        value_type_ = ValueType::default_; +      } + +      void +      fixed (String const& v) +      { +        value_ = v; +        value_type_ = ValueType::fixed; +      } + +    public: +      Member (bool global, bool qualified) +          : global_ (global), +            qualified_ (qualified), +            belongs_to_namespace_ (0), +            value_type_ (ValueType::none) +      { +      } + +      void +      add_edge_left (BelongsToNamespace& e) +      { +        // In the parser we sometimes re-add the same adge. +        // +        belongs_to_namespace_ = &e; +      } + +      using Instance::add_edge_left; + +    private: +      bool global_; +      bool qualified_; +      BelongsToNamespace* belongs_to_namespace_; + +      struct ValueType +      { +        enum Value +        { +          none, +          default_, +          fixed +        }; +      }; + +      String value_; +      ValueType::Value value_type_; +    }; + + +    // Parametric types. +    // + +    class Specialization: public virtual Type +    { +      typedef std::vector<Arguments*> Argumented; + +    public: +      typedef pointer_iterator<Argumented::iterator> ArgumentedIterator; +      typedef +      pointer_iterator<Argumented::const_iterator> +      ArgumentedConstIterator; + +      ArgumentedIterator +      argumented_begin () +      { +        return argumented_.begin (); +      } + +      ArgumentedConstIterator +      argumented_begin () const +      { +        return argumented_.begin (); +      } + +      ArgumentedIterator +      argumented_end () +      { +        return argumented_.end (); +      } + +      ArgumentedConstIterator +      argumented_end () const +      { +        return argumented_.end (); +      } + +      // Shortcut for one-argument specializations. +      // +      Arguments& +      argumented () const +      { +        return *argumented_[0]; +      } + +    public: +      using Type::add_edge_right; + +      void +      add_edge_right (Arguments& a) +      { +        argumented_.push_back (&a); +      } + +      void +      add_edge_right (Arguments& a, ArgumentedIterator const& pos) +      { +        argumented_.insert (pos.base (), &a); +      } + +      void +      remove_edge_right (Arguments&); + +    private: +      Argumented argumented_; +    }; + +    class Arguments: public virtual Edge +    { +    public: +      Type& +      type () const +      { +        return *type_; +      } + +      Specialization& +      specialization () const +      { +        return *specialization_; +      } + +    public: +      void +      set_left_node (Type& n) +      { +        type_ = &n; +      } + +      void +      clear_left_node (Type& n) +      { +        assert (type_ == &n); +        type_ = 0; +      } + +      void +      set_right_node (Specialization& s) +      { +        specialization_ = &s; +      } + +      void +      clear_right_node (Specialization& s) +      { +        assert (specialization_ == &s); +        specialization_ = 0; +      } + +    private: +      Type* type_; +      Specialization* specialization_; +    }; + + +    // +    // +    class AnyType: public virtual Type +    { +    public: +      AnyType (Path const& file, unsigned long line, unsigned long column) +          : Node (file, line, column) +      { +      } + +    protected: +      AnyType () {} // For virtual inheritance. +    }; + + +    // +    // +    class AnySimpleType: public virtual Type +    { +    public: +      AnySimpleType (Path const& file, unsigned long line, unsigned long column) +          : Node (file, line, column) +      { +      } + +    protected: +      AnySimpleType () {} // For virtual inheritance. +    }; +  } +} + +// ADL won't find it because Path is a typedef. Note that this +// function prints in native format. +// +std::wostream& +operator<< (std::wostream& os, XSDFrontend::SemanticGraph::Path const& path); + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx new file mode 100644 index 0000000..93bcf79 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx @@ -0,0 +1,59 @@ +// file      : xsd-frontend/semantic-graph/enumeration.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // Enumeration +    // +    Enumeration:: +    Enumeration (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    // Enumerator +    // +    Enumerator:: +    Enumerator (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      // Enumeration +      // +      struct EnumerationInit +      { +        EnumerationInit () +        { +          type_info ti (typeid (Enumeration)); +          ti.add_base (typeid (Complex)); +          insert (ti); +        } +      } enumeration_init_; + + +      // Enumerator +      // +      struct EnumeratorInit +      { +        EnumeratorInit () +        { +          type_info ti (typeid (Enumerator)); +          ti.add_base (typeid (Instance)); +          insert (ti); +        } +      } enumerator_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx new file mode 100644 index 0000000..90a33d1 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/semantic-graph/enumeration.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Enumeration: public virtual Complex +    { +    public: +      Enumeration (Path const& file, unsigned long line, unsigned long column); +    }; + + +    class Enumerator: public virtual Instance +    { +    public: +      Enumerator (Path const& file, unsigned long line, unsigned long column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx new file mode 100644 index 0000000..cc98449 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx @@ -0,0 +1,1143 @@ +// file      : xsd-frontend/semantic-graph/fundamental.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      using compiler::type_info; + +      // Type +      // +      namespace +      { +        struct TypeInit +        { +          TypeInit () +          { +            type_info ti (typeid (Type)); +            ti.add_base (typeid (SemanticGraph::Type)); +            insert (ti); +          } +        } any_type_init_; +      } + +      Type:: +      Type () +      { +      } + + +      // Byte +      // +      namespace +      { +        struct ByteInit +        { +          ByteInit () +          { +            type_info ti (typeid (Byte)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } byte_init_; +      } + +      Byte:: +      Byte (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // UnsignedByte +      // +      namespace +      { +        struct UnsignedByteInit +        { +          UnsignedByteInit () +          { +            type_info ti (typeid (UnsignedByte)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } unsigned_byte_init_; +      } + +      UnsignedByte:: +      UnsignedByte (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Short +      // +      namespace +      { +        struct ShortInit +        { +          ShortInit () +          { +            type_info ti (typeid (Short)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } short_init_; +      } + +      Short:: +      Short (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // UnsignedShort +      // +      namespace +      { +        struct UnsignedShortInit +        { +          UnsignedShortInit () +          { +            type_info ti (typeid (UnsignedShort)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } unsigned_short_init_; +      } + +      UnsignedShort:: +      UnsignedShort (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Int +      // +      namespace +      { +        struct IntInit +        { +          IntInit () +          { +            type_info ti (typeid (Int)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } int_init_; +      } + +      Int:: +      Int (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // UnsignedInt +      // +      namespace +      { +        struct UnsignedIntInit +        { +          UnsignedIntInit () +          { +            type_info ti (typeid (UnsignedInt)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } unsigned_int_init_; +      } + +      UnsignedInt:: +      UnsignedInt (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Long +      // +      namespace +      { +        struct LongInit +        { +          LongInit () +          { +            type_info ti (typeid (Long)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } long_init_; +      } + +      Long:: +      Long (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // UnsignedLong +      // +      namespace +      { +        struct UnsignedLongInit +        { +          UnsignedLongInit () +          { +            type_info ti (typeid (UnsignedLong)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } unsigned_long_init_; +      } + +      UnsignedLong:: +      UnsignedLong (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Integer +      // +      namespace +      { +        struct IntegerInit +        { +          IntegerInit () +          { +            type_info ti (typeid (Integer)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } integer_init_; +      } + +      Integer:: +      Integer (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NonPositiveInteger +      // +      namespace +      { +        struct NonPositiveIntegerInit +        { +          NonPositiveIntegerInit () +          { +            type_info ti (typeid (NonPositiveInteger)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } non_positive_integer_init_; +      } + +      NonPositiveInteger:: +      NonPositiveInteger (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NonNegativeInteger +      // +      namespace +      { +        struct NonNegativeIntegerInit +        { +          NonNegativeIntegerInit () +          { +            type_info ti (typeid (NonNegativeInteger)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } non_negative_integer_init_; +      } + +      NonNegativeInteger:: +      NonNegativeInteger (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // PositiveInteger +      // +      namespace +      { +        struct PositiveIntegerInit +        { +          PositiveIntegerInit () +          { +            type_info ti (typeid (PositiveInteger)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } positive_integer_init_; +      } + +      PositiveInteger:: +      PositiveInteger (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NegativeInteger +      // +      namespace +      { +        struct NegativeIntegerInit +        { +          NegativeIntegerInit () +          { +            type_info ti (typeid (NegativeInteger)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } negative_integer_init_; +      } + +      NegativeInteger:: +      NegativeInteger (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Boolean +      // +      namespace +      { +        struct BooleanInit +        { +          BooleanInit () +          { +            type_info ti (typeid (Boolean)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } boolean_init_; +      } + +      Boolean:: +      Boolean (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Float +      // +      namespace +      { +        struct FloatInit +        { +          FloatInit () +          { +            type_info ti (typeid (Float)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } float_init_; +      } + +      Float:: +      Float (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Double +      // +      namespace +      { +        struct DoubleInit +        { +          DoubleInit () +          { +            type_info ti (typeid (Double)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } double_init_; +      } + +      Double:: +      Double (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Decimal +      // +      namespace +      { +        struct DecimalInit +        { +          DecimalInit () +          { +            type_info ti (typeid (Decimal)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } decimal_init_; +      } + +      Decimal:: +      Decimal (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // String +      // +      namespace +      { +        struct StringInit +        { +          StringInit () +          { +            type_info ti (typeid (String)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } string_init_; +      } + +      String:: +      String (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NormalizedString +      // +      namespace +      { +        struct NormalizedStringInit +        { +          NormalizedStringInit () +          { +            type_info ti (typeid (NormalizedString)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } normalized_string_init_; +      } + +      NormalizedString:: +      NormalizedString (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Token +      // +      namespace +      { +        struct TokenInit +        { +          TokenInit () +          { +            type_info ti (typeid (Token)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } token_init_; +      } + +      Token:: +      Token (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Name +      // +      namespace +      { +        struct NameInit +        { +          NameInit () +          { +            type_info ti (typeid (Name)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } name_init_; +      } + +      Name:: +      Name (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NameToken +      // +      namespace +      { +        struct NameTokenInit +        { +          NameTokenInit () +          { +            type_info ti (typeid (NameToken)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } name_token_init_; +      } + +      NameToken:: +      NameToken (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NameTokens +      // +      namespace +      { +        struct NameTokensInit +        { +          NameTokensInit () +          { +            type_info ti (typeid (NameTokens)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } name_tokens_init_; +      } + +      NameTokens:: +      NameTokens (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // NCName +      // +      namespace +      { +        struct NCNameInit +        { +          NCNameInit () +          { +            type_info ti (typeid (NCName)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } NC_name_init_; +      } + +      NCName:: +      NCName (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Language +      // +      namespace +      { +        struct LanguageInit +        { +          LanguageInit () +          { +            type_info ti (typeid (Language)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } language_init_; +      } + +      Language:: +      Language (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // QName +      // +      namespace +      { +        struct QNameInit +        { +          QNameInit () +          { +            type_info ti (typeid (QName)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } q_name_init_; +      } + +      QName:: +      QName (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Id +      // +      namespace +      { +        struct IdInit +        { +          IdInit () +          { +            type_info ti (typeid (Id)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } id_init_; +      } + +      Id:: +      Id (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // IdRef +      // +      namespace +      { +        struct IdRefInit +        { +          IdRefInit () +          { +            type_info ti (typeid (IdRef)); +	    ti.add_base (typeid (Type)); +            ti.add_base (typeid (Specialization)); +            insert (ti); +          } + +        } id_ref_init_; +      } + +      IdRef:: +      IdRef (Path const& file, +             unsigned long line, +             unsigned long column) +          : Node (file, line, column) +      { +      } + + +      // IdRefs +      // +      namespace +      { +        struct IdRefsInit +        { +          IdRefsInit () +          { +            type_info ti (typeid (IdRefs)); +	    ti.add_base (typeid (Type)); +            ti.add_base (typeid (Specialization)); +            insert (ti); +          } + +        } id_refs_init_; +      } + +      IdRefs:: +      IdRefs (Path const& file, +              unsigned long line, +              unsigned long column) +          : Node (file, line, column) +      { +      } + + +      // AnyURI +      // +      namespace +      { +        struct AnyURIInit +        { +          AnyURIInit () +          { +            type_info ti (typeid (AnyURI)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } any_URI_init_; +      } + +      AnyURI:: +      AnyURI (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Base64Binary +      // +      namespace +      { +        struct Base64BinaryInit +        { +          Base64BinaryInit () +          { +            type_info ti (typeid (Base64Binary)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } base_64_binary_init_; +      } + +      Base64Binary:: +      Base64Binary (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // HexBinary +      // +      namespace +      { +        struct HexBinaryInit +        { +          HexBinaryInit () +          { +            type_info ti (typeid (HexBinary)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } hex_binary_init_; +      } + +      HexBinary:: +      HexBinary (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Date +      // +      namespace +      { +        struct DateInit +        { +          DateInit () +          { +            type_info ti (typeid (Date)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } date_init_; +      } + +      Date:: +      Date (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // DateTime +      // +      namespace +      { +        struct DateTimeInit +        { +          DateTimeInit () +          { +            type_info ti (typeid (DateTime)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } date_time_init_; +      } + +      DateTime:: +      DateTime (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Duration +      // +      namespace +      { +        struct DurationInit +        { +          DurationInit () +          { +            type_info ti (typeid (Duration)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } duration_init_; +      } + +      Duration:: +      Duration (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Day +      // +      namespace +      { +        struct DayInit +        { +          DayInit () +          { +            type_info ti (typeid (Day)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } day_init_; +      } + +      Day:: +      Day (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Month +      // +      namespace +      { +        struct MonthInit +        { +          MonthInit () +          { +            type_info ti (typeid (Month)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } month_init_; +      } + +      Month:: +      Month (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // MonthDay +      // +      namespace +      { +        struct MonthDayInit +        { +          MonthDayInit () +          { +            type_info ti (typeid (MonthDay)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } month_day_init_; +      } + +      MonthDay:: +      MonthDay (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Year +      // +      namespace +      { +        struct YearInit +        { +          YearInit () +          { +            type_info ti (typeid (Year)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } year_init_; +      } + +      Year:: +      Year (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // YearMonth +      // +      namespace +      { +        struct YearMonthInit +        { +          YearMonthInit () +          { +            type_info ti (typeid (YearMonth)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } year_month_init_; +      } + +      YearMonth:: +      YearMonth (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Time +      // +      namespace +      { +        struct TimeInit +        { +          TimeInit () +          { +            type_info ti (typeid (Time)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } time_init_; +      } + +      Time:: +      Time (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Entity +      // +      namespace +      { +        struct EntityInit +        { +          EntityInit () +          { +            type_info ti (typeid (Entity)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } entity_init_; +      } + +      Entity:: +      Entity (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Entities +      // +      namespace +      { +        struct EntitiesInit +        { +          EntitiesInit () +          { +            type_info ti (typeid (Entities)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } entities_init_; +      } + +      Entities:: +      Entities (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } + + +      // Notation +      // +      namespace +      { +        struct NotationInit +        { +          NotationInit () +          { +            type_info ti (typeid (Notation)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } notation_init_; +      } + +      Notation:: +      Notation (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      } +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 new file mode 100644 index 0000000..c336ab8 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 @@ -0,0 +1,211 @@ +divert(-1) + +# file      : xsd-frontend/semantic-graph/fundamental.cxx.m4 +# copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include(`fundamental.m4') + +define(`fundamental_type', +  `fundamental_type_impl(`make_class_name(`$1')', `make_var_name(`$1')')') + + +define(`fundamental_type_impl', ` + +      // $1 +      // +      namespace +      { +        struct $1Init +        { +          $1Init () +          { +            type_info ti (typeid ($1)); +            ti.add_base (typeid (Type)); +            insert (ti); +          } + +        } $2_init_; +      } + +      $1:: +      $1 (Path const& file, +          unsigned long line, +          unsigned long column) +        : Node (file, line, column) +      { +      }') + +divert(0)dnl +dnl +dnl +dnl +// file      : xsd-frontend/semantic-graph/fundamental.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      using compiler::type_info; + +      // Type +      // +      namespace +      { +        struct TypeInit +        { +          TypeInit () +          { +            type_info ti (typeid (Type)); +            ti.add_base (typeid (SemanticGraph::Type)); +            insert (ti); +          } +        } any_type_init_; +      } + +      Type:: +      Type () +      { +      } +dnl +dnl Integers. +dnl +fundamental_type(`byte') +fundamental_type(`unsigned byte') +fundamental_type(`short') +fundamental_type(`unsigned short') +fundamental_type(`int') +fundamental_type(`unsigned int') +fundamental_type(`long') +fundamental_type(`unsigned long') +fundamental_type(`integer') +fundamental_type(`non positive integer') +fundamental_type(`non negative integer') +fundamental_type(`positive integer') +fundamental_type(`negative integer') +dnl +dnl Boolean. +dnl +fundamental_type(`boolean') +dnl +dnl Floats. +dnl +fundamental_type(`float') +fundamental_type(`double') +fundamental_type(`decimal') +dnl +dnl Strings. +dnl +fundamental_type(`string') +fundamental_type(`normalized string') +fundamental_type(`token') +fundamental_type(`name') +fundamental_type(`name token') +fundamental_type(`name tokens') +fundamental_type(`NC name') +fundamental_type(`language') +dnl +dnl Qualified name. +dnl +fundamental_type(`q name') +dnl +dnl ID/IDREF. +dnl +fundamental_type(`id') + + +      // IdRef +      // +      namespace +      { +        struct IdRefInit +        { +          IdRefInit () +          { +            type_info ti (typeid (IdRef)); +	    ti.add_base (typeid (Type)); +            ti.add_base (typeid (Specialization)); +            insert (ti); +          } + +        } id_ref_init_; +      } + +      IdRef:: +      IdRef (Path const& file, +             unsigned long line, +             unsigned long column) +          : Node (file, line, column) +      { +      } + + +      // IdRefs +      // +      namespace +      { +        struct IdRefsInit +        { +          IdRefsInit () +          { +            type_info ti (typeid (IdRefs)); +	    ti.add_base (typeid (Type)); +            ti.add_base (typeid (Specialization)); +            insert (ti); +          } + +        } id_refs_init_; +      } + +      IdRefs:: +      IdRefs (Path const& file, +              unsigned long line, +              unsigned long column) +          : Node (file, line, column) +      { +      } +dnl +dnl URI. +dnl +fundamental_type(`any URI') +dnl +dnl Binary. +dnl +fundamental_type(`base 64 binary') +fundamental_type(`hex binary') +dnl +dnl Date/time. +dnl +fundamental_type(`date') +fundamental_type(`date time') +fundamental_type(`duration') +fundamental_type(`day') +fundamental_type(`month') +fundamental_type(`month day') +fundamental_type(`year') +fundamental_type(`year month') +fundamental_type(`time') +dnl +dnl Entity. +dnl +fundamental_type(`entity') +fundamental_type(`entities') +dnl +dnl Notation. +dnl +fundamental_type(`notation') +dnl +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx new file mode 100644 index 0000000..d810824 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx @@ -0,0 +1,516 @@ +// file      : xsd-frontend/semantic-graph/fundamental.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      // +      // +      class Type: public virtual SemanticGraph::Type +      { +      protected: +        Type (); +      }; + + +      // +      // +      class Byte: public virtual Type +      { +      public: +        Byte (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class UnsignedByte: public virtual Type +      { +      public: +        UnsignedByte (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Short: public virtual Type +      { +      public: +        Short (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class UnsignedShort: public virtual Type +      { +      public: +        UnsignedShort (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Int: public virtual Type +      { +      public: +        Int (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class UnsignedInt: public virtual Type +      { +      public: +        UnsignedInt (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Long: public virtual Type +      { +      public: +        Long (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class UnsignedLong: public virtual Type +      { +      public: +        UnsignedLong (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Integer: public virtual Type +      { +      public: +        Integer (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NonPositiveInteger: public virtual Type +      { +      public: +        NonPositiveInteger (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NonNegativeInteger: public virtual Type +      { +      public: +        NonNegativeInteger (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class PositiveInteger: public virtual Type +      { +      public: +        PositiveInteger (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NegativeInteger: public virtual Type +      { +      public: +        NegativeInteger (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Boolean: public virtual Type +      { +      public: +        Boolean (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Float: public virtual Type +      { +      public: +        Float (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Double: public virtual Type +      { +      public: +        Double (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Decimal: public virtual Type +      { +      public: +        Decimal (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class String: public virtual Type +      { +      public: +        String (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NormalizedString: public virtual Type +      { +      public: +        NormalizedString (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Token: public virtual Type +      { +      public: +        Token (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Name: public virtual Type +      { +      public: +        Name (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NameToken: public virtual Type +      { +      public: +        NameToken (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NameTokens: public virtual Type +      { +      public: +        NameTokens (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class NCName: public virtual Type +      { +      public: +        NCName (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Language: public virtual Type +      { +      public: +        Language (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class QName: public virtual Type +      { +      public: +        QName (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Id: public virtual Type +      { +      public: +        Id (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class IdRef: public virtual Type, +                   public virtual Specialization +      { +      public: +        IdRef (Path const& file, +               unsigned long line, +               unsigned long column); +      }; + + +      // +      // +      class IdRefs: public virtual Type, +                    public virtual Specialization +      { +      public: +        IdRefs (Path const& file, +                unsigned long line, +                unsigned long column); +      }; + + +      // +      // +      class AnyURI: public virtual Type +      { +      public: +        AnyURI (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Base64Binary: public virtual Type +      { +      public: +        Base64Binary (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class HexBinary: public virtual Type +      { +      public: +        HexBinary (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Date: public virtual Type +      { +      public: +        Date (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class DateTime: public virtual Type +      { +      public: +        DateTime (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Duration: public virtual Type +      { +      public: +        Duration (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Day: public virtual Type +      { +      public: +        Day (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Month: public virtual Type +      { +      public: +        Month (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class MonthDay: public virtual Type +      { +      public: +        MonthDay (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Year: public virtual Type +      { +      public: +        Year (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class YearMonth: public virtual Type +      { +      public: +        YearMonth (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Time: public virtual Type +      { +      public: +        Time (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Entity: public virtual Type +      { +      public: +        Entity (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Entities: public virtual Type +      { +      public: +        Entities (Path const& file, +            unsigned long line, +            unsigned long column); +      }; + + +      // +      // +      class Notation: public virtual Type +      { +      public: +        Notation (Path const& file, +            unsigned long line, +            unsigned long column); +      }; +    } +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 new file mode 100644 index 0000000..52c9c89 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 @@ -0,0 +1,155 @@ +divert(-1) + +# file      : xsd-frontend/semantic-graph/fundamental.hxx.m4 +# copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include(`fundamental.m4') + +define(`fundamental_type', `fundamental_type_impl(`make_class_name(`$1')', `$1')') + +define(`fundamental_type_impl', ` + +      // +      // +      class $1: public virtual Type +      { +      public: +        $1 (Path const& file, +            unsigned long line, +            unsigned long column); +      };') +divert(0)dnl +dnl +dnl +dnl +// file      : xsd-frontend/semantic-graph/fundamental.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      // +      // +      class Type: public virtual SemanticGraph::Type +      { +      protected: +        Type (); +      }; +dnl +dnl Integers. +dnl +fundamental_type(`byte') +fundamental_type(`unsigned byte') +fundamental_type(`short') +fundamental_type(`unsigned short') +fundamental_type(`int') +fundamental_type(`unsigned int') +fundamental_type(`long') +fundamental_type(`unsigned long') +fundamental_type(`integer') +fundamental_type(`non positive integer') +fundamental_type(`non negative integer') +fundamental_type(`positive integer') +fundamental_type(`negative integer') +dnl +dnl Boolean. +dnl +fundamental_type(`boolean') +dnl +dnl Floats. +dnl +fundamental_type(`float') +fundamental_type(`double') +fundamental_type(`decimal') +dnl +dnl Strings. +dnl +fundamental_type(`string') +fundamental_type(`normalized string') +fundamental_type(`token') +fundamental_type(`name') +fundamental_type(`name token') +fundamental_type(`name tokens') +fundamental_type(`NC name') +fundamental_type(`language') +dnl +dnl Qualified name. +dnl +fundamental_type(`q name') +dnl +dnl ID/IDREF. +dnl +fundamental_type(`id') + + +      // +      // +      class IdRef: public virtual Type, +                   public virtual Specialization +      { +      public: +        IdRef (Path const& file, +               unsigned long line, +               unsigned long column); +      }; + + +      // +      // +      class IdRefs: public virtual Type, +                    public virtual Specialization +      { +      public: +        IdRefs (Path const& file, +                unsigned long line, +                unsigned long column); +      }; +dnl +dnl URI. +dnl +fundamental_type(`any URI') +dnl +dnl Binary. +dnl +fundamental_type(`base 64 binary') +fundamental_type(`hex binary') +dnl +dnl Date/time. +dnl +fundamental_type(`date') +fundamental_type(`date time') +fundamental_type(`duration') +fundamental_type(`day') +fundamental_type(`month') +fundamental_type(`month day') +fundamental_type(`year') +fundamental_type(`year month') +fundamental_type(`time') +dnl +dnl Entity. +dnl +fundamental_type(`entity') +fundamental_type(`entities') +dnl +dnl Notation. +dnl +fundamental_type(`notation') +dnl +    } +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 new file mode 100644 index 0000000..b9243f7 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 @@ -0,0 +1,17 @@ +# file      : xsd-frontend/semantic-graph/fundamental.m4 +# copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +define(`upcase', `translit(`$*', `a-z', `A-Z')') + + +define(`capitalize_word', +  `regexp(`$1', `^\(.\)\(.*\)', `upcase(`\1')`\2'')') + + +define(`capitalize', +  `patsubst(`$1', `\w+', `capitalize_word(`\&')')') + +define(`make_class_name', `patsubst(capitalize(`$1'), ` ')') + +define(`make_var_name', `patsubst(`$1', ` ', `_')') diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx new file mode 100644 index 0000000..f62f617 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx @@ -0,0 +1,34 @@ +// file      : xsd-frontend/semantic-graph/list.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/list.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    List:: +    List (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct ListInit +      { +        ListInit () +        { +          type_info ti (typeid (List)); +          ti.add_base (typeid (Specialization)); +          insert (ti); +        } +      } list_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx new file mode 100644 index 0000000..d7f370f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx @@ -0,0 +1,22 @@ +// file      : xsd-frontend/semantic-graph/list.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class List: public virtual Specialization +    { +    public: +      List (Path const& file, unsigned long line, unsigned long column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx new file mode 100644 index 0000000..e33a892 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx @@ -0,0 +1,34 @@ +// file      : xsd-frontend/semantic-graph/namespace.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    Namespace:: +    Namespace (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct NamespaceInit +      { +        NamespaceInit () +        { +          type_info ti (typeid (Namespace)); +          ti.add_base (typeid (Scope)); +          insert (ti); +        } +      } namespace_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx new file mode 100644 index 0000000..ccc9d61 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx @@ -0,0 +1,27 @@ +// file      : xsd-frontend/semantic-graph/namespace.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Namespace : public virtual Scope +    { +    public: +      Namespace (Path const& file, unsigned long line, unsigned long column); + +      void +      add_edge_right (BelongsToNamespace&) {} + +      using Scope::add_edge_right; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx new file mode 100644 index 0000000..c3269e6 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx @@ -0,0 +1,54 @@ +// file      : xsd-frontend/semantic-graph/particle.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // ContainsParticle +    // +    ContainsParticle:: +    ContainsParticle (unsigned long min, unsigned long max) +        : particle_ (0), compositor_ (0), min_ (min), max_ (max) +    { +    } + +    // Particle +    // +    Particle:: +    Particle () +        : contained_particle_ (0) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct ContainsParticleInit +      { +        ContainsParticleInit () +        { +          type_info ti (typeid (ContainsParticle)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } contains_particle_init_; + +      struct ParticleInit +      { +        ParticleInit () +        { +          type_info ti (typeid (Particle)); +          ti.add_base (typeid (Node)); +          insert (ti); +        } +      } particle_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx new file mode 100644 index 0000000..a7f0755 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx @@ -0,0 +1,140 @@ +// file      : xsd-frontend/semantic-graph/particle.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class Particle; +    class Compositor; + + +    // +    // +    class ContainsParticle: public virtual Edge +    { +    public: +      Particle& +      particle () const +      { +        return *particle_; +      } + +      Compositor& +      compositor () const +      { +        return *compositor_; +      } + +    public: +      unsigned long +      min () const +      { +        return min_; +      } + +      unsigned long +      max () const +      { +        return max_; +      } + +    public: +      ContainsParticle (unsigned long min, unsigned long max); + +      void +      set_left_node (Compositor& n) +      { +        compositor_ = &n; +      } + +      void +      set_right_node (Particle& n) +      { +        particle_ = &n; +      } + +      void +      clear_left_node (Compositor& n) +      { +        assert (compositor_ == &n); +        compositor_ = 0; +      } + +      void +      clear_right_node (Particle& n) +      { +        assert (particle_ == &n); +        particle_ = 0; +      } + +    private: +      Particle* particle_; +      Compositor* compositor_; +      unsigned long min_, max_; +    }; + +    // +    // +    class Particle: public virtual Node +    { +    public: +      bool +      contained_particle_p () +      { +        return contained_particle_ != 0; +      } + +      ContainsParticle& +      contained_particle () +      { +        assert (contained_particle_ != 0); +        return *contained_particle_; +      } + +    public: +      unsigned long +      min () const +      { +        assert (contained_particle_ != 0); +        return contained_particle_->min (); +      } + +      unsigned long +      max () const +      { +        assert (contained_particle_ != 0); +        return contained_particle_->max (); +      } + +    public: +      Particle (); + +      void +      add_edge_right (ContainsParticle& e) +      { +        contained_particle_ = &e; +      } + +      void +      remove_edge_right (ContainsParticle& e) +      { +        assert (contained_particle_ == &e); +        contained_particle_ = 0; +      } + +    private: +      ContainsParticle* contained_particle_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx new file mode 100644 index 0000000..d1cbf25 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx @@ -0,0 +1,130 @@ +// file      : xsd-frontend/semantic-graph/schema.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // Schema +    // +    Schema::NamesIteratorPair Schema:: +    find (Name const& name) const +    { +      // Here we are going to create an illusion that the namespace +      // hierarchy is flat. +      names_.clear (); +      schemas_.clear (); + +      find_ (name, names_, schemas_); + +      return NamesIteratorPair (NamesConstIterator (names_.begin ()), +                                NamesConstIterator (names_.end ())); +    } + +    void Schema:: +    find_ (Name const& name, NamesList& names, SchemaSet& set) const +    { +      set.insert (this); + +      // Check our own namespace first so it will end up first in the list. +      // +      NamesIteratorPair pair (Scope::find (name)); +      names.insert (names.end (), pair.first.base (), pair.second.base ()); + +      for (UsesIterator i (uses_begin ()), end (uses_end ()); i != end; ++i) +      { +        Schema& s (i->schema ()); + +        if (set.find (&s) == set.end ()) +          s.find_ (name, names, set); +      } +    } + +    namespace +    { +      using compiler::type_info; + +      // Uses +      // +      struct UsesInit +      { +        UsesInit () +        { +          type_info ti (typeid (Uses)); +          ti.add_base (typeid (Edge)); +          insert (ti); +        } +      } uses_init_; + + +      // Implies +      // +      struct ImpliesInit +      { +        ImpliesInit () +        { +          type_info ti (typeid (Implies)); +          ti.add_base (typeid (Uses)); +          insert (ti); +        } +      } implies_init_; + + +      // Sources +      // +      struct SourcesInit +      { +        SourcesInit () +        { +          type_info ti (typeid (Sources)); +          ti.add_base (typeid (Uses)); +          insert (ti); +        } +      } sources_init_; + + +      // Includes +      // +      struct IncludesInit +      { +        IncludesInit () +        { +          type_info ti (typeid (Includes)); +          ti.add_base (typeid (Uses)); +          insert (ti); +        } +      } includes_init_; + + +      // Imports +      // +      struct ImportsInit +      { +        ImportsInit () +        { +          type_info ti (typeid (Imports)); +          ti.add_base (typeid (Uses)); +          insert (ti); +        } +      } imports_init_; + + +      // Schema +      // +      struct SchemaInit +      { +        SchemaInit () +        { +          type_info ti (typeid (Schema)); +          ti.add_base (typeid (Scope)); +          insert (ti); +        } +      } schema_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx new file mode 100644 index 0000000..803c870 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx @@ -0,0 +1,237 @@ +// file      : xsd-frontend/semantic-graph/schema.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX + +#include <set> +#include <vector> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Schema; + +    class Uses: public virtual Edge +    { +    public: +      Schema& +      user () const +      { +        return *user_; +      } + +      Schema& +      schema () const +      { +        return *schema_; +      } + +      Path +      path () const +      { +        return path_; +      } + +    public: +      Uses (Path const& path): path_ (path) {} + +      void +      set_left_node (Schema& s) +      { +        user_ = &s; +      } + +      void +      set_right_node (Schema& s) +      { +        schema_ = &s; +      } + +    private: +      Path path_; +      Schema* user_; +      Schema* schema_; +    }; + + +    // +    // +    class Implies: public virtual Uses +    { +    public: +      Implies (Path const& path): Uses (path) {} +    }; + + +    // +    // +    class Sources: public virtual Uses +    { +    public: +      Sources (Path const& path): Uses (path) {} +    }; + + +    // +    // +    class Includes: public virtual Uses +    { +    public: +      Includes (Path const& path): Uses (path) {} +    }; + + +    // +    // +    class Imports: public virtual Uses +    { +    public: +      Imports (Path const& path): Uses (path) {} +    }; + +    // +    // +    class Schema: public graph, public virtual Scope +    { +      typedef std::vector<Uses*> UsesList; +      typedef std::vector<Uses*> UsedList; + +    public: +      Schema (Path const& file, unsigned long line, unsigned long column) +          : Node (file, line, column), graph_ (*this) +      { +      } + +    private: +      Schema (Schema const&); +      Schema& operator= (Schema const&); + +    public: +      typedef pointer_iterator<UsesList::const_iterator> UsesIterator; + +      UsesIterator +      uses_begin () const +      { +        return uses_.begin (); +      } + +      UsesIterator +      uses_end () const +      { +        return uses_.end (); +      } + +    public: +      typedef pointer_iterator<UsedList::const_iterator> UsedIterator; + +      UsedIterator +      used_begin () const +      { +        return used_.begin (); +      } + +      UsedIterator +      used_end () const +      { +        return used_.end (); +      } + +      bool +      used_p () const +      { +        return used_begin () != used_end (); +      } + +      virtual NamesIteratorPair +      find (Name const& name) const; + +    public: +      using graph::new_edge; +      using graph::reset_left_node; +      using graph::reset_right_node; +      using graph::add_edge_left; +      using graph::add_edge_right; +      using graph::delete_node; +      using graph::delete_edge; + +      template <typename T> +      T& +      new_node (Path const& file, unsigned long line, unsigned long column) +      { +        return graph_.new_node<T> (file, line, column); +      } + +      template <typename T, typename A0> +      T& +      new_node (Path const& file, unsigned long line, unsigned long column, +                A0 const& a0) +      { +        return graph_.new_node<T> (file, line, column, a0); +      } + +      template <typename T, typename A0, typename A1> +      T& +      new_node (Path const& file, unsigned long line, unsigned long column, +                A0 const& a0, A1 const& a1) +      { +        return graph_.new_node<T> (file, line, column, a0, a1); +      } + +      template <typename T, typename A0, typename A1, typename A2> +      T& +      new_node (Path const& file, unsigned long line, unsigned long column, +                A0 const& a0, A1 const& a1, A2 const& a2) +      { +        return graph_.new_node<T> (file, line, column, a0, a1, a2); +      } + +      template <typename T, typename A0, typename A1, typename A2, +                typename A3> +      T& +      new_node (Path const& file, unsigned long line, unsigned long column, +                A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +      { +        return graph_.new_node<T> (file, line, column, a0, a1, a2, a3); +      } + +    public: +      using Scope::add_edge_left; +      using Node::add_edge_right; + +      void +      add_edge_left (Uses& e) +      { +        uses_.push_back (&e); +      } + +      void +      add_edge_right (Uses& e) +      { +        used_.push_back (&e); +      } + +    private: +      typedef std::set<Schema const*> SchemaSet; + +      void +      find_ (Name const& name, NamesList&, SchemaSet&) const; + +    private: +      graph& graph_; + +      UsesList uses_; +      UsedList used_; + +      mutable NamesList names_; +      mutable SchemaSet schemas_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx new file mode 100644 index 0000000..4e7436d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx @@ -0,0 +1,34 @@ +// file      : xsd-frontend/semantic-graph/union.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <xsd-frontend/semantic-graph/union.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    Union:: +    Union (Path const& file, unsigned long line, unsigned long column) +        : Node (file, line, column) +    { +    } + +    namespace +    { +      using compiler::type_info; + +      struct UnionInit +      { +        UnionInit () +        { +          type_info ti (typeid (Union)); +          ti.add_base (typeid (Specialization)); +          insert (ti); +        } +      } union_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx new file mode 100644 index 0000000..d7ba385 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx @@ -0,0 +1,22 @@ +// file      : xsd-frontend/semantic-graph/union.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Union: public virtual Specialization +    { +    public: +      Union (Path const& file, unsigned long line, unsigned long column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX 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 () +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx new file mode 100644 index 0000000..cafd187 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx @@ -0,0 +1,57 @@ +// file      : xsd-frontend/transformations/anonymous.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    class AnonymousNameTranslator +    { +    public: +      virtual +      ~AnonymousNameTranslator (); + +      // The file argument is empty for the currect translation +      // unit. +      // +      virtual String +      translate (String const& file, +                 String const& ns, +                 String const& name, +                 String const& xpath) = 0; +    }; + +    // This transformation morphs anonymous types into named ones +    // with the names derived from the enclosing attributes and +    // elements. If the detect_unstable_conflicts argument is true +    // then the transformation detects and reports unstable conflicts +    // in name assignment. +    // +    class Anonymous +    { +    public: +      struct Failed {}; + +      Anonymous (AnonymousNameTranslator&); + +      void +      transform (SemanticGraph::Schema&, +                 SemanticGraph::Path const&, +                 bool detect_unstable_conflicts); + +    private: +      AnonymousNameTranslator& trans_; +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx new file mode 100644 index 0000000..26ad16c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx @@ -0,0 +1,245 @@ +// file      : xsd-frontend/transformations/enum-synthesis.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <xsd-frontend/transformations/enum-synthesis.hxx> + +namespace XSDFrontend +{ +  namespace +  { +    typedef std::set<String> Enumerators; + +    struct Enumerator: Traversal::Enumerator +    { +      Enumerator (SemanticGraph::Schema& s, +                  SemanticGraph::Enumeration& e, +                  Enumerators& enumerators) +          : schema_ (s), enum_ (e), enumerators_ (enumerators) +      { +      } + +      virtual void +      traverse (Type& e) +      { +        String const& name (e.name ()); + +        if (enumerators_.find (name) == enumerators_.end ()) +        { +          enumerators_.insert (name); + +          // Clone the enumerator and add it to enum_. +          // +          Type& c (schema_.new_node<Type> (e.file (), e.line (), e.column ())); + +          schema_.new_edge<SemanticGraph::Names> (enum_, c, name); +          schema_.new_edge<SemanticGraph::Belongs> (c, enum_); + +          if (e.annotated_p ()) +            schema_.new_edge<SemanticGraph::Annotates> (e.annotation (), c); +        } +      } + +    private: +      SemanticGraph::Schema& schema_; +      SemanticGraph::Enumeration& enum_; +      Enumerators& enumerators_; +    }; + +    // +    // +    struct Union: Traversal::Union +    { +      Union (SemanticGraph::Schema& schema) +          : schema_ (schema) +      { +      } + +      virtual void +      traverse (Type& u) +      { +        using SemanticGraph::Enumeration; + +        SemanticGraph::Context& uc (u.context ()); + +        if (uc.count ("xsd-frontend-enum-synthesis-processed")) +          return; + +        uc.set ("xsd-frontend-enum-synthesis-processed", true); + +        // First see if this union is suitable for synthesis. +        // +        SemanticGraph::Type* base (0); + +        for (Type::ArgumentedIterator i (u.argumented_begin ()); +             i != u.argumented_end (); ++i) +        { +          if (i->type ().is_a<SemanticGraph::Union> ()) +          { +            // See if we can synthesize an enum for this union. This +            // call can change the value i->type() returns. +            // +            dispatch (i->type ()); +          } + +          SemanticGraph::Type& t (i->type ()); + +          if (!t.is_a<Enumeration> ()) +            return; + +          // Make sure all the enums have a common base. +          // +          if (base == 0) +            base = &t; +          else +          { +            // Traverse the inheritance hierarchy until we fine a +            // common base. +            // +            while (base != 0) +            { +              SemanticGraph::Type* b (&t); + +              for (; b != base && b->inherits_p (); +                   b = &b->inherits ().base ()) ; + +              if (base == b) +                break; + +              // Could not find any match on this level. Go one step +              // lower and try again. +              // +              base = base->inherits_p () ? &base->inherits ().base () : 0; +            } + +            if (base == 0) +              return; // No common base. +          } +        } + +        if (base == 0) +          return; // Empty union. + +        // So this union is suitable for synthesis. Base variable points +        // to the "most-derived" common base type. +        // +        Enumeration& e (schema_.new_node<Enumeration> ( +                          u.file (), u.line (), u.column ())); + +        schema_.new_edge<SemanticGraph::Restricts> (e, *base); + +        // Copy enumerators from the member enums. +        // +        { +          Enumerators set; +          Traversal::Enumeration en; +          Traversal::Names names; +          Enumerator er (schema_, e, set); +          en >> names >> er; + +          for (Type::ArgumentedIterator i (u.argumented_begin ()); +               i != u.argumented_end (); ++i) +          { +            en.dispatch (i->type ()); +          } +        } + +        // Reset edges pointing to union to point to enum. +        // +        if (u.annotated_p ()) +        { +          schema_.reset_right_node (u.annotated (), e); +          schema_.add_edge_right (e, u.annotated ()); +        } + +        schema_.reset_right_node (u.named (), e); +        schema_.add_edge_right (e, u.named ()); + +        for (Type::ClassifiesIterator i (u.classifies_begin ()), +               end (u.classifies_end ()); i != end; ++i) +        { +          schema_.reset_right_node (*i, e); +          schema_.add_edge_right (e, *i); +        } + +        for (Type::BegetsIterator i (u.begets_begin ()), +               end (u.begets_end ()); i != end; ++i) +        { +          schema_.reset_right_node (*i, e); +          schema_.add_edge_right (e, *i); +        } + +        for (Type::ArgumentsIterator i (u.arguments_begin ()), +               end (u.arguments_end ()); i != end; ++i) +        { +          schema_.reset_left_node (*i, e); +          schema_.add_edge_left (e, *i); +        } + +        // Remove Arguments edges pointing to the union. +        // +        while (u.argumented_begin () != u.argumented_end ()) +        { +          SemanticGraph::Arguments& a (*u.argumented_begin ()); +          schema_.delete_edge (a.type (), a.specialization (), a); +        } + +        // Copy context and delete the union node. +        // +        e.context ().swap (uc); +        schema_.delete_node (u); +      } + +    private: +      SemanticGraph::Schema& schema_; +    }; + +    // 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-enum-synthesis-seen")) +        { +          s.context ().set ("xsd-frontend-enum-synthesis-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    void EnumSynthesis:: +    transform (SemanticGraph::Schema& s, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; +      Union u (s); + +      schema >> schema_names >> ns >> ns_names >> u; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-enum-synthesis-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx new file mode 100644 index 0000000..9f0f970 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/transformations/enum-synthesis.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    // This transformation replaces unions of one or more enumerations +    // with the same base with an equivalent synthesized enumeration. +    // This transformation assumes that there are no anonymous types. +    // +    class EnumSynthesis +    { +    public: +      void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/restriction.cxx b/libxsd-frontend/xsd-frontend/transformations/restriction.cxx new file mode 100644 index 0000000..edd74be --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/restriction.cxx @@ -0,0 +1,576 @@ +// file      : xsd-frontend/transformations/restriction.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> +#include <iostream> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <xsd-frontend/transformations/restriction.hxx> + +using namespace std; + +namespace XSDFrontend +{ +  typedef Transformations::Restriction::Failed Failed; +  typedef std::vector<SemanticGraph::Complex*> BaseList; + +  namespace +  { +    // +    // +    struct Complex: Traversal::Complex +    { +      Complex (SemanticGraph::Schema& schema) +          : schema_ (schema) +      { +      } + +      virtual void +      traverse (Type& c) +      { +        using namespace SemanticGraph; +        using SemanticGraph::Complex; + +        if (c.context ().count ("xsd-frontend-restriction-seen")) +          return; + +        c.context ().set ("xsd-frontend-restriction-seen", true); + +        // The base content model can be spread over several types +        // in the inheritance-by-extension hierarchy. +        // +        BaseList base_model; + +        // Since attribute wildcards don't have names, we will have +        // to rely on their relative position to find association. +        // +        BaseList base_list; + +        // Current implementation of semantic graph uses the same Restricts +        // edge for both simple type/content restriction and complex content +        // restriction. Here we are interested in the complex content only. +        // +        // +        if (c.inherits_p () && +            c.inherits ().is_a<Restricts> () && +            !c.inherits ().base ().is_a<AnyType> ()) +        { +          // Go down our inheritance hierarchy until the end or the previous +          // restriction. +          // +          Complex* base (&c); + +          while ((base = dynamic_cast<Complex*> (&base->inherits ().base ()))) +          { +            traverse (*base); // Make sure our base is processed. + +            // Handle attributes. +            // +            merge_attributes (c, *base); + +            base_list.push_back (base); + +            // Collect types that have complex content. +            // +            if (base->contains_compositor_p ()) +              base_model.push_back (base); + +            if (!base->inherits_p () || base->inherits ().is_a<Restricts> ()) +              break; +          } + +          // Handle attribute wildcards. +          // +          handle_any_attributes (c, base_list); + +          // Handle complex content (not for the faint of heart). +          // +          if (c.contains_compositor_p ()) +          { +            // Traverse both restricted content model and base content +            // model (in base_model) while looking for matches. +            // +            Compositor& root (c.contains_compositor ().compositor ()); + +            if (base_model.size () == 1) +              handle (root, +                      base_model[0]->contains_compositor ().compositor ()); +            else +            { +              Compositor::ContainsIterator i (root.contains_begin ()); +              BaseList::reverse_iterator j (base_model.rbegin ()); + +              for (; i != root.contains_end (); ++i, ++j) +              { +                Particle& p (i->particle ()); + +                if (!p.is_a<Compositor> ()) +                { +                  wcerr << p.file () << ":" << p.line () << ":" << p.column () +                        << ": error: expected compositor instead of particle" +                        << endl; +                  throw Failed (); +                } + +                for (; j != base_model.rend (); ++j) +                { +                  if (match (p, (*j)->contains_compositor ().compositor ())) +                  { +                    handle (p, (*j)->contains_compositor ().compositor ()); +                    break; +                  } +                } + +                if (j == base_model.rend ()) +                  break; +              } + +              if (i != root.contains_end ()) +              { +                Particle& p (i->particle ()); + +                wcerr << p.file () << ":" << p.line () << ":" << p.column () +                      << ": error: unable to match restricted compositor" +                      << endl; +                throw Failed (); +              } +            } +          } +        } + +        // Traverse anonymous types (via elements & attributes). +        // +        Traversal::Complex::names (c); +      } + +    private: +      void +      handle (SemanticGraph::Particle& r, SemanticGraph::Particle& b) +      { +        using namespace SemanticGraph; + +        if (r.is_a<Compositor> ()) +        { +          Compositor& rc (dynamic_cast<Compositor&> (r)); +          Compositor& bc (dynamic_cast<Compositor&> (b)); + +          Compositor::ContainsIterator i (rc.contains_begin ()); +          Compositor::ContainsIterator j (bc.contains_begin ()); + +          for (; i != rc.contains_end (); ++i, ++j) +          { +            for (; j != bc.contains_end (); ++j) +            { +              Particle& rp (i->particle ()); +              Particle& bp (j->particle ()); + +              if (typeid (rp) != typeid (bp)) +                continue; + +              if (match (rp, bp)) +              { +                handle (rp, bp); +                break; +              } +            } + +            if (j == bc.contains_end ()) +              break; +          } + +          if (i != rc.contains_end ()) +          { +            Particle& p (i->particle ()); + +            wcerr << p.file () << ":" << p.line () << ":" << p.column () +                  << ": error: unable to match restricted particle" +                  << endl; +            throw Failed (); +          } + +          rc.context ().set ("xsd-frontend-restriction-correspondence", &bc); +        } +        else if (r.is_a<Element> ()) +        { +          // Element +          // +          r.context ().set ("xsd-frontend-restriction-correspondence", +                            dynamic_cast<Element*> (&b)); +        } +        else +        { +          // Wildcard +          // +          r.context ().set ("xsd-frontend-restriction-correspondence", +                            dynamic_cast<Any*> (&b)); +        } +      } + +      bool +      match (SemanticGraph::Particle& r, SemanticGraph::Particle& b) +      { +        using namespace SemanticGraph; + +        if (typeid (r) != typeid (b)) +          return false; + +        if (r.is_a<Compositor> ()) +        { +          Compositor& rc (dynamic_cast<Compositor&> (r)); +          Compositor& bc (dynamic_cast<Compositor&> (b)); + +          Compositor::ContainsIterator i (rc.contains_begin ()); + +          if (i == rc.contains_end ()) +            return true; + +          Particle& rp (i->particle ()); + +          for (Compositor::ContainsIterator j (bc.contains_begin ()); +               j != bc.contains_end (); ++j) +          { +            Particle& bp (j->particle ()); + +            if (typeid (rp) != typeid (bp)) +              continue; + +            if (match (rp, bp)) +              return true; +          } +        } +        else if (r.is_a<Element> ()) +        { +          Element& re (dynamic_cast<Element&> (r)); +          Element& be (dynamic_cast<Element&> (b)); + +          if (re.qualified_p ()) +          { +            if (be.qualified_p () && +                re.name () == be.name () && +                re.namespace_ ().name () == be.namespace_ ().name ()) +              return true; +          } +          else +          { +            if (!be.qualified_p () && re.name () == be.name ()) +              return true; +          } + +          // @@ Need to take into account substitution groups. +          // +        } +        else +        { +          // Wildcard. +          // + +          // @@ To handle this properly we will need to analyze +          //    namespaces. +          // +          return true; +        } + +        return false; +      } + +      void +      merge_attributes (SemanticGraph::Complex& c, +                        SemanticGraph::Complex& base) +      { +        using namespace SemanticGraph; + +        for (Scope::NamesIterator i (base.names_begin ()), +               e (base.names_end ()); i != e; ++i) +        { +          Attribute* prot (dynamic_cast<Attribute*> (&i->named ())); + +          if (prot == 0) +            continue; + +          Name name (prot->name ()); +          Scope::NamesIteratorPair r (c.find (name)); + +          Attribute* a (0); + +          for (; r.first != r.second; ++r.first) +          { +            a = dynamic_cast<Attribute*> (&r.first->named ()); + +            if (a == 0) +              continue; + +            if (prot->qualified_p ()) +            { +              if (a->qualified_p () && +                  prot->namespace_ ().name () == a->namespace_ ().name ()) +              { +                break; +              } +            } +            else +            { +              if (!a->qualified_p ()) +                break; +            } + +            a = 0; +          } + +          if (a == 0) +          { +            a = &schema_.new_node<Attribute> (prot->file (), +                                              prot->line (), +                                              prot->column (), +                                              prot->optional_p (), +                                              prot->global_p (), +                                              prot->qualified_p ()); + +            schema_.new_edge<Names> (c, *a, name); + +            // Transfer namespace. +            // +            if (prot->qualified_p ()) +            { +              schema_.new_edge<BelongsToNamespace> (*a, prot->namespace_ ()); +            } + +            // Default and fixed values if any. +            // +            if (prot->fixed_p ()) +              a->fixed (prot->value ()); +            else if (prot->default_p ()) +              a->default_ (prot->value ()); + +            // Belongs edge. +            // +            schema_.new_edge<Belongs> (*a, prot->type ()); + +            // Transfer annotation. +            // +            if (prot->annotated_p ()) +              schema_.new_edge<Annotates> (prot->annotation (), *a); +          } + +          a->context ().set ("xsd-frontend-restriction-correspondence", prot); +        } +      } + +      void +      handle_any_attributes (SemanticGraph::Complex& c, BaseList& bl) +      { +        using namespace SemanticGraph; + +        BaseList::reverse_iterator bi (bl.rbegin ()), be (bl.rend ()); +        Scope::NamesIterator si; + +        if (bi != be) +          si = (*bi)->names_begin (); + +        for (Scope::NamesIterator i (c.names_begin ()), +               e (c.names_end ()); i != e; ++i) +        { +          AnyAttribute* a (dynamic_cast<AnyAttribute*> (&i->named ())); + +          if (a == 0) +            continue; + +          AnyAttribute* p (0); + +          while (bi != be) +          { +            for (; si != (*bi)->names_end (); ++si) +            { +              p = dynamic_cast<AnyAttribute*> (&si->named ()); + +              if (p != 0) +              { +                ++si; +                break; +              } +            } + +            if (p != 0) +              break; + +            // Didn't find anything in this base. Move on to the next. +            // +            ++bi; + +            if (bi != be) +              si = (*bi)->names_begin (); +          } + +          if (p != 0) +          { +            a->context ().set ("xsd-frontend-restriction-correspondence", p); +          } +          else +          { +            wcerr << a->file () << ":" << a->line () << ":" << a->column () +                  << ": error: unable to find matching wildcard in base type" +                  << endl; +            throw Failed (); +          } +        } +      } + +    private: +      SemanticGraph::Schema& schema_; +    }; + +    // +    // +    struct Anonymous : Traversal::Element, +                       Traversal::Attribute +    { +      Anonymous (Traversal::NodeDispatcher& d1) +          : complex_ (&d1, 0) +      { +        *this >> belongs_ >> complex_; +      } + +      Anonymous (Traversal::NodeDispatcher& d1, +                 Traversal::NodeDispatcher& d2) +          : complex_ (&d1, &d2) +      { +        *this >> belongs_ >> complex_; +      } + +      // Hooks. +      // +    public: +      virtual void +      member_pre (SemanticGraph::Member&) +      { +      } + +      virtual void +      member_post (SemanticGraph::Member&) +      { +      } + +    public: + +      virtual void +      traverse (SemanticGraph::Element& e) +      { +        SemanticGraph::Type& t (e.type ()); + +        if (!t.named_p () && !t.context ().count ("seen")) +        { +          t.context ().set ("seen", true); + +          member_pre (e); + +          Element::belongs (e, belongs_); + +          member_post (e); + +          t.context ().remove ("seen"); +        } +      } + +      virtual void +      traverse (SemanticGraph::Attribute& a) +      { +        SemanticGraph::Type& t (a.type ()); + +        if (!t.named_p () && !t.context ().count ("seen")) +        { +          t.context ().set ("seen", true); + +          member_pre (a); + +          Attribute::belongs (a, belongs_); + +          member_post (a); + +          t.context ().remove ("seen"); +        } +      } + +    private: +      struct Complex : Traversal::Complex +      { +        Complex (Traversal::NodeDispatcher* d1, +                 Traversal::NodeDispatcher* d2) +            : d1_ (d1), d2_ (d2) +        { +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          if (d1_) +            d1_->dispatch (c); + +          if (d2_) +            d2_->dispatch (c); +        } + +      private: +        Traversal::NodeDispatcher* d1_; +        Traversal::NodeDispatcher* d2_; + +      } complex_; + +      Traversal::Belongs belongs_; +    }; + + +    // 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-restriction-seen")) +        { +          s.context ().set ("xsd-frontend-restriction-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    void Restriction:: +    transform (SemanticGraph::Schema& s, 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 (s); +      Anonymous anonymous (complex_type); + +      ns_names >> complex_type; +      ns_names >> anonymous; + +      Traversal::Names names; + +      complex_type >> names >> anonymous; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-restriction-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/restriction.hxx b/libxsd-frontend/xsd-frontend/transformations/restriction.hxx new file mode 100644 index 0000000..6d7410c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/restriction.hxx @@ -0,0 +1,36 @@ +// file      : xsd-frontend/transformations/restriction.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    // This transformation performs two major tasks. It transfers omitted +    // attribute declarations from the base to derived-by-restriction type +    // and establishes correspondence between particles and compositors by +    // adding the "xsd-frontend-restriction-correspondence" key-value pair +    // in the context that contains a pointer to the corresponding particle +    // or compositor in the base. Note that restriction of anyType is +    // a special case and is not handled by this transformation. +    // +    class Restriction +    { +    public: +      struct Failed {}; + +      void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx new file mode 100644 index 0000000..2fc14b5 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx @@ -0,0 +1,469 @@ +// file      : xsd-frontend/transformations/schema-per-type.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <strings.h> // strcasecmp + +#include <map> +#include <set> +#include <vector> + +#include <sstream> +#include <iostream> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <xsd-frontend/transformations/schema-per-type.hxx> + +using std::wcerr; +using std::endl; + +namespace XSDFrontend +{ +  typedef Transformations::SchemaPerType::Failed Failed; +  typedef std::vector<SemanticGraph::Schema*> Schemas; +  typedef std::map<SemanticGraph::Type*, SemanticGraph::Schema*> TypeSchemaMap; + +  // Compare file paths case-insensitively. +  // +  struct FileComparator +  { +    bool +    operator() (NarrowString const& x, NarrowString const& y) const +    { +      return strcasecmp (x.c_str (), y.c_str ()) < 0; +    } +  }; + +  typedef std::set<NarrowString, FileComparator> FileSet; + +  namespace +  { +    // Go into included and imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Includes, +                 Traversal::Imports, +                 Traversal::Implies +    { +      Uses (Schemas& schemas, SemanticGraph::Schema*& xsd) +          : schemas_ (schemas), xsd_ (xsd) +      { +        xsd_ = 0; +      } + +      virtual void +      traverse (SemanticGraph::Includes& i) +      { +        SemanticGraph::Schema& s (i.schema ()); + +        if (!s.context ().count ("xsd-frontend-schema-per-type-seen")) +        { +          schemas_.push_back (&s); +          s.context ().set ("xsd-frontend-schema-per-type-seen", true); +          Traversal::Includes::traverse (i); +        } +      } + +      virtual void +      traverse (SemanticGraph::Imports& i) +      { +        SemanticGraph::Schema& s (i.schema ()); + +        if (!s.context ().count ("xsd-frontend-schema-per-type-seen")) +        { +          schemas_.push_back (&s); +          s.context ().set ("xsd-frontend-schema-per-type-seen", true); +          Traversal::Imports::traverse (i); +        } +      } + +      virtual void +      traverse (SemanticGraph::Implies& i) +      { +        if (xsd_ == 0) +          xsd_ = &i.schema (); +      } + +    private: +      Schemas& schemas_; +      SemanticGraph::Schema*& xsd_; +    }; + +    void +    process_schema (SemanticGraph::Schema& s, +                    SemanticGraph::Schema& root, +                    SemanticGraph::Schema& xsd, +                    TypeSchemaMap& tsm, +                    FileSet& file_set, +                    bool fat_type_file, +                    Transformations::SchemaPerTypeTranslator& trans) +    { +      using namespace SemanticGraph; + +      Path xsd_path ("XMLSchema.xsd"); +      Namespace& ns (dynamic_cast<Namespace&> (s.names_begin ()->named ())); + +      // We should be careful with iterator caching since we are going to +      // remove some of the nodes. +      // +      for (Scope::NamesIterator i (ns.names_begin ()); i != ns.names_end ();) +      { +        Nameable& n (i->named ()); + +        if (n.is_a<Type> ()) +        { +          String name (n.name ()); + +          // Remove from the namespace. +          // +          Scope::NamesIterator tmp (i++); +          root.delete_edge (ns, n, *tmp); + +          // Add a new schema node. +          // +          Path path; +          String tn (trans.translate_type (ns.name (), name)); +          String wbase (tn ? tn : name); + +          try +          { +            NarrowString base (wbase.to_narrow ()); + +            // Escape directory separators unless they came from the +            // translator. +            // +            if (!tn) +            { +              for (NarrowString::iterator i (base.begin ()), e (base.end ()); +                   i != e; ++i) +              { +                if (*i == '/' || *i == '\\') +                  *i = '_'; +              } +            } + +            // Make sure it is unique. +            // +            NarrowString file_name (base); + +            for (unsigned long i (1); +                 file_set.find (file_name) != file_set.end (); +                 ++i) +            { +              std::ostringstream os; +              os << i; +              file_name = base + os.str (); +            } + +            file_set.insert (file_name); +            file_name += ".xsd"; + +            try +            { +              path = Path (file_name); +            } +            catch (InvalidPath const&) +            { +              wcerr << "error: '" << file_name.c_str () << "' is not a valid " +                    << "filesystem path" << endl; + +              wcerr << "info: use type to file name translation mechanism " +                    << "to resolve this" << endl; + +              throw Failed (); +            } +          } +          catch (NonRepresentable const&) +          { +            wcerr << "error: '" << wbase << "' cannot be represented as a " +                  << "narrow string" << endl; + +            wcerr << "info: use type to file name translation mechanism " +                  << "to resolve this" << endl; + +            throw Failed (); +          } + +          Type& t (dynamic_cast<Type&> (n)); + +          Schema& ts (root.new_node<Schema> (path, 1, 1)); +          root.new_edge<Implies> (ts, xsd, xsd_path); + +          Namespace& tns (root.new_node<Namespace> (path, 1, 1)); +          root.new_edge<Names> (ts, tns, ns.name ()); +          root.new_edge<Names> (tns, n, name); + +          // If we are generating fat type files, then also move the global +          // elements this type classifies to the new schema. +          // +          if (fat_type_file) +          { +            for (Type::ClassifiesIterator j (t.classifies_begin ()); +                 j != t.classifies_end (); ++j) +            { +              Instance& e (j->instance ()); + +              // We can only move a global element from the same namespace. +              // +              if (e.is_a<Element> () && +                  e.scope ().is_a<Namespace> () && +                  e.scope ().name () == ns.name ()) +              { +                Names& n (e.named ()); +                String name (n.name ()); + +                // Watch out for the iterator validity: the edge we are +                // about to remove can be from the same list we are +                // currently iterating. +                // +                if (i != ns.names_end () && &*i == &n) +                  ++i; + +                root.delete_edge (n.scope (), e, n); +                root.new_edge<Names> (tns, e, name); +              } +            } +          } + +          // Add include to the original schema and enter into the +          // type-schema map. +          // +          root.new_edge<Includes> (s, ts, path); +          tsm[&t] = &ts; +        } +        else +          ++i; +      } +    } + +    struct Type: Traversal::List, +                 Traversal::Complex, +                 Traversal::Member +    { +      Type (SemanticGraph::Schema& schema, +            SemanticGraph::Schema& root, +            char const* by_value_key, +            TypeSchemaMap& tsm) +          : schema_ (schema), +            root_ (root), +            by_value_key_ (by_value_key), +            tsm_ (tsm) +      { +        *this >> names_ >> *this; +      } + +      virtual void +      traverse (SemanticGraph::List& l) +      { +        // Treat item type as base type since it is impossible +        // to create recursive constructs using list. +        // +        SemanticGraph::Type& t (l.argumented ().type ()); +        set_dep (t, false); +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        if (c.inherits_p ()) +          set_dep (c.inherits ().base (), false); + +        Traversal::Complex::names (c); +      } + +      virtual void +      traverse (SemanticGraph::Member& m) +      { +        SemanticGraph::Type& t (m.type ()); + +        bool weak ( +          by_value_key_ == 0 || +          !t.context ().count (by_value_key_) || +          !t.context ().get<bool> (by_value_key_)); + +        set_dep (t, weak); +      } + +    private: +      void +      set_dep (SemanticGraph::Type& t, bool weak) +      { +        using namespace SemanticGraph; + +        TypeSchemaMap::iterator i (tsm_.find (&t)); + +        // If a type is not present in the map then it must be +        // a built-in type. +        // +        if (i == tsm_.end ()) +          return; + +        // Check if we already saw this type. Theoretically, it could +        // be that we need to upgrade the type of include from weak to +        // strong. But because inheritance is handled first, the type +        // in the set will already be with the right type. +        // +        if (type_set_.find (&t) != type_set_.end ()) +          return; + +        type_set_.insert (&t); + +        Schema& s (*i->second); +        Path path (s.used_begin ()->path ()); +        SemanticGraph::Uses* u; + +        if (s.names_begin ()->name () == schema_.names_begin ()->name ()) +          u = &root_.new_edge<Includes> (schema_, s, path); +        else +          u = &root_.new_edge<Imports> (schema_, s, path); + +        if (weak) +          u->context().set ("weak", true); +      } + +    private: +      SemanticGraph::Schema& schema_; +      SemanticGraph::Schema& root_; +      char const* by_value_key_; +      TypeSchemaMap& tsm_; +      std::set<SemanticGraph::Type*> type_set_; + +      Traversal::Names names_; +    }; +  } + +  namespace Transformations +  { +    SchemaPerType:: +    SchemaPerType (SchemaPerTypeTranslator& trans, +                   bool fat, +                   char const* key) +        : fat_type_file_ (fat), by_value_key_ (key), trans_ (trans) +    { +    } + +    Schemas SchemaPerType:: +    transform (SemanticGraph::Schema& root) +    { +      // Collect initial schema nodes. +      // +      Schemas schemas; +      SemanticGraph::Schema* xsd; + +      { +        Traversal::Schema schema; +        Uses uses (schemas, xsd); + +        schema >> uses >> schema; + +        // Some twisted schemas do recusive inclusions. +        // +        root.context ().set ("xsd-frontend-schema-per-type-seen", true); + +        schema.dispatch (root); +      } + +      // wcerr << schemas.size () << " initial schema nodes" << endl; + +      // Add the schema file names to the file set. +      // +      FileSet file_set; + +      for (Schemas::iterator i (schemas.begin ()); i != schemas.end (); ++i) +      { +        // This path was already normalized by the parser. +        // +        SemanticGraph::Path const& path ( +          (*i)->context ().get<SemanticGraph::Path> ("absolute-path")); + +        // Translate the schema file name. +        // +        NarrowString abs_path; + +        // Try to use the portable representation of the path. If that +        // fails, fall back to the native representation. +        // +        try +        { +          abs_path = path.posix_string (); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          abs_path = path.string (); +        } + +        NarrowString tf (trans_.translate_schema (abs_path)); +        NarrowString file (tf ? tf : path.leaf ().string ()); + +        size_t p (file.rfind ('.')); +        NarrowString ext ( +          p != NarrowString::npos ? NarrowString (file, p) : ""); + +        NarrowString base ( +          p != NarrowString::npos ? NarrowString (file, 0, p) : file); + +        // Make sure it is unique. +        // +        NarrowString new_name (base); + +        for (unsigned long n (1); +             file_set.find (new_name) != file_set.end (); +             ++n) +        { +          std::ostringstream os; +          os << n; +          new_name = base + os.str (); +        } + +        file_set.insert (new_name); +        new_name += ext; + +        try +        { +          (*i)->context ().set ("renamed", SemanticGraph::Path (new_name)); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          wcerr << "error: '" << new_name.c_str () << "' is not a valid " +                << "filesystem path" << endl; + +          wcerr << "info: use schema file name translation mechanism " +                << "to resolve this" << endl; + +          throw Failed (); +        } +      } + +      // Process each schema node. +      // +      TypeSchemaMap tsm; + +      for (Schemas::iterator i (schemas.begin ()); i != schemas.end (); ++i) +      { +        process_schema (**i, root, *xsd, tsm, file_set, fat_type_file_, trans_); +      } + +      // wcerr << tsm.size () << " type schema nodes" << endl; + +      // Establish include/import dependencies. While at it add the +      // new schemas to the list which we will return. +      // +      for (TypeSchemaMap::iterator i (tsm.begin ()); i != tsm.end (); ++i) +      { +        SemanticGraph::Schema& s (*i->second); +        Type t (s, root, by_value_key_, tsm); +        t.dispatch (*i->first); +        schemas.push_back (&s); +      } + +      return schemas; +    } + +    SchemaPerTypeTranslator:: +    ~SchemaPerTypeTranslator () +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx new file mode 100644 index 0000000..8b6a69e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx @@ -0,0 +1,62 @@ +// file      : xsd-frontend/transformations/schema-per-type.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX + +#include <vector> + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    class SchemaPerTypeTranslator +    { +    public: +      virtual +      ~SchemaPerTypeTranslator (); + +      // The following two functions should return empty string if +      // there is no match. +      // +      virtual String +      translate_type (String const& ns, String const& name) = 0; + +      virtual NarrowString +      translate_schema (NarrowString const& abs_path) = 0; +    }; + +    // This transformation restructures the semantic graph to have +    // each type definition in a seperate schema file. +    // +    class SchemaPerType +    { +    public: +      struct Failed {}; + +      // If a type of an element or attribute has a context entry +      // with the by_value_key key and it is true, then the schema +      // for this type is included "strongly". +      // +      SchemaPerType (SchemaPerTypeTranslator&, +                     bool fat_type_file, +                     char const* by_value_key = 0); + +      std::vector<SemanticGraph::Schema*> +      transform (SemanticGraph::Schema&); + +    private: +      bool fat_type_file_; +      char const* by_value_key_; +      SchemaPerTypeTranslator& trans_; +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx new file mode 100644 index 0000000..9372a4a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx @@ -0,0 +1,162 @@ +// file      : xsd-frontend/transformations/simplifier.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <xsd-frontend/transformations/simplifier.hxx> + +namespace XSDFrontend +{ +  namespace +  { +    struct Compositor: Traversal::All, +                       Traversal::Choice, +                       Traversal::Sequence +    { +      Compositor (SemanticGraph::Schema& root) +          : root_ (root) +      { +      } + +      virtual void +      traverse (SemanticGraph::All& a) +      { +        // The all compositor cannot contain compositors. +        // +        if (a.contains_begin () == a.contains_end ()) +          remove (a); +      } + +      virtual void +      traverse (SemanticGraph::Choice& c) +      { +        // Do the depth-first traversal so that we take into account +        // the potential removal of nested compositors. +        // +        using SemanticGraph::Compositor; + +        for (Compositor::ContainsIterator i (c.contains_begin ()); +             i != c.contains_end ();) +        { +          edge_traverser ().dispatch (*i++); +        } + +        Choice::contains (c); + +        if (c.contains_begin () == c.contains_end ()) +          remove (c); +      } + +      virtual void +      traverse (SemanticGraph::Sequence& s) +      { +        // Do the depth-first traversal so that we take into account +        // the potential removal of nested compositors. +        // +        using SemanticGraph::Compositor; + +        for (Compositor::ContainsIterator i (s.contains_begin ()); +             i != s.contains_end ();) +        { +          edge_traverser ().dispatch (*i++); +        } + +        if (s.contains_begin () == s.contains_end ()) +          remove (s); +      } + +    private: +      virtual void +      remove (SemanticGraph::Compositor& c) +      { +        using SemanticGraph::Node; +        using SemanticGraph::Choice; +        using SemanticGraph::Complex; +        using SemanticGraph::Compositor; + +        if (c.contained_particle_p ()) +        { +          Compositor& com (c.contained_particle ().compositor ()); + +          // Empty compositors in choice are important. +          // +          if (!com.is_a<Choice> ()) +            root_.delete_edge (com, c, c.contained_particle ()); +        } +        else +        { +          Complex& con ( +            dynamic_cast<Complex&> (c.contained_compositor ().container ())); +          root_.delete_edge (con, c, c.contained_compositor ()); +        } +      } + +    private: +      SemanticGraph::Schema& root_; +    }; + +    // +    // +    struct Type: Traversal::Complex +    { +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        if (c.contains_compositor_p ()) +          Complex::contains_compositor (c); +      } +    }; + +    // 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-simplifier-seen")) +        { +          s.context ().set ("xsd-frontend-simplifier-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    void Simplifier:: +    transform (SemanticGraph::Schema& s, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; +      Type type; + +      schema >> schema_names >> ns >> ns_names >> type; + +      Compositor compositor (s); +      Traversal::ContainsCompositor contains_compositor; +      Traversal::ContainsParticle contains_particle; + +      type >> contains_compositor >> compositor; +      compositor >> contains_particle >> compositor; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-simplifier-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx b/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx new file mode 100644 index 0000000..674ee45 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/transformations/simplifier.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX + +#include <xsd-frontend/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    // This transformation performs various schema simplifications +    // (e.g., removing empty compositors, etc). This transformation +    // assumes that there are no anonymous types. +    // +    class Simplifier +    { +    public: +      void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal.hxx b/libxsd-frontend/xsd-frontend/traversal.hxx new file mode 100644 index 0000000..10190a1 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal.hxx @@ -0,0 +1,25 @@ +// file      : xsd-frontend/traversal.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_HXX +#define XSD_FRONTEND_TRAVERSAL_HXX + +#include <xsd-frontend/traversal/any.hxx> +#include <xsd-frontend/traversal/any-attribute.hxx> +#include <xsd-frontend/traversal/attribute.hxx> +#include <xsd-frontend/traversal/attribute-group.hxx> +#include <xsd-frontend/traversal/complex.hxx> +#include <xsd-frontend/traversal/compositors.hxx> +#include <xsd-frontend/traversal/element.hxx> +#include <xsd-frontend/traversal/element-group.hxx> +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/traversal/enumeration.hxx> +#include <xsd-frontend/traversal/fundamental.hxx> +#include <xsd-frontend/traversal/list.hxx> +#include <xsd-frontend/traversal/namespace.hxx> +#include <xsd-frontend/traversal/particle.hxx> +#include <xsd-frontend/traversal/schema.hxx> +#include <xsd-frontend/traversal/union.hxx> + +#endif  // XSD_FRONTEND_TRAVERSAL_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx b/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx new file mode 100644 index 0000000..50655dd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx @@ -0,0 +1,21 @@ +// file      : xsd-frontend/traversal/any-attribute.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX +#define XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/any-attribute.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    typedef +    Node<SemanticGraph::AnyAttribute> +    AnyAttribute; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/any.hxx b/libxsd-frontend/xsd-frontend/traversal/any.hxx new file mode 100644 index 0000000..85a320d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/any.hxx @@ -0,0 +1,21 @@ +// file      : xsd-frontend/traversal/any.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ANY_HXX +#define XSD_FRONTEND_TRAVERSAL_ANY_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/any.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    typedef +    Node<SemanticGraph::Any> +    Any; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ANY_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx b/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx new file mode 100644 index 0000000..a40afd7 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx @@ -0,0 +1,29 @@ +// file      : xsd-frontend/traversal/attribute-group.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void AttributeGroup:: +    traverse (Type& g) +    { +      pre (g); +      names (g); +      post (g); +    } + +    void AttributeGroup:: +    pre (Type&) +    { +    } + +    void AttributeGroup:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx b/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx new file mode 100644 index 0000000..03fee14 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx @@ -0,0 +1,29 @@ +// file      : xsd-frontend/traversal/attribute-group.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX +#define XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct AttributeGroup: ScopeTemplate<SemanticGraph::AttributeGroup> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute.cxx b/libxsd-frontend/xsd-frontend/traversal/attribute.cxx new file mode 100644 index 0000000..e61eeb2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute.cxx @@ -0,0 +1,47 @@ +// file      : xsd-frontend/traversal/attribute.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/attribute.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void Attribute:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      name (a); +      post (a); +    } + +    void Attribute:: +    pre (Type&) +    { +    } + +    void Attribute:: +    belongs (Type& a, EdgeDispatcher& d) +    { +      d.dispatch (a.belongs ()); +    } + +    void Attribute:: +    belongs (Type& a) +    { +      belongs (a, *this); +    } + +    void Attribute:: +    name (Type&) +    { +    } + +    void Attribute:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute.hxx b/libxsd-frontend/xsd-frontend/traversal/attribute.hxx new file mode 100644 index 0000000..f3962e4 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute.hxx @@ -0,0 +1,40 @@ +// file      : xsd-frontend/traversal/attribute.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX +#define XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX + +#include <xsd-frontend/traversal/elements.hxx> + +#include <xsd-frontend/semantic-graph/attribute.hxx> + + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Attribute : Node<SemanticGraph::Attribute> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      belongs (Type&, EdgeDispatcher&); + +      virtual void +      belongs (Type&); + +      virtual void +      name (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/complex.cxx b/libxsd-frontend/xsd-frontend/traversal/complex.cxx new file mode 100644 index 0000000..6e936ab --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/complex.cxx @@ -0,0 +1,63 @@ +// file      : xsd-frontend/traversal/complex.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/complex.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void Complex:: +    traverse (Type& c) +    { +      pre (c); +      name (c); +      inherits (c); +      names (c); +      contains_compositor (c); +      post (c); +    } + +    void Complex:: +    pre (Type&) +    { +    } + +    void Complex:: +    name (Type&) +    { +    } + +    void Complex:: +    inherits (Type& c) +    { +      inherits (c, *this); +    } + +    void Complex:: +    inherits (Type& c, EdgeDispatcher& d) +    { +      if (c.inherits_p ()) +        d.dispatch (c.inherits ()); +    } + +    void Complex:: +    contains_compositor (Type& c) +    { +      contains_compositor (c, *this); +    } + +    void Complex:: +    contains_compositor (Type& c, EdgeDispatcher& d) +    { +      if (c.contains_compositor_p ()) +        d.dispatch (c.contains_compositor ()); +    } + +    void Complex:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/complex.hxx b/libxsd-frontend/xsd-frontend/traversal/complex.hxx new file mode 100644 index 0000000..1f55730 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/complex.hxx @@ -0,0 +1,44 @@ +// file      : xsd-frontend/traversal/complex.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX +#define XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Complex : ScopeTemplate<SemanticGraph::Complex> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      name (Type&); + +      virtual void +      inherits (Type&); + +      void +      inherits (Type&, EdgeDispatcher&); + +      virtual void +      contains_compositor (Type&); + +      void +      contains_compositor (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/compositors.cxx b/libxsd-frontend/xsd-frontend/traversal/compositors.cxx new file mode 100644 index 0000000..f2b3dcd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/compositors.cxx @@ -0,0 +1,164 @@ +// file      : xsd-frontend/traversal/compositors.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/compositors.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // ContainsParticle +    // +    void ContainsParticle:: +    traverse (Type& c) +    { +      dispatch (c.particle ()); +    } + + +    // ContainsCompositor +    // +    void ContainsCompositor:: +    traverse (Type& c) +    { +      dispatch (c.compositor ()); +    } + + +    // Compositor +    // +    void Compositor:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    void Compositor:: +    pre (Type&) +    { +    } + +    void Compositor:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    void Compositor:: +    contains (Type& c, EdgeDispatcher& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    void Compositor:: +    post (Type&) +    { +    } + + +    // All +    // +    void All:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    void All:: +    pre (Type&) +    { +    } + +    void All:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    void All:: +    contains (Type& c, EdgeDispatcher& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    void All:: +    post (Type&) +    { +    } + + +    // Choice +    // +    void Choice:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    void Choice:: +    pre (Type&) +    { +    } + +    void Choice:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    void Choice:: +    contains (Type& c, EdgeDispatcher& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    void Choice:: +    post (Type&) +    { +    } + + +    // Sequence +    // +    void Sequence:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    void Sequence:: +    pre (Type&) +    { +    } + +    void Sequence:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    void Sequence:: +    contains (Type& c, EdgeDispatcher& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    void Sequence:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/compositors.hxx b/libxsd-frontend/xsd-frontend/traversal/compositors.hxx new file mode 100644 index 0000000..4761b99 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/compositors.hxx @@ -0,0 +1,135 @@ +// file      : xsd-frontend/traversal/compositors.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX +#define XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // +    // +    struct ContainsParticle: Edge<SemanticGraph::ContainsParticle> +    { +      ContainsParticle () +      { +      } + +      ContainsParticle (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type&); +    }; + + +    // +    // +    struct ContainsCompositor: Edge<SemanticGraph::ContainsCompositor> +    { +      ContainsCompositor () +      { +      } + +      ContainsCompositor (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type&); +    }; + +    // +    // +    struct Compositor : Node<SemanticGraph::Compositor> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      contains (Type&); + +      virtual void +      contains (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; + + +    // +    // +    struct All : Node<SemanticGraph::All> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      contains (Type&); + +      virtual void +      contains (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; + + +    // +    // +    struct Choice : Node<SemanticGraph::Choice> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      contains (Type&); + +      virtual void +      contains (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; + + +    // +    // +    struct Sequence : Node<SemanticGraph::Sequence> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      contains (Type&); + +      virtual void +      contains (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/element-group.cxx b/libxsd-frontend/xsd-frontend/traversal/element-group.cxx new file mode 100644 index 0000000..0b253dd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element-group.cxx @@ -0,0 +1,42 @@ +// file      : xsd-frontend/traversal/element-group.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/element-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void ElementGroup:: +    traverse (Type& g) +    { +      pre (g); +      names (g); +      contains_compositor (g); +      post (g); +    } + +    void ElementGroup:: +    pre (Type&) +    { +    } + +    void ElementGroup:: +    contains_compositor (Type& g, EdgeDispatcher& d) +    { +      d.dispatch (g.contains_compositor ()); +    } + +    void ElementGroup:: +    contains_compositor (Type& g) +    { +      contains_compositor (g, *this); +    } + +    void ElementGroup:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/element-group.hxx b/libxsd-frontend/xsd-frontend/traversal/element-group.hxx new file mode 100644 index 0000000..df13b26 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element-group.hxx @@ -0,0 +1,35 @@ +// file      : xsd-frontend/traversal/element-group.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/element-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct ElementGroup: ScopeTemplate<SemanticGraph::ElementGroup> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      contains_compositor (Type&); + +      virtual void +      contains_compositor (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/element.cxx b/libxsd-frontend/xsd-frontend/traversal/element.cxx new file mode 100644 index 0000000..efdb0a6 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element.cxx @@ -0,0 +1,47 @@ +// file      : xsd-frontend/traversal/element.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/element.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void Element:: +    traverse (Type& m) +    { +      pre (m); +      belongs (m); +      name (m); +      post (m); +    } + +    void Element:: +    pre (Type&) +    { +    } + +    void Element:: +    belongs (Type& m, EdgeDispatcher& d) +    { +      d.dispatch (m.belongs ()); +    } + +    void Element:: +    belongs (Type& m) +    { +      belongs (m, edge_traverser ()); +    } + +    void Element:: +    name (Type&) +    { +    } + +    void Element:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/element.hxx b/libxsd-frontend/xsd-frontend/traversal/element.hxx new file mode 100644 index 0000000..e1af29a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element.hxx @@ -0,0 +1,38 @@ +// file      : xsd-frontend/traversal/element.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/element.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Element : Node<SemanticGraph::Element> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      belongs (Type&, EdgeDispatcher&); + +      virtual void +      belongs (Type&); + +      virtual void +      name (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.cxx b/libxsd-frontend/xsd-frontend/traversal/elements.cxx new file mode 100644 index 0000000..e64e3b9 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.cxx @@ -0,0 +1,76 @@ +// file      : xsd-frontend/traversal/elements.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/elements.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Instance +    // +    void Instance:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      post (a); +    } + +    void Instance:: +    pre (Type&) +    { +    } + +    void Instance:: +    belongs (Type& a, EdgeDispatcher& d) +    { +      d.dispatch (a.belongs ()); +    } + +    void Instance:: +    belongs (Type& a) +    { +      belongs (a, edge_traverser ()); +    } + +    void Instance:: +    post (Type&) +    { +    } + + +    // Member +    // +    void Member:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      post (a); +    } + +    void Member:: +    pre (Type&) +    { +    } + +    void Member:: +    belongs (Type& a, EdgeDispatcher& d) +    { +      d.dispatch (a.belongs ()); +    } + +    void Member:: +    belongs (Type& a) +    { +      belongs (a, edge_traverser ()); +    } + +    void Member:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.hxx b/libxsd-frontend/xsd-frontend/traversal/elements.hxx new file mode 100644 index 0000000..bd1dd70 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.hxx @@ -0,0 +1,411 @@ +// file      : xsd-frontend/traversal/elements.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX + +#include <cutl/compiler/traversal.hxx> + +#include <xsd-frontend/types.hxx> +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    using namespace cutl; + +    typedef compiler::dispatcher<SemanticGraph::Node> NodeDispatcher; +    typedef compiler::dispatcher<SemanticGraph::Edge> EdgeDispatcher; + +    // +    // +    struct NodeBase: NodeDispatcher, EdgeDispatcher +    { +      void +      edge_traverser (EdgeDispatcher& d) +      { +        EdgeDispatcher::traverser (d); +      } + +      EdgeDispatcher& +      edge_traverser () +      { +        return *this; +      } + +      using NodeDispatcher::dispatch; +      using EdgeDispatcher::dispatch; + +      using EdgeDispatcher::iterate_and_dispatch; +    }; + +    struct EdgeBase: EdgeDispatcher, NodeDispatcher +    { +      void +      node_traverser (NodeDispatcher& d) +      { +        NodeDispatcher::traverser (d); +      } + +      NodeDispatcher& +      node_traverser () +      { +        return *this; +      } + +      using EdgeDispatcher::dispatch; +      using NodeDispatcher::dispatch; + +      using NodeDispatcher::iterate_and_dispatch; +    }; + +    inline EdgeBase& +    operator>> (NodeBase& n, EdgeBase& e) +    { +      n.edge_traverser (e); +      return e; +    } + +    inline NodeBase& +    operator>> (EdgeBase& e, NodeBase& n) +    { +      e.node_traverser (n); +      return n; +    } + +    // +    // +    template <typename T> +    struct Node: compiler::traverser_impl<T, SemanticGraph::Node>, +                 virtual NodeBase +    { +      typedef T Type; +    }; + +    template <typename T> +    struct Edge: compiler::traverser_impl<T, SemanticGraph::Edge>, +                 virtual EdgeBase +    { +      typedef T Type; +    }; + +    // +    // Edges +    // + +    // +    // +    struct Names : Edge<SemanticGraph::Names> +    { +      Names () +      { +      } + +      Names (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.named ()); +      } +    }; + + +    // +    // +    struct Belongs : Edge<SemanticGraph::Belongs> +    { +      Belongs () +      { +      } + +      Belongs (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.type ()); +      } +    }; + +    // +    // Nodes +    // + +    // +    // +    struct Nameable : Node<SemanticGraph::Nameable> +    { +    }; + + +    // +    // +    template <typename T> +    struct ScopeTemplate : Node<T> +    { +    public: +      virtual void +      traverse (T& s) +      { +        names (s); +      } + +      template<typename X> +      void +      names (T& s, +             EdgeDispatcher& d, +             void (X::*pre_) (T&) = (void (ScopeTemplate<T>::*)(T&)) (0), +             void (X::*post_) (T&) = (void (ScopeTemplate<T>::*)(T&)) (0), +             void (X::*none_) (T&) = (void (ScopeTemplate<T>::*)(T&)) (0), +             void (X::*next_) (T&) = (void (ScopeTemplate<T>::*)(T&)) (0)) +      { +        X* this_ (dynamic_cast<X*> (this)); + +        typename T::NamesIterator b (s.names_begin ()), e (s.names_end ()); + +        if (b != e) +        { +          if (pre_) +            (this_->*pre_) (s); + +          //iterate_and_dispatch (b, e, d, *this_, next_, s); + +          for (; b != s.names_end ();) +          { +            d.dispatch (*b); + +            if (++b != s.names_end () && next_ != 0) +              (this_->*next_) (s); +          } + +          if (post_) +            (this_->*post_) (s); +        } +        else +        { +          if (none_) +            (this_->*none_) (s); +        } +      } + +      virtual void +      names (T& s, EdgeDispatcher& d) +      { +        names<ScopeTemplate<T> > (s, d); +      } + +      virtual void +      names (T& s) +      { +        names (s, +               *this, +               &ScopeTemplate<T>::names_pre, +               &ScopeTemplate<T>::names_post, +               &ScopeTemplate<T>::names_none, +               &ScopeTemplate<T>::names_next); +      } + +      virtual void +      names_pre (T&) +      { +      } + +      virtual void +      names_next (T&) +      { +      } + +      virtual void +      names_post (T&) +      { +      } + +      virtual void +      names_none (T&) +      { +      } +    }; + + +    // +    // +    typedef +    ScopeTemplate<SemanticGraph::Scope> +    Scope; + + +    // +    // +    struct Type : Node<SemanticGraph::Type> +    { +      virtual void +      traverse (SemanticGraph::Type&) = 0; +    }; + + +    // +    // +    struct Instance : Node<SemanticGraph::Instance> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      belongs (Type&, EdgeDispatcher&); + +      virtual void +      belongs (Type&); + +      virtual void +      post (Type&); +    }; + + +    // +    // +    struct Member : Node<SemanticGraph::Member> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      belongs (Type&, EdgeDispatcher&); + +      virtual void +      belongs (Type&); + +      virtual void +      post (Type&); +    }; + + +    // +    // +    struct Inherits : Edge<SemanticGraph::Inherits> +    { +      Inherits () +      { +      } + +      Inherits (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Extends : Edge<SemanticGraph::Extends> +    { +      Extends () +      { +      } + +      Extends (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Restricts : Edge<SemanticGraph::Restricts> +    { +      Restricts () +      { +      } + +      Restricts (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Argumented : Edge<SemanticGraph::Arguments> +    { +      Argumented () +      { +      } + +      Argumented (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& a) +      { +        dispatch (a.type ()); +      } +    }; + + +    /* +    // +    // +    struct Contains : Edge<SemanticGraph::Contains> +    { +      virtual void +      traverse (Type& e) +      { +        dispatch (e.element ()); +      } +    }; +    */ + +    // +    // +    typedef +    Node<SemanticGraph::AnyType> +    AnyType; + + +    // +    // +    typedef +    Node<SemanticGraph::AnySimpleType> +    AnySimpleType; +  } +} + +#include <xsd-frontend/traversal/elements.txx> + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.txx b/libxsd-frontend/xsd-frontend/traversal/elements.txx new file mode 100644 index 0000000..5b1aec0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.txx @@ -0,0 +1,10 @@ +// file      : xsd-frontend/traversal/elements.txx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx b/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx new file mode 100644 index 0000000..124606f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx @@ -0,0 +1,90 @@ +// file      : xsd-frontend/traversal/enumeration.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Enumeration +    // +    void Enumeration:: +    traverse (Type& e) +    { +      pre (e); +      name (e); +      inherits (e); +      names (e); +      post (e); +    } + +    void Enumeration:: +    pre (Type&) +    { +    } + +    void Enumeration:: +    name (Type&) +    { +    } + +    void Enumeration:: +    inherits (Type& e) +    { +      inherits (e, *this); +    } + +    void Enumeration:: +    inherits (Type& e, EdgeDispatcher& d) +    { +      if (e.inherits_p ()) +        d.dispatch (e.inherits ()); +    } + +    void Enumeration:: +    post (Type&) +    { +    } + + +    // Enumerator +    // +    void Enumerator:: +    traverse (Type& e) +    { +      pre (e); +      belongs (e); +      name (e); +      post (e); +    } + +    void Enumerator:: +    pre (Type&) +    { +    } + +    void Enumerator:: +    belongs (Type& e, EdgeDispatcher& d) +    { +      d.dispatch (e.belongs ()); +    } + +    void Enumerator:: +    belongs (Type& e) +    { +      belongs (e, edge_traverser ()); +    } + +    void Enumerator:: +    name (Type&) +    { +    } + +    void Enumerator:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx b/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx new file mode 100644 index 0000000..960b11c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx @@ -0,0 +1,59 @@ +// file      : xsd-frontend/traversal/enumeration.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX +#define XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Enumeration : ScopeTemplate<SemanticGraph::Enumeration> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      name (Type&); + +      virtual void +      inherits (Type&); + +      void +      inherits (Type&, EdgeDispatcher&); + +      virtual void +      post (Type&); +    }; + +    struct Enumerator : Node<SemanticGraph::Enumerator> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      belongs (Type&, EdgeDispatcher&); + +      virtual void +      belongs (Type&); + +      virtual void +      name (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx b/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx new file mode 100644 index 0000000..5202adf --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx @@ -0,0 +1,12 @@ +// file      : xsd-frontend/traversal/fundamental.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx b/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx new file mode 100644 index 0000000..0b771cd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx @@ -0,0 +1,233 @@ +// file      : xsd-frontend/traversal/fundamental.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX +#define XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    namespace Fundamental +    { +      typedef +      Node<SemanticGraph::Fundamental::Type> +      Type; + +      // Integers. +      // +      typedef +      Node<SemanticGraph::Fundamental::Byte> +      Byte; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedByte> +      UnsignedByte; + +      typedef +      Node<SemanticGraph::Fundamental::Short> +      Short; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedShort> +      UnsignedShort; + +      typedef +      Node<SemanticGraph::Fundamental::Int> +      Int; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedInt> +      UnsignedInt; + +      typedef +      Node<SemanticGraph::Fundamental::Long> +      Long; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedLong> +      UnsignedLong; + +      typedef +      Node<SemanticGraph::Fundamental::Integer> +      Integer; + +      typedef +      Node<SemanticGraph::Fundamental::NonPositiveInteger> +      NonPositiveInteger; + +      typedef +      Node<SemanticGraph::Fundamental::NonNegativeInteger> +      NonNegativeInteger; + +      typedef +      Node<SemanticGraph::Fundamental::PositiveInteger> +      PositiveInteger; + +      typedef +      Node<SemanticGraph::Fundamental::NegativeInteger> +      NegativeInteger; + + +      // Boolean. +      // +      typedef +      Node<SemanticGraph::Fundamental::Boolean> +      Boolean; + + +      // Floats. +      // +      typedef +      Node<SemanticGraph::Fundamental::Float> +      Float; + +      typedef +      Node<SemanticGraph::Fundamental::Double> +      Double; + +      typedef +      Node<SemanticGraph::Fundamental::Decimal> +      Decimal; + + +      // Strings. +      // +      typedef +      Node<SemanticGraph::Fundamental::String> +      String; + +      typedef +      Node<SemanticGraph::Fundamental::NormalizedString> +      NormalizedString; + +      typedef +      Node<SemanticGraph::Fundamental::Token> +      Token; + +      typedef +      Node<SemanticGraph::Fundamental::Name> +      Name; + +      typedef +      Node<SemanticGraph::Fundamental::NameToken> +      NameToken; + +      typedef +      Node<SemanticGraph::Fundamental::NameTokens> +      NameTokens; + +      typedef +      Node<SemanticGraph::Fundamental::NCName> +      NCName; + +      typedef +      Node<SemanticGraph::Fundamental::Language> +      Language; + + +      // Qualified name. +      // +      typedef +      Node<SemanticGraph::Fundamental::QName> +      QName; + + +      // ID/IDREF. +      // +      typedef +      Node<SemanticGraph::Fundamental::Id> +      Id; + +      typedef +      Node<SemanticGraph::Fundamental::IdRef> +      IdRef; + +      typedef +      Node<SemanticGraph::Fundamental::IdRefs> +      IdRefs; + + +      // URI. +      // +      typedef +      Node<SemanticGraph::Fundamental::AnyURI> +      AnyURI; + + +      // Binary. +      // +      typedef +      Node<SemanticGraph::Fundamental::Base64Binary> +      Base64Binary; + +      typedef +      Node<SemanticGraph::Fundamental::HexBinary> +      HexBinary; + + +      // Date/time. +      // +      typedef +      Node<SemanticGraph::Fundamental::Date> +      Date; + +      typedef +      Node<SemanticGraph::Fundamental::DateTime> +      DateTime; + +      typedef +      Node<SemanticGraph::Fundamental::Duration> +      Duration; + +      typedef +      Node<SemanticGraph::Fundamental::Day> +      Day; + +      typedef +      Node<SemanticGraph::Fundamental::Month> +      Month; + +      typedef +      Node<SemanticGraph::Fundamental::MonthDay> +      MonthDay; + +      typedef +      Node<SemanticGraph::Fundamental::Year> +      Year; + +      typedef +      Node<SemanticGraph::Fundamental::YearMonth> +      YearMonth; + +      typedef +      Node<SemanticGraph::Fundamental::Time> +      Time; + + +      // Entity. +      // +      typedef +      Node<SemanticGraph::Fundamental::Entity> +      Entity; + +      typedef +      Node<SemanticGraph::Fundamental::Entities> +      Entities; + + +      // Notation. +      // +      typedef +      Node<SemanticGraph::Fundamental::Notation> +      Notation; +    } +  } +} + + +#endif  // XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/list.cxx b/libxsd-frontend/xsd-frontend/traversal/list.cxx new file mode 100644 index 0000000..9241af1 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/list.cxx @@ -0,0 +1,47 @@ +// file      : xsd-frontend/traversal/list.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/list.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void List:: +    traverse (Type& l) +    { +      pre (l); +      argumented (l); +      name (l); +      post (l); +    } + +    void List:: +    pre (Type&) +    { +    } + +    void List:: +    argumented (Type& l) +    { +      argumented (l, *this); +    } + +    void List:: +    argumented (Type& l, EdgeDispatcher& d) +    { +      d.dispatch (l.argumented ()); +    } + +    void List:: +    name (Type&) +    { +    } + +    void List:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/list.hxx b/libxsd-frontend/xsd-frontend/traversal/list.hxx new file mode 100644 index 0000000..06aa154 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/list.hxx @@ -0,0 +1,38 @@ +// file      : xsd-frontend/traversal/list.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_LIST_HXX +#define XSD_FRONTEND_TRAVERSAL_LIST_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/list.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct List: Node<SemanticGraph::List> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      argumented (Type&); + +      virtual void +      argumented (Type&, EdgeDispatcher& d); + +      virtual void +      name (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_LIST_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/namespace.cxx b/libxsd-frontend/xsd-frontend/traversal/namespace.cxx new file mode 100644 index 0000000..fbf1105 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/namespace.cxx @@ -0,0 +1,12 @@ +// file      : xsd-frontend/traversal/namespace.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/namespace.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/namespace.hxx b/libxsd-frontend/xsd-frontend/traversal/namespace.hxx new file mode 100644 index 0000000..0dd0901 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/namespace.hxx @@ -0,0 +1,44 @@ +// file      : xsd-frontend/traversal/namespace.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX +#define XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Namespace: ScopeTemplate<SemanticGraph::Namespace> +    { +      virtual void +      traverse (Type& m) +      { +        pre (m); +        name (m); +        names (m); +        post (m); +      } + +      virtual void +      pre (Type&) +      { +      } + +      virtual void +      name (Type&) +      { +      } + +      virtual void +      post (Type&) +      { +      } +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/particle.cxx b/libxsd-frontend/xsd-frontend/traversal/particle.cxx new file mode 100644 index 0000000..1dd0ce0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/particle.cxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/traversal/particle.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/particle.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Particle +    // +    void Particle:: +    traverse (Type& c) +    { +      pre (c); +      post (c); +    } + +    void Particle:: +    pre (Type&) +    { +    } + +    void Particle:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/particle.hxx b/libxsd-frontend/xsd-frontend/traversal/particle.hxx new file mode 100644 index 0000000..5346ae9 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/particle.hxx @@ -0,0 +1,29 @@ +// file      : xsd-frontend/traversal/particle.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX +#define XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Particle : Node<SemanticGraph::Particle> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/schema.cxx b/libxsd-frontend/xsd-frontend/traversal/schema.cxx new file mode 100644 index 0000000..090e964 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/schema.cxx @@ -0,0 +1,12 @@ +// file      : xsd-frontend/traversal/schema.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/schema.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/schema.hxx b/libxsd-frontend/xsd-frontend/traversal/schema.hxx new file mode 100644 index 0000000..a38ddfd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/schema.hxx @@ -0,0 +1,149 @@ +// file      : xsd-frontend/traversal/schema.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX +#define XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // +    // +    struct Uses: Edge<SemanticGraph::Uses> +    { +      Uses () +      { +      } + +      Uses (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + +    // +    // +    struct Implies: Edge<SemanticGraph::Implies> +    { +      Implies () +      { +      } + +      Implies (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Sources: Edge<SemanticGraph::Sources> +    { +      Sources () +      { +      } + +      Sources (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Includes: Edge<SemanticGraph::Includes> +    { +      Includes () +      { +      } + +      Includes (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Imports: Edge<SemanticGraph::Imports> +    { +      Imports () +      { +      } + +      Imports (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Schema: ScopeTemplate<SemanticGraph::Schema> +    { +      virtual void +      traverse (Type& s) +      { +        pre (s); + +        iterate_and_dispatch ( +          s.uses_begin (), s.uses_end (), edge_traverser ()); + +        names (s); + +        post (s); +      } + +      virtual void +      pre (Type&) +      { +      } + +      virtual void +      post (Type&) +      { +      } +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/union.cxx b/libxsd-frontend/xsd-frontend/traversal/union.cxx new file mode 100644 index 0000000..fe8f7d0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/union.cxx @@ -0,0 +1,47 @@ +// file      : xsd-frontend/traversal/union.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/union.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    void Union:: +    traverse (Type& u) +    { +      pre (u); +      argumented (u); +      name (u); +      post (u); +    } + +    void Union:: +    pre (Type&) +    { +    } + +    void Union:: +    argumented (Type& u) +    { +      argumented (u, *this); +    } + +    void Union:: +    argumented (Type& u, EdgeDispatcher& d) +    { +      iterate_and_dispatch (u.argumented_begin (), u.argumented_end (), d); +    } + +    void Union:: +    name (Type&) +    { +    } + +    void Union:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/union.hxx b/libxsd-frontend/xsd-frontend/traversal/union.hxx new file mode 100644 index 0000000..8012036 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/union.hxx @@ -0,0 +1,38 @@ +// file      : xsd-frontend/traversal/union.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_UNION_HXX +#define XSD_FRONTEND_TRAVERSAL_UNION_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/union.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Union: Node<SemanticGraph::Union> +    { +      virtual void +      traverse (Type&); + +      virtual void +      pre (Type&); + +      virtual void +      argumented (Type&); + +      virtual void +      argumented (Type&, EdgeDispatcher& d); + +      virtual void +      name (Type&); + +      virtual void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_UNION_HXX diff --git a/libxsd-frontend/xsd-frontend/types.cxx b/libxsd-frontend/xsd-frontend/types.cxx new file mode 100644 index 0000000..49faf92 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/types.cxx @@ -0,0 +1,61 @@ +// file      : xsd-frontend/types.cxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cstdlib> // std::mbstowcs + +#include <xsd-frontend/types.hxx> + +namespace XSDFrontend +{ +  // NonRepresentable +  // +  char const* NonRepresentable:: +  what () const throw () +  { +    return "character is not representable in the narrower encoding"; +  } + +  // StringTemplate +  // + +  // Specialization for char to wchar_t conversion. +  // +  template <> +  void StringTemplate<wchar_t, char>:: +  from_narrow (char const* s) +  { +    size_type size (std::mbstowcs (0, s, 0) + 1); + +    // I dare to change the guts! +    // +    resize (size - 1); + +    wchar_t* p (const_cast<wchar_t*> (data ())); + +    std::mbstowcs (p, s, size); +  } + +  // Specialization for wchar_t to char conversion. +  // +  template <> +  StringTemplate<char> StringTemplate<wchar_t, char>:: +  to_narrow () const +  { +    size_type size (std::wcstombs (0, c_str (), 0)); + +    if (size == size_type (-1)) +      throw NonRepresentable (); + +    // I dare to change the guts! +    // +    StringTemplate<char> r; +    r.resize (size); + +    char* p (const_cast<char*> (r.data ())); + +    std::wcstombs (p, c_str (), size + 1); + +    return r; +  } +} diff --git a/libxsd-frontend/xsd-frontend/types.hxx b/libxsd-frontend/xsd-frontend/types.hxx new file mode 100644 index 0000000..0cd1ad1 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/types.hxx @@ -0,0 +1,250 @@ +// file      : xsd-frontend/types.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TYPES_HXX +#define XSD_FRONTEND_TYPES_HXX + +#include <string> +#include <cstddef> // std::size_t + +namespace XSDFrontend +{ +  using std::size_t; + +  namespace Bits +  { +    struct None {}; + +    template <typename C> +    struct NarrowerChar +    { +      typedef None Type; +    }; + +    template <> +    struct NarrowerChar<wchar_t> +    { +      typedef char Type; +    }; +  } + +  struct NonRepresentable: std::exception +  { +    virtual char const* +    what () const throw (); +  }; + +  template <typename C, typename NC = typename Bits::NarrowerChar<C>::Type> +  class StringTemplate; + +  template <> +  class StringTemplate<Bits::None, Bits::None> +  { +  }; + +  template <typename C, typename NC> +  class StringTemplate : public std::basic_string<C> +  { +    typedef std::basic_string<C> Base; +    typedef std::basic_string<NC> NarrowerBase; + +    Base& +    base () +    { +      return *this; +    } + +    Base const& +    base () const +    { +      return *this; +    } + +  public: +    typedef typename Base::size_type size_type; + +    using Base::npos; + +  public: +    StringTemplate () +    { +    } + +    StringTemplate (StringTemplate const& str, +                    size_type pos, +                    size_type n = npos) +        : Base (str, pos, n) +    { +    } + +    StringTemplate (C const* s, size_type n) +        : Base (s, n) +    { +    } + +    StringTemplate (C const* s) +        : Base (s) +    { +    } + +    StringTemplate (size_type n, C c) +        : Base (n, c) +    { +    } + +    template <typename I> +    StringTemplate(I begin, I end) +        : Base (begin, end) +    { +    } + +    StringTemplate (StringTemplate const& other) +        : Base (other) +    { +    } + +    // Conversion from Base. +    // +    StringTemplate (Base const& str) +        : Base (str) +    { +    } + +    // Conversion from the Narrower type. Experimental. +    // +    StringTemplate (NC const* s) +    { +      from_narrow (s); +    } + +    StringTemplate (StringTemplate<NC> const& other) +    { +      from_narrow (other.c_str ()); +    } + +    StringTemplate (NarrowerBase const& other) +    { +      from_narrow (other.c_str ()); +    } + +    // Assignment. +    // +    StringTemplate& +    operator= (StringTemplate const& str) +    { +      base () = str; +      return *this; +    } + +    StringTemplate& +    operator= (C const* s) +    { +      base () = s; +      return *this; +    } + +    StringTemplate& +    operator= (C c) +    { +      base () = c; +      return *this; +    } + +    // Assignment from Base. +    // +    StringTemplate& +    operator= (Base const& str) +    { +      base () = str; +      return *this; +    } + +  public: +    StringTemplate& +    operator+= (StringTemplate const& str) +    { +      base () += str; +      return *this; +    } + +    StringTemplate& +    operator+= (C const* s) +    { +      base () += s; +      return *this; +    } + +    StringTemplate& +    operator+= (C c) +    { +      base () += c; +      return *this; +    } + +    // Conversion to the Narrower type. +    // +  public: +    StringTemplate<NC> +    to_narrow () const; + +    // Conversion to bool. +    // +  private: +    typedef void (StringTemplate::*BooleanConvertible)(); +    void true_ () {} + +  public: +    operator BooleanConvertible () const +    { +      return this->empty () ? 0 : &StringTemplate::true_; +    } + +  private: +    void +    from_narrow (NC const* s); +  }; + + +  template<typename C> +  StringTemplate<C> +  operator+ (StringTemplate<C> const& lhs, StringTemplate<C> const& rhs) +  { +    return StringTemplate<C> (lhs) += rhs; +  } + +  template<typename C> +  StringTemplate<C> +  operator+ (C const* lhs, StringTemplate<C> const& rhs) +  { +    return StringTemplate<C> (lhs) += rhs; +  } + +  template<typename C> +  StringTemplate<C> +  operator+ (StringTemplate<C> const& lhs, C const* rhs) +  { +    return StringTemplate<C> (lhs) += rhs; +  } + +  template<typename C> +  StringTemplate<C> +  operator+ (C lhs, StringTemplate<C> const& rhs) +  { +    return StringTemplate<C> (1, lhs) += rhs; +  } + +  template<typename C> +  StringTemplate<C> +  operator+ (StringTemplate<C> const& lhs, C rhs) +  { +    return StringTemplate<C> (lhs) += rhs; +  } + +  typedef StringTemplate<char> NarrowString; +  typedef StringTemplate<wchar_t> WideString; + +  typedef WideString String; +} + +#endif  // XSD_FRONTEND_TYPES_HXX diff --git a/libxsd-frontend/xsd-frontend/version.hxx b/libxsd-frontend/xsd-frontend/version.hxx new file mode 100644 index 0000000..fa6d1de --- /dev/null +++ b/libxsd-frontend/xsd-frontend/version.hxx @@ -0,0 +1,14 @@ +// file      : xsd-frontend/version.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_VERSION_HXX +#define XSD_FRONTEND_VERSION_HXX + +#include <xercesc/util/XercesVersion.hpp> + +#if _XERCES_VERSION < 30000 +#  error Xerces-C++ 2-series is not supported +#endif + +#endif  // XSD_FRONTEND_VERSION_HXX diff --git a/libxsd-frontend/xsd-frontend/xml.hxx b/libxsd-frontend/xsd-frontend/xml.hxx new file mode 100644 index 0000000..d33f6bf --- /dev/null +++ b/libxsd-frontend/xsd-frontend/xml.hxx @@ -0,0 +1,559 @@ +// file      : xsd-frontend/xml.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_XML_HXX +#define XSD_FRONTEND_XML_HXX + +#include <vector> +#include <ostream> + +#include <xercesc/dom/DOM.hpp> +#include <xercesc/util/XMLString.hpp> + +#include <xsd-frontend/version.hxx>            // Check Xerces-C++ version. +#include <xsd-frontend/types.hxx> +#include <xsd-frontend/schema-dom-parser.hxx> + +namespace XSDFrontend +{ +  namespace XML +  { +    namespace Xerces = xercesc; + +    inline +    String +    transcode (XMLCh const* s, size_t length) +    { +      if (sizeof (wchar_t) == 4) +      { +        // UTF-32 +        // +        XMLCh const* end (s + length); + +        // Find what the resulting buffer size will be. +        // +        size_t rl (0); +        bool valid (true); + +        for (XMLCh const* p (s); p < end; ++p) +        { +          rl++; + +          if ((*p >= 0xD800) && (*p <= 0xDBFF)) +          { +            // Make sure we have one more char and it has a valid +            // value for the second char in a surrogate pair. +            // +            if (++p == end || !((*p >= 0xDC00) && (*p <= 0xDFFF))) +            { +              valid = false; +              break; +            } +          } +        } + +        if (!valid) +          return String (); + +        String r; +        r.reserve (rl + 1); +        r.resize (rl); +        wchar_t* rs (const_cast<wchar_t*> (r.c_str ())); + +        size_t i (0); + +        for (XMLCh const* p (s); p < end; ++p) +        { +          XMLCh x (*p); + +          if (x < 0xD800 || x > 0xDBFF) +            rs[i++] = wchar_t (x); +          else +            rs[i++] = ((x - 0xD800) << 10) + (*++p - 0xDC00) + 0x10000; +        } + +        return r; +      } +      else if (sizeof (wchar_t) == 2) +      { +        // UTF-16 +        // +        return String (reinterpret_cast<const wchar_t*> (s), length); +      } +      else +        return String (); +    } + +    inline +    String +    transcode (XMLCh const* s) +    { +      return transcode (s,  Xerces::XMLString::stringLen (s)); +    } + +    inline +    NarrowString +    transcode_to_narrow (XMLCh const* xs) +    { +      char* s (Xerces::XMLString::transcode (xs)); +      NarrowString r (s); +      Xerces::XMLString::release (&s); +      return r; +    } + +    inline +    XMLCh* +    transcode (String const& str) +    { +      size_t l (str.size ()); +      wchar_t const* s (str.c_str ()); + +      if (sizeof (wchar_t) == 4) +      { +        // Find what the resulting buffer size will be. +        // +        size_t rl (0); + +        for (wchar_t const* p (s); p < s + l; ++p) +        { +          rl += (*p & 0xFFFF0000) ? 2 : 1; +        } + +        XMLCh* r (new XMLCh[rl + 1]); +        XMLCh* ir (r); + +        for (wchar_t const* p (s); p < s + l; ++p) +        { +          wchar_t w (*p); + +          if (w & 0xFFFF0000) +          { +            // Surrogate pair. +            // +            *ir++ = static_cast<XMLCh> (((w - 0x10000) >> 10) + 0xD800); +            *ir++ = static_cast<XMLCh> ((w & 0x3FF) + 0xDC00); +          } +          else +            *ir++ = static_cast<XMLCh> (w); +        } + +        *ir = XMLCh (0); + +        return r; +      } +      else if (sizeof (wchar_t) == 2) +      { +        XMLCh* r (new XMLCh[l + 1]); +        XMLCh* ir (r); + +        for (size_t i (0); i < l; ++ir, ++i) +          *ir = static_cast<XMLCh> (s[i]); + +        *ir = XMLCh (0); + +        return r; +      } +      else +        return 0; +    } + +    class XMLChString +    { +    public : +      XMLChString (String const& s) +          : s_ (transcode (s)) +      { +      } + +      XMLChString (wchar_t const* s) +          : s_ (transcode (String (s))) +      { +      } + +      ~XMLChString () +      { +        delete[] s_; +      } + +      XMLCh const* +      c_str () const +      { +        return s_; +      } + +    private: +      XMLChString (XMLChString const&); + +      XMLChString& +      operator= (XMLChString const&); + +    private: +      XMLCh* s_; +    }; + + +    class Element +    { +    public: +      Element (Xerces::DOMElement* e) +          : e_ (e), +            name_ (transcode (e->getLocalName ())), +            namespace__ (transcode (e->getNamespaceURI ())) +      { +      } + +      String +      name () const +      { +        return name_; +      } + +      String +      namespace_ () const +      { +        return namespace__; +      } + +    public: +      unsigned long +      line () const +      { +        //@@ cache +        // +        return reinterpret_cast<unsigned long> (e_->getUserData (line_key)); +      } + +      unsigned long +      column () const +      { +        //@@ cache +        // +        return reinterpret_cast<unsigned long> (e_->getUserData (column_key)); +      } + +    public: +      Element +      parent () const +      { +        return dynamic_cast<Xerces::DOMElement*>(e_->getParentNode ()); +      } + +    public: +      // Attribute identified by a name. +      // +      bool +      attribute_p (String const& name) const +      { +        return attribute_p ("", name); +      } + +      String +      attribute (String const& name) const +      { +        return attribute ("", name); +      } + +      String +      operator[] (String const& name) const +      { +        return attribute (name); +      } + +      // Attribute identified by namespace and name. +      // + +      bool +      attribute_p (String const& namespace_, String const& name) const +      { +        Xerces::DOMAttr* a ( +          e_->getAttributeNodeNS ( +            XMLChString (namespace_).c_str (), +            XMLChString (name).c_str ())); + +        return a != 0; +      } + +      String +      attribute (String const& namespace_, String const& name) const +      { +        XMLCh const* value ( +          e_->getAttributeNS ( +            XMLChString (namespace_).c_str (), +            XMLChString (name).c_str ())); + +        return transcode (value); +      } + +    public: +      Xerces::DOMElement* +      dom_element () const +      { +        return e_; +      } + +    private: +      Xerces::DOMElement* e_; + +      String name_; +      String namespace__; +    }; + +    inline String +    prefix (String const& n) +    { +      size_t i (0); +      while (i < n.length () && n[i] != L':') ++i; + +      //std::wcerr << "prefix " << n << " " +      //           << String (n, i == n.length () ? i : 0, i) << std::endl; + +      return String (n, i == n.length () ? i : 0, i); +    } + +    inline String +    uq_name (String const& n) +    { +      size_t i (0); +      while (i < n.length () && n[i] != L':') ++i; + +      return String (n.c_str () + (i == n.length () ? 0 : i + 1)); +    } + +    struct NoMapping +    { +      NoMapping (String const& prefix) +          : prefix_ (prefix) +      { +      } + +      String const& +      prefix () const +      { +        return prefix_; +      } + +    private: +      String prefix_; +    }; + +    // Throws NoMapping if there is no prefix-namespace association. +    // +    inline String +    ns_name (Xerces::DOMElement const* e, String const& prefix) +    { +      // 'xml' prefix requires special handling and Xerces folks refuse +      // to handle this in DOM so I have to do it myself. +      // +      if (prefix == L"xml") +        return L"http://www.w3.org/XML/1998/namespace"; + +      // 0 means "no prefix" to Xerces. +      // +      XMLCh const* xns ( +        e->lookupNamespaceURI ( +          prefix.empty () ? 0 : XMLChString (prefix).c_str ())); + +      if (xns == 0) +        throw NoMapping (prefix); + +      return transcode (xns); +    } + +    class NoPrefix {}; + +    inline String +    ns_prefix (Element const& e, String const& wns) +    { +      XMLChString ns (wns); +      XMLCh const* p (e.dom_element ()->lookupPrefix (ns.c_str ())); + +      if (p == 0) +      { +        bool r (e.dom_element ()->isDefaultNamespace (ns.c_str ())); + +        if (r) +          return L""; +        else +        { +          // 'xml' prefix requires special handling and Xerces folks refuse +          // to handle this in DOM so I have to do it myself. +          // +          if (wns == L"http://www.w3.org/XML/1998/namespace") +            return L"xml"; + +          throw NoPrefix (); +        } +      } + +      return transcode (p); +    } + +    inline String +    fq_name (Element const& e, String const& n) +    { +      String un (uq_name (n)); + +      try +      { +        String ns (ns_name (e.dom_element (), prefix (n))); +        return ns + L'#' + un; +      } +      catch (XML::NoMapping const&) +      { +        return un; +      } +    } + + +    // Simple auto_ptr version that calls release() instead of delete. +    // + +    template <typename X> +    struct AutoPtrRef +    { +      X* x_; + +      explicit +      AutoPtrRef (X* x) +          : x_ (x) +      { +      } +    }; + +    template <typename X> +    struct AutoPtr +    { +      ~AutoPtr () +      { +        reset (); +      } + +      explicit +      AutoPtr (X* x = 0) +          : x_ (x) +      { +      } + +      AutoPtr (AutoPtr& y) +          : x_ (y.release ()) +      { +      } + +      AutoPtr (AutoPtrRef<X> r) +          : x_ (r.x_) +      { +      } + +      AutoPtr& +      operator= (AutoPtr& y) +      { +        if (this != &y) +        { +          reset (y.release ()); +        } + +        return *this; +      } + +      AutoPtr& +      operator= (AutoPtrRef<X> r) +      { +        if (r.x_ != x_) +        { +          reset (r.x_); +        } + +        return *this; +      } + +      operator AutoPtrRef<X> () +      { +        return AutoPtrRef<X> (release ()); +      } + +    public: +      X& +      operator* () const +      { +        return *x_; +      } + +      X* +      operator-> () const +      { +        return x_; +      } + +      X* +      get () const +      { +        return x_; +      } + +      X* +      release () +      { +        X* x (x_); +        x_ = 0; +        return x; +      } + +      void +      reset (X* x = 0) +      { +        if (x_) +          x_->release (); + +        x_ = x; +      } + +      // Conversion to bool. +      // +      typedef X* (AutoPtr::*boolConvertible)() const; + +      operator boolConvertible () const throw () +      { +        return x_ ? &AutoPtr<X>::operator-> : 0; +      } + +    private: +      X* x_; +    }; + +    template <typename X> +    struct PtrVector: std::vector<X*> +    { +      typedef std::vector<X*> Base; + +      ~PtrVector () +      { +        for (typename Base::iterator i (this->begin ()), e (this->end ()); +             i != e; ++i) +        { +          if (*i) +            (*i)->release (); +        } +      } + +      void +      push_back (AutoPtr<X>& x) +      { +        Base::push_back (0); +        this->back () = x.release (); +      } +    }; +  } +} + +// Xerces DOoM. +// +// +inline +std::wostream& +operator<< (std::wostream& o, XMLCh const* s) +{ +  return o << XSDFrontend::XML::transcode (s); +} + +#endif  // XSD_FRONTEND_XML_HXX  | 
