2014-11-06 4 views
2

입력을 std :: string으로 구문 분석 할 때 문자열을 얻지 만 double_으로 구문 분석하면 융합 구조체에 예상되는 것보다 아주 작은 수가 포함됩니다.왜이 double을 구문 분석 할 수 없습니까?

#include <boost/spirit/include/qi.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <string> 

// http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/employee.cpp 

namespace FormatConverter { 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 
    // TODO: should this have an initializer? 
    struct asc { 
     double timestamp; 
    }; 
} 

BOOST_FUSION_ADAPT_STRUCT(
    FormatConverter::asc, 
     (double, timestamp) 
) 

namespace FormatConverter { 

    template <typename Iterator> 
    struct asc_parser : qi::grammar< Iterator, asc(), ascii::space_type > 
    { 
     asc_parser() 
      : asc_parser::base_type(start) { 
       timestamp %= qi::double_ ; 
       start %= timestamp ; 
       ; 
     } 
     qi::rule< Iterator, double, ascii::space_type > timestamp; 
     qi::rule< Iterator, asc(), ascii::space_type > start; 
    }; 
} 

내가 이것을 테스트입니다 :

#define BOOST_TEST_MODULE parser 
#include <boost/test/included/unit_test.hpp> 

#include "../FormatConverter/FormatConverter.h" 

#include <string> 

BOOST_AUTO_TEST_SUITE(TestSuite1) 
BOOST_AUTO_TEST_CASE(timestamp) { 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 
    using iterator_type = std::string::iterator; 
    using parser_type = FormatConverter::asc_parser<iterator_type>; 

    parser_type grammar; 
    FormatConverter::asc record; 

    std::string str("161.096841 "); 
    auto beg = str.begin(); 
    auto end = str.end(); 

    auto success = qi::phrase_parse(beg, end, grammar, ascii::space, record); 
    BOOST_REQUIRE(success); 
    BOOST_REQUIRE(beg==end); 

    std::cout << "timestamp: " << boost::fusion::as_vector(record) << std::endl; 
} 
BOOST_AUTO_TEST_SUITE_END() 
+0

매번, 나는 그것을 올바르게 쓸 수 없다고 맹세합니다. 나는 그것을 알고있다. 그러나 그것은 항상 내가 입력하는 방식이다. – user2240431

답변

6

당신은 속성의 ()을 놓친 :

qi::rule< Iterator, double, ascii::space_type > timestamp; 

qi::rule< Iterator, double(), ascii::space_type > timestamp; 

해야합니다 때문에 PARAMS 순서 qi::rule은 임의적 일 수 있습니다 (Iterator 제외). 내부적으로 lib는 어떤 특성을 사용하여 skipper인지 attr인지를 식별합니다. attr 필드는 function-sig 형식이어야합니다 (예 : synthesized(inherited)). double을 쓰면 attr으로 인식되지 않으므로 timestamp 규칙은 실제로 이됩니다 (즉,) record.timestamp은 파서로 채워지지 않을 것이므로 초기화되지 않았습니다.

+1

저자는 최근에'T()'에 덧붙여 평범한 형태의'T'를 지원하기로 결정했다. [[1] (https://github.com/boostorg/spirit/) commit/e34a955f2fbbf374870dee3329f89805cd775e6c]], 전자는 향후 릴리스에서 작동합니다. – Jamboree

+0

감사합니다. 나는 내장 타입에()가 필요하지 않다고 가정했다. 나에게 double()을 쓰는 것은 반 직관적 인 것처럼 보입니다. – user2240431