1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // Copyright (c) 2001-2011 Joel de Guzman 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM) 8 #define BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/support/unused.hpp> 15 #include <boost/spirit/home/karma/nonterminal/rule.hpp> 16 #include <boost/spirit/home/karma/nonterminal/debug_handler_state.hpp> 17 #include <boost/function.hpp> 18 #include <boost/fusion/include/at.hpp> 19 #include <boost/fusion/include/vector.hpp> 20 #include <boost/fusion/include/out.hpp> 21 #include <iostream> 22 23 namespace boost { namespace spirit { namespace karma 24 { 25 template < 26 typename OutputIterator, typename Context, typename Delimiter 27 , typename Properties, typename F> 28 struct debug_handler 29 { 30 typedef detail::output_iterator<OutputIterator, Properties> 31 output_iterator; 32 typedef detail::enable_buffering<output_iterator> buffer_type; 33 34 typedef function<bool(output_iterator&, Context&, Delimiter const&)> 35 function_type; 36 debug_handlerboost::spirit::karma::debug_handler37 debug_handler(function_type subject, F f, std::string const& rule_name) 38 : subject(subject) 39 , f(f) 40 , rule_name(rule_name) 41 {} 42 operator ()boost::spirit::karma::debug_handler43 bool operator()(output_iterator& sink, Context& context 44 , Delimiter const& delim) const 45 { 46 buffer_type buffer(sink); 47 bool r = false; 48 49 f (sink, context, pre_generate, rule_name, buffer); 50 { 51 detail::disable_counting<output_iterator> nocount(sink); 52 r = subject(sink, context, delim); 53 } 54 55 if (r) 56 { 57 f (sink, context, successful_generate, rule_name, buffer); 58 buffer.buffer_copy(); 59 return true; 60 } 61 f (sink, context, failed_generate, rule_name, buffer); 62 return false; 63 } 64 65 function_type subject; 66 F f; 67 std::string rule_name; 68 }; 69 70 template <typename OutputIterator 71 , typename T1, typename T2, typename T3, typename T4, typename F> debug(rule<OutputIterator,T1,T2,T3,T4> & r,F f)72 void debug(rule<OutputIterator, T1, T2, T3, T4>& r, F f) 73 { 74 typedef rule<OutputIterator, T1, T2, T3, T4> rule_type; 75 76 typedef 77 debug_handler< 78 OutputIterator 79 , typename rule_type::context_type 80 , typename rule_type::delimiter_type 81 , typename rule_type::properties 82 , F> 83 debug_handler; 84 r.f = debug_handler(r.f, f, r.name()); 85 } 86 87 struct simple_trace; 88 89 namespace detail 90 { 91 // This class provides an extra level of indirection through a 92 // template to produce the simple_trace type. This way, the use 93 // of simple_trace below is hidden behind a dependent type, so 94 // that compilers eagerly type-checking template definitions 95 // won't complain that simple_trace is incomplete. 96 template<typename T> 97 struct get_simple_trace 98 { 99 typedef simple_trace type; 100 }; 101 } 102 103 template <typename OutputIterator 104 , typename T1, typename T2, typename T3, typename T4> debug(rule<OutputIterator,T1,T2,T3,T4> & r)105 void debug(rule<OutputIterator, T1, T2, T3, T4>& r) 106 { 107 typedef rule<OutputIterator, T1, T2, T3, T4> rule_type; 108 109 typedef 110 debug_handler< 111 OutputIterator 112 , typename rule_type::context_type 113 , typename rule_type::delimiter_type 114 , typename rule_type::properties 115 , simple_trace> 116 debug_handler; 117 typedef typename karma::detail::get_simple_trace<OutputIterator>::type 118 trace; 119 r.f = debug_handler(r.f, trace(), r.name()); 120 } 121 122 }}} 123 124 /////////////////////////////////////////////////////////////////////////////// 125 // Utility macro for easy enabling of rule and grammar debugging 126 #if !defined(BOOST_SPIRIT_DEBUG_NODE) 127 #if defined(BOOST_SPIRIT_KARMA_DEBUG) 128 #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); debug(r) 129 #else 130 #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); 131 #endif 132 #endif 133 134 #endif 135