C++ 使用Boost Spirit X3解析变体地图

C++ 使用Boost Spirit X3解析变体地图,c++,boost,c++14,boost-spirit,boost-spirit-x3,C++,Boost,C++14,Boost Spirit,Boost Spirit X3,我正在尝试(但失败)使用Boost Spirit X3解析映射,代码如下: #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 <

我正在尝试(但失败)使用Boost Spirit X3解析
映射,代码如下:

#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
名称空间x3=boost::spirit::x3;
int main(){
自动变量=x3::rule()=(*x3::alnum | x3::float|);
auto pairRule=x3::rule()=x3::int\u>>“:”>>variantRule;
自动映射规则=x3::rule()=pairRule>>*(“,”>>pairRule);
string input=“1:1.0,2:hello,3:world”;
地图变数图;
自动成功=x3::短语解析(input.begin()、input.end()、mapRule、x3::space、variantMap);
返回0;
}
由于某些原因,我无法解析
对的映射。虽然我能够解析变量向量,但只有当我尝试解析变量映射时,我的代码才会失败。值得一提的是,我还学习了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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
名称空间x3=boost::spirit::x3;
int main(){
自动字符串规则=x3::rule()=x3::lexeme[x3::alpha>>*x3::alnum];
自动变量=x3::rule()=(stringRule | x3::float|);
auto pairRule=x3::rule()=x3::int \'u>>':'>>variantRule;
自动映射规则=x3::rule()=pairRule%;
string input=“1:1.0,2:hello,3:world”;
地图变数图;
auto bg=input.begin(),ed=input.end();
自动成功=x3::短语解析(bg,ed,mapRule,x3::space,variantMap)&&bg==ed;

如果(!success)无法如果您希望
spirit
识别
std::pair
std::map
,则需要包含
std::pair
的融合适配器:

#include <boost/fusion/adapted/std_pair.hpp>
#包括
这应该可以解决您的问题。但是您的代码中还有其他问题,此规则
(*x3::alnum | x3::float)
无法满足您的需要,因为左侧部分可以直接匹配为空。您需要重新考虑如何定义此标识符

另外,编写
pairRule%”,“
pairRule>>*(“,”>>pairRule);
更好


您应该以左值迭代器的形式传递输入begin,因为在解析过程中它将被提升,这样您就可以检查解析器是否提前终止。

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

#include <boost/fusion/adapted/std_pair.hpp>
#包括
这应该可以解决您的问题。但是您的代码中还有其他问题,此规则
(*x3::alnum | x3::float)
无法满足您的需要,因为左侧部分可以直接匹配为空。您需要重新考虑如何定义此标识符

另外,编写
pairRule%”,“
pairRule>>*(“,”>>pairRule);
更好


您应该将输入作为左值迭代器传递begin,因为在解析过程中它将被提升,这样您就可以检查解析器是否提前终止。

或者,在末尾添加
>x3::eoi
,以确保在st上发现fusion的
std\u对问题时解析失败确认溢出:。通过该
包括
、您的建议和一些其他更改,我终于能够让它正常工作。请参阅更新的答案。我仍在试图找出使用
pairRule>>*(','>>pairRule)的原因
而不是
pairRule%”,“
我得到一个编译错误:
错误:没有匹配的函数来调用'std::map::insert(…)
。这两个规则不是应该以相同的方式工作吗?@JaimeIvanCervantes应该是这样的。看看我回答中的在线编译器链接,您的原始代码只需添加fusion Adapter include即可编译。如果您的新代码仍然出现错误,我建议您问另一个问题。或者,在最后添加
>x3::eoi
,以确保如果没有使用完整的输入,arsing将失败。fusion的
std_pair
堆栈溢出问题:。有了
包含
、您的建议和一些其他更改,我终于能够让它工作了。请参阅更新的答案。我仍在试图找出为什么我使用
pairRule>*(','>>pairRule)
而不是
pairRule%”,“
我得到一个编译错误:
错误:没有匹配的函数来调用'std::map::insert(…)
。这两个规则不是应该以相同的方式工作吗?@JaimeIvanCervantes应该是这样的。请查看我回答中的联机编译器链接,您的原始代码只需添加fusion Adapter include即可编译。如果您的新代码仍然出现错误,我建议您问另一个问题。