サンプルの動作確認バージョン [GCC4.4/1.41.0] [VC9/1.41.0]
#include <iostream>
#include <fstream>
#include <string>
#include <boost/wave.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
using namespace std;
using namespace boost::wave;
int main(int argc, const char* argv[])
{
try
{
// ファイル argv[1] の内容を全部 text に読み込む
ifstream fin( argv[1] );
string text( istreambuf_iterator<char>(fin.rdbuf()),
istreambuf_iterator<char>() );
// プリプロセッサを用意
typedef context<string::iterator,
cpplexer::lex_iterator< cpplexer::lex_token<> > > context_t;
context_t ctx( text.begin(), text.end(), argv[1] );
// オプションやマクロを設定
ctx.set_language(language_support(support_cpp | support_option_variadics));
ctx.add_macro_definition("_WIN32");
ctx.add_macro_definition("_MSC_VER=1400");
ctx.add_sysinclude_path("C:\\Develop\\Boost");
ctx.add_sysinclude_path("C:\\Develop\\vs2005\\VC\\INCLUDE");
// イテレータを取得して
context_t::iterator_type it = ctx.begin();
context_t::iterator_type end = ctx.end();
// トークンを順番に表示
for(; it!=end; ++it)
cout << it->get_position() << " :: " << it->get_value() << endl;
}
catch( cpp_exception& e )
{
// エラー時
cerr << e.file_name() << "(" << e.line_no() << "):"
<< e.description() << endl;
}
}
> cat test.c int main() { return 0; } > ./a.out test.c C:/test.c:1:1 :: int C:/test.c:1:4 :: C:/test.c:1:5 :: main C:/test.c:1:9 :: ( C:/test.c:1:10 :: ) C:/test.c:1:11 :: C:/test.c:1:12 :: { C:/test.c:1:13 :: C:/test.c:1:14 :: return C:/test.c:1:20 :: C:/test.c:1:21 :: 0 C:/test.c:1:22 :: ; C:/test.c:1:23 :: C:/test.c:1:24 :: } C:/test.c:1:25 :: C:/test.c:2:1 ::
Spirit を使って実装されたC/C++のプリプロセッサです。 #include とか #define を展開して、結果のトークン列をイテレータ経由で返してくれます。 プリプロセス処理にフックを入れたりできるので、構文解析までいかないトークンレベルでできる C/C++ソースの解析に色々使えるかもしれません。ただし、ベンチマークとったわけではありませんが、 感覚的にはあんまり処理速度は速くない気がします。