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