1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 Copyright (c) 2001-2011 Hartmut Kaiser 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #if !defined(BOOST_SPIRIT_X3_SIMPLE_TRACE_DECEMBER_06_2008_1102AM) 9 #define BOOST_SPIRIT_X3_SIMPLE_TRACE_DECEMBER_06_2008_1102AM 10 11 #include <boost/spirit/home/x3/support/unused.hpp> 12 #include <boost/spirit/home/x3/support/traits/print_token.hpp> 13 #include <boost/spirit/home/x3/support/traits/print_attribute.hpp> 14 #include <boost/spirit/home/x3/nonterminal/debug_handler_state.hpp> 15 #include <boost/type_traits/is_same.hpp> 16 #include <iostream> 17 18 // The stream to use for debug output 19 #if !defined(BOOST_SPIRIT_X3_DEBUG_OUT) 20 #define BOOST_SPIRIT_X3_DEBUG_OUT std::cerr 21 #endif 22 23 // number of tokens to print while debugging 24 #if !defined(BOOST_SPIRIT_X3_DEBUG_PRINT_SOME) 25 #define BOOST_SPIRIT_X3_DEBUG_PRINT_SOME 20 26 #endif 27 28 // number of spaces to indent 29 #if !defined(BOOST_SPIRIT_X3_DEBUG_INDENT) 30 #define BOOST_SPIRIT_X3_DEBUG_INDENT 2 31 #endif 32 33 namespace boost { namespace spirit { namespace x3 34 { 35 namespace detail 36 { 37 template <typename Char> token_printer(std::ostream & o,Char c)38 inline void token_printer(std::ostream& o, Char c) 39 { 40 // allow customization of the token printer routine 41 x3::traits::print_token(o, c); 42 } 43 } 44 45 template <int IndentSpaces = 2, int CharsToPrint = 20> 46 struct simple_trace 47 { simple_traceboost::spirit::x3::simple_trace48 simple_trace(std::ostream& out) 49 : out(out), indent(0) {} 50 print_indentboost::spirit::x3::simple_trace51 void print_indent(int n) const 52 { 53 n *= IndentSpaces; 54 for (int i = 0; i != n; ++i) 55 out << ' '; 56 } 57 58 template <typename Iterator> print_someboost::spirit::x3::simple_trace59 void print_some( 60 char const* tag 61 , Iterator first, Iterator const& last) const 62 { 63 print_indent(indent); 64 out << '<' << tag << '>'; 65 int const n = CharsToPrint; 66 for (int i = 0; first != last && i != n && *first; ++i, ++first) 67 detail::token_printer(out, *first); 68 out << "</" << tag << '>' << std::endl; 69 70 // $$$ FIXME convert invalid xml characters (e.g. '<') to valid 71 // character entities. $$$ 72 } 73 74 template <typename Iterator, typename Attribute, typename State> operator ()boost::spirit::x3::simple_trace75 void operator()( 76 Iterator const& first 77 , Iterator const& last 78 , Attribute const& attr 79 , State state 80 , std::string const& rule_name) const 81 { 82 switch (state) 83 { 84 case pre_parse: 85 print_indent(indent++); 86 out 87 << '<' << rule_name << '>' 88 << std::endl; 89 print_some("try", first, last); 90 break; 91 92 case successful_parse: 93 print_some("success", first, last); 94 if (!is_same<Attribute, unused_type>::value) 95 { 96 print_indent(indent); 97 out 98 << "<attributes>"; 99 traits::print_attribute(out, attr); 100 out 101 << "</attributes>"; 102 out << std::endl; 103 } 104 print_indent(--indent); 105 out 106 << "</" << rule_name << '>' 107 << std::endl; 108 break; 109 110 case failed_parse: 111 print_indent(indent); 112 out << "<fail/>" << std::endl; 113 print_indent(--indent); 114 out 115 << "</" << rule_name << '>' 116 << std::endl; 117 break; 118 } 119 } 120 121 std::ostream& out; 122 mutable int indent; 123 }; 124 125 namespace detail 126 { 127 typedef simple_trace< 128 BOOST_SPIRIT_X3_DEBUG_INDENT, BOOST_SPIRIT_X3_DEBUG_PRINT_SOME> 129 simple_trace_type; 130 131 inline simple_trace_type& get_simple_trace()132 get_simple_trace() 133 { 134 static simple_trace_type tracer(BOOST_SPIRIT_X3_DEBUG_OUT); 135 return tracer; 136 } 137 } 138 }}} 139 140 #endif 141