Boost Spirit フレーズレベル解析と文字レベル解析を少し検証してみる

Boost Spiritのパーサーには、２つの解析のレベルがある。

■ フレーズレベル解析
■ 文字レベル解析

コードを見てみる。。。

     1#include <iostream>
     2#include <string>
     3#include <boost/spirit.hpp>
     4using namespace std;
     5using namespace boost::spirit;
     6
     7struct VariableWordList : grammar<VariableWordList>
     8{
     9    template<typename ScannerT>
    10      struct definition
    11      {
    12          rule<ScannerT> word, word_list;
    13          definition( const VariableWordList& )
    14          {
    15              word = (alpha_p|'_') >> *(alpha_p|'_'|digit_p);
    16              word_list = word % ',';
    17          }
    18          const rule<ScannerT>& start() const { return word_list; }
    19      };
    20};
    21
    22int main()
    23{
    24    for( string line; cout<<"# ", getline(cin, line); )
    25       if( parse(line.c_str(), VariableWordList()).full )
    26             cout << "OK" << endl;
    27        else cout << "fail" << endl;
    28    return 0;
    29}

実行してみる。。。

<pre>
# g++ -o directive0 directive0.cpp -lboost_system
In file included from directive0.cpp:3: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"
    ^~~~~~~
# ./directive0
# fuge,guwa 
OK
# huge, guwa
fail
</pre>

コンマ(,)の後にスペースを入れるとfailになる。。。
これを避けるには、space_pを使う。

<pre>
    25      if( parse(line.c_str(), VariableWordList(), space_p).full )
</pre>

Boost的には、「space_pを使ってフレーズレベル解析をするようにする」と云ふ。

     1#include <iostream>
     2#include <string>
     3#include <boost/spirit.hpp>
     4using namespace std;
     5using namespace boost::spirit;
     6
     7struct VariableWordList : grammar<VariableWordList>
     8{
     9    template<typename ScannerT>
    10      struct definition
    11      {
    12          rule<ScannerT> word, word_list;
    13          definition( const VariableWordList& )
    14          {
    15              word = (alpha_p|'_') >> *(alpha_p|'_'|digit_p);
    16              word_list = word % ',';
    17          }
    18          const rule<ScannerT>& start() const { return word_list; }
    19      };
    20};
    21
    22int main()
    23{
    24    for( string line; cout<<"# ", getline(cin, line); )
    25      if( parse(line.c_str(), VariableWordList(), space_p).full )
    26             cout << "OK" << endl;
    27        else cout << "fail" << endl;
    28    return 0;
    29}

実行してみる。。。

<pre>
# g++ -o directive1 directive1.cpp -lboost_system
In file included from directive1.cpp:3: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"
    ^~~~~~~
# ./directive1
# gege,huga 
OK
# huge, hyogya
OK
</pre>

すかし、このような入力↓でもOKが出るようになってしまう。 (´Д｀;)

<pre>
# ./directive1
# huge, gyao
OK
# h ge, gu wa
OK
</pre>

この場合、15行目にlexeme_dを使う。

<pre>
    15              word = lexeme_d[ (alpha_p|'_') >> *(alpha_p|'_'|digit_p) ];
</pre>

     1#include <iostream>
     2#include <string>
     3#include <boost/spirit.hpp>
     4using namespace std;
     5using namespace boost::spirit;
     6
     7struct VariableWordList : grammar<VariableWordList>
     8{
     9    template<typename ScannerT>
    10      struct definition
    11      {
    12          rule<ScannerT> word, word_list;
    13          definition( const VariableWordList& )
    14          {
    15              word = lexeme_d[ (alpha_p|'_') >> *(alpha_p|'_'|digit_p) ];
    16              word_list = word % ',';
    17          }
    18          const rule<ScannerT>& start() const { return word_list; }
    19      };
    20};
    21
    22int main()
    23{
    24    for( string line; cout<<"# ", getline(cin, line); )
    25      if( parse(line.c_str(), VariableWordList(), space_p).full )
    26             cout << "OK" << endl;
    27        else cout << "fail" << endl;
    28    return 0;
    29}

実行してみる。。。

<pre>
# ./directive_lexmed 
# huge,goga
OK
# huge, fuga
OK
# h ge, gya o
fail
</pre>

（｀ー´）b

図にするとこうなる。。。

![qiita-lexmed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/a8018db9-653d-14ab-18dc-748117a01b9e.png)