ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 提升精神还原解析

2019-09-30 00:07:17  阅读:220  来源: 互联网

标签:boost-spirit-qi c boost boost-spirit boost-phoenix


我想解析包含以下结构的文件:

some
garbage *&%
section1 {
    section_content
}
section2 {
    section_content
}

规则解析section_name1 {…} section_name2 {…}已经定义:

section_name_rule = lexeme[+char_("A-Za-z0-9_")];
section = section_name_rule > lit("{") > /*some complicated things*/... > lit("}");
sections %= +section;

所以我需要跳过任何垃圾,直到满足部分规则.
有没有办法实现这个目标?我试过寻找[部分],但似乎没有用.

编辑:
我找到了搜索不起作用的原因:如果我使用跟随运算符(>>),那么它可以工作.如果使用期望解析器(>),则会抛出异常.这是一个示例代码:

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
using boost::phoenix::push_back;

struct section_t {
    std::string name, contents;
    friend std::ostream& operator<<(std::ostream& os, section_t const& s) { return os << "section_t[" << s.name << "] {" << s.contents << "}"; }
};

BOOST_FUSION_ADAPT_STRUCT(section_t, (std::string, name)(std::string, contents))

    typedef std::vector<section_t> sections_t;

    template <typename It, typename Skipper = qi::space_type>
    struct grammar : qi::grammar<It, sections_t(), Skipper>
{
    grammar() : grammar::base_type(start) {
        using namespace qi;
        using boost::spirit::repository::qi::seek;
        section_name_rule = lexeme[+char_("A-Za-z0-9_")];
        //Replacing '>>'s with '>'s throws an exception, while this works as expected!!
        section = section_name_rule
            >>
            lit("{") >> lexeme[*~char_('}')] >> lit("}");
        start = seek [ hold[section[push_back(qi::_val, qi::_1)]] ]
            >> *(section[push_back(qi::_val, qi::_1)]);
    }
    private:
    qi::rule<It, sections_t(),  Skipper> start;
    qi::rule<It, section_t(),   Skipper> section;
    qi::rule<It, std::string(), Skipper> section_name_rule;
};

int main() {
    typedef std::string::const_iterator iter;
    std::string storage("sdfsdf\n sd:fgdfg section1 {dummy } section2 {dummy  } section3 {dummy  }");
    iter f(storage.begin()), l(storage.end());
    sections_t sections;
    if (qi::phrase_parse(f, l, grammar<iter>(), qi::space, sections))
    {
        for(auto& s : sections)
            std::cout << "Parsed: " << s << "\n";
    }
    if (f != l)
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

所以在真实的例子中,我的整个语法是用期望运算符构造的.我是否必须更改所有内容以使“搜索”工作,或者是否有任何其他方式(让我们说,寻找一个简单的“{”,然后还原一个section_name_rule)?

解决方法:

这是一个演示,使用哈姆雷特的灵感:Live On Coliru

start = *seek [ no_skip[eol] >> hold [section] ];

笔记:

>降低期望点
>通过要求在部分名称之前开始行来进行优化

输入示例:

some
garbage *&%
section1 {
   Claudius: ...But now, my cousin Hamlet, and my son —
   Hamlet: A little more than kin, and less than kind.
}
WE CAN DO MOAR GARBAGE
section2 {
   Claudius: How is it that the clouds still hang on you?
   Hamlet: Not so my lord; I am too much i' the sun 
}

输出:

Parsed: section_t[section1] {Claudius: ...But now, my cousin Hamlet, and my son —
   Hamlet: A little more than kin, and less than kind.
}
Parsed: section_t[section2] {Claudius: How is it that the clouds still hang on you?
   Hamlet: Not so my lord; I am too much i' the sun 
}

参考清单

// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>

namespace qi = boost::spirit::qi;

struct section_t { 
    std::string name, contents;
    friend std::ostream& operator<<(std::ostream& os, section_t const& s) { return os << "section_t[" << s.name << "] {" << s.contents << "}"; }
};

BOOST_FUSION_ADAPT_STRUCT(section_t, (std::string, name)(std::string, contents))

typedef std::vector<section_t> sections_t;

template <typename It, typename Skipper = qi::space_type>
struct grammar : qi::grammar<It, sections_t(), Skipper>
{
    grammar() : grammar::base_type(start) {
        using namespace qi;
        using boost::spirit::repository::qi::seek;

        section_name_rule = lexeme[+char_("A-Za-z0-9_")];
        section           = section_name_rule >> '{' >> lexeme[*~char_('}')] >> '}';
        start             = *seek [ no_skip[eol] >> hold [section] ];

        BOOST_SPIRIT_DEBUG_NODES((start)(section)(section_name_rule))
    }
  private:
    qi::rule<It, sections_t(),  Skipper> start;
    qi::rule<It, section_t(),   Skipper> section;
    qi::rule<It, std::string(), Skipper> section_name_rule;
};

int main() {
    using It = boost::spirit::istream_iterator;
    It f(std::cin >> std::noskipws), l;

    sections_t sections;
    if (qi::phrase_parse(f, l, grammar<It>(), qi::space, sections))
    {
        for(auto& s : sections)
            std::cout << "Parsed: " << s << "\n";
    }
    if (f != l)
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

标签:boost-spirit-qi,c,boost,boost-spirit,boost-phoenix
来源: https://codeday.me/bug/20190929/1833803.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有