Advertisement
Guest User

debug_position

a guest
Nov 7th, 2012
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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,
  22.             std::string const& pos );
  23.     };
  24.  
  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.  
  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.         os << std::endl;
  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.     struct use_terminal<qi::domain, mbl::tag::debug_position>
  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.         {
  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. } }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement