Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Copyright (c) 2001-2011 Joel de Guzman Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM) Chris@16: #define BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace spirit { namespace karma Chris@16: { Chris@16: template < Chris@16: typename OutputIterator, typename Context, typename Delimiter Chris@16: , typename Properties, typename F> Chris@16: struct debug_handler Chris@16: { Chris@16: typedef detail::output_iterator Chris@16: output_iterator; Chris@16: typedef detail::enable_buffering buffer_type; Chris@16: Chris@16: typedef function Chris@16: function_type; Chris@16: Chris@16: debug_handler(function_type subject, F f, std::string const& rule_name) Chris@16: : subject(subject) Chris@16: , f(f) Chris@16: , rule_name(rule_name) Chris@16: {} Chris@16: Chris@16: bool operator()(output_iterator& sink, Context& context Chris@16: , Delimiter const& delim) const Chris@16: { Chris@16: buffer_type buffer(sink); Chris@16: bool r = false; Chris@16: Chris@16: f (sink, context, pre_generate, rule_name, buffer); Chris@16: { Chris@16: detail::disable_counting nocount(sink); Chris@16: r = subject(sink, context, delim); Chris@16: } Chris@16: Chris@16: if (r) Chris@16: { Chris@16: f (sink, context, successful_generate, rule_name, buffer); Chris@16: buffer.buffer_copy(); Chris@16: return true; Chris@16: } Chris@16: f (sink, context, failed_generate, rule_name, buffer); Chris@16: return false; Chris@16: } Chris@16: Chris@16: function_type subject; Chris@16: F f; Chris@16: std::string rule_name; Chris@16: }; Chris@16: Chris@16: template Chris@16: void debug(rule& r, F f) Chris@16: { Chris@16: typedef rule rule_type; Chris@16: Chris@16: typedef Chris@16: debug_handler< Chris@16: OutputIterator Chris@16: , typename rule_type::context_type Chris@16: , typename rule_type::delimiter_type Chris@16: , typename rule_type::properties Chris@16: , F> Chris@16: debug_handler; Chris@16: r.f = debug_handler(r.f, f, r.name()); Chris@16: } Chris@16: Chris@16: struct simple_trace; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: // This class provides an extra level of indirection through a Chris@16: // template to produce the simple_trace type. This way, the use Chris@16: // of simple_trace below is hidden behind a dependent type, so Chris@16: // that compilers eagerly type-checking template definitions Chris@16: // won't complain that simple_trace is incomplete. Chris@16: template Chris@16: struct get_simple_trace Chris@16: { Chris@16: typedef simple_trace type; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: void debug(rule& r) Chris@16: { Chris@16: typedef rule rule_type; Chris@16: Chris@16: typedef Chris@16: debug_handler< Chris@16: OutputIterator Chris@16: , typename rule_type::context_type Chris@16: , typename rule_type::delimiter_type Chris@16: , typename rule_type::properties Chris@16: , simple_trace> Chris@16: debug_handler; Chris@16: typedef typename karma::detail::get_simple_trace::type Chris@16: trace; Chris@16: r.f = debug_handler(r.f, trace(), r.name()); Chris@16: } Chris@16: Chris@16: }}} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Utility macro for easy enabling of rule and grammar debugging Chris@16: #if !defined(BOOST_SPIRIT_DEBUG_NODE) Chris@16: #if defined(BOOST_SPIRIT_KARMA_DEBUG) Chris@16: #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); debug(r) Chris@16: #else Chris@16: #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: #endif