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 | } } |