From 707cc94fe52463870a9c6c8e2e66eaaa389e601d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 24 Feb 2009 15:16:26 +0200 Subject: Start tracking XSD/e with git after version 3.0.0 --- xsde/cxx/parser/parser-source.cxx | 1626 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1626 insertions(+) create mode 100644 xsde/cxx/parser/parser-source.cxx (limited to 'xsde/cxx/parser/parser-source.cxx') diff --git a/xsde/cxx/parser/parser-source.cxx b/xsde/cxx/parser/parser-source.cxx new file mode 100644 index 0000000..5e1e9bd --- /dev/null +++ b/xsde/cxx/parser/parser-source.cxx @@ -0,0 +1,1626 @@ +// file : xsde/cxx/parser/parser-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + String const& ret (ret_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + String const& base_ret (ret_type (base)); + + Boolean same (ret == base_ret); + Boolean base_same ( + base.inherits_p () && + base_ret == ret_type (base.inherits ().base ())); + + if (same || ret == L"void" || poly_code || + (tiein && !(base_same || base_ret == L"void"))) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (same || ret == L"void") + { + String const& post (post_name (e)); + + os << ret << " " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (e)); + + os << "if (this->" << impl << ")" << endl + << (ret != L"void" ? "return " : "") << "this->" << + impl << "->" << post << " ();"; + } + + if (same) + { + if (tiein) + os << "else" << endl; + + if (ret == L"void") + os << post_name (base) << " ();"; + else + os << "return " << post_name (base) << " ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (e.name ()); + + if (String ns = xml_ns_name (e)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (validation) + { + Boolean gen (!anonymous (e)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + e.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein && !(base_same || base_ret == L"void")) + { + String const& impl (etiein (base)); + String const& base_post (post_name (base)); + + os << base_ret << " " << name << "::" << endl + << base_post << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << base_post << " ();" + << "}"; + } + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String item (unclash (name, "item")); + String inst (L"_xsde_" + item + L"_"); + String const& post (post_name (t)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // item + // + String const& arg (arg_type (t)); + + os << "void " << name << "::" << endl + << item; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl (etiein (l)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << item << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + + // post + // + if (ret_type (l) == L"void") + { + String const& post (post_name (l)); + + os << "void " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (l)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << post << " ();"; + } + + os << "}"; + } + + // reset + // + if (reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << list_base << "::_reset ();" + << endl + << "if (this->" << inst << ")" << endl + << "this->" << inst << "->_reset ();" + << "}"; + } + + // parse_item + // + os << "void " << name << "::" << endl + << "_xsde_parse_item (const " << string_type << "& v)" + << "{" + << "if (this->" << inst << ")" + << "{" + << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + // This implementation should work for both validating + // and non-validating cases. + // + if (!exceptions || validation) + { + String const& ret (ret_type (t)); + + os << "this->" << inst << "->pre ();"; + + if (!exceptions) + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + os << "this->" << inst << "->_pre_impl (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_characters (v);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_post_impl ();" + << endl + << "if (!ctx.error_type ())" << endl; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << endl; + else + os << "{" + << arg_type (t) << " tmp = this->" << inst << "->" << + post << " ();" + << endl; + + if (!exceptions) + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + if (ret == L"void") + os << "this->" << item << " ();"; + else + os << "this->" << item << " (tmp);" + << "}"; + } + else + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_characters (v);" + << "this->" << inst << "->_post_impl ();"; + + if (ret_type (t) == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << item << " ();"; + else + os << "this->" << item << " (this->" << inst << "->" << + post << " ());"; + } + + os << "}" + << "}"; + + // + // + if (poly_code) + { + String id (l.name ()); + + if (String ns = xml_ns_name (l)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + String const& ret (ret_type (u)); + + if (ret == L"void" || poly_code) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (ret == L"void") + { + String const& post (post_name (u)); + + os << "void " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (u)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << post << " ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (u.name ()); + + if (String ns = xml_ns_name (u)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct ParticleReset: Traversal::Element, Context + { + ParticleReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& m (emember (e)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + String const& map (emember_map (e)); + + os << "if (this->" << map << ")" << endl + << "this->" << map << "->reset ();" + << endl; + } + } + }; + + struct AttributeReset: Traversal::Attribute, Context + { + AttributeReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& m (emember (a)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + } + }; + + // + // + struct StartElement : Traversal::Element, Context + { + StartElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + Boolean poly (poly_code && !anonymous (e.type ())); + Boolean subst (poly && e.global ()); + String const& inst (poly ? emember_cache (e) : emember (e)); + + if (e.qualified () && e.namespace_ ().name ()) + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " &&" << endl + << "ns == " << strlit (e.namespace_ ().name ()); + } + else + { + os << "if (" << (subst ? "(" : "") << + "n == " << L << strlit (e.name ()) << " && ns.empty ()"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (subst) + { + String root_id (e.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + root_id += L' '; + root_id += ns; + } + + os << ") ||" << endl + << "::xsde::cxx::parser::substitution_map_instance ()" << + ".check (" << endl + << "ns, n, " << strlit (root_id) << ", t)"; + } + + os << ")" + << "{"; + + if (poly) + { + // In case of mixin we use virtual inheritance and only + // dynamic_cast can be used. + // + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + String fq_type (fq_name (e.type ())); + String const& member (emember (e)); + String const& member_map (emember_map (e)); + + os << "if (t == 0 && this->" << member << " != 0)" << endl + << "this->" << inst << " = this->" << member << ";" + << "else" + << "{" + << "const char* ts = " << fq_type << "::_static_type ();" + << endl + << "if (t == 0)" << endl + << "t = ts;" + << endl + << "if (this->" << member << " != 0 && " << + "strcmp (t, ts) == 0)" << endl + << "this->" << inst << " = this->" << member << ";" + << "else if (this->" << member_map << " != 0)" << endl + << "this->" << inst << " = " << cast << "< " << fq_type << + "* > (" << endl + << "this->" << member_map << "->find (t));" + << "else" << endl + << "this->" << inst << " = 0;" + << "}"; + } + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);"; + } + else + { + // Note that after pre() we need to check both parser and + // context error states because of the recursive parsing. + // + os << "this->" << inst << "->pre ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_pre_impl (ctx);"; + } + + os << "}" + << "else" << endl + << "ctx.current_.depth_++;" // Ignoring document fragment. + << endl + << "return true;" + << "}"; + } + }; + + + // + // + struct EndElement : Traversal::Element, Context + { + EndElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + Boolean poly (poly_code && !anonymous (e.type ())); + Boolean subst (poly && e.global ()); + String const& inst (poly ? emember_cache (e) : emember (e)); + + if (e.qualified () && e.namespace_ ().name ()) + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " &&" << endl + << "ns == " << strlit (e.namespace_ ().name ()); + } + else + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " && ns.empty ()"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (subst) + { + String root_id (e.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + root_id += L' '; + root_id += ns; + } + + os << ") ||" << endl + << "::xsde::cxx::parser::substitution_map_instance ()" << + ".check (" << endl + << "ns, n, " << strlit (root_id) << ")"; + } + + os << ")" + << "{"; + + SemanticGraph::Type& type (e.type ()); + String const& post (post_name (type)); + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret_type (type) == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << name << " ();"; + else + os << "this->" << name << " (this->" << inst << "->" << + post << " ());"; + } + else + { + // Note that after post() we need to check both parser and + // context error states because of the recursive parsing. + // + if (ret_type (type) == L"void") + { + os << "this->" << inst << "->" << post << " ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << name << " ();"; + } + else + { + os << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << name << " (tmp);"; + } + } + + os << "}" + << "return true;" + << "}"; + } + }; + + + // + // + struct Attribute : Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& name (ename (a)); + String const& inst (emember (a)); + + if (a.qualified () && a.namespace_ ().name ()) + { + os << "if (n == " << L << strlit (a.name ()) << " &&" << endl + << "ns == " << L << strlit (a.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n == " << L << strlit (a.name ()) << " && ns.empty ())" + << "{"; + } + + SemanticGraph::Type& type (a.type ()); + String const& post (post_name (type)); + String const& ret (ret_type (type)); + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_characters (v);" + << "this->" << inst << "->_post_impl ();"; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << name << " ();"; + else + os << "this->" << name << " (this->" << inst << "->" << + post << " ());"; + } + else + { + os << "this->" << inst << "->pre ();" + << endl + << "if (!this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_pre_impl (ctx);" + << "else" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_characters (v);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_post_impl ();" + << endl + << "if (!ctx.error_type ())" << endl; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << endl; + else + os << "{" + << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();" + << endl; + + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + if (ret == L"void") + os << "this->" << name << " ();"; + else + os << "this->" << name << " (tmp);" + << "}"; + } + + os << "}" + << "return true;" + << "}"; + } + }; + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (correspondent (a) == 0) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + SemanticGraph::Scope& s (scope (a)); + String const& present (epresent (a)); + + os << "void " << ename (s) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (s))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << present << " ();"; + } + + os << "}"; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () == c.contains_end ()) + return; + + if (correspondent (c) == 0) + { + SemanticGraph::Scope& s (scope (c)); + String const& arm (earm (c)); + + os << "void " << ename (s) << "::" << endl + << arm << " (" << earm_tag (c) << (tiein ? " x" : "") << ")" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (s))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << arm << " (x);"; + } + + os << "}"; + + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // Root compositor that models inheritance by extension + // may not have an association so we may fall through + // in to the 'if' case even though this is a restriction. + // This is ok since such a compositor always has max == + // min == 1 and so nothing is generated. + // + if (SemanticGraph::Compositor* b = correspondent (s)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (b->max () != 1 && s.min () == 0) + { + SemanticGraph::Scope& ss (scope (s)); + + os << "void " << ename (ss) << "::" << endl + << epresent (s) << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << enext (s) << " ();"; + } + else + os << "this->" << enext (s) << " ();"; + + os << "}"; + } + } + else + { + if (s.max () != 1) + { + SemanticGraph::Scope& ss (scope (s)); + String const& next (enext (s)); + + os << "void " << ename (ss) << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << next << " ();"; + } + + os << "}"; + } + else if (s.min () == 0) + { + SemanticGraph::Scope& ss (scope (s)); + String const& present (epresent (s)); + + os << "void " << ename (ss) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << present << " ();"; + } + + os << "}"; + } + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + }; + + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (correspondent (e) == 0) + { + String const& name (ename (e)); + String const& arg (arg_type (e.type ())); + + os << "void " << ename (e.scope ()) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (e.scope ()))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + } + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + String const& arg (arg_type (a.type ())); + + os << "void " << ename (a.scope ()) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (a.scope ()))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_val_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_reset_ (c), + attribute_reset_ (c), + start_element_ (c), + end_element_ (c), + attribute_ (c) + { + // Callback. + // + if (validation) + { + contains_compositor_callback_ >> compositor_callback_val_; + compositor_callback_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_val_; + } + else + { + contains_compositor_callback_ >> compositor_callback_non_val_; + compositor_callback_non_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_non_val_; + } + + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Reset. + // + contains_compositor_reset_ >> compositor_reset_; + compositor_reset_ >> contains_particle_reset_; + contains_particle_reset_ >> compositor_reset_; + contains_particle_reset_ >> particle_reset_; + + names_attribute_reset_ >> attribute_reset_; + + // + // + contains_compositor_start_ >> start_compositor_; + start_compositor_ >> contains_particle_start_; + contains_particle_start_ >> start_compositor_; + contains_particle_start_ >> start_element_; + + // + // + contains_compositor_end_ >> end_compositor_; + end_compositor_ >> contains_particle_end_; + contains_particle_end_ >> end_compositor_; + contains_particle_end_ >> end_element_; + + // + // + names_attribute_ >> attribute_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean restriction (restriction_p (c)); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + + Boolean hra (false); // Has required attribute. + if (ha) + { + RequiredAttributeTest test (hra); + Traversal::Names names_test (test); + names (c, names_test); + } + + String const& name (ename (c)); + String const& ret (ret_type (c)); + Boolean same (hb && ret == ret_type (c.inherits ().base ())); + + String base_ret; + Boolean base_same (true); + + if (tiein && hb) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + base_ret = ret_type (base); + base_same = base.inherits_p () && + base_ret == ret_type (base.inherits ().base ()); + } + + if (he || ha || same || ret == L"void" || poly_code || + (tiein && !(base_same || base_ret == L"void"))) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + // Member callbacks. + // + if (!restriction) + { + if (ha) + names (c, names_attribute_callback_); + } + + if (!restriction || validation) + { + if (he || hae) + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + if (same || ret == L"void") + { + String const& post (post_name (c)); + + os << ret << " " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (c)); + + os << "if (this->" << impl << ")" << endl + << (ret != L"void" ? "return " : "") << "this->" << + impl << "->" << post << " ();"; + } + + if (same) + { + if (tiein) + os << "else" << endl; + + SemanticGraph::Type& base (c.inherits ().base ()); + + if (ret == L"void") + os << post_name (base) << " ();"; + else + os << "return " << post_name (base) << " ();"; + } + + os << "}"; + } + + // reset + // + if (!restriction && (he || ha) && reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + // Avoid recursion in case of recursive parsing. + // + if (he) + os << "if (this->resetting_)" << endl + << "return;" + << endl; + + // Reset the base. We cannot use the fully-qualified base name + // directly because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << base << "::_reset ();" + << endl; + + // Reset validation state. + // + if (validation) + { + if (he || hae) + { + os << "this->v_state_stack_.clear ();" + << endl; + + SemanticGraph::Compositor& comp ( + c.contains_compositor ().compositor ()); + + if (comp.is_a () && + comp.context().count ("p:comp-number")) + { + os << "this->v_all_count_.clear ();" + << endl; + } + } + + if (hra) + os << "this->v_state_attr_stack_.clear ();" + << endl; + } + + // Reset member parsers. + // + + if (ha) + names (c, names_attribute_reset_); + + if (he) + { + os << "this->resetting_ = true;" + << endl; + + contains_compositor (c, contains_compositor_reset_); + + os << "this->resetting_ = false;" + << endl; + } + + os << "}"; + } + + // + // + if (poly_code) + { + String id (c.name ()); + + if (String ns = xml_ns_name (c)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (hb && validation) + { + Boolean gen (!anonymous (c)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + c.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + // Base post + // + if (tiein && !(base_same || base_ret == L"void")) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + String const& impl (etiein (base)); + String const& base_post (post_name (base)); + + os << base_ret << " " << name << "::" << endl + << base_post << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << base_post << " ();" + << "}"; + } + + // The rest is parsing/validation code which is generated in + // *-validation-source.cxx. + // + if (validation) + return; + + // Don't use the restriction_p result from here since we don't + // want special treatment of anyType. + // + restriction = hb && c.inherits ().is_a (); + + // _start_element_impl & _end_element_impl + // + if (he) + { + // _start_element_impl + // + + os << "bool " << name << "::" << endl + << "_start_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n"; + + if (poly_runtime) + os << "," << endl + << "const char*" << (poly_code ? " t" : ""); + + os << ")" + << "{"; + + if (poly_code) + os << "XSDE_UNUSED (t);" + << endl; + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::"; + + if (poly_runtime) + os << "_start_element_impl (ns, n, " << + (poly_code ? "t" : "0") << "))" << endl; + else + os << "_start_element_impl (ns, n))" << endl; + + os << "return true;" + << endl; + } + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + contains_compositor (c, contains_compositor_start_); + + os << "return false;" + << "}"; + + + // _end_element_impl + // + os << "bool " << name << "::" << endl + << "_end_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n)" + << "{"; + + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::_end_element_impl (ns, n))" << endl + << "return true;" + << endl; + } + + if (!exceptions) + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + contains_compositor (c, contains_compositor_end_); + + os << "return false;" + << "}"; + } + + + if (ha) + { + // _attribute_impl + // + + os << "bool " << name << "::" << endl + << "_attribute_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n," << endl + << "const " << string_type << "& v)" + << "{"; + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::_attribute_impl (ns, n, v))" + << "{" + << "return true;" + << "}"; + } + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + names (c, names_attribute_); + + os << "return false;" + << "}"; + } + } + + private: + // + // + CompositorCallback compositor_callback_val_; + Traversal::Compositor compositor_callback_non_val_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_reset_; + ParticleReset particle_reset_; + Traversal::ContainsCompositor contains_compositor_reset_; + Traversal::ContainsParticle contains_particle_reset_; + + AttributeReset attribute_reset_; + Traversal::Names names_attribute_reset_; + + // + // + Traversal::Compositor start_compositor_; + StartElement start_element_; + Traversal::ContainsCompositor contains_compositor_start_; + Traversal::ContainsParticle contains_particle_start_; + + // + // + Traversal::Compositor end_compositor_; + EndElement end_element_; + Traversal::ContainsCompositor contains_compositor_end_; + Traversal::ContainsParticle contains_particle_end_; + + // + // + Attribute attribute_; + Traversal::Names names_attribute_; + }; + + // Generate substitution group map entries. + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (e.substitutes_p ()) + { + String name (escape (e.name ())); + Type& r (e.substitutes ().root ()); + + SemanticGraph::Type& type (e.type ()); + + String m_id (e.name ()); + String r_id (r.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + m_id += L' '; + m_id += ns; + } + + if (String const& ns = r.namespace_ ().name ()) + { + r_id += L' '; + r_id += ns; + } + + os << "// Substitution map entry for " << comment (e.name ()) << + "." << endl + << "//" << endl + << "static" << endl + << "const ::xsde::cxx::parser::substitution_map_entry" << endl + << "_xsde_" << name << "_substitution_map_entry_ (" << endl + << strlit (m_id) << "," << endl + << strlit (r_id) << "," << endl + << fq_name (type) << "::_static_type ());" + << endl; + } + } + }; + } + + Void + generate_parser_source (Context& ctx) + { + if (ctx.tiein) + ctx.os << "#include " << endl + << endl; + + if (ctx.poly_code) + { + ctx.os << "#include " << endl + << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl + << endl; + else + ctx.os << endl; + + ctx.os << "static" << endl + << "const ::xsde::cxx::parser::substitution_map_init" << endl + << "_xsde_substitution_map_init_;" + << endl; + + if (ctx.validation) + { + ctx.os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_init" << endl + << "_xsde_inheritance_map_init_;" + << endl; + } + } + + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement global_element (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.poly_code) + names >> global_element; + + schema.dispatch (ctx.schema_root); + } + } +} -- cgit v1.1