View difference between Paste ID: 275S6Czu and yftwXNcw
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
} }