加强精神船长问题
Boost spirit skipper issues
我有问题,促进精神船长。
我需要像这样解析一个文件:
ROW int
int [int, int]
int [int, int]
...
我能够毫无问题地解析它(感谢stackoverflow;),只有当我在第一个int后添加一个'_'。
实际上,我认为skipper位于第一个int之后的行尾,因此第一个和第二个(在第二行)看起来只是一个int。我不明白如何保持活力,但要吃空间。我找到了使用自定义解析器的示例,如这里和这里。
我尝试了qi::blank,自定义解析器与一个单一规则lit(' ')不管我用什么船长,空间和油总是被吃掉的。
我的语法是:
一行:
struct rowType
{
unsigned int number;
std::list<unsigned int> list;
};
存储在结构体中的完整问题:
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::空间是我的问题,解决这个问题的一种方法是不使用skipper,但是phrase_parse需要一个,然后我的解析器也需要一个。
我已经被困了好几个小时了…我想我误解了一些很明显的东西。谢谢你的帮助。
一般来说,以下指令有助于在语法中间抑制/切换跳码:
-
qi::lexeme [ p ]
禁止跳过,例如,如果你想确保你解析一个标识符没有内部跳过)-参见no_skip
进行比较 -
qi::raw [ p ]
像往常一样解析,包括跳过,但返回匹配源序列的原始迭代器范围(包括跳过的位置) -
qi::no_skip [ p ]
没有预跳过的抑制跳过(我在这里创建了一个最小的示例来演示差异:Boost Spirit lexeme与no_skip) -
qi::skip(s) [ p ]
用另一个船长s
代替船长(注意你需要在这样的skip[]
子句中使用适当声明的qi::rule<>
实例)
其中p
为任意解析器表达式。
qi::space
吃掉了所有的空格。我不可能知道你的语法有什么问题(因为你既没有显示完整的语法,也没有显示相关的输入)。
因此,这就是我要写的。请注意
- 使用
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 1n"
"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 << "successn";
else std::cout << "failedn";
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 << "successn";
else std::cout << "failedn";
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'n";
}
更新作为对注释的回应:下面是一个显示如何从文件中读取输入的代码片段。这是经过测试的,对我来说很好:
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;
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- C++格式化输出问题
- 加强精神船长问题