2012-03-15 60 views
8

我已成功使用boost::spirit::qi解析由内置解析器组成的流(例如byte_,little_word等)。但是,我现在需要解析不完整地属于这些类别之一的数据。例如,我想将16.16定点二进制数转换为双精度;例如因此little_word << little_16p16会解析uint16_t后跟double(从定点数解析)。使用boost :: spirit解析二进制文件时更改属性类型

我首先考虑了语义动作,但是(我认为...)他们不合适,因为他们不改变与解析器相关的属性的类型。我也不知道如何修改employee struct-parsing example这种情况,因为它依靠boost::fusion提供的隐式转换。这种方法在这里不起作用,因为我显然不能定义从uint32_tdouble的隐式转换,而不会导致重大问题。

我的倾向是我需要添加非终端来包装内置的二进制原语解析器或从头开始编写终端解析器。即使在查看qi_binary.hpp的来源之后,我也不知道该怎么做。任何人都可以提供一些示例代码和/或指导我参考相关参考以开始使用?

回答

7
template < typename Iterator > 
    struct parser : boost::spirit::qi::grammar < Iterator, double(), boost::spirit::ascii::space_type > 
    { 
     struct cast_impl 
     { 
      template < typename A > 
      struct result { typedef double type; }; 

      double operator()(boost::fusion::vector < boost::uint16_t, boost::uint16_t > arg) const 
      { 
       // cast here 
       return 0; 
      } 
     }; 

     parser() : parser::base_type(main) 
     { 
      pair = boost::spirit::qi::little_word >> '.' >> boost::spirit::qi::little_word; 
      main = pair[boost::spirit::qi::_val = cast(boost::spirit::qi::_1)]; 
     } 

     boost::spirit::qi::rule < Iterator, boost::fusion::vector < boost::uint16_t, boost::uint16_t >(), boost::spirit::ascii::space_type > pair; 
     boost::spirit::qi::rule < Iterator, double(), boost::spirit::ascii::space_type > main; 

     boost::phoenix::function<cast_impl> cast; 
    }; 

    int _tmain(int argc, _TCHAR* argv[]) 
    { 
     typedef std::string container; 

     container data_ = "\x01\x02.\x01\x02"; 

     container::iterator iterator_ = data_.begin(); 

     double value_; 

     bool result_ = 
      boost::spirit::qi::phrase_parse(iterator_, data_.end(), 
      parser <container::iterator>(), 
      boost::spirit::ascii::space, 
      value_); 

     return 0; 
    } 
+0

谢谢!我可以通过删除'ascii :: space_type'模板参数并替换适当的'operator()'函数来得到你想要的代码。 – 2012-03-18 07:44:36