Boost::qi 解析字符串

问题描述

我需要从下一个 hls 标签解析“标题

标签样式: #EXTINF:[,]

例如真实标签

#EXTINF:10,Title of the segment => I need "Title of the segment" phrase

#EXTINF:20,Title => I need "Title" phrase

#EXTINF:12 => I need "" phrase

我写了下一个代码

double duration;
std::string title;

boost::spirit::qi::rule<Iterator,std::string()> quoutedString;
quoutedString %= lexeme[+(char_)];

bool r = parse(first,last,("#EXTINF:" >> double_[ref(duration) = _1] >> -(',' >> quoutedString[ref(title) = _1] ) )
);
if (!r || first != last) {
    addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag"));
    return false;
}

但是我在编译过程中遇到了下一个错误

error: call of overloaded ‘ref(std::__cxx11::string&)’ is ambiguous
         ("#EXTINF:" >> double_[ref(duration) = _1] >> -(',' >> quoutedString[ref(title) = _1] ) )

请帮帮我。我做错了什么?

解决方法

您过多地使用命名空间。此外,ADL 无论如何都会为 Box 1 : B1,B2,B3 Box 2 : ------------------ Box 1 : B2,B3 Box 2 : B1 ------------------ Box 1 : B1,B3 Box 2 : B2 ------------------ Box 1 : B3 Box 2 : B1,B2 ------------------ Box 1 : B1,B2 Box 2 : B3 ------------------ Box 1 : B2 Box 2 : B1,B3 ------------------ Box 1 : B1 Box 2 : B2,B3 ------------------ Box 1 : Box 2 : B1,B3 参数引入 std::ref,除非 std::string 被加括号或命名空间限定。

过度使用 ref 从来都不是一个好主意(参见例如 Why is "using namespace std;" considered bad practice?),在这种情况下,该消息阐明了 using namespacestd::ref 之间的混淆(可能还有其他人,但您没有提供完整的信息)。

说不:

Live On Coliru

boost::phoenix::ref

印刷品

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/optional.hpp>
#include <iomanip>

namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;

#define addMinorProblem(...) do {} while (0)

boost::optional<std::pair<double,std::string>> parse(std::string_view input)
{
    using Iterator = std::string_view::const_iterator;

    Iterator    first = begin(input),last = end(input);
    double      duration;
    std::string title;

    boost::spirit::qi::rule<Iterator,std::string()> quoutedString;
    quoutedString %= qi::lexeme[+(qi::char_)];

    bool r = parse(first,last,("#EXTINF:" >> qi::double_[px::ref(duration) = qi::_1] >>
                    -(',' >> quoutedString[px::ref(title) = qi::_1])));
    if (!r || first != last) {
        addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag"));
        return {};
    }

    return std::make_pair(duration,title);
}

int main()
{
    for (std::string const input : {
             "#EXTINF:10,Title of the segment",// => I need "Title of the
                                                // segment" phrase
             "#EXTINF:20,Title",// => I need "Title" phrase
             "#EXTINF:12",// => I need "" phrase
         }) {
        if (auto result = parse(input)) {
            std::cout << "Parsed: (" << result->first << "," << std::quoted(result->second) << ")\n";
        } else {
            std::cout << "Cannot parse " << std::quoted(input) << "\n";
        }
    }
}

改进,小事

  1. 通过一些明智的local using 声明,您可以再次使其“更短”:

    Parsed: (10,"Title of the segment")
    Parsed: (20,"Title")
    Parsed: (12,"")
    

    我个人觉得这比清晰更模糊(想象自己在代码审查中解释 using namespace qi::labels; using px::ref; bool r = parse(first,("#EXTINF:" >> qi::double_[ref(duration) = _1] >> -(',' >> quoutedString[(ref)(title) = _1]))); ?)

  2. 没有语义动作的 (ref)(title) 没有意义

  3. operator %= 没有船长是没有意义的(见 Boost spirit skipper issues

  4. qi::lexeme[] [原文如此] 用词不当(目前?)因为它不解析引号

  5. 为什么不使用自动属性传播来代替痛苦的语义操作?它们只会增加编译时间,正如您所发现的,还会增加开发时间。见Boost Spirit: "Semantic actions are evil"?

  6. 此外,与其在解析后繁琐地检查 quoutedString,还不如简单地匹配表达式中的 first == last

以上所有简化为以下内容:

Live On Coliru

>> qi::eoi

没有更多的boost::optional<std::pair<double,std::string>> parse(std::string_view input) { namespace qi = boost::spirit::qi; double duration; std::string title; if (qi::parse( begin(input),end(input),// ("#EXTINF:" >> qi::double_ >> -(',' >> +qi::char_) >> qi::eoi),duration,title)) { return std::make_pair(duration,title); } addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag")); return {}; } ,语义动作,什么不是。仍在打印:

phoenix

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...