diff options
author | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 |
commit | aad5ad9bf0c02aa4e79bc6b7d6c934612fff4026 (patch) | |
tree | 9cc224b059f248a6229ab0dcdc64eb4a73fa9800 /xsd/cxx/parser/state-processor.cxx | |
parent | c1034fc5e99197f507caf450aa15bc178698b26e (diff) |
New upstream version 4.2.0upstream/4.2.0upstream
Diffstat (limited to 'xsd/cxx/parser/state-processor.cxx')
-rw-r--r-- | xsd/cxx/parser/state-processor.cxx | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/xsd/cxx/parser/state-processor.cxx b/xsd/cxx/parser/state-processor.cxx new file mode 100644 index 0000000..a2b8fbf --- /dev/null +++ b/xsd/cxx/parser/state-processor.cxx @@ -0,0 +1,319 @@ +// file : xsd/cxx/parser/state-processor.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> +#include <iostream> + +#include <xsd/cxx/parser/state-processor.hxx> + +#include <xsd/cxx/parser/elements.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ + namespace Parser + { + namespace + { + typedef vector<SemanticGraph::Particle*> Particles; + + /* + void + print (Particles const& p) + { + using std::wcerr; + using std::endl; + + wcerr << "prefixes: " << endl; + + for (Particles::const_iterator i (p.begin ()); i != p.end (); ++i) + { + if (SemanticGraph::Element* e = + dynamic_cast<SemanticGraph::Element*> (*i)) + { + wcerr << e->name () << endl; + } + else + { + wcerr << "<any>" << endl; + } + } + + wcerr << endl; + } + */ + + // + // + struct Particle: Traversal::All, + Traversal::Choice, + Traversal::Sequence + { + Particle (size_t& all, + size_t& choice, + size_t& sequence, + size_t& depth) + : all_ (all), + choice_ (choice), + sequence_ (sequence), + depth_ (depth) + { + } + + virtual void + traverse (SemanticGraph::All& a) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If all prefixes of this compositor have minOccurs = 0, then + // the compositor itself effectively has minOccurs = 0 regardless + // of the actual value specified in the schema. + // + // Note that we don't need to care about depth since the 'all' + // compositor cannot contain any nested compositors. + // + + size_t state (0); + size_t min (0); + + for (Compositor::ContainsIterator ci (a.contains_begin ()); + ci != a.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + // The 'all' compositor can only include elements. + // + prefixes_.push_back (&p); + + if (min == 0 && ci->min () != 0) + min = 1; + + p.context ().set ("prefix", true); + p.context ().set ("state", state++); + } + + if (!prefixes_.empty ()) + { + a.context ().set ("comp-number", choice_++); + a.context ().set ("prefixes", prefixes_); + a.context ().set ("state-count", size_t (prefixes_.size ())); + + // effective-min = min * actual-min + // + if (min == 1) + min = a.min (); + + a.context ().set ("effective-min", min); + + // print (prefixes_); + } + } + + virtual void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If any prefix of this compositor have minOccurs = 0, then the + // compositor itself effectively has minOccurs = 0 regardless of + // the actual value specified in the schema. + // + + size_t state (0); + size_t min (1); + + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a<SemanticGraph::Element> () || + p.is_a<SemanticGraph::Any> ()) + { + prefixes_.push_back (&p); + + if (min == 1 && ci->min () == 0) + min = 0; + } + else + { + size_t depth (0); + Particle t (all_, choice_, sequence_, depth); + t.dispatch (p); + + if (t.prefixes_.empty ()) + continue; // Skip empty compositors. + + if (++depth > depth_) // One for this compositor. + depth_ = depth; + + prefixes_.insert (prefixes_.end (), + t.prefixes_.begin (), + t.prefixes_.end ()); + + if (min == 1 && + p.context ().get<size_t> ("effective-min") == 0) + min = 0; + } + + p.context ().set ("prefix", true); + p.context ().set ("state", state++); + } + + if (!prefixes_.empty ()) + { + c.context ().set ("comp-number", choice_++); + c.context ().set ("prefixes", prefixes_); + + // effective-min = min * actual-min + // + if (min == 1) + min = c.min (); + + c.context ().set ("effective-min", min); + + // print (prefixes_); + } + } + + virtual void + traverse (SemanticGraph::Sequence& s) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If all prefixes of this compositor have minOccurs = 0, then + // the compositor itself effectively has minOccurs = 0 regardless + // of the actual value specified in the schema. + // + + bool prefix (true); + size_t state (0); + size_t min (0); + + for (Compositor::ContainsIterator ci (s.contains_begin ()); + ci != s.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a<SemanticGraph::Element> () || + p.is_a<SemanticGraph::Any> ()) + { + if (prefix) + { + prefixes_.push_back (&p); + + if (ci->min () != 0) + min = 1; + } + } + else + { + size_t depth (0); + Particle t (all_, choice_, sequence_, depth); + t.dispatch (p); + + if (t.prefixes_.empty ()) + continue; // Skip empty compositors. + + if (++depth > depth_) // One for this compositor. + depth_ = depth; + + if (prefix) + { + prefixes_.insert (prefixes_.end (), + t.prefixes_.begin (), + t.prefixes_.end ()); + + if (p.context ().get<size_t> ("effective-min") != 0) + min = 1; + } + } + + p.context ().set ("state", state++); + + if (prefix) + p.context ().set ("prefix", true); + + if (prefix && min != 0) + prefix = false; + } + + if (!prefixes_.empty ()) + { + s.context ().set ("comp-number", sequence_++); + s.context ().set ("prefixes", prefixes_); + + // effective-min = min * actual-min + // + if (min == 1) + min = s.min (); + + s.context ().set ("effective-min", min); + + // print (prefixes_); + } + } + + private: + Particles prefixes_; + + size_t& all_; + size_t& choice_; + size_t& sequence_; + + size_t& depth_; + }; + + + // + // + struct Complex: Traversal::Complex + { + virtual void + traverse (Type& c) + { + if (c.contains_compositor_p ()) + { + size_t all (0), choice (0), sequence (0), depth (0); + Particle t (all, choice, sequence, depth); + t.dispatch (c.contains_compositor ().compositor ()); + + // Set the maximum stack depth for this type. Used to + // allocate fixed-size state stack. + // + c.context ().set ("depth", depth + 1); + } + } + }; + } + + void StateProcessor:: + process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) + { + Traversal::Schema schema; + Sources sources; + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> ns_names; + + Complex complex_type; + + ns_names >> complex_type; + + schema.dispatch (tu); + } + } +} |