1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
*
* Copyright (c) 1998-2002
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE regex_grep_example_3.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: regex_grep example 3: searches a cpp file for class definitions,
* using a bound member function callback.
*/
#include <string>
#include <map>
#include <boost/regex.hpp>
#include <functional>
#include <boost/detail/workaround.hpp>
// purpose:
// takes the contents of a file in the form of a string
// and searches for all the C++ class definitions, storing
// their locations in a map of strings/int's
typedef std::map<std::string, std::string::difference_type, std::less<std::string> > map_type;
const char* re =
// possibly leading whitespace:
"^[[:space:]]*"
// possible template declaration:
"(template[[:space:]]*<[^;:{]+>[[:space:]]*)?"
// class or struct:
"(class|struct)[[:space:]]*"
// leading declspec macros etc:
"("
"\\<\\w+\\>"
"("
"[[:blank:]]*\\([^)]*\\)"
")?"
"[[:space:]]*"
")*"
// the class name
"(\\<\\w*\\>)[[:space:]]*"
// template specialisation parameters
"(<[^;:{]+>)?[[:space:]]*"
// terminate in { or :
"(\\{|:[^;\\{()]*\\{)";
class class_index
{
boost::regex expression;
map_type index;
std::string::const_iterator base;
bool grep_callback(boost::match_results<std::string::const_iterator> what);
public:
map_type& get_map() { return index; }
void IndexClasses(const std::string& file);
class_index()
: expression(re) {}
};
bool class_index::grep_callback(boost::match_results<std::string::const_iterator> what)
{
// what[0] contains the whole string
// what[5] contains the class name.
// what[6] contains the template specialisation if any.
// add class name and position to map:
index[std::string(what[5].first, what[5].second) + std::string(what[6].first, what[6].second)] =
what[5].first - base;
return true;
}
void class_index::IndexClasses(const std::string& file)
{
std::string::const_iterator start, end;
start = file.begin();
end = file.end();
base = start;
#if BOOST_WORKAROUND(_MSC_VER, < 1300) && !defined(_STLP_VERSION)
boost::regex_grep(std::bind1st(std::mem_fun1(&class_index::grep_callback), this),
start,
end,
expression);
#else
boost::regex_grep(std::bind1st(std::mem_fun(&class_index::grep_callback), this),
start,
end,
expression);
#endif
}
#include <fstream>
#include <iostream>
using namespace std;
void load_file(std::string& s, std::istream& is)
{
s.erase();
if(is.bad()) return;
s.reserve(static_cast<std::string::size_type>(is.rdbuf()->in_avail()));
char c;
while(is.get(c))
{
if(s.capacity() == s.size())
s.reserve(s.capacity() * 3);
s.append(1, c);
}
}
int main(int argc, const char** argv)
{
std::string text;
for(int i = 1; i < argc; ++i)
{
cout << "Processing file " << argv[i] << endl;
std::ifstream fs(argv[i]);
load_file(text, fs);
fs.close();
class_index idx;
idx.IndexClasses(text);
cout << idx.get_map().size() << " matches found" << endl;
map_type::iterator c, d;
c = idx.get_map().begin();
d = idx.get_map().end();
while(c != d)
{
cout << "class \"" << (*c).first << "\" found at index: " << (*c).second << endl;
++c;
}
}
return 0;
}
|