diff options
Diffstat (limited to 'libxsd-frontend/xsd-frontend/transformations/simplifier.cxx')
-rw-r--r-- | libxsd-frontend/xsd-frontend/transformations/simplifier.cxx | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx new file mode 100644 index 0000000..2ccaed2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx @@ -0,0 +1,167 @@ +// file : xsd-frontend/transformations/simplifier.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/simplifier.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/vector.hxx> + +namespace XSDFrontend +{ + using namespace Cult; + + 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); + } + } +} |