// file : xsde/cxx/parser/name-processor.cxx // copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include #include #include #include #include #include #include using namespace std; namespace CXX { namespace Parser { namespace { // // typedef set NameSet; class Context: public CXX::Context { public: Context (Parser::options const& ops, SemanticGraph::Schema& root, SemanticGraph::Path const& path) : CXX::Context (std::wcerr, root, path, ops, "p:name", "char"), skel_suffix_ (ops.skel_type_suffix ()), impl_suffix_ (ops.impl_type_suffix ()), impl (ops.generate_noop_impl () || ops.generate_print_impl () || ops.generate_test_driver ()), tiein (!ops.reuse_style_mixin () && !ops.reuse_style_none ()), skel_suffix (skel_suffix_), impl_suffix (impl_suffix_), global_type_names (global_type_names_), validation (!ops.suppress_validation ()), polymorphic (ops.generate_polymorphic ()) { } protected: Context (Context& c) : CXX::Context (c), impl (c.impl), tiein (c.tiein), skel_suffix (c.skel_suffix), impl_suffix (c.impl_suffix), global_type_names (c.global_type_names), validation (c.validation), polymorphic (c.polymorphic) { } public: String find_name (String const& n, String const& suffix, NameSet& set) { String name (escape (n + suffix)); for (size_t i (1); set.find (name) != set.end (); ++i) { std::wostringstream os; os << i; name = escape (n + os.str () + suffix); } set.insert (name); return name; } String find_name (String const& n, NameSet& set) { return find_name (n, L"", set); } private: String const skel_suffix_; String const impl_suffix_; map global_type_names_; public: bool const impl; bool const tiein; String const& skel_suffix; String const& impl_suffix; map& global_type_names; bool validation; bool polymorphic; }; // Primary names. // struct PrimaryParticle: Traversal::Element, Context { PrimaryParticle (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction) { } virtual void traverse (SemanticGraph::Element& e) { using SemanticGraph::Element; SemanticGraph::Context& ec (e.context ()); if (!restriction_) { ec.set ("p:name", find_name (e.name (), set_)); } else { Element* prot ( ec.get ("xsd-frontend-restriction-correspondence")); ec.set ("p:name", prot->context ().get ("p:name")); } } private: NameSet& set_; bool restriction_; }; struct PrimaryAttribute: Traversal::Attribute, Context { PrimaryAttribute (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction) { } virtual void traverse (SemanticGraph::Attribute& a) { using SemanticGraph::Attribute; SemanticGraph::Context& ac (a.context ()); if (!restriction_) { ac.set ("p:name", find_name (a.name (), set_)); } else { Attribute* prot ( ac.get ("xsd-frontend-restriction-correspondence")); ac.set ("p:name", prot->context ().get ("p:name")); } } private: NameSet& set_; bool restriction_; }; // // Secondary names. // struct ParticleTag: Traversal::Element, Traversal::Any, Traversal::Choice, Traversal::Sequence, Context { ParticleTag (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction) { } virtual void traverse (SemanticGraph::Element& e) { using SemanticGraph::Element; SemanticGraph::Context& ec (e.context ()); if (!restriction_) { String const base (ec.get ("p:name")); ec.set ("p:tag", find_name (base, L"_tag", set_)); } else { Element* prot = ec.get ( "xsd-frontend-restriction-correspondence"); ec.set ("p:tag", prot->context ().get ("p:tag")); } } virtual void traverse (SemanticGraph::Any& a) { using SemanticGraph::Any; SemanticGraph::Context& ac (a.context ()); if (!restriction_) ac.set ("p:tag", find_name (L"any", L"_tag", set_)); else { Any* prot = ac.get ( "xsd-frontend-restriction-correspondence"); ac.set ("p:tag", prot->context ().get ("p:tag")); } } virtual void traverse (SemanticGraph::Choice& c) { using SemanticGraph::Compositor; SemanticGraph::Context& cc (c.context ()); if (!restriction_) { cc.set ("p:tag", find_name (L"choice", L"_tag", set_)); } else { Compositor* prot = cc.get ( "xsd-frontend-restriction-correspondence"); cc.set ("p:tag", prot->context ().get ("p:tag")); } } virtual void traverse (SemanticGraph::Sequence& s) { using SemanticGraph::Compositor; SemanticGraph::Context& sc (s.context ()); if (!restriction_) { sc.set ("p:tag", find_name (L"sequence", L"_tag", set_)); } else { Compositor* prot = sc.get ( "xsd-frontend-restriction-correspondence"); sc.set ("p:tag", prot->context ().get ("p:tag")); } } private: NameSet& set_; bool restriction_; }; struct SecondaryCompositor: Traversal::All, Traversal::Choice, Traversal::Sequence, Context { SecondaryCompositor (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction), particle_tag_ (c, set, restriction) { contain_particle_tag_ >> particle_tag_; } virtual void traverse (SemanticGraph::All& a) { // For the all compositor, maxOccurs=1 and minOccurs={0,1} // and it cannot be used in restriction. // if (a.min () == 0) { a.context ().set ( "p:present", find_name (L"all", L"_present", set_)); } Traversal::All::traverse (a); } virtual void traverse (SemanticGraph::Choice& c) { if (c.contains_begin () == c.contains_end ()) return; SemanticGraph::Context& cc (c.context ()); if (!restriction_) { cc.set ("p:arm-tag", find_name (L"choice", L"_arm_tag", set_)); Traversal::Choice::contains (c, contain_particle_tag_); cc.set ("p:arm", find_name (L"choice", L"_arm", set_)); } else { SemanticGraph::Compositor& b ( *cc.get ( "xsd-frontend-restriction-correspondence")); SemanticGraph::Context& bc (b.context ()); cc.set ("p:arm-tag", bc.get ("p:arm-tag")); Traversal::Choice::contains (c, contain_particle_tag_); cc.set ("p:arm", bc.get ("p:arm")); } Traversal::Choice::traverse (c); } virtual void traverse (SemanticGraph::Sequence& s) { SemanticGraph::Context& sc (s.context ()); if (!restriction_) { if (s.max () != 1) sc.set ("p:next", find_name (L"sequence", L"_next", set_)); else if (s.min () == 0) sc.set ("p:present", find_name (L"sequence", L"_present", set_)); } else { // Root compositor that models inheritance by extension // may not have an association. // if (sc.count ("xsd-frontend-restriction-correspondence")) { SemanticGraph::Compositor& b ( *sc.get ( "xsd-frontend-restriction-correspondence")); SemanticGraph::Context& bc (b.context ()); if (b.max () != 1) { sc.set ("p:next", bc.get ("p:next")); // Add the *_present callback if this is a restriction // of sequence to optional. // if (s.min () == 0) sc.set ("p:present", find_name (L"sequence", L"_present", set_)); } else if (b.min () == 0) sc.set ("p:present", bc.get ("p:present")); } } Traversal::Sequence::traverse (s); } private: NameSet& set_; bool restriction_; ParticleTag particle_tag_; Traversal::ContainsParticle contain_particle_tag_; }; struct SecondaryParticle: Traversal::Element, Context { SecondaryParticle (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction) { } virtual void traverse (SemanticGraph::Element& e) { bool poly ( polymorphic && !e.type ().context ().count ("anonymous")); SemanticGraph::Context& ec (e.context ()); if (!restriction_) { String const& base (ec.get ("p:name")); ec.set ("p:parser", find_name (base + L"_parser", set_)); ec.set ("p:member", find_name (base + L"_parser_", set_)); if (poly) ec.set ( "p:member-map", find_name (base + L"_parser_map_", set_)); } else { SemanticGraph::Context& bc ( ec.get ( "xsd-frontend-restriction-correspondence")->context ()); ec.set ("p:parser", bc.get ("p:parser")); ec.set ("p:member", bc.get ("p:member")); if (poly) ec.set ("p:member-map", bc.get ("p:member-map")); } } private: NameSet& set_; bool restriction_; }; struct SecondaryAttribute: Traversal::Attribute, Context { SecondaryAttribute (Context& c, NameSet& set, bool restriction) : Context (c), set_ (set), restriction_ (restriction) { } virtual void traverse (SemanticGraph::Attribute& a) { using SemanticGraph::Attribute; SemanticGraph::Context& ac (a.context ()); if (!restriction_) { String const& base (ac.get ("p:name")); a.context ().set ( "p:parser", find_name (base + L"_parser", set_)); a.context ().set ( "p:member", find_name (base + L"_parser_", set_)); } else { SemanticGraph::Context& bc ( ac.get ( "xsd-frontend-restriction-correspondence")->context ()); ac.set ("p:parser", bc.get ("p:parser")); ac.set ("p:member", bc.get ("p:member")); } } private: NameSet& set_; bool restriction_; }; // // struct Complex: Traversal::Complex, Context { Complex (Context& c) : Context (c) { } virtual void traverse (Type& c) { SemanticGraph::Context& cc (c.context ()); // Use processed name. // String const& name (cc.get ("p:name")); // We leave this set around to allow other mappings to use // this information. // cc.set ("cxx-parser-name-processor-member-set", NameSet ()); NameSet& member_set ( cc.get ("cxx-parser-name-processor-member-set")); member_set.insert (name); // Add our base's members to the initial list unless we are // inheriting by restriction in which case we need to have // the same names as our base. // bool restriction (false); if (c.inherits_p ()) { // @@ What if this types name is the same as one of base's // members? // SemanticGraph::Type& base (c.inherits ().base ()); if (base.is_a ()) { if (!base.context ().count ( "cxx-parser-name-processor-member-set")) { dispatch (base); } NameSet const& base_set ( base.context ().get ( "cxx-parser-name-processor-member-set")); member_set.insert (base_set.begin (), base_set.end ()); // Inheritance by restriction from anyType is a special case. // restriction = c.inherits ().is_a () && !c.inherits ().base ().is_a (); } } // First assign the "primary" names. // { if (c.contains_compositor_p ()) { PrimaryParticle particle (*this, member_set, restriction); Traversal::Compositor compositor; Traversal::ContainsCompositor contains_compositor; Traversal::ContainsParticle contains_particle; contains_compositor >> compositor >> contains_particle; contains_particle >> compositor; contains_particle >> particle; Complex::contains_compositor (c, contains_compositor); } // // PrimaryAttribute attribute (*this, member_set, restriction); Traversal::Names names (attribute); Complex::names (c, names); } // Assign "secondary" names. // { if (c.contains_compositor_p ()) { // In case of validation we generate some extra callbacks // for compositors. // if (validation) { SecondaryParticle particle (*this, member_set, restriction); SecondaryCompositor compositor (*this, member_set, restriction); Traversal::ContainsCompositor contains_compositor; Traversal::ContainsParticle contains_particle; contains_compositor >> compositor >> contains_particle; contains_particle >> compositor; contains_particle >> particle; Complex::contains_compositor (c, contains_compositor); } else { SecondaryParticle particle (*this, member_set, restriction); Traversal::Compositor compositor; Traversal::ContainsCompositor contains_compositor; Traversal::ContainsParticle contains_particle; contains_compositor >> compositor >> contains_particle; contains_particle >> compositor; contains_particle >> particle; Complex::contains_compositor (c, contains_compositor); } } // // SecondaryAttribute attribute (*this, member_set, restriction); Traversal::Names names (attribute); Complex::names (c, names); } } }; // // struct GlobalType: Traversal::Type, Context { GlobalType (Context& c, NameSet& set) : Context (c), set_ (set) { } virtual void traverse (SemanticGraph::Type& t) { SemanticGraph::Context& c (t.context ()); String const& n (t.name ()); String name (find_name (n + skel_suffix, set_)); c.set ("p:name", name); // Assign the post_* name. // c.set ("p:post", find_post_name (t)); if (tiein) c.set ("p:tiein", escape (n + L"_impl_")); // Note that we do not add this name to the set so that it // does not influence other names. // if (impl) c.set ("p:impl", escape (n + impl_suffix)); } private: String find_post_name (SemanticGraph::Type& t) { String const& n (t.name ()); // It is possible that our base has the same type name (just // in a different namespaces). Avoid name clash in this case. // using SemanticGraph::Complex; Complex* c = dynamic_cast (&t); if (c == 0 || !c->inherits_p ()) { return escape (L"post_" + n); } else { NameSet set; // Collect all base's post_*. In some mutual inclusion cases it // is possible that our base won't have the post name assigned // yet. In this situation will will have to figure it out // ourselves (we can do it since we use the "raw" type name). // SemanticGraph::Type* b (&c->inherits ().base ()); while (true) { if (b->context ().count ("p:post")) set.insert (b->context ().get ("p:post")); else set.insert (find_post_name (*b)); Complex* cb (dynamic_cast (b)); if (cb != 0 && cb->inherits_p ()) { b = &cb->inherits ().base (); continue; } break; } String base_name (escape (L"post_" + n)); String post (base_name); for (size_t i (1); set.find (post) != set.end (); ++i) { std::wostringstream os; os << i; post = base_name + os.str (); } return post; } } private: NameSet& set_; }; struct Namespace: Traversal::Namespace, Context { Namespace (Context& c) : Context (c) { } virtual void traverse (Type& ns) { SemanticGraph::Context& nsc (ns.context ()); String const& name (ns.name ()); // Use a name set associated with this namespace if present. // This will make sure that we don't get any conflicts in the // multi-mapping translation case. Note that here we assume // that all mappings traverse schemas in the same order which // is currently the case. // if (global_type_names.find (name) == global_type_names.end ()) { if (!nsc.count ("name-set")) nsc.set ("name-set", NameSet ()); NameSet& s (nsc.get ("name-set")); global_type_names[name] = &s; } NameSet& type_set (*global_type_names[name]); GlobalType type (*this, type_set); Traversal::Names names (type); Traversal::Namespace::names (ns, names); } }; struct FundType : Traversal::AnyType, Traversal::AnySimpleType, Traversal::Fundamental::Byte, Traversal::Fundamental::UnsignedByte, Traversal::Fundamental::Short, Traversal::Fundamental::UnsignedShort, Traversal::Fundamental::Int, Traversal::Fundamental::UnsignedInt, Traversal::Fundamental::Long, Traversal::Fundamental::UnsignedLong, Traversal::Fundamental::Integer, Traversal::Fundamental::NonPositiveInteger, Traversal::Fundamental::NonNegativeInteger, Traversal::Fundamental::PositiveInteger, Traversal::Fundamental::NegativeInteger, Traversal::Fundamental::Boolean, Traversal::Fundamental::Float, Traversal::Fundamental::Double, Traversal::Fundamental::Decimal, Traversal::Fundamental::String, Traversal::Fundamental::NormalizedString, Traversal::Fundamental::Token, Traversal::Fundamental::Name, Traversal::Fundamental::NameToken, Traversal::Fundamental::NameTokens, Traversal::Fundamental::NCName, Traversal::Fundamental::Language, Traversal::Fundamental::QName, Traversal::Fundamental::Id, Traversal::Fundamental::IdRef, Traversal::Fundamental::IdRefs, Traversal::Fundamental::AnyURI, Traversal::Fundamental::Base64Binary, Traversal::Fundamental::HexBinary, Traversal::Fundamental::Date, Traversal::Fundamental::DateTime, Traversal::Fundamental::Duration, Traversal::Fundamental::Day, Traversal::Fundamental::Month, Traversal::Fundamental::MonthDay, Traversal::Fundamental::Year, Traversal::Fundamental::YearMonth, Traversal::Fundamental::Time, Traversal::Fundamental::Entity, Traversal::Fundamental::Entities, Context { FundType (Context& c) : Context (c) { } // anyType & anySimpleType. // virtual void traverse (SemanticGraph::AnyType& t) { set_names (t, "any_type"); } virtual void traverse (SemanticGraph::AnySimpleType& t) { set_names (t, "any_simple_type"); } // Boolean. // virtual void traverse (SemanticGraph::Fundamental::Boolean& t) { set_names (t, "boolean"); } // Integral types. // virtual void traverse (SemanticGraph::Fundamental::Byte& t) { set_names (t, "byte"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedByte& t) { set_names (t, "unsigned_byte"); } virtual void traverse (SemanticGraph::Fundamental::Short& t) { set_names (t, "short"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedShort& t) { set_names (t, "unsigned_short"); } virtual void traverse (SemanticGraph::Fundamental::Int& t) { set_names (t, "int"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedInt& t) { set_names (t, "unsigned_int"); } virtual void traverse (SemanticGraph::Fundamental::Long& t) { set_names (t, "long"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedLong& t) { set_names (t, "unsigned_long"); } virtual void traverse (SemanticGraph::Fundamental::Integer& t) { set_names (t, "integer"); } virtual void traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) { set_names (t, "non_positive_integer"); } virtual void traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) { set_names (t, "non_negative_integer"); } virtual void traverse (SemanticGraph::Fundamental::PositiveInteger& t) { set_names (t, "positive_integer"); } virtual void traverse (SemanticGraph::Fundamental::NegativeInteger& t) { set_names (t, "negative_integer"); } // Floats. // virtual void traverse (SemanticGraph::Fundamental::Float& t) { set_names (t, "float"); } virtual void traverse (SemanticGraph::Fundamental::Double& t) { set_names (t, "double"); } virtual void traverse (SemanticGraph::Fundamental::Decimal& t) { set_names (t, "decimal"); } // Strings. // virtual void traverse (SemanticGraph::Fundamental::String& t) { set_names (t, "string"); } virtual void traverse (SemanticGraph::Fundamental::NormalizedString& t) { set_names (t, "normalized_string"); } virtual void traverse (SemanticGraph::Fundamental::Token& t) { set_names (t, "token"); } virtual void traverse (SemanticGraph::Fundamental::NameToken& t) { set_names (t, "nmtoken"); } virtual void traverse (SemanticGraph::Fundamental::NameTokens& t) { set_names (t, "nmtokens"); } virtual void traverse (SemanticGraph::Fundamental::Name& t) { set_names (t, "name"); } virtual void traverse (SemanticGraph::Fundamental::NCName& t) { set_names (t, "ncname"); } virtual void traverse (SemanticGraph::Fundamental::Language& t) { set_names (t, "language"); } // Qualified name. // virtual void traverse (SemanticGraph::Fundamental::QName& t) { set_names (t, "qname"); } // ID/IDREF. // virtual void traverse (SemanticGraph::Fundamental::Id& t) { set_names (t, "id"); } virtual void traverse (SemanticGraph::Fundamental::IdRef& t) { set_names (t, "idref"); } virtual void traverse (SemanticGraph::Fundamental::IdRefs& t) { set_names (t, "idrefs"); } // URI. // virtual void traverse (SemanticGraph::Fundamental::AnyURI& t) { set_names (t, "uri"); } // Binary. // virtual void traverse (SemanticGraph::Fundamental::Base64Binary& t) { set_names (t, "base64_binary"); } virtual void traverse (SemanticGraph::Fundamental::HexBinary& t) { set_names (t, "hex_binary"); } // Date/time. // virtual void traverse (SemanticGraph::Fundamental::Date& t) { set_names (t, "date"); } virtual void traverse (SemanticGraph::Fundamental::DateTime& t) { set_names (t, "date_time"); } virtual void traverse (SemanticGraph::Fundamental::Duration& t) { set_names (t, "duration"); } virtual void traverse (SemanticGraph::Fundamental::Day& t) { set_names (t, "gday"); } virtual void traverse (SemanticGraph::Fundamental::Month& t) { set_names (t, "gmonth"); } virtual void traverse (SemanticGraph::Fundamental::MonthDay& t) { set_names (t, "gmonth_day"); } virtual void traverse (SemanticGraph::Fundamental::Year& t) { set_names (t, "gyear");; } virtual void traverse (SemanticGraph::Fundamental::YearMonth& t) { set_names (t, "gyear_month"); } virtual void traverse (SemanticGraph::Fundamental::Time& t) { set_names (t, "time"); } // Entity. // virtual void traverse (SemanticGraph::Fundamental::Entity& t) { set_names (t, "entity"); } virtual void traverse (SemanticGraph::Fundamental::Entities& t) { set_names (t, "entities"); } private: String make_skel_name (String const& base) { return escape (base + skel_suffix); } String make_impl_name (String const& base) { return escape (base + impl_suffix); } void set_names (SemanticGraph::Type& t, String const& name) { SemanticGraph::Context& c (t.context ()); wchar_t const* ns = validation ? L"::xsde::cxx::parser::validating::" : L"::xsde::cxx::parser::non_validating::"; String skel (make_skel_name (name)); c.set ("p:name", skel); c.set ("p:real-name", ns + skel); String impl (make_impl_name (name)); c.set ("p:impl", impl); c.set ("p:real-impl", ns + impl); c.set ("p:post", L"post_" + name); if (tiein) c.set ("p:tiein", name + L"_impl_"); } }; // Go into sourced/included/imported schemas while making sure // we don't process the same stuff more than once. // struct Uses: Traversal::Sources, Traversal::Includes, Traversal::Imports { virtual void traverse (SemanticGraph::Sources& sr) { SemanticGraph::Schema& s (sr.schema ()); if (!s.context ().count ("cxx-parser-name-processor-seen")) { s.context ().set ("cxx-parser-name-processor-seen", true); Traversal::Sources::traverse (sr); } } virtual void traverse (SemanticGraph::Includes& i) { SemanticGraph::Schema& s (i.schema ()); if (!s.context ().count ("cxx-parser-name-processor-seen")) { s.context ().set ("cxx-parser-name-processor-seen", true); Traversal::Includes::traverse (i); } } virtual void traverse (SemanticGraph::Imports& i) { SemanticGraph::Schema& s (i.schema ()); if (!s.context ().count ("cxx-parser-name-processor-seen")) { s.context ().set ("cxx-parser-name-processor-seen", true); Traversal::Imports::traverse (i); } } }; // Go into implied schemas while making sure we don't process // the same stuff more than once. // struct Implies: Traversal::Implies { virtual void traverse (SemanticGraph::Implies& i) { SemanticGraph::Schema& s (i.schema ()); if (!s.context ().count ("cxx-parser-name-processor-seen")) { s.context ().set ("cxx-parser-name-processor-seen", true); Traversal::Implies::traverse (i); } } }; void process_impl (options const& ops, SemanticGraph::Schema& tu, SemanticGraph::Path const& file, bool deep) { Context ctx (ops, tu, file); if (tu.names_begin ()->named ().name () == L"http://www.w3.org/2001/XMLSchema") { // XML Schema namespace. // Traversal::Schema schema; Traversal::Names schema_names; Traversal::Namespace ns; Traversal::Names ns_names; FundType fund_type (ctx); schema >> schema_names >> ns >> ns_names >> fund_type; schema.dispatch (tu); } else { // Pass one - assign names to fundamental types. // { Traversal::Schema schema; Implies implies; Traversal::Schema xs_schema; schema >> implies >> xs_schema; Traversal::Names xs_schema_names; Traversal::Namespace ns; Traversal::Names ns_names; FundType fund_type (ctx); xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; schema.dispatch (tu); } // Pass two - assign names to global types. This pass cannot // be combined with pass three because of possible recursive // schema inclusions. Also note that we check first if this // schema has already been processed which may happen in the // file-per-type compilation mode. // if (!tu.context ().count ("cxx-parser-name-processor-seen")) { Traversal::Schema schema; Uses uses; schema >> uses >> schema; Traversal::Names schema_names; Namespace ns (ctx); schema >> schema_names >> ns; // Some twisted schemas do recusive self-inclusion. // tu.context ().set ("cxx-parser-name-processor-seen", true); schema.dispatch (tu); } if (!deep) return; // Pass three - assign names inside complex types. Here we don't // need to go into included/imported schemas. // { Traversal::Schema schema; Sources sources; schema >> sources >> schema; Traversal::Names schema_names; Traversal::Namespace ns; Traversal::Names ns_names; schema >> schema_names >> ns >> ns_names; Complex complex (ctx); ns_names >> complex; schema.dispatch (tu); } } } } void NameProcessor:: process (options const& ops, SemanticGraph::Schema& tu, SemanticGraph::Path const& file, bool deep) { process_impl (ops, tu, file, deep); } } }