Chris@16: /*============================================================================= 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_DEBUG_HANDLER_DECEMBER_05_2008_0734PM) Chris@16: #define BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM 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: #include Chris@16: Chris@16: namespace boost { namespace spirit { namespace qi Chris@16: { Chris@16: template < Chris@16: typename Iterator, typename Context Chris@16: , typename Skipper, typename F> Chris@16: struct debug_handler Chris@16: { Chris@16: typedef function< Chris@16: bool(Iterator& first, Iterator const& last Chris@16: , Context& context Chris@16: , Skipper const& skipper Chris@16: )> Chris@16: function_type; Chris@16: Chris@16: debug_handler( Chris@16: function_type subject_ Chris@16: , F f_ Chris@16: , 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: Chris@16: bool operator()( Chris@16: Iterator& first, Iterator const& last Chris@16: , Context& context, Skipper const& skipper) const Chris@16: { Chris@16: f(first, last, context, pre_parse, rule_name); Chris@16: try // subject might throw an exception Chris@16: { Chris@16: if (subject(first, last, context, skipper)) Chris@16: { Chris@16: f(first, last, context, successful_parse, rule_name); Chris@16: return true; Chris@16: } Chris@16: f(first, last, context, failed_parse, rule_name); Chris@16: } Chris@16: catch (expectation_failure const& e) Chris@16: { Chris@16: f(first, last, context, failed_parse, rule_name); Chris@16: boost::throw_exception(e); Chris@16: } 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: Iterator Chris@16: , typename rule_type::context_type Chris@16: , typename rule_type::skipper_type 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: Iterator Chris@16: , typename rule_type::context_type Chris@16: , typename rule_type::skipper_type Chris@16: , simple_trace> Chris@16: debug_handler; Chris@16: Chris@16: typedef typename qi::detail::get_simple_trace::type 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_DEBUG) || defined(BOOST_SPIRIT_QI_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: #define BOOST_SPIRIT_DEBUG_NODE_A(r, _, name) \ Chris@16: BOOST_SPIRIT_DEBUG_NODE(name); \ Chris@16: /***/ Chris@16: Chris@16: #define BOOST_SPIRIT_DEBUG_NODES(seq) \ Chris@16: BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEBUG_NODE_A, _, seq) \ Chris@16: /***/ Chris@16: Chris@16: #endif