我想解析由CCn组成的字符串,其中包含1 <= n <= 4,或从SERVICEk解析1 <= k <= 63。
有效字符串:"CC1“、"CC2”、"CC3“、"CC4”、"SERVICE1“、"SERVICE2”、.、"SERVICE63“。
我写了下一个表达式:
( '"' >> (qi::raw["CC" >> qi::uint_] | qi::raw["SERVICE" >> qi::uint_]) >> '"' >> qi::eoi)但是我怎么能限制n和k呢?
在输出中,我需要得到完整的字符串CC1,CC2,.SERVICE63
发布于 2021-07-09 12:19:47
最简单的方法是使用symbols<>。
详细的方法是验证语义动作中的数字。
我的建议是,要么是符号,要么是独立的语义验证与解析(即解析原始数字并在解析后验证AST )。
符号
这可能更灵活、最有效,并且允许您在AST域中进行强类型输入。它避开了语义操作的编译开销和复杂性:促进精神:“语义行为是邪恶的”?
住在Coliru
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
int main() {
qi::symbols<char> cc, service;
cc += "CC1", "CC2", "CC3", "CC4";
service += "SERVICE1", "SERVICE2", "SERVICE3", "SERVICE4", "SERVICE5",
"SERVICE6", "SERVICE7", "SERVICE8", "SERVICE9", "SERVICE10",
"SERVICE11", "SERVICE12", "SERVICE13", "SERVICE14", "SERVICE15",
"SERVICE16", "SERVICE17", "SERVICE18", "SERVICE19", "SERVICE20",
"SERVICE21", "SERVICE22", "SERVICE23", "SERVICE24", "SERVICE25",
"SERVICE26", "SERVICE27", "SERVICE28", "SERVICE29", "SERVICE30",
"SERVICE31", "SERVICE32", "SERVICE33", "SERVICE34", "SERVICE35",
"SERVICE36", "SERVICE37", "SERVICE38", "SERVICE39", "SERVICE40",
"SERVICE41", "SERVICE42", "SERVICE43", "SERVICE44", "SERVICE45",
"SERVICE46", "SERVICE47", "SERVICE48", "SERVICE49", "SERVICE50",
"SERVICE51", "SERVICE52", "SERVICE53", "SERVICE54", "SERVICE55",
"SERVICE56", "SERVICE57", "SERVICE58", "SERVICE59", "SERVICE60",
"SERVICE61", "SERVICE62", "SERVICE63";
for (std::string const input : {
// valid:
"CC1",
"CC2",
"CC3",
"CC4",
"SERVICE1",
"SERVICE2",
"SERVICE63",
// invalid:
"CC0",
"CC5",
"SERVICE0",
"SERVICE64",
}) {
bool valid = parse(begin(input), end(input), service|cc);
std::cout << std::quoted(input) << " -> "
<< (valid ? "valid" : "invalid") << "\n";
}
}打印
"CC1" -> valid
"CC2" -> valid
"CC3" -> valid
"CC4" -> valid
"SERVICE1" -> valid
"SERVICE2" -> valid
"SERVICE63" -> valid
"CC0" -> invalid
"CC5" -> invalid
"SERVICE0" -> invalid
"SERVICE64" -> invalid奖金:强类型的想法:http://coliru.stacked-crooked.com/a/2cb07d4da9aad39e
语义行为
简而言之:
qi::rule<It, intmax_t(intmax_t min, intmax_t max)> constrained_num =
qi::uint_[_pass = (_1 >= _r1 && _1 <= _r2)];
qi::rule<It> cc = "CC" >> constrained_num(1, 4),
service = "SERVICE" >> constrained_num(1, 63);住在Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
int main() {
using namespace qi::labels;
qi::rule<It, intmax_t(intmax_t min, intmax_t max)> constrained_num =
qi::uint_[_pass = (_1 >= _r1 && _1 <= _r2)];
qi::rule<It> cc = "CC" >> constrained_num(1, 4),
service = "SERVICE" >> constrained_num(1, 63);
for (std::string const input : {
// valid:
"CC1",
"CC2",
"CC3",
"CC4",
"SERVICE1",
"SERVICE2",
"SERVICE63",
// invalid:
"CC0",
"CC5",
"SERVICE0",
"SERVICE64",
}) {
bool valid = parse(begin(input), end(input), service|cc);
std::cout << std::quoted(input) << " -> "
<< (valid ? "valid" : "invalid") << "\n";
}
}打印与上面相同
发布于 2021-07-09 12:07:58
要限制uint_范围,可以在语义操作中执行范围检查。例如,它可以作为lambda实现,或者更简洁地作为Boost.Phenix表达式实现。
以下代码将这些数字解析为向量(省略字符串):
#include <iostream>
#include <string>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
int main()
{
std::string input = "CC1 CC2 CC3 CC4 SERVICE1 SERVICE2";
std::vector<unsigned int> out;
using namespace boost::spirit::qi;
phrase_parse(
input.begin(),
input.end(),
*(lexeme[lit("CC") >> uint_ [ _pass = (_1>=1 && _1<=4) ]] |
lexeme[lit("SERVICE") >> uint_ [ _pass = (_1>=1 && _1<=63) ]]),
ascii::space,
out
);
for (auto i : out)
std::cout << i << std::endl;
}https://stackoverflow.com/questions/68315418
复制相似问题