最自然的方法是为您的更多限制场合使用不同的解析器。
另外,如果性能如此重要,您甚至不能多做 3 或 4 个字符比较
也就是说,这里有一些选项:
1。通过qi::lazy使用可变规则
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
int main()
{
typedef std::string::const_iterator It;
qi::rule<It>
request = "request",
response = "response",
status = "status",
query = "query",
//
allowed;
static qi::rule<It> const start = qi::lazy(phx::ref(allowed)) >> qi::lit("\r\n");
static const auto test = [](std::string const& input) { return qi::parse(begin(input), end(input), start); };
for (int i=0; i<10; ++i)
{
switch(rand()%3)
{
case 0: allowed = request; break;
case 1: allowed = request | response | query; break;
case 2: allowed = request | response | status | query; break;
}
std::cout << "status: " << test("status\r\n") << "\t"
<< "response: " << test("response\r\n") << "\t"
<< "request: " << test("request\r\n") << "\n";
}
}
就像 Mike 提到的,这也用于 Nabialek 技巧,尽管 qi::lazy 是这里的基本要素。
这个打印,例如:
status: 0 response: 1 request: 1
status: 0 response: 1 request: 1
status: 0 response: 0 request: 1
status: 0 response: 1 request: 1
status: 1 response: 1 request: 1
status: 0 response: 1 request: 1
status: 0 response: 1 request: 1
status: 0 response: 0 request: 1
status: 0 response: 0 request: 1
status: 0 response: 1 request: 1
2。使用带有qi::lazy 的继承属性
与上面非常相似,您可以将“子规则”作为继承属性传递。我不确定我是否会推荐这个,因为我在过去的示例中看到了未定义的行为,请参见例如
3。只需使用单独的规则
在我看来这是最自然的:
std::function<bool(string)> test;
switch(rand()%3)
{
case 0: test = [&](std::string const& input) { return qi::parse(begin(input), end(input), request); }; break;
case 1: test = [&](std::string const& input) { return qi::parse(begin(input), end(input), request | response | query); }; break;
case 2: test = [&](std::string const& input) { return qi::parse(begin(input), end(input), request | response | status | query); }; break;
}
查看完整示例:http://coliru.stacked-crooked.com/a/603f093add6b9799