【问题标题】:extracting string from bracket using boost spirit使用增强精神从括号中提取字符串
【发布时间】:2015-07-06 09:40:13
【问题描述】:

我有以下字符串:

%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)

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

我的规则如下:

std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
std::string strStartTokenRecur;
std::string token_intRecur;
bool bParsedLine1 = qi::phrase_parse(strLinesRecur.begin(), strLinesRecur.end(), +char_>>+char_,':', token_intRecur, strStartTokenRecur);

【问题讨论】:

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


    【解决方案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'
    

    【讨论】:

      【解决方案2】:

      好的,假设我们得到了以下using 和别名命名空间指令:

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

      并给出字符串:

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

      我们想将括号内的“代码”提取成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_(')'));
      

      它会解析以两个% 开头的任何内容,后跟一些字母字符和一个:,然后是括号内的一些“代码”。

      这一点的重点是as_string[lexeme[code]][phx::ref(res) = _1]。如果我们将其分解:lexeme[code] 只是说将解析的code 视为一个原子单元,as_string“返回”结果为std::string(而不是std::vector&lt;char&gt;)和[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 和grammar 中存储语法片段的方法。否则,auto 的使用将失败(可能存在分段错误)。

      【讨论】:

      • 嗯我不知道qi::copy o.O 我总是使用boost::proto::deep_copy 或BOOST_SPIRIT_AUTO(这也有在c++03 中工作的好处)。
      • 在这里,我根据您的看法向您提供我的(大大:))简化版本:Live On Coliru
      • 谢谢各位上帝保佑你:)
      猜你喜欢
      • 1970-01-01
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      相关资源
      最近更新 更多