Boost Spirit解析字符串以前缀开头

Posted

技术标签:

【中文标题】Boost Spirit解析字符串以前缀开头【英文标题】:Boost spirit parse string starts with a prefix 【发布时间】:2019-11-20 12:42:28 【问题描述】:

我目前正在尝试解析字符串,从一些前缀 + 数字开始。 喜欢abc_.+ \d+。但是有一些大问题。 这是一个测试代码

#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/phoenix/phoenix.hpp>


namespace qi = boost::spirit::qi;

struct S 
        std::string s;
        int n = 0;
;
BOOST_FUSION_ADAPT_STRUCT(S, s, n)

struct parser : qi::grammar<std::string::const_iterator, S(), qi::ascii::space_type> 
    typedef std::string::const_iterator Iterator;

    qi::rule<Iterator, S(), qi::ascii::space_type> start;
    qi::rule<Iterator, std::string(), qi::ascii::space_type> abc;

        parser() : parser::base_type(start) 
        abc = qi::raw[ "abc_" >> +(qi::alnum)];
        //abc = qi::raw[ "abc_" >> +(qi::alpha)];
        start %=  abc >> qi::int_;
        BOOST_SPIRIT_DEBUG_NODES( (start)(abc))
    
;


int main() 
    using boost::spirit::ascii::space;
    parser g;

    for(std::string str : "abc 1", "abc_ 1", "abc_aaa 1", "abc_555 1", "cba_aaa 1") 
        std::cout << str << " - ";
        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        S s;
        bool r = phrase_parse(iter, end, g, space, s);
        if(r)
            std::cout << "Ok";
        else
            std::cout << "fail";
        std::cout << std::endl;
    

由于某种原因,qi::alnum 也会占用空间:

abc_aaa 1 - <start>
  <try>abc_aaa 1</try>
  <abc>
    <try>abc_aaa 1</try>
    <success></success>
    <attributes>[[a, b, c, _, a, a, a,  , 1]]</attributes>
  </abc>
  <fail/>
</start>
fail

如果我把它改成 qi::alpha

abc_aaa 1 - <start>
  <try>abc_aaa 1</try>
  <abc>
    <try>abc_aaa 1</try>
    <success>1</success>
    <attributes>[[a, b, c, _, a, a, a,  ]]</attributes>
  </abc>
  <success></success>
  <attributes>[[[a, b, c, _, a, a, a,  ], 1]]</attributes>
</start>
Ok

工作正常,但无法解析像 abc_123 这样的标记。

有什么建议吗?

谢谢!

Try it on Coliru

【问题讨论】:

另见***.com/questions/17072987/… 【参考方案1】:

由于您提供了一个船长,sequence parser 以及 plus 解析器(和其他一些)它在原始解析器匹配之间使用,因此 abc 解析器匹配 abc_(\s*[0-9a-zA-Z])+

对于您的情况,有一个 lexeme 指令,它提供了一种机制来禁用不需要的跳过。像abc = qi::raw[qi::lexeme["abc_" &gt;&gt; +qi::alnum]]一样使用它会匹配abc_[0-9a-zA-Z]+,整个语法会匹配abc_[0-9a-zA-Z]+\s*\d+

【讨论】:

谢谢尼基塔! abc = qi::raw[qi::lexeme["abc_" &gt;&gt; +qi::alnum]] 完成了这项工作。

以上是关于Boost Spirit解析字符串以前缀开头的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost Spirit 解析带有二进制信封的文本文件

boost::spirit 解析器的编译错误

Boost.Spirit 的单元测试

防止 Boost Spirit Symbol 解析器过早接受关键字

将文件路径字符串传递给 Boost.Spirit 中的语义操作

Boost Spirit X3:跳过啥都不做的解析器