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/detail/expectation_failure.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