2017-05-24 6 views
2

방금 ​​Qi에 기본 파서를 구현하여 지정된 TCP 포트 범위를 확인했습니다. 80-444.Boost Spirit Qi : 특수 uint_parser의 태그 변경

template<class It> 
    struct port_range_grammar : qi::grammar<It, port_range_type()> 
    { 
    port_range_grammar() 
     : port_range_grammar::base_type(start, "port_range") 
    { 
     using qi::lit; 

     start = port > lit("-") > port; 
    } 

    private: 
    qi::rule<It, port_range_type()> start; 
    qi::uint_parser<uint16_t, 10, 2, 5> port; 
    }; 

I (이 하나를 내장 일부 상위 문법에서) 시작 규칙에 오류 핸들러를 첨부했습니다보다 설명적인 오류가, 예를 들면 만들려면 :

// this how the code is attached to the start rule in the top level grammar: 

    start = (tcp_endpoint | ipc_endpoint | inproc_endpoint)[_val=_1] > eoi; 

    on_error<fail> 
    (start 
    , pnx::bind 
     ([](auto const& what, auto begin, auto end) 
      { 
      ERROR_AC << "Expecting " 
        << what 
        << " here: '" 
        << std::string(begin, end) 
        << "'" 
      ; 
      } 
     , _4 
     , _3 
     , _2 
    ) 
    ) 
    ; 

모든 하나와 함께 잘 작동 내가 포트로 내가 오류가 일부 무효 16 비트 부호없는 수를 통과하지만 충분히 설명하지 않은 경우 사소한 예외 :

Expecting <unsigned-integer> here: '74888' 

이제 라이브러리의 사용자는 74,888이 잘못 16bi는 것을 이해할 수 없다 t uint. unsiged-integerqi::uint_parser에 부착 된 태그입니다. 이 태그를 변경할 수있는 방법이 있습니까?

답변

2

단순히 비 터미널 규칙에 이름을 첨부 줄은 :

 port = uint_parser<uint16_t, 10, 2, 5>(); 
     port.name("valid port number 10-65535"); 

Live On Coliru

#include <boost/fusion/adapted/std_pair.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
namespace qi = boost::spirit::qi; 
namespace pnx = boost::phoenix; 

using port_range_type = std::pair<uint16_t, uint16_t>; 

template<class It> 
struct port_range_grammar : qi::grammar<It, port_range_type()> 
{ 
    port_range_grammar() 
     : port_range_grammar::base_type(start, "port_range") 
    { 
     using namespace qi; 
     port = uint_parser<uint16_t, 10, 2, 5>(); 
     port.name("valid port number 10-65535"); 

     start = port > lit("-") > port; 
     /*start = (tcp_endpoint | ipc_endpoint | inproc_endpoint)[_val=_1] > eoi;*/ 

     on_error<fail> 
      (start 
       , pnx::bind 
       ([](auto const& what, auto begin, auto end) 
       { 
        std::cerr << "Expecting " 
         << what 
         << " here: '" 
         << std::string(begin, end) 
         << "'\n" 
         ; 
       } , _4 , _3 , _2 
      ) 
      ) 
      ; 
    } 

    private: 
    qi::rule<It, port_range_type()> start; 
    qi::rule<It, uint16_t()> port; 
}; 

int main() { 
    using It = std::string::const_iterator; 
    std::string const input = "11-1q0"; 

    It f = input.begin(), l = input.end(); 
    port_range_type range; 
    bool ok = qi::parse(f, l, port_range_grammar<It>{}, range); 

    if (ok) { 
     std::cout << "Parsed port " << range.first << " to " << range.second << "\n"; 
    } else { 
     std::cout << "Parse failed\n"; 
    } 

    if (f!=l) 
     std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; 
} 

인쇄

Expecting <valid port number 10-65535> here: '1q0' 
Parse failed 
Remaining unparsed: '11-1q0' 
+0

아, 확인을 참조하십시오. 이제 알았어. 포트 구문 분석기가 규칙에 할당됩니다. 이것은 속임수입니다. 그 전에 나는 포트 파서를 회원으로 직접 사용했다. ( – ovanes

+1

이제 멋진 메시지를 보게 될 것이다! <유효한 포트 범위 : (10, 65535)> : '74888'고마워! – ovanes