debug_handler.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM)
  7. #define BOOST_SPIRIT_DEBUG_HANDLER_DECEMBER_05_2008_0734PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/qi/nonterminal/rule.hpp>
  12. #include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
  13. #include <boost/spirit/home/qi/detail/expectation_failure.hpp>
  14. #include <boost/function.hpp>
  15. #include <string>
  16. namespace boost { namespace spirit { namespace qi
  17. {
  18. template <
  19. typename Iterator, typename Context
  20. , typename Skipper, typename F>
  21. struct debug_handler
  22. {
  23. typedef function<
  24. bool(Iterator& first, Iterator const& last
  25. , Context& context
  26. , Skipper const& skipper
  27. )>
  28. function_type;
  29. debug_handler(
  30. function_type subject_
  31. , F f_
  32. , std::string const& rule_name_)
  33. : subject(subject_)
  34. , f(f_)
  35. , rule_name(rule_name_)
  36. {
  37. }
  38. bool operator()(
  39. Iterator& first, Iterator const& last
  40. , Context& context, Skipper const& skipper) const
  41. {
  42. f(first, last, context, pre_parse, rule_name);
  43. try // subject might throw an exception
  44. {
  45. if (subject(first, last, context, skipper))
  46. {
  47. f(first, last, context, successful_parse, rule_name);
  48. return true;
  49. }
  50. f(first, last, context, failed_parse, rule_name);
  51. }
  52. catch (expectation_failure<Iterator> const& e)
  53. {
  54. f(first, last, context, failed_parse, rule_name);
  55. boost::throw_exception(e);
  56. }
  57. return false;
  58. }
  59. function_type subject;
  60. F f;
  61. std::string rule_name;
  62. };
  63. template <typename Iterator
  64. , typename T1, typename T2, typename T3, typename T4, typename F>
  65. void debug(rule<Iterator, T1, T2, T3, T4>& r, F f)
  66. {
  67. typedef rule<Iterator, T1, T2, T3, T4> rule_type;
  68. typedef
  69. debug_handler<
  70. Iterator
  71. , typename rule_type::context_type
  72. , typename rule_type::skipper_type
  73. , F>
  74. debug_handler;
  75. r.f = debug_handler(r.f, f, r.name());
  76. }
  77. struct simple_trace;
  78. namespace detail
  79. {
  80. // This class provides an extra level of indirection through a
  81. // template to produce the simple_trace type. This way, the use
  82. // of simple_trace below is hidden behind a dependent type, so
  83. // that compilers eagerly type-checking template definitions
  84. // won't complain that simple_trace is incomplete.
  85. template<typename T>
  86. struct get_simple_trace
  87. {
  88. typedef simple_trace type;
  89. };
  90. }
  91. template <typename Iterator
  92. , typename T1, typename T2, typename T3, typename T4>
  93. void debug(rule<Iterator, T1, T2, T3, T4>& r)
  94. {
  95. typedef rule<Iterator, T1, T2, T3, T4> rule_type;
  96. typedef
  97. debug_handler<
  98. Iterator
  99. , typename rule_type::context_type
  100. , typename rule_type::skipper_type
  101. , simple_trace>
  102. debug_handler;
  103. typedef typename qi::detail::get_simple_trace<Iterator>::type trace;
  104. r.f = debug_handler(r.f, trace(), r.name());
  105. }
  106. }}}
  107. ///////////////////////////////////////////////////////////////////////////////
  108. // Utility macro for easy enabling of rule and grammar debugging
  109. #if !defined(BOOST_SPIRIT_DEBUG_NODE)
  110. #if defined(BOOST_SPIRIT_DEBUG) || defined(BOOST_SPIRIT_QI_DEBUG)
  111. #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); debug(r)
  112. #else
  113. #define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r)
  114. #endif
  115. #endif
  116. #define BOOST_SPIRIT_DEBUG_NODE_A(r, _, name) \
  117. BOOST_SPIRIT_DEBUG_NODE(name); \
  118. /***/
  119. #define BOOST_SPIRIT_DEBUG_NODES(seq) \
  120. BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_DEBUG_NODE_A, _, seq) \
  121. /***/
  122. #endif