0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Boost.Qiのqi::skip_flag::dont_postskipを追求する

Last updated at Posted at 2020-08-22

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があるからには、こういうことをしたい(数字で出るまでスペースをスキップしたい)ケースがあるのだろう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?