Boost.Qiのparse_phraseにqi::skip_flag::dont_postskipというオプションがある。
英語では、
"boost::spirit::qi::skip_flag::dont_postskip passed to boost::spirit::qi::phrase_parse() tell the parser not to skip spaces that occur after a successfully parsed digit, but before the first unsuccessfully parsed character. "
となるが、よくわからない。。
コードを見てみる。。
1 #include <boost/spirit/include/qi.hpp>
2 #include <string>
3 #include <iostream>
4
5 using namespace boost::spirit;
6
7 int main()
8 {
9 std::string s;
10 std::getline(std::cin, s);
11 auto it = s.begin();
12 bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
13 qi::skip_flag::dont_postskip);
14 std::cout << std::boolalpha << match << ":" << *it << '\n';
15 if (it != s.end())
16 std::cout << std::string{it, s.end()} << '\n';
17 }
実行してみる。。
# ./a.out
1234
true:2
234
# ./a.out
1 2345
true:
2345
# ./a.out
1 2345 59
true:
2345 59
上記から、初めの数字1文字(ここでは"1")をパースした後は、スペースをスキップしないということだ。
"but before the first unsuccessfully parsed character. "
は、逆に、初めの数字("1")をパースするまでは、スペースをスキップするということになる。
実行してみる。。。
# ./a.out
234
true:3
34
# ./a.out
2345 04
true:3
345 04
確かに、初めの数字2をパースするまでは、スペースをスキップしている。。。
また、これは少しわかりにくいが、14行目の*itをはじめの数字をパースあとの文字を指している。
14 std::cout << std::boolalpha << match << ":" << *it << '\n';
15 if (it != s.end())
16 std::cout << std::string{it, s.end()} << '\n';
なので、" 234"で2をパースした場合は3を指すことになる。。
くどいが、こう変更するといいかもしれない。
1#include <boost/spirit/include/qi.hpp>
2#include <string>
3#include <iostream>
4
5using namespace boost::spirit;
6
7int main()
8{
9 std::string s;
10 std::getline(std::cin, s);
11 auto it = s.begin();
12 bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
13 qi::skip_flag::dont_postskip);
14 *it--;
15 std::cout << std::boolalpha << match << ":" << *it << '\n';
16 *it++;
17 if (it != s.end())
18 std::cout << std::string{it, s.end()} << '\n';
19}
14行目で、マッチした数字(digit)へポインタを巻き戻し、16行目でもとに戻している。
$ ./a.out
2345 04
true:2
345 04
個人的には経験はないが、qi::skip_flag::dont_postskipがあるからには、こういうことをしたい(数字で出るまでスペースをスキップしたい)ケースがあるのだろう。