我正在尝试使用boost :: spirit为Open Inventor .iv文件编写解析器。
我有以下VertexProperty节点的结构:
struct VertexProperty
{
std::vector<std::vector<float> > vertices;
std::vector<std::vector<float> > normals;
std::vector<std::vector<float> > texCoords;
};
BOOST_FUSION_ADAPT_STRUCT(
VertexProperty,
(std::vector<std::vector<float> >, vertices)
(std::vector<std::vector<float> >, normals)
(std::vector<std::vector<float> >, texCoords)
)
以下解析它的规则(没有编译):
qi::rule<Iterator, VertexProperty(), Skipper> RULE_VertexProperty;
RULE_VertexProperty = lit("VertexProperty")
>> char_('{')
>> lit("vertex") >> char_('[')
>> repeat(3)[qi::float_] >> *(char_(',') >> repeat(3)[qi::float_])
>> char_(']')
>> lit("normal") >> char_('[')
>> repeat(3)[qi::float_] >> *(char_(',') >> repeat(3)[qi::float_])
>> char_(']')
>> lit("texCoord") >> char_('[')
>> repeat(2)[qi::float] >> *(char_(',') >> repeat(2)[qi::float_])
>> char_(']') >> char_('}');
根据此规则,以下内容应导致有效的VertexProperty解析:
VertexProperty {
vertex [ 0.0 0.0 1.0,
1.0 1.0 1.0,
1.0 0.0 1.0]
normal [1.0 0.0 0.0,
0.0 1.0 0.0,
0.0 0.0 1.0]
texCoord [0.0 0.0,
1.0 0.0,
1.0 1.0]
}
我的假设是问题来自于我如何尝试将逗号分隔的元组解析为向量的向量。
解析表单的3元组和/或2元组列表的正确方法是什么:
[float float float, float float float, float float float]
使用boost :: spirit?
答案 0 :(得分:3)
编辑我误解了这个问题。这是重写:
<强> Live On Coliru 强>
Live On Coliru (带调试输出)
struct V2 { float a, b; } ;
struct V3 { float a, b, c; } ;
struct VertexProperty {
std::vector<V3> vertices, normals;
std::vector<V2> texCoords;
};
BOOST_FUSION_ADAPT_STRUCT(V2, a,b)
BOOST_FUSION_ADAPT_STRUCT(V3, a,b,c)
BOOST_FUSION_ADAPT_STRUCT(VertexProperty, vertices,normals,texCoords)
template <typename Iterator>
struct Parser : qi::grammar<Iterator, VertexProperty()> {
Parser() : Parser::base_type(start) {
v2 = qi::double_ >> qi::double_;
v3 = qi::double_ >> qi::double_ >> qi::double_;
vertexproperty = qi::lit("VertexProperty")
>> '{'
>> "vertex" >> '[' >> (v3 % ',') >> ']'
>> "normal" >> '[' >> (v3 % ',') >> ']'
>> "texCoord" >> '[' >> (v2 % ',') >> ']'
>> '}';
start = qi::skip(qi::space) [vertexproperty];
BOOST_SPIRIT_DEBUG_NODES((v2)(v3)(vertexproperty))
}
private:
qi::rule<Iterator, VertexProperty()> start;
qi::rule<Iterator, VertexProperty(), qi::space_type> vertexproperty;
qi::rule<Iterator, V2(), qi::space_type> v2;
qi::rule<Iterator, V3(), qi::space_type> v3;
};
注意:
qi::lit
)代替qi::char_
,因为您不希望公开匹配的内部功能a % b
已匹配a [b a]...
)//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;
struct V2 { float a, b; } ;
struct V3 { float a, b, c; } ;
struct VertexProperty {
std::vector<V3> vertices, normals;
std::vector<V2> texCoords;
};
BOOST_FUSION_ADAPT_STRUCT(V2, a,b)
BOOST_FUSION_ADAPT_STRUCT(V3, a,b,c)
BOOST_FUSION_ADAPT_STRUCT(VertexProperty, vertices,normals,texCoords)
template <typename Iterator>
struct Parser : qi::grammar<Iterator, VertexProperty()> {
Parser() : Parser::base_type(start) {
v2 = qi::double_ >> qi::double_;
v3 = qi::double_ >> qi::double_ >> qi::double_;
vertexproperty = qi::lit("VertexProperty")
>> '{'
>> "vertex" >> '[' >> (v3 % ',') >> ']'
>> "normal" >> '[' >> (v3 % ',') >> ']'
>> "texCoord" >> '[' >> (v2 % ',') >> ']'
>> '}';
start = qi::skip(qi::space) [vertexproperty];
BOOST_SPIRIT_DEBUG_NODES((v2)(v3)(vertexproperty))
}
private:
qi::rule<Iterator, VertexProperty()> start;
qi::rule<Iterator, VertexProperty(), qi::space_type> vertexproperty;
qi::rule<Iterator, V2(), qi::space_type> v2;
qi::rule<Iterator, V3(), qi::space_type> v3;
};
int main() {
using Iterator = std::string::const_iterator;
std::string const sample = "VertexProperty {\n"
" vertex [ 0.0 0.0 1.0,\n"
" 1.0 1.0 1.0,\n"
" 1.0 0.0 1.0]\n"
" normal [1.0 0.0 0.0,\n"
" 0.0 1.0 0.0,\n"
" 0.0 0.0 1.0]\n"
" texCoord [0.0 0.0,\n"
" 1.0 0.0,\n"
" 1.0 1.0]\n"
"}";
auto f = sample.begin(), l = sample.end();
VertexProperty data;
bool ok = qi::parse(f, l, Parser<Iterator>(), data);
if (ok) {
std::cout << "Parsed: " << data.vertices.size() << ", " << data.normals.size() << ", " << data.texCoords.size() << "\n";
} else {
std::cout << "Parse failed\n";
}
if (f!=l)
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
打印
Parsed: 3, 3, 3
使用调试信息
<vertexproperty>
<try>VertexProperty {\n ve</try>
<v3>
<try> 0.0 0.0 1.0,\n 1</try>
<success>,\n 1.0 1.0 1.0,\n</success>
<attributes>[[0, 0, 1]]</attributes>
</v3>
<v3>
<try>\n 1.0 1.0 1.0,\n </try>
<success>,\n 1.0 0.0 1.0]\n</success>
<attributes>[[1, 1, 1]]</attributes>
</v3>
<v3>
<try>\n 1.0 0.0 1.0]\n </try>
<success>]\n normal [1.0 0.0 0</success>
<attributes>[[1, 0, 1]]</attributes>
</v3>
<v3>
<try>1.0 0.0 0.0,\n 0.</try>
<success>,\n 0.0 1.0 0.0,\n</success>
<attributes>[[1, 0, 0]]</attributes>
</v3>
<v3>
<try>\n 0.0 1.0 0.0,\n </try>
<success>,\n 0.0 0.0 1.0]\n</success>
<attributes>[[0, 1, 0]]</attributes>
</v3>
<v3>
<try>\n 0.0 0.0 1.0]\n </try>
<success>]\n texCoord [0.0 0.0</success>
<attributes>[[0, 0, 1]]</attributes>
</v3>
<v2>
<try>0.0 0.0,\n 1.0 0.</try>
<success>,\n 1.0 0.0,\n </success>
<attributes>[[0, 0]]</attributes>
</v2>
<v2>
<try>\n 1.0 0.0,\n </try>
<success>,\n 1.0 1.0]\n}</success>
<attributes>[[1, 0]]</attributes>
</v2>
<v2>
<try>\n 1.0 1.0]\n}</try>
<success>]\n}</success>
<attributes>[[1, 1]]</attributes>
</v2>
<success></success>
<attributes>[[[[0, 0, 1], [1, 1, 1], [1, 0, 1]], [[1, 0, 0], [0, 1, 0], [0, 0, 1]], [[0, 0], [1, 0], [1, 1]]]]</attributes>
</vertexproperty>