我试图简单地解析这个并用Boost :: Spirit来构建xml-minded结构,
One{
Two{
Three{
}
}
}
代码组织如下:
结构定义以保持精神:
struct config;
typedef boost::variant< boost::recursive_wrapper<config> , std::string > config_node;
struct config
{
std::string name;
std::vector<config_node> children;
};
BOOST_FUSION_ADAPT_STRUCT(
config,
(std::string, name)
(std::vector<config_node>, children)
)
(从xml介绍中无耻窃取)
规则声明(在解析器类上)
qi::rule<Iterator, config(), qi::locals<std::string>, ascii::space_type> cfg;
qi::rule<Iterator, config_node(), ascii::space_type> node;
qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
解析器'解析'方法中规则的定义。
node = cfg;
start_tag = +(char_ -'{') >> '{';
end_tag = char_('}');
cfg %= start_tag[_a = _1]
>> *node
>> end_tag(_a);
_a和_1是boost :: phoenix变量。
此规则适用于上面粘贴的小剪裁,但如果我将其更改为:
One{
Two{
}
Three{
}
}
(同一范围内的两个组,而不是其他组内的组)解析器失败。 我不明白为什么。
答案 0 :(得分:2)
为了将来参考,您的代码看起来像是Boost教程中的mini_xml2.cpp的简化版本(又名“无耻偷走的”)。
要使您的示例正常工作,您必须更改该行:
start_tag = +(char_ -'{') >> '{';
到
start_tag = +(char_ -'{' - '}') >> '{';
现在它已经很明显了:)每当解析器解析start_tag
时,它就会开始寻找node
s(因为>> *node
部分)。由于}
是合法的start_tag
,因此可以将其识别为一个,但不应该。{/ p>
btw您可能会考虑修复代码中的一些冗余。例如:
在原始的mini_xml2.cpp示例中,end_tag
用作检查您关闭与打开的标记相同的标记的函数(因此签名为void(std::string)
)。
cfg %= start_tag[_a = _1]
>> *node
>> "}";
mini_xml2.cpp示例中的多态性节点,因此boost::variant
与访问者一起使用。在您的示例中,这也是多余的。老实说,它让我想知道如何行
node = cfg
在编译期间没有出现任何问题,因为node
具有boost::variant
类型。仅供参考,在最初的例子中,这一行是:
node %= xml | text;
并且%=
运算符正确'猜测'了RHS的类型,因为|
运算符将结果读为boost::variant
。