提高精神船长问题
我有助于提高精神船长的麻烦。
我需要parsing一个这样的文件:
ROW int int [int, int] int [int, int] ...
我能parsing它没有问题(感谢stackoverflow;)只有当我在第一个int后面添加一个'_'。
实际上,我认为船长在第一个int之后吃掉了行尾,所以第一个和第二个(在第二行)看起来只有一个int。 我不明白如何保持爱情,但吃空间。 我已经find了使用像这里和这里的自定义分析器的例子。
我试过qi :: blank,用单个规则点亮的自定义分析器('')不pipe我用什么队长,空间和eol总是吃东西。
我的语法是:
一行:
struct rowType { unsigned int number; std::list<unsigned int> list; };
完整的问题存储在一个结构中:
struct problemType { unsigned int ROW; std::vector<rowType> rows; };
行parsing器:
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; };
和问题parsing器:
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是我的问题,解决我的问题的方法是不使用skipper,但是,phrase_parse需要一个,然后我的parsing器需要一个。
自从现在几个小时以来,我被卡住了…我认为这是显而易见的误解。
谢谢你的帮助。
一般来说,下面的指令有助于禁止/切换船长中级语法:
-
qi::lexeme [ p ]
这会抑制船长,例如,如果你想确保你parsing一个没有内部跳过的标识符) -
qi::raw [ p ]
它像往常一样parsing,包括跳过,但返回匹配源序列的原始迭代器范围(包括跳过的位置) -
qi::no_skip [ p ]
禁止跳过前跳过 -
qi::skip(s) [ p ]
(其中一个队长将其replace为另一个队长)(请注意,您需要在这样的skip[]
子句中使用适当声明的qi::rule<>
实例)
其中p
是任何parsing器expression式。
具体解决scheme
你已经知道,你的问题可能是qi::space
吃所有的空白。 我不可能知道你的语法有什么问题(因为你不显示完整的语法或相关的input)。
因此,这是我写的。 注意
- 使用
qi::eol
明确要求特定位置的换行符 - 作为队长使用
qi::blank
(不包括eol
) - 为了简洁起见,我组合了语法
码:
#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\n" "2 [3, 4]\n" "5 [6, 7]\n"; 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\n"; else std::cout << "failed\n"; if (f!=l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; }
如果你真的不想要换行符:
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\n"; else std::cout << "failed\n"; if (f!=l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; }
更新
在回应评论:这是一个片段,显示如何从文件中读取input。 这是testing,并为我工作正常:
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;