SHOW:
|
|
- or go back to the newest paste.
1 | #if (defined(_DEBUG) && !defined(MBLQI_DONT_DEBUG_RULES)) || defined(MBLQI_DEBUG_RULES) | |
2 | # define MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) \ | |
3 | ::mbl::debug_position( pdbg, pname, ppos ) | |
4 | # define MBL_QI_DEBUG_PARSER_( pdbg, pname, ppos ) MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) >> | |
5 | # define _MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) >> MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) | |
6 | #else | |
7 | # define MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) | |
8 | # define MBL_QI_DEBUG_PARSER_( pdbg, pname, ppos ) | |
9 | # define _MBL_QI_DEBUG_PARSER( pdbg, pname, ppos ) | |
10 | #endif | |
11 | ||
12 | #define MBL_QI_DEBUG_MSG_START "<START>" | |
13 | #define MBL_QI_DEBUG_MSG_END "<END>" | |
14 | #define MBL_QI_DEBUG_PARSER_START( pdbg, pname ) MBL_QI_DEBUG_PARSER_( pdbg, pname, MBL_QI_DEBUG_MSG_START ) | |
15 | #define MBL_QI_DEBUG_PARSER_END( pdbg, pname ) _MBL_QI_DEBUG_PARSER( pdbg, pname, MBL_QI_DEBUG_MSG_END ) | |
16 | ||
17 | namespace mbl { | |
18 | ||
19 | struct parser_debugger { | |
20 | // could be virtual, but I want my type to be POD | |
21 | - | bool (*report)( parser_debugger*, char const* parserName, char const* msg, std::string const& pos ); |
21 | + | bool (*report)( parser_debugger*, char const* parserName, char const* msg, |
22 | std::string const& pos ); | |
23 | }; | |
24 | - | static bool report_impl_base( parser_debugger*, char const* pname, char const* msg, std::string const& pos, |
24 | + | |
25 | - | std::ostream& os, size_t line_size, size_t pname_len, size_t msg_len ) |
25 | + | static bool report_impl_base( parser_debugger*, char const* pname, |
26 | char const* msg, std::string const& pos, std::ostream& os, size_t line_size, | |
27 | size_t pname_len, size_t msg_len ) | |
28 | { | |
29 | size_t n = strlen( msg ); | |
30 | std::string pad; | |
31 | if( n < msg_len ) pad.assign( (msg_len - n) / 2, ' ' ); | |
32 | ||
33 | std::ios_base::fmtflags f = os.flags(); | |
34 | os.flags( f | std::ios_base::left ); | |
35 | os << std::setw(pname_len) << pname | |
36 | << '(' << pad << std::setw(msg_len - pad.size()) << msg << "): "; | |
37 | os.flags( f ); | |
38 | - | std::size_t cnt = (std::max<size_t>)(strlen(pname), pname_len) + (std::max<size_t>)(n, msg_len) + 4; |
38 | + | |
39 | bool sp = false; | |
40 | std::size_t cnt = (std::max<size_t>)(strlen(pname), pname_len) + | |
41 | (std::max<size_t>)(n, msg_len) + 4; | |
42 | ||
43 | for( auto i = pos.begin(); i != pos.end(); i++ ) { | |
44 | char c = *i; | |
45 | if( ::isspace(c) ) { | |
46 | if( sp ) continue; | |
47 | sp = true; | |
48 | c = ' '; | |
49 | } else { | |
50 | sp = false; | |
51 | } | |
52 | ||
53 | if( cnt++ >= line_size ) { | |
54 | os << "..."; | |
55 | break; | |
56 | } else { | |
57 | os << c; | |
58 | } | |
59 | } | |
60 | - | static bool report_impl( parser_debugger* pd, char const* pname, char const* msg, std::string const& pos ) { |
60 | + | |
61 | return true; | |
62 | } | |
63 | static bool report_impl( parser_debugger* pd, char const* pname, char const* msg, | |
64 | std::string const& pos ) | |
65 | { | |
66 | return report_impl_base( pd, pname, msg, pos, std::clog, 100, 20, 10 ); | |
67 | } | |
68 | static parser_debugger& default_parser_debugger() { | |
69 | static parser_debugger res = { {&report_impl} }; | |
70 | return res; | |
71 | } | |
72 | ||
73 | BOOST_SPIRIT_TERMINAL_EX( debug_position ); | |
74 | struct debug_position_parser : qi::primitive_parser<debug_position_parser> { | |
75 | debug_position_parser( parser_debugger* pdebugger, char const* pname, char const* msg ) | |
76 | : pdebugger_( pdebugger ), pname_( pname ), msg_( msg ) {} | |
77 | ||
78 | template< typename ContextT, typename IteratorT > | |
79 | struct attribute { typedef spirit::unused_type type; }; | |
80 | ||
81 | template< typename IteratorT, typename ContextT, typename SkipperT, typename AttributeT > | |
82 | bool parse( IteratorT& first, IteratorT const& last, ContextT& context, | |
83 | SkipperT const& skipper, AttributeT& attr ) const | |
84 | { | |
85 | typedef std::iterator_traits<IteratorT>::value_type char_type; | |
86 | typedef std::basic_string<char_type> string_type; | |
87 | ||
88 | qi::skip_over( first, last, skipper ); | |
89 | if( !pdebugger_ ) return true; | |
90 | ||
91 | pdebugger_->report( pdebugger_, pname_, msg_, | |
92 | boost::locale::conv::utf_to_utf<char>(string_type(first, last)) ); | |
93 | ||
94 | return true; | |
95 | } | |
96 | ||
97 | template< class ContextT > | |
98 | spirit::info what( ContextT& context ) const { | |
99 | return spirit::info( "debug_position", expression_ ); | |
100 | } | |
101 | ||
102 | char const* pname_; | |
103 | char const* msg_; | |
104 | parser_debugger* pdebugger_; | |
105 | }; | |
106 | ||
107 | } | |
108 | ||
109 | namespace boost { namespace spirit { | |
110 | ||
111 | template<> | |
112 | - | > : is_convertible<A0, mbl::parser_debugger*> {}; // enable debug_position( debugger, name, pos ) |
112 | + | |
113 | : mpl::true_ {}; // enable debug_position | |
114 | template< typename A0, typename A1, typename A2 > | |
115 | struct use_terminal<qi::domain, | |
116 | terminal_ex<mbl::tag::debug_position, fusion::vector3<A0, A1, A2> > | |
117 | > : is_convertible<A0, mbl::parser_debugger*> {}; // enable debug_position( debugger, name, pos ) | |
118 | template<> | |
119 | struct use_lazy_terminal<qi::domain, mbl::tag::debug_position, 3 /*arity*/> | |
120 | : mpl::true_ {}; // enable lazy support for debug_position | |
121 | ||
122 | namespace qi { | |
123 | ||
124 | template< typename A0, typename A1, typename A2, typename ModifiersT > | |
125 | struct make_primitive< | |
126 | terminal_ex<mbl::tag::debug_position, fusion::vector3<A0, A1, A2> >, ModifiersT > | |
127 | - | return result_type( fusion::at_c<0>(term.args), fusion::at_c<1>(term.args), fusion::at_c<2>(term.args) ); |
127 | + | |
128 | typedef mbl::debug_position_parser result_type; | |
129 | ||
130 | template< typename TerminalT > | |
131 | result_type operator()( TerminalT const& term, unused_type ) const { | |
132 | return result_type( fusion::at_c<0>(term.args), | |
133 | fusion::at_c<1>(term.args), fusion::at_c<2>(term.args) ); | |
134 | } | |
135 | }; | |
136 | ||
137 | } | |
138 | ||
139 | } } |