我目前正在尝试解析字符串,以一些前缀+数字开头。像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
之类的标记。
有什么建议吗?
谢谢!
由于提供了一个船长,sequence parser以及加号解析器(以及其他解析器),因此它在原始解析器匹配之间使用,并且因为abc
解析器与abc_(\s*[0-9a-zA-Z])+
匹配。
正是针对您的情况,有一个lexeme
指令,该指令提供了一种在不需要的地方禁用跳过的机制。像lexeme
一样使用它会匹配abc = qi::raw[qi::lexeme["abc_" >> +qi::alnum]]
,并且整个语法也会与abc_[0-9a-zA-Z]+
匹配。