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

问题描述 投票:1回答:1

我目前正在尝试解析字符串,以一些前缀+数字开头。像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

c++ string boost-spirit prefix
1个回答
0
投票

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

正是针对您的情况,有一个lexeme指令,该指令提供了一种在不需要的地方禁用跳过的机制。像lexeme一样使用它会匹配abc = qi::raw[qi::lexeme["abc_" >> +qi::alnum]],并且整个语法也会与abc_[0-9a-zA-Z]+匹配。

© www.soinside.com 2019 - 2024. All rights reserved.