我用boost :: spirit :: qi :: rule写了一些语法来解析互联网数据包。语法是这样的:
qi::rule<Iterator> start, request, response, status, query ;
start = (request | response | status | query) >> lit("\r\n");
为了提高性能,用户可能希望跳过运行时中的一些规则,例如忽略“响应”,“状态”,“查询”并且只尝试匹配请求,因此规则将更改为:
start = (request ) >> lit("\r\n");
可以这样做吗?例如,是否有像“禁用()”这样的功能来禁用规则“响应”,“状态”和“查询”?
答案 0 :(得分:6)
最自然的方法是在更多受约束的场合使用不同的解析器。
此外,如果表现如此重要,您甚至无法进行3或4次额外角色比较
那就是说,这里有一些选择:
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";
}
}
就像迈克提到的那样,这也用在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
qi::lazy
与上面的内容非常类似,您可以将'subrules'作为继承属性传递。我不确定我会推荐这个,因为我在过去的例子中看到了未定义的行为,见例如。
qi::lazy
本身如何不支持继承属性在我看来,这是最自然的:
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;
}
答案 1 :(得分:1)
是的,可以使用qi::symbols
解析器。可以在运行时更改使用的符号,因此您可以更改行为。要将此解析器用于完整规则,有一个小技巧,称为nabialek技巧http://boost-spirit.com/home/articles/qi-example/nabialek-trick/。
基本上它显示了如何在符号解析器中挂钩完整的规则。