simple_trace.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  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_SIMPLE_TRACE_DECEMBER_06_2008_1102AM)
  8. #define BOOST_SPIRIT_SIMPLE_TRACE_DECEMBER_06_2008_1102AM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/support/unused.hpp>
  13. #include <boost/spirit/home/qi/nonterminal/debug_handler_state.hpp>
  14. #include <boost/fusion/include/out.hpp>
  15. #include <iostream>
  16. #include <boost/mpl/if.hpp>
  17. #include <boost/mpl/and.hpp>
  18. #include <boost/type_traits/is_convertible.hpp>
  19. #include <boost/spirit/home/support/attributes.hpp>
  20. // The stream to use for debug output
  21. #if !defined(BOOST_SPIRIT_DEBUG_OUT)
  22. #define BOOST_SPIRIT_DEBUG_OUT std::cerr
  23. #endif
  24. // number of tokens to print while debugging
  25. #if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
  26. #define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
  27. #endif
  28. // number of spaces to indent
  29. #if !defined(BOOST_SPIRIT_DEBUG_INDENT)
  30. #define BOOST_SPIRIT_DEBUG_INDENT 2
  31. #endif
  32. namespace boost { namespace spirit { namespace qi
  33. {
  34. namespace detail
  35. {
  36. template<typename Char>
  37. inline void token_printer(std::ostream& o, Char c)
  38. {
  39. // allow to customize the token printer routine
  40. spirit::traits::print_token(o, c);
  41. }
  42. }
  43. struct simple_trace
  44. {
  45. int& get_indent() const
  46. {
  47. static int indent = 0;
  48. return indent;
  49. }
  50. void print_indent(int n) const
  51. {
  52. n *= BOOST_SPIRIT_DEBUG_INDENT;
  53. for (int i = 0; i != n; ++i)
  54. BOOST_SPIRIT_DEBUG_OUT << ' ';
  55. }
  56. template <typename Iterator>
  57. void print_some(
  58. char const* tag
  59. , int /*indent*/
  60. , Iterator first, Iterator const& last) const
  61. {
  62. print_indent(get_indent());
  63. BOOST_SPIRIT_DEBUG_OUT << '<' << tag << '>';
  64. int const n = BOOST_SPIRIT_DEBUG_PRINT_SOME;
  65. for (int i = 0; first != last && i != n && *first; ++i, ++first)
  66. detail::token_printer(BOOST_SPIRIT_DEBUG_OUT, *first);
  67. BOOST_SPIRIT_DEBUG_OUT << "</" << tag << '>' << std::endl;
  68. // $$$ FIXME convert invalid xml characters (e.g. '<') to valid
  69. // character entities. $$$
  70. }
  71. template <typename Iterator, typename Context, typename State>
  72. void operator()(
  73. Iterator const& first
  74. , Iterator const& last
  75. , Context const& context
  76. , State state
  77. , std::string const& rule_name) const
  78. {
  79. switch (state)
  80. {
  81. case pre_parse:
  82. print_indent(get_indent()++);
  83. BOOST_SPIRIT_DEBUG_OUT
  84. << '<' << rule_name << '>'
  85. << std::endl;
  86. print_some("try", get_indent(), first, last);
  87. break;
  88. case successful_parse:
  89. print_some("success", get_indent(), first, last);
  90. print_indent(get_indent());
  91. BOOST_SPIRIT_DEBUG_OUT
  92. << "<attributes>";
  93. traits::print_attribute(
  94. BOOST_SPIRIT_DEBUG_OUT,
  95. context.attributes
  96. );
  97. BOOST_SPIRIT_DEBUG_OUT
  98. << "</attributes>";
  99. if (!fusion::empty(context.locals))
  100. BOOST_SPIRIT_DEBUG_OUT
  101. << "<locals>"
  102. << context.locals
  103. << "</locals>";
  104. BOOST_SPIRIT_DEBUG_OUT << std::endl;
  105. print_indent(--get_indent());
  106. BOOST_SPIRIT_DEBUG_OUT
  107. << "</" << rule_name << '>'
  108. << std::endl;
  109. break;
  110. case failed_parse:
  111. print_indent(get_indent());
  112. BOOST_SPIRIT_DEBUG_OUT << "<fail/>" << std::endl;
  113. print_indent(--get_indent());
  114. BOOST_SPIRIT_DEBUG_OUT
  115. << "</" << rule_name << '>'
  116. << std::endl;
  117. break;
  118. }
  119. }
  120. };
  121. }}}
  122. #endif