我想知道如何在 boost::spirit::qi
中用换行符解析 python 样式列表。
一个基本的解析器将是:
list_ = '[' >> -(test_ % ',') >> -lit(",") >> ']';
以 boost::spirit::ascii::space
作为 skipper 。
但是在我的例子中,我想自己在其他语法规则中明确匹配换行符。结果,我切换到 boost::spirit::ascii::blank
作为 skipper 。虽然我仍然想在列表的定义中允许换行。
我最终得出这样的结论:
list_ = '[' >> -(test_ % (-eol >> ',' >> -eol)) >> -lit(",") >> -eol >> ']';
基本上我在每个可能的位置添加了eol
。这种语法有效,但看起来很糟糕。
有没有更简洁的方法来实现这一点?或者更具体地说,如果可以包含 eol
作为单个规则而不是整个语法的 skipper 。
最佳答案
只需为相关部分使用单独的 skipper 。
只是将 skipper “烘焙”到语法的外部接口(interface)中,这有点像教程中的固定装置。在 99% 的情况下,这根本没有意义:更改 skipper 会破坏语法。所以,我已经开始按照众神的意图封装 skipper (开玩笑):
代替
template <typename It>
struct MyGrammar : qi::grammar<It, Attribute(), qi::space_type> {
MyGrammar() : MyGrammar::base_type(start) {
start = /*....*/;
}
private:
qi::rule<It, Attribute(), qi::space_type> start;
};
我写
template <typename It>
struct MyGrammar : qi::grammar<It, Attribute()> {
MyGrammar() : MyGrammar::base_type(start) {
start = qi::skip(qi::space) [ mainRule ];
mainRule = /*....*/;
}
private:
qi::rule<It, Attribute()> start;
qi::rule<It, Attribute(), qi::space_type> mainRule;
};
这意味着你可以写
bool ok = qi::parse(f,l, MyGrammar<It>{});
它仍然会使用正确的 skipper 。即使你做了
bool ok = qi::phrase_parse(f, l, MyGrammar<It>{}, qi::char_);
它仍然会使用正确的 skipper !
不同规则的不同 skipper
您必须决定您的主要 skipper 是什么,但是您可以使用 qi::skip()[]
指令来切换任意 skipper 。所以让我们假设,就像在大多数编程语言中一样,换行符通常是无意义的空格,所以你会有
qi::rule<It, qi::space_type> a_whole, bunch_of, rules;
然后在您的 bunch_of
规则中您要使用 differentRule
,它确实有明显的空白:
qi::rule<It, qi::blank_type> differentRule;
然后你像这样切换它:
bunch_of = "stuff" >> '{' >> qi::skip(qi::blank) [ differentRule ] >> '}';
就是这样。当然,如果你不想在 differentRule
中完全跳过,你可以像往常一样使用 qi::lexeme[]
,或者实际上只是从规则声明中删除了 skipper :
// implicit lexeme
qi::rule<It> differentRule;
背景
以上所有内容都在这个更广泛的答案中进行了详细说明:Boost spirit skipper issues
关于c++ - 我如何在 boost::spirit::qi 中解析带有换行符的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47046805/