使用 Boost.Spirit 仅解析特定数字

Parse only specific numbers with Boost.Spirit

如何构建 Boost.Spirit 仅匹配特定范围内的数字的解析器?

考虑简单的解析器 qi::uint_。它匹配所有无符号整数。是否可以构造一个匹配数字 012345 但不匹配 12346 和更大的解析器?

一种方法是将语义操作附加到 qi::uint_ 解析器,该语义操作检查解析器的属性并相应地设置语义操作的第三个参数:

#include <iostream>
#include <string>
#include <vector>

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main() {
  qi::rule<std::string::const_iterator, unsigned(), qi::ascii::space_type> rule;

  const auto not_greater_than_12345 = [](const unsigned& attr, auto&, bool& pass) {
    pass = !(attr > 12345U);
  };
  rule %= qi::uint_[not_greater_than_12345];

  std::vector<std::string> numbers{"0", "123", "1234", "12345", "12346", "123456"};
  for (const auto& number : numbers) {
    unsigned result;
    auto iter = number.cbegin();
    if (qi::phrase_parse(iter, number.cend(), rule, qi::ascii::space, result) &&
        iter == number.cend()) {
      std::cout << result << '\n';  // 0 123 1234 12345
    }
  }
}

Live on Wandbox

语义动作可以写得更简洁 the Phoenix placeholders _pass and _1:

#include <iostream>
#include <string>
#include <vector>

#include <boost/phoenix/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main() {
  qi::rule<std::string::const_iterator, unsigned(), qi::ascii::space_type> rule;

  rule %= qi::uint_[qi::_pass = !(qi::_1 > 12345U)];

  std::vector<std::string> numbers{"0", "123", "1234", "12345", "12346", "123456"};
  for (const auto& number : numbers) {
    unsigned result;
    auto iter = number.cbegin();
    if (qi::phrase_parse(iter, number.cend(), rule, qi::ascii::space, result) &&
        iter == number.cend()) {
      std::cout << result << '\n';  // 0 123 1234 12345
    }
  }
}

Live on Wandbox


来自Semantic Actions with Parsers

The possible signatures for functions to be used as semantic actions are:

...
template <typename Attrib, typename Context>
void fa(Attrib& attr, Context& context, bool& pass);

... Here Attrib is the attribute type of the parser attached to the semantic action. ... The third parameter, pass, can be used by the semantic action to force the associated parser to fail. If pass is set to false the action parser will immediately return false as well, while not invoking p and not generating any output.