为什么没有我的boost :: spirit规则编译用于解析列表列表?

时间:2016-02-10 23:30:43

标签: c++ boost boost-spirit boost-spirit-qi

我正在尝试使用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?

1 个答案:

答案 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;
};

注意:

  • 使用类型化元素而不是“只是”向量
  • 为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>
相关问题