假设我们要像这样解析一个递归 block 。当“skip_comments_tag
”作为 block 的前缀时,我们递归地跳过该 block 内的所有评论(/*...*/
)。
{
{}
{
skip_comments_tag{
{} /*comments*/
{ /*comments*/ }
}
}
}
像 Coliru 中那样很容易想出一个递归解析器.
namespace Parser {
auto const ruleComment = x3::lit("/*") >> *(x3::char_ - "*/") >> "*/" | x3::space;
x3::rule<struct SBlockId> const ruleBlock;
auto const ruleBlock_def = x3::lit('{') >> *(ruleBlock | "skip_comments_tag" >> x3::skip(ruleComment)[ruleBlock]) >> '}';
BOOST_SPIRIT_DEFINE(ruleBlock)
}
但它不会编译(当 parse
函数被调用时)因为它会生成一个无限上下文(通过 x3::make_context
in x3: :skip_directive
). x3::no_case
和x3::with
也有这个问题,因为它们在实现中都使用了x3::make_context
。
问题:
- 是否总有更好的方法来为这种类型编写解析器? 避免此类编译错误的问题以及如何避免?
- 或者
x3::make_context
实现是否被认为存在此类问题的缺陷?
最佳答案
老实说,我确实认为这是 make_context
工具中的一个限制,是的,它以前曾困扰过我。
您可以通过使用 TU 分离(BOOST_SPIRIT_DECLARE
、BOOST_SPIRIT_DEFINE
和
BOOST_SPIRIT_INSTANTIATE
宏)。
老实说,我会在邮件列表中报告它:[spirit-general]
另见 http://boost.2283326.n4.nabble.com/Horrible-compiletimes-and-memory-usage-while-compiling-a-parser-with-X3-td4689104i20.html (FWIW 我觉得“序列分区”问题无关)
关于c++ - spirit :不能在其规则定义中使用 x3::skip(skipper)[一些递归规则],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45282293/