如何在不跳过行尾的情况下使用跳过器ascii :: space?

9

我需要使用boost::spirit进行解析,我想使用phrase_parse函数:

qi::phrase_parse(str.begin(), str.end(), grammar, ascii::space - qi::eol); 

但是第四个术语(ascii::space - qi::eol)在我的编译器中不被允许。 如何使用跳过器ascii::space而不跳过eol?


1
编译器对 ascii::space - qi::eol 有什么问题?这会对可能的解决方案产生很大影响。 - Mahmoud Al-Qudsi
可能是 https://dev59.com/j0zSa4cB1Zd3GeqPnYQt 的重复问题。 - TemplateRex
1
@rhalbersma:但似乎没有给出可编译的解决方案。 - Frank
1
在“可能重复”的解决方案中,skipper 是 ascii::space - eol,但是“- eol”不被允许,这就是我的问题,我想跳过 ascii::space 但不跳过 qi::eol。 - Henri Sylvain
1个回答

15

最简单的答案是

qi::phrase_parse(str.begin(), str.end(), grammar, ascii::blank); 

当然,这也取决于你的语法:如果它需要特定的跳过类别,你可能需要更改它。请参见下面的通用处理方式(虽然您可以为仅接受qi::blank的语法指定qi::blank_type)。
示例还处理任意跳过器。
其他提示:
Spirit有几个指令影响跳过器的使用。
  • qi::lexeme

    将解析子表达式,而不考虑跳过器(在语法中使用字符串字面量时非常有用)

  • qi::raw

    将返回原始源迭代器范围,意味着跳过的输入将包含在结果中

  • qi::no_skip, qi::skip

    可用于显式更改用于子表达式的跳过器类型

推荐阅读

Boost Spirit网站有一篇关于这类问题的好文章

通用样例

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper>
    struct parser : qi::grammar<It, Skipper>
{
    parser() : parser::base_type(start)
    {
        start = *qi::int_;
    }

  private:
    qi::rule<It, Skipper> start;
};

template <typename C, typename Skipper>
    void doParse(const C& input, const Skipper& skipper)
{
    auto f(std::begin(input)), l(std::end(input));

    parser<decltype(f), Skipper> p;
    bool ok = qi::phrase_parse(f,l,p,skipper);

    if (ok)   
        std::cout << "parse success\n";
}

int main()
{
    const std::string input = "1 2 3 4";
    doParse(input, qi::blank);
    doParse(input, qi::space);
    doParse(input, ~qi::char_("0-9"));
}

+1 正是我需要的,可以将一堆只能处理单行的小解析器粘合在一起。 - kfmfe04
如果规则采用输出类型(如std::string()),Skipper会去哪里? - Kerrek SB
括号非常重要 **"(尽管您可以为只接受qi::blank_type的语法指定qi::blank_type)"**。虽然有些不对劲,因为现在我必须将所有语法更改为qi::blank_type,即使子标记不需要知道关于eol的信息。我想这是因为我还没有像一个灵魂一样思考。 - alfC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接