我想解析一个形式为的字符串: string_number。 我不知道如何为boost qi解析器编写语法。
现在我的语法看起来像:
+qi::char_("a-zA-Z0-9_-") >> lit('
_
') >> qi::int_
但看起来不像是有效的。 示例字符串是: ab_bcd_123 - >令牌(ab_bcd,123) ab_123 --->代币(ab,123)
答案 0 :(得分:1)
但看起来并不合适。
那是因为0-9
吃了数字。这应该有效:
+qi::char_("a-zA-Z_") >> '_' >> qi::uint_
如果您也想允许ab-3_bcd_123
,请设备预先检测您是否已到达终点,例如eoi
:
qi::raw[
(+qi::alnum|'-') % (!('_' >> qi::uint_ >> eoi))
] >> '_' >> qi::uint_
不过,到现在为止,我只是忘了它并做到了:
qi::lexeme [ +qi::char_("a-zA-Z0-9_-") ] [ _val = split_ident(_1) ];
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
using NumberedIdent = std::pair<std::string, int>;
namespace Demo {
struct SplitIdent {
NumberedIdent operator()(std::vector<char> const& v, bool& pass) const {
std::string s(v.begin(), v.end());
try {
auto n = s.rfind('_');
pass = n > 0;
return { s.substr(0, n), std::stoi(s.substr(n+1)) };
} catch(...) {
pass = false; return {s, 0};
}
}
};
using It = std::string::const_iterator;
using namespace qi;
static boost::phoenix::function<SplitIdent> split_ident;
rule<It, NumberedIdent()> const rule
= lexeme [ +char_("a-zA-Z0-9_-") ] [ _val = split_ident(_1, _pass) ];
}
int main() {
for (std::string const input : {
"ab_bcd_123",
"ab-3_bcd_123 = 'something'",
// failing:
"ab_bcd_123_q = 'oops'",
"ab_bcd_123_ = 'oops'",
"_123 = 'oops'",
"_",
"q",
""
})
{
NumberedIdent parsed;
Demo::It f = input.begin(), l = input.end();
bool ok = parse(f, l, Demo::rule, parsed);
if (ok) {
std::cout << "SUCCESS: ['" << parsed.first << "', " << parsed.second << "]\n";
} else {
std::cout << "parse failed ('" << input << "')\n";
}
if (f != l) {
std::cout << " remaining input '" << std::string(f,l) << "'\n";
}
}
}
打印:
SUCCESS: ['ab_bcd', 123]
SUCCESS: ['ab-3_bcd', 123]
remaining input ' = 'something''
然后所有失败的测试用例(按设计):
parse failed ('ab_bcd_123_q = 'oops'')
remaining input 'ab_bcd_123_q = 'oops''
parse failed ('ab_bcd_123_ = 'oops'')
remaining input 'ab_bcd_123_ = 'oops''
parse failed ('_123 = 'oops'')
remaining input '_123 = 'oops''
parse failed ('_')
remaining input '_'
parse failed ('q')
remaining input 'q'
parse failed ('')