我对提升::精神深感钦佩,不理解它永远的挫折;)
我有太贪婪的字符串的问题,因此它不匹配.下面是一个不解析的最小示例,因为txt规则会结束.
关于我想做什么的更多信息:目标是解析一些伪SQL并跳过空格.在一个声明中
select foo.id, bar.id from foo, baz
Run Code Online (Sandbox Code Playgroud)
我需要将其from视为特殊关键字.规则是这样的
"select" >> txt % ',' >> "from" >> txt % ','
Run Code Online (Sandbox Code Playgroud)
但它显然不起作用 bar.id from foo看作一个项目.
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
int main(int, char**) {
auto txt = +(qi::char_("a-zA-Z_"));
auto rule = qi::lit("Hello") >> txt % ',' >> "end";
std::string str = "HelloFoo,Moo,Bazend";
std::string::iterator begin = str.begin();
if (qi::parse(begin, str.end(), rule))
std::cout << "Match !" << std::endl;
else
std::cout << "No match :'(" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
pho*_*oji 10
这是我的版本,更改标记为:
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
int main(int, char**) {
auto txt = qi::lexeme[+(qi::char_("a-zA-Z_"))]; // CHANGE: avoid eating spaces
auto rule = qi::lit("Hello") >> txt % ',' >> "end";
std::string str = "Hello Foo, Moo, Baz end"; // CHANGE: re-introduce spaces
std::string::iterator begin = str.begin();
if (qi::phrase_parse(begin, str.end(), rule, qi::ascii::space)) { // CHANGE: used phrase_parser with a skipper
std::cout << "Match !" << std::endl << "Remainder (should be empty): '"; // CHANGE: show if we parsed the whole string and not just a prefix
std::copy(begin, str.end(), std::ostream_iterator<char>(std::cout));
std::cout << "'" << std::endl;
}
else {
std::cout << "No match :'(" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
这与GCC 4.4.3和Boost 1.4something一起编译和运行; 输出:
Match !
Remainder (should be empty): ''
Run Code Online (Sandbox Code Playgroud)
通过使用lexeme,您可以避免有条件地txt占用空间,因此仅匹配单词边界.这产生了预期的结果:因为"Baz"后面没有逗号,并且txt不吃空格,我们从不会意外消耗"end".
无论如何,我不是100%肯定这是你正在寻找的东西 - 特别是,str缺少空格作为一个说明性的例子,或者你不知何故被迫使用这种(无空间)格式?
旁注:如果要确保已解析整个字符串,请添加一个检查以查看是否begin == str.end().如上所述,即使只str解析了非空前缀,您的代码也会报告匹配.
更新:添加后缀打印.