使用Boost Spirit解析文本文件,同时跳过文本文件的大部分 [英] Using Boost Spirit to parse a text file while skipping large parts of it

查看:182
本文介绍了使用Boost Spirit解析文本文件,同时跳过文本文件的大部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 std :: string

<lots of text not including "label A" or "label B">    
label A: 34
<lots of text not including "label A" or "label B">
label B: 45
<lots of text not including "label A" or "label B">
...

我想在所有出现<$ c $后提取单个整数c>标签A 或标签B ,并将它们放在相应的向量< int& a,b 。一个简单但不是优雅的方法是使用 find(label A) find(label B)和解析以先到为准。有没有一种简洁的方式使用精神表达?如何跳过标签A 标签B

I want extract single integral numbers following all occurrences of label A or label B and place them in corresponding vector<int> a, b. A simple, but not elegant way of doing it is using find("label A") and find("label B") and parsing whichever is first. Is there a succinct way of expressing it using Spirit? How do you skip everything but label A or label B?

推荐答案

您只需

omit [ eol >> *char_ - ("\nlabel A:") ] >> eol

示例: Live on Coliru

Example: Live On Coliru

还有 seek [] 指令。以下等价于上述:

There's also the seek[] directive in the repository. The following is equivalent to the above:

 repo::seek [ eol >> &lit("int main") ] 

以下是解析原始示例的示例: p>

Here's a sample that parses your original sample:

*repo::seek [ eol >> "label" >> char_("A-Z") >> ':' >> int_ ],

这将解析为 std :: vector< std :: pair< char,int>

This will parse into std::vector<std::pair<char, int> > without anything else.

在Coliru Too

On Coliru Too:

#if 0
<lots of text not including "label A" or "label B">    
label A: 34
<lots of text not including "label A" or "label B">
label B: 45
<lots of text not including "label A" or "label B">
...
#endif
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>
#include <fstream>

namespace qi   = boost::spirit::qi;
namespace repo = boost::spirit::repository::qi;

int main()
{
    std::ifstream ifs("main.cpp");
    ifs >> std::noskipws;

    boost::spirit::istream_iterator f(ifs), l;

    std::vector<std::pair<char, int> > parsed;
    using namespace qi;
    bool ok = phrase_parse(
            f, l, 
            *repo::seek [ eol >> "label" >> char_("A-Z") >> ':' >> int_ ],
            blank,
            parsed
        );

    if (ok)
    {
        std::cout << "Found:\n";
        for (auto& p : parsed)
            std::cout << "'" << p.first << "' has value " << p.second << "\n";
    }
    else
        std::cout << "Fail at: '" << std::string(f,l) << "'\n";
}

注意:


  • seek 会显示匹配的属性,这是非常强大的:

  • seek does expose the attribute matched, which is pretty powerful:

repo::seek [ eol >> "label" >> char_("ABCD") >> ':' ] 

会吃标签, c>'A''B''C' c $ c>'D')作为属性。

will 'eat' the label, but expose the label letter ('A', 'B', 'C', or 'D') as the attribute.

跳过时的性能可能相当惊人,文档 http: //www.boost.org/doc/libs/1_55_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/seek.html

Performance when skipping can be pretty surprising, read the warning in the documentation http://www.boost.org/doc/libs/1_55_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/seek.html

输出为

Found:
'A' has value 34
'B' has value 45

这篇关于使用Boost Spirit解析文本文件,同时跳过文本文件的大部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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