1 /*=============================================================================
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_DEBUG_HANDLER_DECEMBER_05_2008_0734PM)
8 #define BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM
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/qi/nonterminal/rule.hpp>
16 #include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
17 #include <boost/spirit/home/qi/operator/expect.hpp>
18 #include <boost/function.hpp>
19 #include <boost/fusion/include/at.hpp>
20 #include <boost/fusion/include/vector.hpp>
21 #include <boost/fusion/include/out.hpp>
22 #include <iostream>
23 
24 namespace boost { namespace spirit { namespace qi
25 {
26     template <
27         typename Iterator, typename Context
28       , typename Skipper, typename F>
29     struct debug_handler
30     {
31         typedef function<
32             bool(Iterator& first, Iterator const& last
33               , Context& context
34               , Skipper const& skipper
35             )>
36         function_type;
37 
debug_handlerboost::spirit::qi::debug_handler38         debug_handler(
39             function_type subject_
40           , F f_
41           , std::string const& rule_name_)
42           : subject(subject_)
43           , f(f_)
44           , rule_name(rule_name_)
45         {
46         }
47 
operator ()boost::spirit::qi::debug_handler48         bool operator()(
49             Iterator& first, Iterator const& last
50           , Context& context, Skipper const& skipper) const
51         {
52             f(first, last, context, pre_parse, rule_name);
53             try // subject might throw an exception
54             {
55                 if (subject(first, last, context, skipper))
56                 {
57                     f(first, last, context, successful_parse, rule_name);
58                     return true;
59                 }
60                 f(first, last, context, failed_parse, rule_name);
61             }
62             catch (expectation_failure<Iterator> const& e)
63             {
64                 f(first, last, context, failed_parse, rule_name);
65                 boost::throw_exception(e);
66             }
67             return false;
68         }
69 
70         function_type subject;
71         F f;
72         std::string rule_name;
73     };
74 
75     template <typename Iterator
76       , typename T1, typename T2, typename T3, typename T4, typename F>
debug(rule<Iterator,T1,T2,T3,T4> & r,F f)77     void debug(rule<Iterator, T1, T2, T3, T4>& r, F f)
78     {
79         typedef rule<Iterator, T1, T2, T3, T4> rule_type;
80 
81         typedef
82             debug_handler<
83                 Iterator
84               , typename rule_type::context_type
85               , typename rule_type::skipper_type
86               , F>
87         debug_handler;
88         r.f = debug_handler(r.f, f, r.name());
89     }
90 
91     struct simple_trace;
92 
93     namespace detail
94     {
95         // This class provides an extra level of indirection through a
96         // template to produce the simple_trace type. This way, the use
97         // of simple_trace below is hidden behind a dependent type, so
98         // that compilers eagerly type-checking template definitions
99         // won't complain that simple_trace is incomplete.
100         template<typename T>
101         struct get_simple_trace
102         {
103             typedef simple_trace type;
104         };
105     }
106 
107     template <typename Iterator
108       , typename T1, typename T2, typename T3, typename T4>
debug(rule<Iterator,T1,T2,T3,T4> & r)109     void debug(rule<Iterator, T1, T2, T3, T4>& r)
110     {
111         typedef rule<Iterator, T1, T2, T3, T4> rule_type;
112 
113         typedef
114             debug_handler<
115                 Iterator
116               , typename rule_type::context_type
117               , typename rule_type::skipper_type
118               , simple_trace>
119         debug_handler;
120 
121         typedef typename qi::detail::get_simple_trace<Iterator>::type trace;
122         r.f = debug_handler(r.f, trace(), r.name());
123     }
124 
125 }}}
126 
127 ///////////////////////////////////////////////////////////////////////////////
128 //  Utility macro for easy enabling of rule and grammar debugging
129 #if !defined(BOOST_SPIRIT_DEBUG_NODE)
130   #if defined(BOOST_SPIRIT_DEBUG) || defined(BOOST_SPIRIT_QI_DEBUG)
131     #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r); debug(r)
132   #else
133     #define BOOST_SPIRIT_DEBUG_NODE(r)  r.name(#r)
134   #endif
135 #endif
136 
137 #define BOOST_SPIRIT_DEBUG_NODE_A(r, _, name)                                   \
138     BOOST_SPIRIT_DEBUG_NODE(name);                                              \
139     /***/
140 
141 #define BOOST_SPIRIT_DEBUG_NODES(seq)                                           \
142     BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEBUG_NODE_A, _, seq)                    \
143     /***/
144 
145 #endif
146