如何在boost :: spirit :: qi中用换行符解析列表?

时间:2017-11-01 01:11:05

标签: c++ parsing boost

我想知道如何在boost::spirit::qi中使用换行符解析python样式列表。

基本解析器将是:

list_ = '[' >> -(test_ % ',') >> -lit(",") >> ']';

boost::spirit::ascii::space作为队长。

但是在我的情况下,我想在其他语法规则中明确地匹配换行符。结果,我作为船长切换到boost::spirit::ascii::blank。虽然我仍然想在列表的定义中允许换行。

我最终得到了类似的东西:

list_ = '[' >> -(test_ % (-eol >> ',' >> -eol)) >> -lit(",") >> -eol >> ']';

基本上我在每个可能的位置添加eol。这个语法有效,但看起来很糟糕。

有更清洁的方法来实现这一目标吗?或者更具体地说,如果可以包含eol作为单个规则的队长而不是整个语法。

1 个答案:

答案 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