2012-01-18 4 views
-2

나는 Boost.Spirit이 어떻게 작동하는지 배우려고합니다. 불행히도, 문서는 나에게 너무 간결하며 실제로 작동하는 방법을 알 수 없습니다.Boost.Spirit에 double_과 비슷한 파서를 만드는 법?

그럼, 제 문제로 옮기십시오. 나는 std::complex 타입의 파서를 작성하려고하는데, 그것은 내장 파서와 같은 방식으로 작동 할 것이다. int_ 또는 double_. 1.2+2i, 3-i*4, 5*i 등과 같이 다른 형식으로 복소수를 파싱하고 싶습니다. 솔직히 말해서 나는 무엇을 해야할지 몰랐습니다. 이 방법을 시도했습니다 :

typedef std::complex<double> Complex; 

struct complex_parser : qi::grammar<Iterator, Complex(), ascii::space_type> 
{ 
    complex_parser() : complex_parser::base_type(value) 
    { 
     real = (
      double_[_val = _1] 
     ); 

     imaginary = (
      (double_[_val = Complex(0.0, _1)] >> -(lit('*')) >> 'i') 
      | ('i' >> -(lit('*')) >> double_[_val = Complex(0.0, _1)]) 
     ); 

     value = (
      imaginary[_val = _1] 
      | real[_val = _1] >> -('+' >> imaginary[_val += _1]) 
      | real[_val = _1] >> -('-' >> imaginary[_val -= _1]) 
     ); 
    } 

    qi::rule<Iterator, Complex(), ascii::space_type> value; 
    qi::rule<Iterator, double(), ascii::space_type> real; 
    qi::rule<Iterator, double(), ascii::space_type> imaginary; 
}; 

하지만 작동하지 않습니다. 6 과부하 아무도 [모든 인수 형식을 변환 할 수 없었다 :

오류 C2665 : '표준 : 복잡한 :: 복잡'구문 분석 할 때 imaginary, 자리 _1double 타입이 아니기 때문에 심지어 컴파일되지 않습니다 ...] 인수 목록 '(double, const boost :: spirit :: _ 1_type)과 일치 시키려고 시도하는 중'

왜 그런가? 나는 Complex() 대신 imaginary 규칙 (물론 real) double() 매개 변수를주었습니다. 자리 표시자를 double- 동일 유형으로 지정하면 안됩니까? 그렇지 않다면 왜 규칙에 유형을 설정해야합니까? 어떻게 그들을 제대로 사용 하는가?

답변

1

boost::phoenix::construct을 사용할 수 있습니다.

#define BOOST_SPIRIT_USE_PHOENIX_V3 

#include <complex> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
using namespace boost::spirit::qi; 
namespace phx = boost::phoenix; 

typedef std::complex<double> Complex; 
typedef std::string::iterator Iterator; 

struct complex_parser : qi::grammar<Iterator, Complex(), ascii::space_type> 
{ 
    complex_parser() : complex_parser::base_type(value) 
    { 
     real = (
      double_[_val = _1] 
     ); 

     imaginary = (
      (double_[_val = phx::construct<Complex>(0.0, _1)] >> -(lit('*')) >> 'i') 
      | ('i' >> -(lit('*')) >> double_[_val = phx::construct<Complex>(0.0, _1)]) 
     ); 

     value = (
      imaginary[_val = _1] 
      | real[_val = _1] >> -('+' >> imaginary[_val += _1]) 
      | real[_val = _1] >> -('-' >> imaginary[_val -= _1]) 
     ); 
    } 

    qi::rule<Iterator, Complex(), ascii::space_type> value; 
    qi::rule<Iterator, double(), ascii::space_type> real; 
    qi::rule<Iterator, Complex(), ascii::space_type> imaginary; 
}; 
+0

그럼 내가 올바르게 이해하자. 게으른 평가에 관한 것입니다. 맞습니까? 즉,'phoenix :: construct'에 의한 게으른 평가가 없다면, 컴파일러는'_1' 자리 표시자가 어떤 타입인지 알지 못합니다. – Archie

+0

_1은 특수 값 및 유형입니다. _1은 모든 유형의 값을 대체합니다. _1은 대상 유형에 대해 아무것도 모릅니다. (죄송합니다, 영어가 나쁩니다.) –

+1

부스트 :: 스피릿과 부스트 :: 피닉스의 내부에 대해 잘 이해하려면이 훌륭한 시리즈를 살펴보십시오. http://cpp-next.com/archive/2010/08/expressive-c-introduction/ – mark