我想知道如何在boost::spirit::qi
中使用换行符解析python样式列表。
基本解析器将是:
list_ = '[' >> -(test_ % ',') >> -lit(",") >> ']';
以boost::spirit::ascii::space
作为队长。
但是在我的情况下,我想在其他语法规则中明确地匹配换行符。结果,我作为船长切换到boost::spirit::ascii::blank
。虽然我仍然想在列表的定义中允许换行。
我最终得到了类似的东西:
list_ = '[' >> -(test_ % (-eol >> ',' >> -eol)) >> -lit(",") >> -eol >> ']';
基本上我在每个可能的位置添加eol
。这个语法有效,但看起来很糟糕。
有更清洁的方法来实现这一目标吗?或者更具体地说,如果可以包含eol
作为单个规则的队长而不是整个语法。
答案 0 :(得分:2)
只需为相关部分使用单独的队长。
这只是教程的一部分,只是将船长“烘焙”到语法的外部界面。在99%的情况下,根本没有任何意义:改变船长可以破坏语法。所以,我已经按照众神(笑话)的意图封装了船长:
而不是
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>{});
它仍然会使用正确的队长。即使你做了
bool ok = qi::phrase_parse(f, l, MyGrammar<It>{}, qi::char_);
它仍然会使用正确的船长!
你必须决定你的主要船长是什么,但你可以使用qi::skip()[]
指令来切换任意船长。因此,我们假设,与大多数编程语言一样,换行符通常是无关紧要的空格,所以你有
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[]
,或者确实只是从规则的声明中删除了队长:
// implicit lexeme
qi::rule<It> differentRule;
以上所有内容都在这个更广泛的答案中详述:Boost spirit skipper issues