//print demangled typename in tree format #ifndef UTILITY_STR_TREE_TYPE_NAME_PRINT_HPP #define UTILITY_STR_TREE_TYPE_NAME_PRINT_HPP #include #include #include #include #include namespace utility { struct str_tree_type_name_parser_print : public boost::spirit::grammar { marg_ostream& my_out ; explicit str_tree_type_name_parser_print(marg_ostream& a_out=mout()) : my_out(a_out) {} struct children_closure : boost::spirit::closure { member1 tag //Start character for delimiting children. //e.g. { or { or <. ; }; struct print_label { marg_ostream& my_out ; explicit print_label(marg_ostream& a_out) : my_out(a_out) {} template void operator() (ActionIterT const &first, ActionIterT const &last) const { std::string item(first,last-first); my_out< void operator() (ActionIterT const &first, ActionIterT const &last) const { std::string item(first,last-first); my_out< void operator() (ActionIterT const &first) const { --my_out; my_out< void operator() (ActionIterT const &first, ActionIterT const &last) const { std::string item(first,last-first); --my_out; my_out< void operator() (ActionIterT const &first, ActionIterT const &last) const { if(first == last) return; std::string item(first,last-first); my_out< struct definition { marg_ostream& my_out ; definition(str_tree_type_name_parser_print const& a_parser) : my_out(a_parser.my_out) { using namespace boost::spirit; using namespace phoenix; children = start_tag[print_open(my_out)] >> !( tree >> *( ch_p(delimiter_infix)[print_infix(my_out)] >> tree ) ) >> end_tag[print_close(my_out)] ; start_tag = chset_p(delimiters_open()) [ children.tag = construct_(arg1) ] ; end_tag = f_ch_p(phoenix::bind(&close_delimiter)(children.tag)); std::string not_label_chr =std::string(delimiters_open())+delimiters_close()+delimiter_infix; ident = +(anychar_p - chset_p(not_label_chr.c_str())) //identifier ; label = ( ( ch_p('(') >> ident >> ch_p(')') >> uint_p )//for example, for an enum numeral in mpl::integral_c. | ident )[print_string(my_out)] ; modifiers = (*( ch_p('*') | '&' | "const" ) )[print_string(my_out)] ; tree = label >> !children >> modifiers ; } typedef boost::spirit::rule < ScannerT , children_closure::context_t > children_type; children_type children; boost::spirit::rule start_tag; boost::spirit::rule end_tag; boost::spirit::rule ident; boost::spirit::rule label; boost::spirit::rule modifiers; boost::spirit::rule tree; boost::spirit::rule const& start() const { return tree; } }; }; boost::spirit::parse_info<> str_tree_type_name_print(std::string const& str) /**@brief * Prints a string representing a typename in formatted * tree form. For example, the string: * * xconst &,e &> * * is printed as: * * x * < a * , b * < c * , d * > const & * , e & * > * */ { str_tree_type_name_parser_print p; // Our parser return boost::spirit::parse(str.c_str(), p, boost::spirit::space_p); } boost::spirit::parse_info<> str_tree_type_name_print_trace(std::string const& str) /**@brief * Same as str_tree_type_name_print but also prints input * and diagnostics. */ { bool const trace=false; str_tree_type_name_parser_print p(mout()); // Our parser if(trace) { p.my_out << "String:\n"; ++p.my_out; p.my_out< info = boost::spirit::parse(str.c_str(), p, boost::spirit::space_p); if(trace) { --p.my_out; } if (info.full) { if(trace) { p.my_out << "-------------------------\n"; p.my_out << "Parsing succeeded\n"; p.my_out << "-------------------------\n"; } } else { p.my_out << "-------------------------\n"; p.my_out << "Parsing failed\n"; p.my_out << "input: \"" << str <<"\"\n"; p.my_out << "stopped at: \": " << info.stop << "\"\n"; p.my_out << "-------------------------\n"; } return info; } }//exit utility namespace #endif