如何解析条目后面跟分号或换行符(boost :: spirit)? [英] How to parse entries followed by semicolon or newline (boost::spirit)?

查看:167
本文介绍了如何解析条目后面跟分号或换行符(boost :: spirit)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Boost :: Spirit中,如何解析后面跟有分号或带有可选分号的换行符的条目?

In Boost::Spirit, how can I parse entries that are followed by either a semicolon or by a newline with optional semicolon?

输入示例,其中每个条目都是int和double:

Example input, where each entry is an int and a double:

12 1.4;
63 13.2
2423 56.4 ; 5 8.1

这里是只解析空格的条目的示例代码:

Here is example code that just parses entries followed by whitespace:

#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;

typedef std::pair<int, double> Entry;

template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper> {
  MyGrammar() : MyGrammar::base_type(entries) {
    entry = qi::int_ >> qi::double_;
    entries = +entry;
  }
  qi::rule<Iterator, Entry(), Skipper> entry;
  qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
};

int main() {
  typedef boost::spirit::istream_iterator It;
  std::cin.unsetf(std::ios::skipws);
  It it(std::cin), end;

  MyGrammar<It, qi::space_type> entry_grammar;
  std::vector<Entry> entries;
  if (qi::phrase_parse(it, end, entry_grammar, qi::space, entries)
      && it == end) {
    BOOST_FOREACH(Entry const& entry, entries) {
      std::cout << entry.first << " and " << entry.second << std::endl;
    }
  }
  else {
    std::cerr << "FAIL" << std::endl;
    exit(1);
  }
  return 0;
}

现在,解析我想要的方式(每个条目后跟分号或换行符用可选的分号),我替换了:

Now, to parse the way I want (each entry followed by semicolon or newline with optional semicolon), I replaced this:

    entries = +entry;

 entries = +(entry >> (qi::no_skip[qi::eol] || ';'));

其中 boost :: spirit code> || 表示:(a后跟可选b)或b。但如果在此示例输入中 1.4 后面有空格,则会出错:

where the boost::spirit operator || means: (a followed by optional b) or b. But gives an error if there is a space after the 1.4 in this example input:

12 1.4
63 13.2

因为 no_skip 但我找不到解决方案。

It makes sense that the space is not matched because of the no_skip but I wasn't able to find a solution.

推荐答案

这是我的采访。


  • 您可能想要了解 qi :: blank c $ c> qi :: space except qi :: eol )。这将删除 no_skip 的需要。

  • 核心语法变为:

  • You might want to know about qi::blank (which is qi::space except qi::eol). This will remove the need for no_skip.
  • The core grammar becomes:

    entry = qi::int_ >> qi::double_;
    entries = entry % +qi::char_("\n;") >> qi::omit[*qi::space];


  • 使用BOOST_SPIRIT_DEBUG了解解析失败的原因和原因(例如回溯)

    输出:

    12 and 1.4
    63 and 13.2
    2423 and 56.4
    5 and 8.1
    

    完整代码:

    //#define BOOST_SPIRIT_DEBUG
    #include <iostream>
    #include <boost/foreach.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/support_istream_iterator.hpp>
    #include <boost/fusion/include/std_pair.hpp>
    namespace qi = boost::spirit::qi;
    
    typedef std::pair<int, double> Entry;
    
    template <typename Iterator, typename Skipper>
    struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper> {
        MyGrammar() : MyGrammar::base_type(entries) {
            entry = qi::int_ >> qi::double_;
            entries = 
                entry % +qi::char_("\n;")          // the data
                >> qi::omit[*qi::space] > qi::eoi; // trailing whitespace
            BOOST_SPIRIT_DEBUG_NODE(entry);
            BOOST_SPIRIT_DEBUG_NODE(entries);
        }
        qi::rule<Iterator, Entry(), Skipper> entry;
        qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
    };
    
    int main() {
        typedef boost::spirit::istream_iterator It;
        std::cin.unsetf(std::ios::skipws);
        It it(std::cin), end;
    
        MyGrammar<It, qi::blank_type> entry_grammar;
        std::vector<Entry> entries;
        if (qi::phrase_parse(it, end, entry_grammar, qi::blank, entries)
                && it == end) {
            BOOST_FOREACH(Entry const& entry, entries) {
                std::cout << entry.first << " and " << entry.second << std::endl;
            }
        }
        else {
            std::cerr << "FAIL" << std::endl;
            exit(1);
        }
        return 0;
    }
    

    这篇关于如何解析条目后面跟分号或换行符(boost :: spirit)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆