// file : xsde/cxx/hybrid/parser-header.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 Hybrid { namespace { struct List: Traversal::List, Context { List (Context& c) : Context (c) { } virtual Void traverse (Type& l) { String const& name (epimpl_custom (l)); // We may not need to generate the class if this parser is // being customized. // if (name) { String item (unclash (epskel (l), "item")); os << "class " << name << ": public " << (mixin ? "virtual " : "") << epskel (l) << "{" << "public:" << endl; // d-tor & c-tor // os << "~" << name << " ();" << name << " (bool = false);" << endl; // reset // if (reset) os << "virtual void" << endl << "_reset ();" << endl; // pre // os << "virtual void" << endl << "pre ();" << endl; // item // String const& arg (parg_type (l.argumented ().type ())); os << "virtual void" << endl << item << " (" << arg << ");" << endl; // post // String const& ret (pret_type (l)); os << "virtual " << ret << endl << post_name (l) << " ();" << endl; // pre_impl // String const& type (fq_name (l)); os << "void" << endl << pre_impl_name (l) << " (" << type << "*);" << endl; os << (tiein ? "public:" : "protected:") << endl; // State. // os << type << "* " << epstate_member (l) << ";" << "bool " << epstate_base (l) << ";" << "};"; } // Generate include for custom parser. // if (l.context ().count ("p:impl-include")) { close_ns (); os << "#include " << process_include_path ( l.context ().get ("p:impl-include")) << endl << endl; open_ns (); } } }; struct Union: Traversal::Union, Context { Union (Context& c) : Context (c) { } virtual Void traverse (Type& u) { String const& name (epimpl_custom (u)); // We may not need to generate the class if this parser is // being customized. // if (name) { Boolean fl (fixed_length (u)); os << "class " << name << ": public " << (mixin ? "virtual " : "") << epskel (u) << "{" << "public:" << endl; if (!fl) { // d-tor & c-tor // os << "~" << name << " ();" << name << " (bool = false);" << endl; // reset // if (reset) os << "virtual void" << endl << "_reset ();" << endl; } // pre // os << "virtual void" << endl << "pre ();" << endl; // _characters // os << "virtual void" << endl << "_characters (const " << string_type << "&);" << endl; // post // String const& ret (pret_type (u)); os << "virtual " << ret << endl << post_name (u) << " ();" << endl; String const& type (fq_name (u)); // pre_impl // if (!fl) os << "void" << endl << pre_impl_name (u) << " (" << type << "*);" << endl; os << (tiein ? "public:" : "protected:") << endl; // State. // String const& state_type (epstate_type (u)); os << "struct " << state_type << "{"; if (!fl) os << type << "* " << "x_;"; if (stl) os << "::std::string str_;"; else os << "::xsde::cxx::string str_;"; os << "};" << state_type << " " << epstate (u) << ";"; if (!fl) os << "bool " << epstate_base (u) << ";"; os << "};"; } // Generate include for custom parser. // if (u.context ().count ("p:impl-include")) { close_ns (); os << "#include " << process_include_path ( u.context ().get ("p:impl-include")) << endl << endl; open_ns (); } } }; // // State. // struct CompositorState: Traversal::Compositor, Context { CompositorState (Context& c) : Context (c) { } virtual Void traverse (SemanticGraph::Compositor& c) { if (c.max () != 1) { String scope (fq_scope (c)); os << scope << "::" << etype (c) << "* " << epstate_member (c) << ";"; } Compositor::traverse (c); } }; // // Callbacks. // struct CompositorCallback: Traversal::All, Traversal::Choice, Traversal::Sequence, Context { CompositorCallback (Context& c) : Context (c) { } virtual Void traverse (SemanticGraph::All& a) { // For the all compositor, maxOccurs=1 and minOccurs={0,1}. // if (a.min () == 0) { os << "virtual void" << endl << eppresent (a) << " ();" << endl; } Traversal::All::traverse (a); } virtual Void traverse (SemanticGraph::Choice& c) { os << "virtual void" << endl << eparm (c) << " (" << eparm_tag (c) << ");" << endl; Traversal::Choice::traverse (c); } virtual Void traverse (SemanticGraph::Sequence& s) { if (s.max () != 1) { os << "virtual void" << endl << epnext (s) << " ();" << endl; } else if (s.min () == 0) { os << "virtual void" << endl << eppresent (s) << " ();" << endl; } Traversal::Sequence::traverse (s); } }; struct ParticleCallback: Traversal::Element, Context { ParticleCallback (Context& c) : Context (c) { } virtual Void traverse (SemanticGraph::Element& e) { String const& arg (parg_type (e.type ())); os << "virtual void" << endl << epname (e) << " ("; if (arg != L"void") os << arg; os << ");" << endl; } }; struct AttributeCallback: Traversal::Attribute, Context { AttributeCallback (Context& c) : Context (c) { } virtual Void traverse (SemanticGraph::Attribute& a) { String const& arg (parg_type (a.type ())); os << "virtual void" << endl << epname (a) << " ("; if (arg != L"void") os << arg; os << ");" << endl; } }; // // struct Complex : Traversal::Complex, Context { Complex (Context& c) : Context (c), // State. // compositor_state_ (c), // Callbacks. // compositor_callback_ (c), particle_callback_ (c), attribute_callback_ (c) { // State. // contains_compositor_state_ >> compositor_state_; compositor_state_ >> contains_particle_state_; contains_particle_state_ >> compositor_state_; // Callbacks. // contains_compositor_callback_ >> compositor_callback_; compositor_callback_ >> contains_particle_callback_; contains_particle_callback_ >> compositor_callback_; contains_particle_callback_ >> particle_callback_; names_attribute_callback_ >> attribute_callback_; } virtual Void traverse (Type& c) { String const& name (epimpl_custom (c)); // We may not need to generate the class if this parser is // being customized. // if (name) { Boolean hb (c.inherits_p ()); Boolean he (has (c)); Boolean ha (has (c)); Boolean hae (has_particle (c)); Boolean restriction (restriction_p (c)); Boolean fixed (fixed_length (c)); String const& ret (pret_type (c)); os << "class " << name << ": public " << (mixin ? "virtual " : "") << epskel (c); if (mixin && hb) os << "," << endl << " public " << fq_name (c.inherits ().base (), "p:impl"); os << "{" << "public:" << endl; // c-tor // if (!fixed || (hb && tiein)) os << name << " (" << (fixed ? "" : "bool = false") << ");" << endl; if (!fixed) { // d-tor // os << "~" << name << " ();" << endl; // reset // if (reset) os << "virtual void" << endl << "_reset ();" << endl; } // pre // os << "virtual void" << endl << "pre ();" << endl; // In case of an inheritance-by-restriction, we don't need to // generate parser callbacks, etc. since they are the same as // in the base. // if (!restriction) { if (ha) { os << "// Attributes." << endl << "//" << endl; names (c, names_attribute_callback_); } if (he || hae) { os << "// Elements." << endl << "//" << endl; contains_compositor (c, contains_compositor_callback_); } } // post // os << "virtual " << ret << endl << post_name (c) << " ();" << endl; // pre_impl // String const& type (fq_name (c)); if (!fixed) os << (tiein ? "public:" : "protected:") << endl << "void" << endl << pre_impl_name (c) << " (" << type << "*);" << endl; // State. // String const& state_type (epstate_type (c)); String const& member (epstate_member (c)); os << (tiein ? "public:" : "protected:") << endl << "struct " << state_type << "{"; if (fixed) os << type << " " << member << ";"; else os << type << "* " << member << ";"; if (!restriction && c.contains_compositor_p ()) contains_compositor (c, contains_compositor_state_); os << "};" << state_type << " " << epstate (c) << ";"; if (!fixed) os << "bool " << epstate_base (c) << ";"; os << endl; // Base implementation. // if (tiein && hb) os << (tiein ? "public:" : "protected:") << endl << fq_name (c.inherits ().base (), "p:impl") << " base_impl_;" << endl; os << "};"; } // Generate include for custom parser. // if (c.context ().count ("p:impl-include")) { close_ns (); os << "#include " << process_include_path ( c.context ().get ("p:impl-include")) << endl << endl; open_ns (); } } private: // State. // CompositorState compositor_state_; Traversal::ContainsCompositor contains_compositor_state_; Traversal::ContainsParticle contains_particle_state_; // Callbacks. // CompositorCallback compositor_callback_; ParticleCallback particle_callback_; Traversal::ContainsCompositor contains_compositor_callback_; Traversal::ContainsParticle contains_particle_callback_; AttributeCallback attribute_callback_; Traversal::Names names_attribute_callback_; }; } Void generate_parser_header (Context& ctx) { Traversal::Schema schema; Traversal::Sources sources; Includes includes (ctx, Includes::impl_header); Traversal::Names schema_names; Namespace ns (ctx, true); Traversal::Names names; schema >> includes; schema >> sources >> schema; schema >> schema_names >> ns >> names; List list (ctx); Union union_ (ctx); Complex complex (ctx); names >> list; names >> union_; names >> complex; schema.dispatch (ctx.schema_root); } } }