了解Boost.spirit的字符串解析器

Ash*_*hot 6 c++ parsing boost boost-spirit boost-spirit-qi

#include <iostream>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
int main ()
{
    using qi::string;

    std::string input("a");
    std::string::iterator strbegin = input.begin();
    std::string p;
    bool ok = qi::phrase_parse(strbegin, input.end(),
            ((string("a")  >> string("a")) | string("a")),
            qi::space,                  
            p);                               

    if (ok && strbegin == input.end()) {
        std::cout << p << std::endl;
        std::cout << p.size() << std::endl;
    } else {
        std::cout << "fail" << std::endl;
        std::cout << std::string(strbegin, input.end()) << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

该计划输出aa.这怎么可能?输入字符串是a.解析器应匹配aaa.我写的string("a")只是测试运营商.

使用时char_也是如此string.

seh*_*ehe 6

它不是字符串匹配器本身.它的[属性传播] + [回溯]在行动中.

字符串属性是容器属性,并且可以通过不同的解析器子表达式将许多元素分配给它.现在出于效率原因,Spirit不会回溯在回溯时发出的属性的值.

通常这根本不是问题,但正如你所看到的,来自替代方案失败的第一个分支的'a'仍然存在.

无论是改写还是采用"大枪" qi::hold[]指令:

(qi::hold [ string("a")  >> string("a") ] | string("a")),
Run Code Online (Sandbox Code Playgroud)

重写可能看起来像:

qi::string("a") >> -qi::string("a"),
Run Code Online (Sandbox Code Playgroud)

此外,如果您真的只是想匹配某些文本字符串,请考虑:

(qi::raw [ qi::lit("aa") | "a" ]), 
// or even just
qi::string("aa") | qi::string("a"),
Run Code Online (Sandbox Code Playgroud)

现在哪一个最适用,取决于你的语法.