提高精神船长问题

我有助于提高精神船长的麻烦。

我需要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; 
Interesting Posts