2012-03-15 16 views
8

boost::spirit::qi'u kullanarak, yerleşik ayrıştırıcılardan oluşan bir akışı ayrıştırmak için başarıyla kullanıyorum (örneğin, byte_, little_word, vb.). Ancak, şu anda bu kategorilerden birine girmeyen verileri ayrıştırmam gerekiyor. Örneğin, 16.16 sabit nokta ikili sayısının bir çifte dönüştürülmesini istiyorum; Örneğin. Bu nedenle little_word << little_16p16, uint16_t'u ve ardından double'u (sabit nokta numarasından ayrıştırmalar) ayrıştırır.İkili ayrıştırma sırasında öznitelik türünü değiştir :: spirit

İlk olarak anlamsal eylemleri düşündüm, ancak (sanırım ...) uygun olmadıklarını çünkü bir ayrıştırıcıyla ilişkilendirilen özniteliğin türünü değiştirmediklerini düşünüyorum. boost::fusion tarafından sağlanan örtülü yayınlara dayandığı için bu duruma employee struct-parsing example'u nasıl uyarlayacağımı da anlayamıyorum. Bu yaklaşım burada çalışmaz çünkü açık bir şekilde uint32_t'dan double'a bir örtük yayın tanımlayamıyorum, büyük sorunlara neden olmadan.

Benim eğim, yerleşik olmayan ikili ilkel ayrıştırıcıları sarmak için terminal olmayanları eklemem veya sıfırdan bir uç çözümleyici yazmam gerektiğidir. qi_binary.hpp kaynağına baktıktan sonra bile, nasıl yapılacağından emin değilim. Başlamak için bazı örnek kodlar verebilir ve/veya ilgili referanslara yönlendirebilir miyim?

cevap

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

Teşekkürler! Örnek kodunuzu 'ascii :: space_type' şablon parametresini kaldırarak ve uygun işleç() işlevini kullanarak tam olarak istediğimi yapabildim. –