使用提升精神从括号中提取字符串

时间:2015-07-06 09:40:13

标签: c++ boost boost-spirit boost-spirit-qi

我有以下字符串:

regname : temp1
regname : temp2
regname : temp3
regname : temp4
value at index : 0 is  : temp1
value at index : 1 is  : temp2
value at index : 2 is  : temp3
value at index : 3 is  : temp4

我想解析它并存储/提取括号中的%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C) 字符串。

我的规则如下:

90pv-RKSJ-UCS2C

2 个答案:

答案 0 :(得分:1)

看起来你认为船长是拆分分隔符。它完全相反(Boost spirit skipper issues)。

在这种罕见的情况下,我认为我更喜欢正则表达式。但是,既然你问过这里的精神:

<强> Live On Coliru

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main() {
    std::string const line = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";

    auto first = line.begin(), last = line.end();

    std::string label, token;
    bool ok = qi::phrase_parse(
            first, last, 
            qi::lexeme [ "%%" >> +~qi::char_(":") ] >> ':' >> qi::lexeme["CMap"] >> '(' >> qi::lexeme[+~qi::char_(')')] >> ')',
            qi::space,
            label, token);

    if (ok)
        std::cout << "Parse success: label='" << label << "', token='" << token << "'\n";
    else
        std::cout << "Parse failed\n";

    if (first!=last)
        std::cout << "Remaining unparsed input: '" << std::string(first, last) << "'\n";
}

打印

Parse success: label='DocumentNeededResources', token='90pv-RKSJ-UCS2C'

答案 1 :(得分:1)

好吧,假设我们给出了以下using和别名命名空间指令:

using namespace boost::spirit::qi;
namespace phx = boost::phoenix;

给出字符串:

std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";

我们希望提取&#34;代码&#34;在括号内res

std::string res;

执行此操作的一种方法是使用boost::phoenix::ref作为语义操作。 因此给出了一个代码语法:

using boost::spirit::ascii::alnum;
auto code = copy(+(alnum | char_('-')));

(这与正则表达式[a-zA-Z\-]中的内容一致)

我们可以为整个字符串创建自己的语法:

using boost::spirit::ascii::alpha;
auto grammar = copy(
    (char_('%') >> char_('%') >> +alpha >> char_(':')) 
        >> +alpha >> char_('(') >> as_string[lexeme[code]][phx::ref(res) = _1] >> char_(')'));

分析以两个%开头的任何内容,后跟一些字母字符和:,然后是一些&#34;代码&#34;在括号内。

关键是as_string[lexeme[code]][phx::ref(res) = _1]。如果我们将其分解:lexeme[code]只是将解析后的code视为原子单位,as_string&#34;返回&#34;结果为std::string(与std::vector<char>相对)和[phx::ref(res) = _1]使用语义操作将已解析的字符串存储到res中(_1是第一个占位符在那个语法中匹配。)

在这种情况下,以下调用会跳过空格:

using boost::spirit::ascii::blank;
phrase_parse(begin(strLinesRecur), end(strLinesRecur), grammar, blank);

Live demo

这当然只是一个符合字符串的语法示例。

注意:copy是指qi::copy,它是一种能够存储对象code和{{1}中的语法片段的方法}。没有它,grammar的使用将失败(可能存在分段错误)。