解析文本以制作树数据结构
假设我正在从文件中读取一行:
Let's say I'm reading a line from a file:
{Parent{{ChildA}{ChildB}}}
更复杂的例子:
{Parent{{ChildA{ChildC}{ChildD}}{ChildB{ChildE}{ChildF}}}}
用于构造树的语法是什么.
Which is the grammar used to construct a tree.
{}
括号内的任何名称都是一个节点,如果在该括号内还有其他节点(括号),则这些节点是子节点.
Any name inside {}
brackets is a node, and if within that bracket there are other nodes (brackets), those nodes are children.
我能够使用计数器解析第一个特定示例,但只能找到节点的文本名称.我如何解析它以便我可以确定哪些节点是彼此的子节点?我似乎无法理解我将使用的代码.我有一种感觉,我会使用递归.
I'm able to parse the first specific example using a counter, but only to find the text names of the nodes. How can I parse this so that I can determine what nodes are children of one another? I can't seem to wrap my mind around the code I would use. I have a feeling I would use recursion.
任何帮助或建议将不胜感激.
Any help or advice would be appreciated.
C++ 是首选.
非常感谢.
推荐答案
如果是家庭作业,你无论如何都无法使用的答案破坏了乐趣:
Spoiling the fun with an answer you can't use anyway if it's homework:
Boost Spirit Qi 的最小实现:
A minimal implementation with Boost Spirit Qi:
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
typedef boost::make_recursive_variant<
std::vector<boost::recursive_variant_>,
std::string>::type ast_t;
void dump(const ast_t&);
// adhoc parser rule:
static const qi::rule<std::string::iterator, ast_t()> node =
'{' >> *node >> '}' | +~qi::char_("{}");
int main()
{
std::string input = "{Parent{{ChildA{ChildC}{ChildD}}{ChildB{ChildE}{ChildF}}}}";
std::string::iterator f(input.begin()), l(input.end());
ast_t tree;
if (qi::parse(f, l, node, tree))
dump(tree);
else
std::cerr << "Unparsed: " << std::string(f, l) << std::endl;
}
很遗憾,dump
的实现几乎是等量的代码:)
The implementation of dump
is regrettably almost the equivalent amount of code :)
它会打印:
{
Parent
{
{
ChildA
{
ChildC
}
{
ChildD
}
}
{
ChildB
{
ChildE
}
{
ChildF
}
}
}
}
<子>这是dump(const ast_t&)
的定义:
struct dump_visitor : boost::static_visitor<>
{
dump_visitor(int indent=0) : _indent(indent) {}
void operator()(const std::string& s) const { print(s); }
template <class V>
void operator()(const V& vec) const
{
print("{");
for(typename V::const_iterator it=vec.begin(); it!=vec.end(); it++)
boost::apply_visitor(dump_visitor(_indent+1), *it);
print("}");
}
private:
template <typename T> void print(const T& v) const
{ std::cout << std::string(_indent*4, ' ') << v << std::endl; }
int _indent;
};
void dump(const ast_t& tree)
{
boost::apply_visitor(dump_visitor(), tree);
}
相关文章