本文介绍了提升精神船长问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我在使用提升精神船长时遇到了麻烦.I have trouble with boost spirit skippers.我需要解析这样的文件:I need to parse a file like that :ROW intint [int, int]int [int, int]...我能够毫无问题地解析它(感谢stackoverflow;)只有当我在第一个int之后添加一个'_'时.I am able to parse it without problem (thanks to stackoverflow ;) only if I add an '_' after the first int.事实上,我认为船长在第一个 int 之后吃掉了行尾,所以第一个和第二个(在第二行)看起来只有一个 int.我不明白如何保持 eol 但吃空间.我找到了使用自定义解析器的示例,例如 here 和这里.In fact, I think the skipper eat the end of line after the first int, so the first and second (on second line) look as only one int. I don't understand how to keep eol but eat spaces. I've found examples to use a custom parser like here and here.我尝试了 qi::blank,自定义解析器,带有一个单一规则 lit(' ')不管我用什么船长,space 和 eol 总是吃.I tried qi::blank, custom parser with one single rule lit(' ')No matter what skipper I use, space and eol are always eat.我的语法是:一行:struct rowType{ unsigned int number; std::list<unsigned int> list;};存储在结构中的完整问题:the full problem stored in a structure :struct problemType{ unsigned int ROW; std::vector<rowType> rows;};行解析器:template<typename Iterator>struct row_parser : qi::grammar<Iterator, rowType(), qi::space_type>{ row_parser() : row_parser::base_type(start) { list = '[' >> -(qi::int_ % ',') >> ']'; start = qi::int_ >> list; } qi::rule<Iterator, rowType(), qi::space_type> start; qi::rule<Iterator, std::list<unsigned int>(), qi::space_type> list;};和问题解析器:template<typename Iterator>struct problem_parser : qi::grammar<Iterator,problemType(),qi::space_type>{ problem_parser() : problem_parser::base_type(start) { using boost::phoenix::bind; using qi::lit; start = qi::int_ >> lit('_') >> +(row); //BOOST_SPIRIT_DEBUG_NODE(start); } qi::rule<Iterator, problemType(),qi::space_type> start; row_parser<Iterator> row;};我是这样使用的:main() {static const problem_parser<spirit::multi_pass<base_iterator_type> > p;...spirit::qi::phrase_parse(first, last , p, qi::space, pb);}当然,qi::space 是我的问题,解决我的问题的一种方法是不使用船长,但phrase_parse 需要一个,然后我的解析器需要一个.Of course, the qi::space is my problem, and a way to solve my problem would be to don't use a skipper, but phrase_parse requires one, and then my parser requires one.我已经卡住了几个小时了...我认为这很明显是我误解了.I'm stuck since some hours now...I think it's something obvious I have misunderstood.感谢您的帮助.推荐答案总的来说,以下指令有助于在语法中阻止/切换跳过:In general the following directives are helpful for inhibiting/switching skippers mid-grammar:qi::lexeme [ p ] 禁止船长,例如如果您想确保在没有内部跳过的情况下解析标识符) - 另请参阅 no_skip 以进行比较qi::raw [ p ] 像往常一样解析,包括跳过,但返回匹配源序列的原始迭代器范围(包括跳过的位置))qi::raw [ p ]which parses like always, including skips, but returns the raw iterator range of the matched source sequence (including the skipped positions)qi::no_skip [ p ]在没有预跳过的情况下禁止跳过(我已经创建了一个最小的例子来演示这里的区别:Boost Spirit lexeme vs no_skip)qi::skip(s) [ p ] 用另一个船长 s 完全替换船长(注意你需要在这样的 skip[] 子句中使用适当声明的 qi::rule 实例)qi::skip(s) [ p ]which replaces the skipper by another skipper s altogether (note that you need to use appropriately declared qi::rule<> instances inside such a skip[] clause)其中 p 是任何解析器表达式.where p is any parser expression.正如您已经知道的那样,您的问题可能是 qi::space 吃掉了所有 空格.我不可能知道你的语法有什么问题(因为你既没有显示完整的语法,也没有显示相关的输入).Your problem, as you already know, might be that qi::space eats all whitespace. I can't possibly know what is wrong in your grammar (since you don't show either the full grammar, or relevant input).因此,这就是我要写的.注意Therefore, here's what I'd write. Note使用qi::eol明确要求在特定位置换行使用qi::blank作为船长(不包括eol)为简洁起见,我合并了语法the use of qi::eol to explicitely require linebreaks at specific locationsthe use of qi::blank as a skipper (not including eol)for brevity I combined the grammars代码:#define BOOST_SPIRIT_DEBUG#include <boost/fusion/adapted.hpp>#include <boost/spirit/include/qi.hpp>#include <boost/spirit/include/phoenix.hpp>namespace qi = boost::spirit::qi;namespace phx = boost::phoenix;struct rowType { unsigned int number; std::list<unsigned int> list;};struct problemType { unsigned int ROW; std::vector<rowType> rows;};BOOST_FUSION_ADAPT_STRUCT(rowType, (unsigned int, number)(std::list<unsigned int>, list))BOOST_FUSION_ADAPT_STRUCT(problemType, (unsigned int, ROW)(std::vector<rowType>, rows))template<typename Iterator>struct problem_parser : qi::grammar<Iterator,problemType(),qi::blank_type>{ problem_parser() : problem_parser::base_type(problem) { using namespace qi; list = '[' >> -(int_ % ',') >> ']'; row = int_ >> list >> eol; problem = "ROW" >> int_ >> eol >> +row; BOOST_SPIRIT_DEBUG_NODES((problem)(row)(list)); } qi::rule<Iterator, problemType() , qi::blank_type> problem; qi::rule<Iterator, rowType() , qi::blank_type> row; qi::rule<Iterator, std::list<unsigned int>(), qi::blank_type> list;};int main(){ const std::string input = "ROW 1" "2 [3, 4]" "5 [6, 7]"; auto f = begin(input), l = end(input); problem_parser<std::string::const_iterator> p; problemType data; bool ok = qi::phrase_parse(f, l, p, qi::blank, data); if (ok) std::cout << "success"; else std::cout << "failed"; if (f!=l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'";}如果你真的不想要求换行:If you really didn't want to require line breaks:template<typename Iterator>struct problem_parser : qi::grammar<Iterator,problemType(),qi::space_type>{ problem_parser() : problem_parser::base_type(problem) { using namespace qi; list = '[' >> -(int_ % ',') >> ']'; row = int_ >> list; problem = "ROW" >> int_ >> +row; BOOST_SPIRIT_DEBUG_NODES((problem)(row)(list)); } qi::rule<Iterator, problemType() , qi::space_type> problem; qi::rule<Iterator, rowType() , qi::space_type> row; qi::rule<Iterator, std::list<unsigned int>(), qi::space_type> list;};int main(){ const std::string input = "ROW 1 " // NOTE whitespace, obviously required! "2 [3, 4]" "5 [6, 7]"; auto f = begin(input), l = end(input); problem_parser<std::string::const_iterator> p; problemType data; bool ok = qi::phrase_parse(f, l, p, qi::space, data); if (ok) std::cout << "success"; else std::cout << "failed"; if (f!=l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'";}更新回应评论:这里是一个片段,展示了如何从文件中读取输入.这已经过测试,对我来说效果很好:UpdateIn response to the comment: here is a snippet that shows how to read the input from a file. This was tested and works fine for me:std::ifstream ifs("input.txt"/*, std::ios::binary*/);ifs.unsetf(std::ios::skipws);boost::spirit::istream_iterator f(ifs), l;problem_parser<boost::spirit::istream_iterator> p; 这篇关于提升精神船长问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-21 12:45