使用 Boost.Spirit 仅解析特定数字
Parse only specific numbers with Boost.Spirit
如何构建 Boost.Spirit 仅匹配特定范围内的数字的解析器?
考虑简单的解析器 qi::uint_
。它匹配所有无符号整数。是否可以构造一个匹配数字 0
到 12345
但不匹配 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
}
}
}
语义动作可以写得更简洁 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
}
}
}
来自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.
如何构建 Boost.Spirit 仅匹配特定范围内的数字的解析器?
考虑简单的解析器 qi::uint_
。它匹配所有无符号整数。是否可以构造一个匹配数字 0
到 12345
但不匹配 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
}
}
}
语义动作可以写得更简洁 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
}
}
}
来自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. Ifpass
is set to false the action parser will immediately return false as well, while not invoking p and not generating any output.