Boost Semantic Actionで各行の文字列を数える

本当は、セマンティックアクションでトークンを切り出すプログラムを作りたかったのだが、(*´Д｀)
Semantic Actionで各行の文字列をカウントするプログラムを作った。

↓セマンティックアクションの部分。

<pre>
    14    struct MyAction
    15    {
    16        template<typename Ite>
    17          void operator()( Ite i1, Ite i2 ) const
    18            { cout << "# of characters: " << i2 - i1 << endl    
    19                   << "string: " << string(i1,i2) << endl; }
    20    };
</pre>

29行目で、任意の文字が続いたらMyAction()を呼び出す。

<pre>
    27          definition( const Abc& self )
    28          {
    29            r = (*anychar_p)[MyAction()];
    30            // r_list = r % +blank_p;                                                                                                                                                 
    31            // r = (+alnum_p)[MyAction()] % ',';                                                                                                                                      
    32            //r = (+alnum_p >> blank_p)[MyAction()]; //' '; // blank_p;                                                                                                               
    33            // r = 'a' >> (*ch_p('b'))[MyAction()] >> 'c';                                                                                                                            
    34          }
</pre>

コードを見てみる。。。


     1#include <iostream>
     2#include <string>
     3#include <vector>
     4#include <fstream>
     5
     6#include <boost/spirit.hpp>
     7#include <boost/lambda/lambda.hpp>
     8#include <boost/lambda/bind.hpp>
     9using namespace std;
    10using namespace boost::spirit;
    11
    12struct Abc : grammar<Abc>
    13{
    14    struct MyAction
    15    {
    16        template<typename Ite>
    17          void operator()( Ite i1, Ite i2 ) const
    18            { cout << "# of characters: " << i2 - i1 << endl    
    19                   << "string: " << string(i1,i2) << endl; }
    20    };
    21
    22    template<typename ScannerT>
    23      struct definition
    24      {
    25          typedef rule<ScannerT> rule_t;
    26          rule_t r; rule_t r_list;
    27          definition( const Abc& self )
    28          {
    29            r = (*anychar_p)[MyAction()];
    30            // r_list = r % +blank_p;                                                                                                                                                 
    31            // r = (+alnum_p)[MyAction()] % ',';                                                                                                                                      
    32            //r = (+alnum_p >> blank_p)[MyAction()]; //' '; // blank_p;                                                                                                               
    33            // r = 'a' >> (*ch_p('b'))[MyAction()] >> 'c';                                                                                                                            
    34          }
    35          const rule_t& start() const { return r; }
    36      };
    37};
    38
    39/*                                                                                                                                                                                    
    40int main()                                                                                                                                                                            
    41{                                                                                                                                                                                     
    42    for( string line; cout<<"# ", getline(cin, line); )                                                                                                                               
    43        if( parse( line.begin(), line.end(), Abc() ).full );                                                                                                                          
    44    return 0;                                                                                                                                                                         
    45}                                                                                                                                                                                     
    46*/
    47
    48#include <typeinfo>
    49int main(int argc, char* argv[]){
    50    using namespace std;
    51
    52    if(argc != 2){
    53        cerr << "wrong # of args." << endl;
    54        cerr << "./spirit_file_read input.txt" << endl;
    55        return 1;
    56    }
    57
    58    ifstream ifs(argv[1], ios::in);
    59    if(!ifs){
    60        cerr << "Error: file not opened." << endl;
    61        return 1;
    62    }
    63
    64    string tmp;
    65    string str;
    66
    67    int counter = 0;
    68
    69    Abc parser;
    70
    71    while(getline(ifs, tmp)){
    72
    73        cout << "line:" << counter << ":" << tmp << endl;
    74
    75        parse_info<string::const_iterator> info =
    76        parse( tmp.begin(), tmp.end(), Abc() );
    77        cout << (info.full ? "OK" : "") << endl;
    78
    79        counter++;
    80    }
    81
    82    ifs.close();
    83    return 0;
    84}

https://github.com/RuoAndo/qiita/blob/master/spirit_file_read_3.cpp

今回はこのようなファイルを処理してみる。

     1int main
     2FILE* fp = fopen(FILENAME, "r");
     3if (fp == NULL)
     4    exit(EXIT_FAILURE);
     5char* line = NULL;
     6size_t len = 0;
     7while ((getline(&line, &len, fp)) != -1) {
     8    // using printf() in all tests for consistency                                                                                                                                    
     9    printf("%s", line);
    10}
    11fclose(fp);
    12if (line)
    13free(line);

実行してみる。。。

<pre>
$ g++ spirit_file_read_3.cpp -lboost_system
In file included from spirit_file_read_3.cpp:6:0:
/usr/include/boost/spirit.hpp:18:4: warning: #warning "This header is deprecated. Please use: boost/spirit/include/classic.hpp" [-Wcpp]
 #  warning "This header is deprecated. Please use: boost/spirit/include/classic.hpp"
    ^~~~~~~
$ ./a.out getline.c
line:0:int main
# of characters: 8
string: int main
OK
line:1:FILE* fp = fopen(FILENAME, "r");
# of characters: 32
string: FILE* fp = fopen(FILENAME, "r");
OK
line:2:if (fp == NULL)
# of characters: 15
string: if (fp == NULL)
OK
line:3:    exit(EXIT_FAILURE);
# of characters: 23
string:     exit(EXIT_FAILURE);
OK
line:4:char* line = NULL;
</pre>