【发布时间】:2013-07-09 21:54:19
【问题描述】:
我已经编写了一些规则来将浮点数解析为两个 std::vector 的浮点数,然后将它们存储在一个结构中:
数据输入:
#
# object name01
#
v -1.5701 33.8087 0.3592
v -24.0119 0.0050 21.7439
# a comment
vn 0.0000 0.5346 0.8451
vn 0.8331 0.5531 -0.0000
# another comment
结构:
struct ObjParseData
{
ObjParseData() : verts(), norms() {}
std::vector<float> verts;
std::vector<float> norms;
};
以及相关的解析代码:
struct objGram : qi::grammar<std::string::const_iterator, ObjParseData(), iso8859::space_type>
{
objGram() : objGram::base_type(start)
{
vertex = 'v' >> qi::double_ >> qi::double_ >> qi::double_;
normal = "vn" >> qi::double_ >> qi::double_ >> qi::double_;
comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];
vertexList = *(vertex | comment);
normalList = *(normal | comment);
start = vertexList >> normalList;
}
qi::rule<std::string::const_iterator, ObjParseData(), iso8859::space_type> start;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertexList;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normalList;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normal;
qi::rule<std::string::const_iterator, iso8859::space_type> comment;
} objGrammar;
ObjParseData resultData;
std::string::const_iterator f = data.cbegin();
bool res = qi::phrase_parse( f, data.cend(), objGrammar, iso8859::space, resultData );
这很有效。它将所有以“v”开头的浮点数解析为结构的顶点向量,并将所有以“vn”开头的浮点数解析为范数。这很好,但我真的不知道为什么会这样。
现在,如果我理解正确的话,如下定义的规则会将其所有结果放入浮点数的 std::vector 中。
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;
因此,查看上面显示的解析代码并知道像 vertex 这样的规则会解析成一个 std::vector 浮点数,显然像 vertexList(如上所示)这样的规则将来自 vertex 的结果连接到一个 std::浮点数向量?所以看到这种行为,你会认为你可以把这两个规则(顶点和顶点列表)写成一个,但不幸的是这不起作用:
vertex = *('v' >> qi::double_ >> qi::double_ >> qi::double_) | comment;
normal = *("vn" >> qi::double_ >> qi::double_ >> qi::double_) | comment;
comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];
start = vertex >> normal;
代码确实编译并且 qi::phrase_parse 确实返回了一个成功的解析,但是结构中的 std::vector 不再填充了。我在这里缺少什么?
【问题讨论】:
-
您声明
vertex生成 std::vector() 但 comment打破了这一点。换句话说,您不能在同一规则中使用生成不同输出的替代解析器。 -
@G.Civardi 评论规则暴露了
qi::unused_type(无属性)所以没有区别:) -
@sehe - 是的,你是对的!出于某种原因,我认为任何替代解析器都会成功——它必须与规则的输出属性兼容——在这种情况下是 std::vector
.
标签: c++ boost-spirit boost-spirit-qi wavefront