2013-07-08 58 views
2

我是Spirit :: Qi的新手,我正在尝试编写一个简单的Wavefront Obj解析器。我遵循了Boost :: Spirit文档站点(link)的教程,并且我掌握了大部分内联规则。我已经开始尝试使用语法,但我似乎无法让它们工作。一段时间后,我确实让它编译,但解析失败。我真的不知道我做错了什么。语法解析与精神::齐失败

展开,取出简单,我已经创建了一个包含以下内容的简单的文本文件:

v -1.5701 33.8087 0.3592 
v -24.0119 0.0050 21.7439 
v 20.8717 0.0050 21.7439 
v 20.8717 0.0050 -21.0255 
v -24.0119 0.0050 -21.0255 
v -1.5701 0.0050 0.3592 

只是可以肯定:读取输入文件时工作正常。

我写了一个小功能应该解析输入字符串,但由于某种原因失败:

bool Model::parseObj(std::string &data, std::vector<float> &v) 
{ 
    struct objGram : qi::grammar<std::string::const_iterator, float()> 
    { 
     objGram() : objGram::base_type(vertex) 
     { 
      vertex = 'v' >> qi::float_ 
         >> qi::float_ 
         >> qi::float_; 
     } 

     qi::rule<std::string::const_iterator, float()> vertex; 
    }; 

    objGram grammar; 

    return qi::phrase_parse(data.cbegin(), data.cend(), 
           grammar, iso8859::space, v); 
} 

齐:: phrase_parse保持返回false和性病::向量v仍然是空的结束...

有什么建议吗?

编辑:

加入添加空间船长(?是,正确的名称),仅第一“V”被添加到标准::编码为浮动(118.0f)载体,但实际的后数字不会被添加。我的猜测是我的规则不正确。我只想添加数字并跳过v。

这里是我的修改功能:

bool Model::parseObj(std::string &data, std::vector<float> &v) 
{ 
    struct objGram : qi::grammar<std::string::const_iterator, float(), iso8859::space_type> 
    { 
     objGram() : objGram::base_type(vertex) 
     { 
      vertex = qi::char_('v') >> qi::float_ 
         >> qi::float_ 
         >> qi::float_; 
     } 

     qi::rule<std::string::const_iterator, float(), iso8859::space_type> vertex; 
    } objGrammar; 

    return qi::phrase_parse(data.cbegin(), data.cend(), 
           objGrammar, iso8859::space, v); 
} 
+1

1)如果提供完整的代码,你有更多的关注 2)让看一眼的机会...... 118是ASCII码为你的“V”所以它传播到错误输出。如果你想避免它,你有两种选择(可能更多): a)qi :: lit('v')>> qi :: float_ >> qi :: float_ >> qi :: float_ b)qi: :省略[qi :: char _('v')] >> qi :: float_ >> qi :: float_ >> qi :: float_ –

+0

@ G.Civardi Ah。你在同一时间发现了这个问题。你错过了罪魁祸首,但我链接到你的答案浮法精度问题:)干杯 – sehe

+0

@sehe没有问题,非常感谢:-)干杯 –

回答

2

你的统治宣告错误的暴露属性。更改:

qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex; 

然而,因为你不模板在任何你的语法结构(如迭代器/船长型),它是没有意义有一个语法结构。相反,让phrase_parse简单地推导出迭代器,船长和规则类型一下子写:

bool parseObj(std::string const& data, std::vector<float> &v) 
{ 
    return qi::phrase_parse( 
      data.cbegin(), data.cend(), 
      'v' >> qi::float_ >> qi::float_ >> qi::float_, 
      qi::space, v); 
} 

我想你会同意这是更重要的一点。作为奖励,它“just works”(TM),因为自动属性传播规则的真棒。

然而,看到你的语法,你一定会希望看到这些:

+0

很好的答案!非常感谢你。所以你一开始说的是,如果我使用模板,我应该只使用语法结构?另一个问题:如何以您描述的方式使用phrase_parse时如何实现多个规则?因为最终我还想分析以“vn”和“vt”开头的浮动块,它们都在同一个* .obj文件中。我是否为每个单独的规则运行phrase_parse函数? Thx :) – Krienie

+0

@KrienLinnenbank我在说,语法结构不是拉重量。有更多的理由来建立语法结构,但是不管怎样,你都不会在本地定义它。 – sehe

+1

关于第二个问题:无论如何我会分割出一个语法结构,并且解析你的语法,因为它是_(这就是你使用解析器生成器的原因!)。即我不会**通过单独的规则运行单独的行。如果你卡住了,也许你应该让它成为一个问题。 (现在,一定要访问第一个关于想法的其他答案) – sehe