【问题标题】:Parsing map of variants with Boost Spirit X3使用 Boost Spirit X3 解析变体图
【发布时间】:2018-12-28 04:20:28
【问题描述】:

我正在尝试(但失败)使用 Boost Spirit X3 解析 map<int, variant<string, float>>,代码如下:

#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <map>
#include <variant>
#include <string>

using namespace std;

namespace x3 = boost::spirit::x3;

int main() {
    auto variantRule = x3::rule<class VariantClass, x3::variant<std::string, float>>() = (*x3::alnum | x3::float_);

    auto pairRule = x3::rule<class PairClass, pair<int, x3::variant<std::string, float>>>() = x3::int_ >> ":" >> variantRule;

    auto mapRule = x3::rule<class MapClass, map<int, x3::variant<std::string, float>>>() = pairRule >>  * ( "," >> pairRule );

    string input = "1 : 1.0, 2 : hello, 3 : world";

    map<int, x3::variant<std::string, float>> variantMap;

    auto success = x3::phrase_parse(input.begin(), input.end(), mapRule, x3::space, variantMap);

    return 0;
}

由于某种原因,我无法解析 pair&lt;int, variant&lt;string, float&gt;&gt; 的地图。虽然我能够解析变体向量,但只有当我尝试解析变体映射时,我的代码才会失败。值得一提的是,我还阅读了 X3 教程。任何帮助将不胜感激。

编辑 1

考虑到@liliscent 的回答和其他一些更改,我终于能够让它工作,这是正确的代码:

#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <map>
#include <variant>
#include <string>

using namespace std;

namespace x3 = boost::spirit::x3;

int main() {
    auto stringRule = x3::rule<class StringClass, string>() = x3::lexeme[x3::alpha >> *x3::alnum];

    auto variantRule = x3::rule<class VariantClass, x3::variant<std::string, float>>() = (stringRule | x3::float_);

    auto pairRule = x3::rule<class PairClass, pair<int, x3::variant<std::string, float>>>() = x3::int_ >> ':' >> variantRule;

    auto mapRule = x3::rule<class MapClass, map<int, x3::variant<std::string, float>>>() = pairRule % ",";

    string input = "1 : 1.0, 2 : hello, 3 : world";

    map<int, x3::variant<std::string, float>> variantMap;

    auto bg = input.begin(), ed = input.end();

    auto success = x3::phrase_parse(bg, ed, mapRule, x3::space, variantMap) && bg == ed;

    if (!success) cout<<"Parsing not succesfull";

    return 0;
}

【问题讨论】:

    标签: c++ boost c++14 boost-spirit boost-spirit-x3


    【解决方案1】:

    如果您想让spirit 识别std::pairstd::map,则需要包含std::pair 的融合适配器:

    #include <boost/fusion/adapted/std_pair.hpp>
    

    这应该可以修复您的compilation problem。但是你的代码还有其他问题,这条规则(*x3::alnum | x3::float_);不会做你想做的事,因为左边部分可以直接匹配空。您需要重新考虑如何定义此标识符。

    另外,写pairRule % "," 比写pairRule &gt;&gt; * ( "," &gt;&gt; pairRule ); 更好。

    并且你应该将输入 begin 作为一个左值迭代器传递,因为这样它会在解析过程中被推进,这样你就可以检查解析器是否已经过早终止。

    【讨论】:

    • 或者,在末尾添加 &gt;&gt; x3::eoi 以确保在未使用完整输入时解析失败
    • 我发现了 fusion 的 std_pair 堆栈溢出问题:stackoverflow.com/questions/4874075/…。有了include、您的建议和其他一些更改,我终于能够让它发挥作用。查看更新的答案。
    • 我仍在试图弄清楚为什么如果我使用 pairRule &gt;&gt; *(',' &gt;&gt; pairRule) 而不是 pairRule % ',' 我得到一个编译错误:error: no matching function for call to 'std::map&lt;...&gt;::insert(...)。两个规则不应该以同样的方式工作吗?
    • @JaimeIvanCervantes 它应该。看看我回答中的在线编译器链接,您的原始代码只需添加融合适配器包含即可编译。如果你的新代码仍然出错,我建议你再问一个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 2021-10-28
    相关资源
    最近更新 更多