From 49d8e39f9a42ff1963c5df0f6e9ed903d66f2eb0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 11 Feb 2011 17:18:30 +0200 Subject: Fix recursive polymorphic parsing in C++/Parser New test: cxx/parser/polyrecur. --- .../cxx/hybrid/custom/wildcard/envelope-pimpl.cxx | 6 +- examples/cxx/hybrid/wildcard/envelope-pimpl.cxx | 6 +- examples/cxx/parser/wildcard/driver.cxx | 16 +- libxsde/xsde/cxx/parser/context.hxx | 18 +++ libxsde/xsde/cxx/parser/expat/document.cxx | 26 +++- tests/cxx/parser/makefile | 2 +- tests/cxx/parser/polyrecur/driver.cxx | 87 +++++++++++ tests/cxx/parser/polyrecur/makefile | 95 ++++++++++++ tests/cxx/parser/polyrecur/test-000.std | 22 +++ tests/cxx/parser/polyrecur/test-000.xml | 15 ++ tests/cxx/parser/polyrecur/test-pimpl.cxx | 163 +++++++++++++++++++++ tests/cxx/parser/polyrecur/test-pimpl.hxx | 117 +++++++++++++++ tests/cxx/parser/polyrecur/test.xsd | 53 +++++++ xsde/cxx/parser/element-validation-source.cxx | 58 ++++---- xsde/cxx/parser/elements.cxx | 6 - xsde/cxx/parser/elements.hxx | 3 - xsde/cxx/parser/name-processor.cxx | 8 - xsde/cxx/parser/parser-header.cxx | 3 +- xsde/cxx/parser/parser-source.cxx | 83 ++++++----- 19 files changed, 673 insertions(+), 114 deletions(-) create mode 100644 tests/cxx/parser/polyrecur/driver.cxx create mode 100644 tests/cxx/parser/polyrecur/makefile create mode 100644 tests/cxx/parser/polyrecur/test-000.std create mode 100644 tests/cxx/parser/polyrecur/test-000.xml create mode 100644 tests/cxx/parser/polyrecur/test-pimpl.cxx create mode 100644 tests/cxx/parser/polyrecur/test-pimpl.hxx create mode 100644 tests/cxx/parser/polyrecur/test.xsd diff --git a/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx index eee573f..d88edf9 100644 --- a/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx +++ b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx @@ -50,7 +50,7 @@ namespace email // xml_schema::parser_context& ctx = _context (); p->pre (); - p->_pre_impl (ctx); + ctx.nested_parser (p); } } } @@ -64,10 +64,6 @@ namespace email { if (ns == "http://www.codesynthesis.com/email") { - // Note that we don't call _post_impl() (corresponding to - // _pre_impl()) here. It is called automatically by the - // infrastructure. - // envelope* env = envelope_base_pimpl_state_.envelope_; if (name == "text") diff --git a/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx b/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx index 16bd2e5..bb5827c 100644 --- a/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx +++ b/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx @@ -61,7 +61,7 @@ namespace email // xml_schema::parser_context& ctx = _context (); p->pre (); - p->_pre_impl (ctx); + ctx.nested_parser (p); } } } @@ -75,10 +75,6 @@ namespace email { if (ns == "http://www.codesynthesis.com/email") { - // Note that we don't call _post_impl() (corresponding to - // _pre_impl()) here. It is called automatically by the - // infrastructure. - // envelope* env = envelope_base_pimpl_state_.envelope_; if (name == "text") diff --git a/examples/cxx/parser/wildcard/driver.cxx b/examples/cxx/parser/wildcard/driver.cxx index aed2560..7ed7aa6 100644 --- a/examples/cxx/parser/wildcard/driver.cxx +++ b/examples/cxx/parser/wildcard/driver.cxx @@ -104,7 +104,7 @@ namespace email #ifndef XSDE_POLYMORPHIC _start_any_element (const ro_string& ns, const ro_string& name) #else - _start_any_element (const ro_string& ns, + _start_any_element (const ro_string& ns, const ro_string& name, const char*) #endif @@ -147,7 +147,9 @@ namespace email return; } #endif - p->_pre_impl (ctx); + // Indicate transition to the nested parser. + // + ctx.nested_parser (p); } } @@ -167,11 +169,6 @@ namespace email { if (name == "text") { - // Note that we don't call _post_impl() (corresponding to - // _pre_impl()) here. It is called automatically by the - // infrastructure. - // - string text (string_p_.post_string ()); #ifndef XSDE_EXCEPTIONS @@ -188,11 +185,6 @@ namespace email } else if (name == "binary") { - // Note that we don't call _post_impl() (corresponding to - // _pre_impl()) here. It is called automatically by the - // infrastructure. - // - binary_p_.post_binary (); #ifndef XSDE_EXCEPTIONS diff --git a/libxsde/xsde/cxx/parser/context.hxx b/libxsde/xsde/cxx/parser/context.hxx index cd68631..f3e49e0 100644 --- a/libxsde/xsde/cxx/parser/context.hxx +++ b/libxsde/xsde/cxx/parser/context.hxx @@ -142,6 +142,18 @@ namespace xsde void start_wildcard_content (); + parser_base* + nested_parser () const + { + return nested_parser_; + } + + void + nested_parser (parser_base* p) + { + nested_parser_ = p; + } + void reset (XML_Parser); @@ -154,6 +166,12 @@ namespace xsde public: parser_state current_; + private: + // Nested parser when transitioning from outer to inner or from + // inner to outer parsers. + // + parser_base* nested_parser_; + protected: XML_Parser xml_parser_; diff --git a/libxsde/xsde/cxx/parser/expat/document.cxx b/libxsde/xsde/cxx/parser/expat/document.cxx index 2ebde82..3afca7b 100644 --- a/libxsde/xsde/cxx/parser/expat/document.cxx +++ b/libxsde/xsde/cxx/parser/expat/document.cxx @@ -875,14 +875,30 @@ namespace xsde else if (cur.parser_) { // The "normal" case: call _start_element which will - // call pre() and _pre_impl() (which will push the - // new parser). + // call pre() and set the nested parser. We then call + // _pre_impl on that (which will push the new parser). // + + context_.nested_parser (0); + #ifdef XSDE_POLYMORPHIC cur.parser_->_start_element (ns, name, type); #else cur.parser_->_start_element (ns, name); #endif + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (context_.error_type ()) + { + XML_StopParser (xml_parser_, false); + return; + } +#endif + if (parser_base* p = context_.nested_parser ()) + p->_pre_impl (context_); + else + if (!cur.any_) + cur.depth_++; // Ignoring. } else { @@ -1073,7 +1089,7 @@ namespace xsde // The "normal" case: call _post to pop the parser and then // call _end_element on the "outer" parser which calls post(). // - parser_base* p = cur.parser_; + context_.nested_parser (cur.parser_); cur.parser_->_post_impl (); #if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) @@ -1091,7 +1107,7 @@ namespace xsde { // End of the root element. post() is called by the user. // - end_root_element (ns, name, p); + end_root_element (ns, name, context_.nested_parser ()); } } else @@ -1113,6 +1129,8 @@ namespace xsde } else { + context_.nested_parser (0); + if (cur.any_) { // Handling content matched by a wildcard. diff --git a/tests/cxx/parser/makefile b/tests/cxx/parser/makefile index 39b9f61..e2fe635 100644 --- a/tests/cxx/parser/makefile +++ b/tests/cxx/parser/makefile @@ -33,7 +33,7 @@ endif # exceptions ifeq ($(xsde_polymorphic),y) ifeq ($(xsde_reuse_style),tiein) -build_tests += polymorphism +build_tests += polymorphism polyrecur endif endif diff --git a/tests/cxx/parser/polyrecur/driver.cxx b/tests/cxx/parser/polyrecur/driver.cxx new file mode 100644 index 0000000..856b01b --- /dev/null +++ b/tests/cxx/parser/polyrecur/driver.cxx @@ -0,0 +1,87 @@ +// file : tests/cxx/parser/polyrecur/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test recursive polymorphic parsing. +// +#include + +#include "test-pskel.hxx" +#include "test-pimpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + +#ifdef XSDE_EXCEPTIONS + try + { +#endif + + // Instantiate individual parsers. + // + xml_schema::int_pimpl int_p; + + root_pimpl root_p; + expression_pimpl expression_p; + recursive_pimpl recursive_p; + value_a_pimpl value_a_p; + value_b_pimpl value_b_p; + + xml_schema::parser_map_impl expression_map (5); + + // Connect the parsers together. + // + expression_map.insert (value_a_p); + expression_map.insert (value_b_p); + expression_map.insert (recursive_p); + + root_p.parsers (expression_p); + root_p.expression_parser (expression_map); + + recursive_p.parsers (expression_p); + recursive_p.expression_parser (expression_map); + + value_a_p.parsers (int_p); + value_b_p.parsers (int_p); + + xml_schema::document_pimpl doc_p (root_p, "test", "root", true); + + root_p.pre (); + doc_p.parse (argv[1]); + +#ifndef XSDE_EXCEPTIONS + if (doc_p._error ()) + { + cerr << "error" << endl; + return 1; + } +#endif + + root_p.post_root (); + +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +#endif + + return 0; +} diff --git a/tests/cxx/parser/polyrecur/makefile b/tests/cxx/parser/polyrecur/makefile new file mode 100644 index 0000000..8a553f8 --- /dev/null +++ b/tests/cxx/parser/polyrecur/makefile @@ -0,0 +1,95 @@ +# file : tests/cxx/parser/polyrecur/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := test.xsd +cxx := driver.cxx test-pimpl.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.o)) +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +skelf := $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.ixx) $(xsd:.xsd=-pskel.cxx) +skel := $(addprefix $(out_base)/,$(skelf)) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): $(out_root)/xsde/xsde +$(skel) $(dist) $(dist-win): xsde_options += --generate-polymorphic + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Test. +# +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test-000.xml $(src_base)/test-000.std + $(call message,test $$1,$$1 $(src_base)/test-000.xml | diff -u $(src_base)/test-000.std -,$(driver)) + + +# Dist. +# +$(dist) $(dist-win): opt := -src $(src_base) -cmd cxx-parser -xsd "$(xsd)" \ +-cxx "$(cxx)" -gen "$(skelf)" -opt "$(xsde_options)" -out $(dist_prefix) + +$(dist): + $(call message,install $(src_base),$(scf_root)/dist $(opt)) + +$(dist-win): + $(call message,install $(src_base),$(scf_root)/dist -win $(opt)) + + +# Clean. +# +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=-pskel.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(skel): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(skelf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(scf_root)/xsde/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/polyrecur/test-000.std b/tests/cxx/parser/polyrecur/test-000.std new file mode 100644 index 0000000..28a835f --- /dev/null +++ b/tests/cxx/parser/polyrecur/test-000.std @@ -0,0 +1,22 @@ +root start +recursive start +value_a begin +value->constant +value: post_expression override +value_a: post_value override +value_a end +recursive->expression event +recursive start +value_b begin +value->constant +value: post_expression override +value_b: post_value override +value_b end +recursive->expression event +recursive: post_expression override +recursive end +recursive->expression event +recursive: post_expression override +recursive end +root->expression +root end diff --git a/tests/cxx/parser/polyrecur/test-000.xml b/tests/cxx/parser/polyrecur/test-000.xml new file mode 100644 index 0000000..42035ba --- /dev/null +++ b/tests/cxx/parser/polyrecur/test-000.xml @@ -0,0 +1,15 @@ + + + + + 1 + + + + 2 + + + + diff --git a/tests/cxx/parser/polyrecur/test-pimpl.cxx b/tests/cxx/parser/polyrecur/test-pimpl.cxx new file mode 100644 index 0000000..158ad55 --- /dev/null +++ b/tests/cxx/parser/polyrecur/test-pimpl.cxx @@ -0,0 +1,163 @@ +// file : tests/cxx/parser/polyrecur/test-pimpl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include "test-pimpl.hxx" + +using namespace std; + +namespace test +{ + // root_pimpl + // + + void root_pimpl:: + pre () + { + cout << "root start" << endl; + } + + void root_pimpl:: + expression () + { + cout << "root->expression" << endl; + } + + void root_pimpl:: + post_root () + { + cout << "root end" << endl; + } + + // expression_pimpl + // + + void expression_pimpl:: + pre () + { + cout << "expression begin" << endl; + } + + void expression_pimpl:: + post_expression () + { + cout << "expression end" << endl; + } + + // recursive_pimpl + // + + void recursive_pimpl:: + pre () + { + cout << "recursive start" << endl; + } + + void recursive_pimpl:: + expression () + { + cout << "recursive->expression event" << endl; + } + + void recursive_pimpl:: + post_expression () + { + cout << "recursive: post_expression override" << endl; + post_recursive (); + } + + void recursive_pimpl:: + post_recursive () + { + cout << "recursive end" << endl; + } + + // value_pimpl + // + + void value_pimpl:: + pre () + { + cout << "value begin" << endl; + } + + void value_pimpl:: + constant (int) + { + cout << "value->constant" << endl; + } + + void value_pimpl:: + post_expression () + { + cout << "value: post_expression override" << endl; + post_value (); + } + + void value_pimpl:: + post_value () + { + cout << "value end" << endl; + } + + // value_a_pimpl + // + + void value_a_pimpl:: + pre () + { + cout << "value_a begin" << endl; + } + + void value_a_pimpl:: + post_expression () + { + cout << "value: post_expression override" << endl; + post_value (); + } + + void value_a_pimpl:: + post_value () + { + cout << "value_a: post_value override" << endl; + post_value_a (); + } + + void value_a_pimpl:: + post_value_a () + { + cout << "value_a end" << endl; + } + + // value_b_pimpl + // + + void value_b_pimpl:: + pre () + { + cout << "value_b begin" << endl; + } + + void value_b_pimpl:: + post_expression () + { + cout << "value: post_expression override" << endl; + post_value (); + } + + void value_b_pimpl:: + post_value () + { + cout << "value_b: post_value override" << endl; + post_value_b (); + } + + void value_b_pimpl:: + post_value_b () + { + cout << "value_b end" << endl; + } +} diff --git a/tests/cxx/parser/polyrecur/test-pimpl.hxx b/tests/cxx/parser/polyrecur/test-pimpl.hxx new file mode 100644 index 0000000..fa6e206 --- /dev/null +++ b/tests/cxx/parser/polyrecur/test-pimpl.hxx @@ -0,0 +1,117 @@ +// file : tests/cxx/parser/polyrecur/test-pimpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef TEST_PIMPL_HXX +#define TEST_PIMPL_HXX + +#include "test-pskel.hxx" + +namespace test +{ + class root_pimpl: public root_pskel + { + public: + virtual void + pre (); + + virtual void + expression (); + + virtual void + post_root (); + }; + + class expression_pimpl: public expression_pskel + { + public: + virtual void + pre (); + + virtual void + post_expression (); + }; + + class recursive_pimpl: public recursive_pskel + { + public: + recursive_pimpl (): recursive_pskel (&base_impl_) {} + + virtual void + pre (); + + virtual void + expression (); + + virtual void + post_expression (); + + virtual void + post_recursive (); + + expression_pimpl base_impl_; + }; + + class value_pimpl: public value_pskel + { + public: + value_pimpl (): value_pskel (&base_impl_) {} + + virtual void + pre (); + + virtual void + constant (int); + + virtual void + post_expression (); + + virtual void + post_value (); + + expression_pimpl base_impl_; + }; + + class value_a_pimpl: public value_a_pskel + { + public: + value_a_pimpl (): value_a_pskel (&base_impl_) {} + + virtual void + pre (); + + virtual void + post_expression (); + + virtual void + post_value (); + + virtual void + post_value_a (); + + value_pimpl base_impl_; + }; + + class value_b_pimpl: public value_b_pskel + { + public: + value_b_pimpl (): value_b_pskel (&base_impl_) {} + + virtual void + pre (); + + virtual void + post_expression (); + + virtual void + post_value (); + + virtual void + post_value_b (); + + value_pimpl base_impl_; + }; +} + +#endif // TEST_PIMPL_HXX diff --git a/tests/cxx/parser/polyrecur/test.xsd b/tests/cxx/parser/polyrecur/test.xsd new file mode 100644 index 0000000..affcc8a --- /dev/null +++ b/tests/cxx/parser/polyrecur/test.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsde/cxx/parser/element-validation-source.cxx b/xsde/cxx/parser/element-validation-source.cxx index eec0c2f..92eb73c 100644 --- a/xsde/cxx/parser/element-validation-source.cxx +++ b/xsde/cxx/parser/element-validation-source.cxx @@ -386,23 +386,27 @@ namespace CXX Boolean poly (poly_code && !anonymous (type)); String const& name (ename (*e)); - String inst (poly ? emember_cache (*e) : emember (*e)); + String fq_type (fq_name (type)); - String def_parser, map; + String def_parser, map, inst; if (poly) { def_parser = emember (*e); map = emember_map (*e); + inst = "p"; } + else + inst = L"this->" + emember (*e); if (poly) { String cast (mixin ? L"dynamic_cast" : L"static_cast"); - String fq_type (fq_name (type)); - os << "if (t == 0 && this->" << def_parser << " != 0)" << endl - << "this->" << inst << " = this->" << def_parser << ";" + os << fq_type << "* p = 0;" + << endl + << "if (t == 0 && this->" << def_parser << " != 0)" << endl + << inst << " = this->" << def_parser << ";" << "else" << "{" << "const char* ts = " << fq_type << "::_static_type ();" @@ -412,7 +416,7 @@ namespace CXX << endl << "if (this->" << def_parser << " != 0 && " << "strcmp (t, ts) == 0)" << endl - << "this->" << inst << " = this->" << def_parser << ";" + << inst << " = this->" << def_parser << ";" << "else" << "{"; @@ -427,50 +431,46 @@ namespace CXX << "}"; os << "if (this->" << map << " != 0)" << endl - << "this->" << inst << " = " << cast << "< " << - fq_type << "* > (" << endl + << inst << " = " << cast << "< " << fq_type << "* > (" << endl << "this->" << map << "->find (t));" - << "else" << endl - << "this->" << inst << " = 0;" << "}" << "}"; } String const& post (post_name (type)); - os << "if (this->" << inst << ")" + os << "if (" << inst << ")" << "{" - << "this->" << inst << "->pre ();"; + << inst << "->pre ();"; if (!exceptions) { - // Note that after pre() we need to check both parser and - // context error states because of the recursive parsing. - // os << endl - << "if (this->" << inst << "->_error_type ())" << endl - << "this->" << inst << "->_copy_error (ctx);" - << endl - << "if (!ctx.error_type ())" << endl; + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; } - os << "this->" << inst << "->_pre_impl (ctx);" + os << "ctx.nested_parser (" << inst << ");" << endl << "}" - << "else" << endl - << "ctx.current_.depth_++;" // Ignoring document fragment. - << endl << "}" << "else" // start - << "{" - << "if (this->" << inst << ")" + << "{"; + + if (poly) + os << fq_type << "* p =" << endl + << "static_cast< " << fq_type << "* > (ctx.nested_parser ());" + << endl; + + os << "if (" << inst << " != 0)" << "{"; String const& ret (ret_type (type)); if (ret == L"void") - os << "this->" << inst << "->" << post << " ();"; + os << inst << "->" << post << " ();"; else - os << arg_type (type) << " tmp = this->" << inst << "->" << + os << arg_type (type) << " tmp = " << inst << "->" << post << " ();"; if (!exceptions) @@ -479,8 +479,8 @@ namespace CXX // context error states because of the recursive parsing. // os << endl - << "if (this->" << inst << "->_error_type ())" << endl - << "this->" << inst << "->_copy_error (ctx);" + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" << endl << "if (!ctx.error_type ())" << endl; } diff --git a/xsde/cxx/parser/elements.cxx b/xsde/cxx/parser/elements.cxx index 2ef3a23..1e58262 100644 --- a/xsde/cxx/parser/elements.cxx +++ b/xsde/cxx/parser/elements.cxx @@ -171,12 +171,6 @@ namespace CXX } String const& Context:: - emember_cache (SemanticGraph::Member& m) - { - return m.context ().get ("p:member-cache"); - } - - String const& Context:: emember_map (SemanticGraph::Member& m) { return m.context ().get ("p:member-map"); diff --git a/xsde/cxx/parser/elements.hxx b/xsde/cxx/parser/elements.hxx index e6d755f..020e51b 100644 --- a/xsde/cxx/parser/elements.hxx +++ b/xsde/cxx/parser/elements.hxx @@ -151,9 +151,6 @@ namespace CXX emember (SemanticGraph::Member&); static String const& - emember_cache (SemanticGraph::Member&); - - static String const& emember_map (SemanticGraph::Member&); static String const& diff --git a/xsde/cxx/parser/name-processor.cxx b/xsde/cxx/parser/name-processor.cxx index d6d7340..c3c2ec3 100644 --- a/xsde/cxx/parser/name-processor.cxx +++ b/xsde/cxx/parser/name-processor.cxx @@ -417,13 +417,8 @@ namespace CXX ec.set ("p:member", find_name (base + L"_parser_", set_)); if (poly) - { - ec.set ( - "p:member-cache", find_name (base + L"_parser_cache_", set_)); - ec.set ( "p:member-map", find_name (base + L"_parser_map_", set_)); - } } else { @@ -435,10 +430,7 @@ namespace CXX ec.set ("p:member", bc.get ("p:member")); if (poly) - { - ec.set ("p:member-cache", bc.get ("p:member-cache")); ec.set ("p:member-map", bc.get ("p:member-map")); - } } } diff --git a/xsde/cxx/parser/parser-header.cxx b/xsde/cxx/parser/parser-header.cxx index 3b8663c..9d45b45 100644 --- a/xsde/cxx/parser/parser-header.cxx +++ b/xsde/cxx/parser/parser-header.cxx @@ -547,8 +547,7 @@ namespace CXX if (poly_code && !anonymous (e.type ())) { - os << type << "* " << emember_cache (e) << ";" - << parser_map << "* " << emember_map (e) << ";" + os << parser_map << "* " << emember_map (e) << ";" << endl; } } diff --git a/xsde/cxx/parser/parser-source.cxx b/xsde/cxx/parser/parser-source.cxx index 5c5093f..47e4867 100644 --- a/xsde/cxx/parser/parser-source.cxx +++ b/xsde/cxx/parser/parser-source.cxx @@ -493,7 +493,6 @@ namespace CXX { Boolean poly (poly_code && !anonymous (e.type ())); Boolean subst (poly && e.global_p ()); - String const& inst (poly ? emember_cache (e) : emember (e)); if (e.qualified_p () && e.namespace_ ().name ()) { @@ -528,6 +527,8 @@ namespace CXX os << ")" << "{"; + String inst; + if (poly) { // In case of mixin we use virtual inheritance and only @@ -537,9 +538,12 @@ namespace CXX String fq_type (fq_name (e.type ())); String const& member (emember (e)); String const& member_map (emember_map (e)); + inst = "p"; - os << "if (t == 0 && this->" << member << " != 0)" << endl - << "this->" << inst << " = this->" << member << ";" + os << fq_type << "* p = 0;" + << endl + << "if (t == 0 && this->" << member << " != 0)" << endl + << inst << " = this->" << member << ";" << "else" << "{" << "const char* ts = " << fq_type << "::_static_type ();" @@ -549,42 +553,30 @@ namespace CXX << endl << "if (this->" << member << " != 0 && " << "strcmp (t, ts) == 0)" << endl - << "this->" << inst << " = this->" << member << ";" + << inst << " = this->" << member << ";" << "else if (this->" << member_map << " != 0)" << endl - << "this->" << inst << " = " << cast << "< " << fq_type << + << inst << " = " << cast << "< " << fq_type << "* > (" << endl << "this->" << member_map << "->find (t));" - << "else" << endl - << "this->" << inst << " = 0;" << "}"; } + else + inst = L"this->" + emember (e); - os << "if (this->" << inst << ")" - << "{"; + os << "if (" << inst << ")" + << "{" + << inst << "->pre ();"; - if (exceptions) + 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 << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; } - os << "}" - << "else" << endl - << "ctx.current_.depth_++;" // Ignoring document fragment. - << endl + os << "ctx.nested_parser (" << inst << ");" << endl + << "}" << "return true;" << "}"; } @@ -606,7 +598,6 @@ namespace CXX String const& name (ename (e)); Boolean poly (poly_code && !anonymous (e.type ())); Boolean subst (poly && e.global_p ()); - String const& inst (poly ? emember_cache (e) : emember (e)); if (e.qualified_p () && e.namespace_ ().name ()) { @@ -643,17 +634,31 @@ namespace CXX SemanticGraph::Type& type (e.type ()); String const& post (post_name (type)); + String inst; - os << "if (this->" << inst << ")" + if (poly) + { + String fq_type (fq_name (e.type ())); + inst = "p"; + + os << fq_type << "* p =" << endl + << "static_cast< " << fq_type << "* > (" << + "this->_context ().nested_parser ());" + << endl; + } + else + inst = L"this->" + emember (e); + + os << "if (" << inst << ")" << "{"; if (exceptions) { if (ret_type (type) == L"void") - os << "this->" << inst << "->" << post << " ();" + os << inst << "->" << post << " ();" << "this->" << name << " ();"; else - os << "this->" << name << " (this->" << inst << "->" << + os << "this->" << name << " (" << inst << "->" << post << " ());"; } else @@ -663,21 +668,21 @@ namespace CXX // if (ret_type (type) == L"void") { - os << "this->" << inst << "->" << post << " ();" + os << inst << "->" << post << " ();" << endl - << "if (this->" << inst << "->_error_type ())" << endl - << "this->" << inst << "->_copy_error (ctx);" + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" << endl << "if (!ctx.error_type ())" << endl << "this->" << name << " ();"; } else { - os << arg_type (type) << " tmp = this->" << inst << "->" << + os << arg_type (type) << " tmp = " << inst << "->" << post << " ();" << endl - << "if (this->" << inst << "->_error_type ())" << endl - << "this->" << inst << "->_copy_error (ctx);" + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" << endl << "if (!ctx.error_type ())" << endl << "this->" << name << " (tmp);"; -- cgit v1.1