Spirit V2は、Spirit.Qi, Spirit.Karma, Spirit.Lexの三つ巴で紹介されることが多いが、Spirit.Karma, Spirit.Lexは使ったことがないので、Spirit.Qiを調べることにする。
Spirit.Qiは、単純に言うとパーサーである。
さらに端的には、qi::parseとqi::phrase_parseの2つがある。
qi::phrase_parseは、qi::ruleやqi::grammerで拡張可能であり、この時になると、EBNF然にかけるSpirit.Qiが本領を発揮するらしい。(-ω- )o<
+c++ qi::parse(it, str.end(), int_ % ',', result) && it==str.end(); +
↑ 1文字(この場合は整数)のパース
+c++ qi::phrase_parse(it, str.end(), +( "x:" >> double_ >> "y:" >> double_ ), +
↑ 2文字以上のパース
+(...) の「+」は、一文字以上の文字の繰り返しという意味。
コードを見てみる。。。
+c++ qi::parse(it, str.end(), int_ % ',', result) && it==str.end(); +
1#include <iostream>
2#include <string>
3#include <vector>
4#include <boost/fusion/tuple.hpp>
5#include <boost/spirit/include/qi.hpp>
6#include <boost/spirit/include/phoenix.hpp>
7using namespace std;
8using namespace boost;
9using namespace boost::spirit;
10
11bool parse_csv( const string& str, std::vector<int>& result )
12{
13 string::const_iterator it = str.begin();
14 return qi::parse(it, str.end(), int_ % ',', result) && it==str.end();
15}
16
17int main()
18{
19 {
20 std::vector<int> result;
21 if( parse_csv( "4,2,7", result ) )
22 cout << result.size() << " integers parsed" << endl;
23 else
24 cout << "error" << endl;
25 }
26 {
27 std::vector<int> result;
28 if( parse_csv( "9 6 5", result ) )
29 cout << result.size() << " integers parsed" << endl;
30 else
31 cout << "error" << endl;
32 }
33}
実行してみる。。。
$ ./a.out
3 integers parsed
error
+c++ qi::phrase_parse(it, str.end(), +( "x:" >> double_ >> "y:" >> double_ ), +
コードを見てみる。。。
1#include <iostream>
2#include <string>
3#include <vector>
4#include <boost/fusion/tuple.hpp>
5#include <boost/spirit/include/qi.hpp>
6#include <boost/spirit/include/phoenix.hpp>
7using namespace std;
8using namespace boost;
9using namespace boost::spirit;
10
11bool parse_points( const string& str, std::vector< fusion::tuple<double,double> >& result )
12{
13 string::const_iterator it = str.begin();
14 return qi::phrase_parse(it, str.end(),
15 +( "x:" >> double_ >> "y:" >> double_ ),
16 ascii::space,
17 result
18 ) && it==str.end();
19}
20
21int main()
22{
23 std::vector<int> result;
24 {
25 std::vector< fusion::tuple<double,double> > result;
26 if( parse_points( "x: 1 y: 2.0 x: 3 y: -4.5", result ) )
27 cout << result.size() << " points parsed" << endl;
28 else
29 cout << "error" << endl;
30 }
31}
実行してみる。。。
$ ./a.out
2 points parsed