使用 Boost Spirit X3 解析变体图
Parsing map of variants with Boost Spirit X3
我正在尝试(但失败了)使用 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<int, variant<string, float>>
的地图。虽然我能够解析变体向量,但只有当我尝试解析变体映射时,我的代码才会失败。值得一提的是,我还浏览了 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;
}
如果你想让spirit
识别std::pair
和std::map
,你需要包含std::pair
的融合适配器:
#include <boost/fusion/adapted/std_pair.hpp>
这应该可以解决您的 compilation problem。但是你的代码还有其他问题,这条规则 (*x3::alnum | x3::float_);
不会做你想要的,因为左边部分可以直接匹配空。您需要重新考虑如何定义此标识符。
另外,pairRule % ","
比 pairRule >> * ( "," >> pairRule );
更好。
并且您应该将输入 begin 作为左值迭代器传递,因为这样它会在解析期间提前,以便您可以检查解析器是否过早终止。
我正在尝试(但失败了)使用 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<int, variant<string, float>>
的地图。虽然我能够解析变体向量,但只有当我尝试解析变体映射时,我的代码才会失败。值得一提的是,我还浏览了 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;
}
如果你想让spirit
识别std::pair
和std::map
,你需要包含std::pair
的融合适配器:
#include <boost/fusion/adapted/std_pair.hpp>
这应该可以解决您的 compilation problem。但是你的代码还有其他问题,这条规则 (*x3::alnum | x3::float_);
不会做你想要的,因为左边部分可以直接匹配空。您需要重新考虑如何定义此标识符。
另外,pairRule % ","
比 pairRule >> * ( "," >> pairRule );
更好。
并且您应该将输入 begin 作为左值迭代器传递,因为这样它会在解析期间提前,以便您可以检查解析器是否过早终止。