提升精神解析字符串以前缀开头

Boost spirit parse string starts with a prefix

本文关键字:字符串 前缀 开头      更新时间:2023-10-16

>我目前正在尝试解析字符串,从一些前缀+数字开始。 喜欢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那样解析令牌。

有什么建议吗?

谢谢!

在科里鲁身上试试

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

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