提振精神的复归解析 [英] Boost spirit revert parsing
问题描述
欲解析包含以下结构的文件:
I want to parse a file containing the following structure:
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;
所以,我需要跳过任何垃圾,直到规则满足部分。
有什么办法做到这一点?我曾尝试寻求[段]
,但它似乎没有工作。
So I need to skip any garbage until the sections
rule is met.
Is there any way to accomplish this? I have tried seek[sections]
, but it seems not to work.
修改:
我为什么本地化寻求的原因无法正常工作:如果我使用如下操作符(>>
),那么它的工作原理。如果使用期望解析器(>
),那么它抛出一个异常。下面是一个示例code:
EDIT:
I localized the reason why seek is not working: if I use follows operator(>>
), then it works. If expectation parser is used (>
), then it throws an exception. Here is a sample code:
#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";
}
因此,在实际的例子我的整个语法构造与预期的运营商。我一定要改变一切,使求的工作,或有任何其他方式(比方说,寻求一种简单的{,并恢复1 section_name_rule回)??
So in the real example my entire grammar is constructed with expectation operators. Do I have to change everything to make the "seek" work, or is there any other way (let's say, seek a simple "{", and revert one section_name_rule back)??
推荐答案
下面是一个示范,用哈姆雷特的灵感:的住在Coliru
Here's a demonstration, using Hamlet for inspiration: 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";
}
这篇关于提振精神的复归解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!