Boost Spiritのパーサーには、2つの解析のレベルがある。
■ フレーズレベル解析
■ 文字レベル解析
コードを見てみる。。。
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}
実行してみる。。。
# 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
コンマ(,)の後にスペースを入れるとfailになる。。。
これを避けるには、space_pを使う。
25 if( parse(line.c_str(), VariableWordList(), space_p).full )
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}
実行してみる。。。
# 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
すかし、このような入力↓でもOKが出るようになってしまう。 (´Д`;)
# ./directive1
# huge, gyao
OK
# h ge, gu wa
OK
この場合、15行目にlexeme_dを使う。
15 word = lexeme_d[ (alpha_p|'_') >> *(alpha_p|'_'|digit_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 = 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}
実行してみる。。。
# ./directive_lexmed
# huge,goga
OK
# huge, fuga
OK
# h ge, gya o
fail
(`ー´)b
図にするとこうなる。。。