2017-10-20 15 views
1

부스트 1.65.1에서 Spirit X3을 사용하여 파서를 만들려고합니다. 나는 간단한 구조로 다음과 같은 작은 예에 내 문제를 감소 :기본 생성자가없는 Boost-Spirit (X3) 구문 분석

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/home/x3.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <iostream> 
#include <vector> 

struct MyPair { 
    MyPair(int x, int y) : mx(x), my(y) {}; 
    //MyPair() {} // No default constructor - neither needed nor wanted. 
    int mx; 
    int my; 
}; 

/* 
BOOST_FUSION_ADAPT_STRUCT(
    MyPair, 
    (int, mx) 
    (int, my) 
) 
*/ 

int main() 
{ 
    using boost::spirit::x3::int_; 
    using boost::spirit::x3::parse; 

    std::vector<MyPair> pairs; 
    char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first); 
    auto pair = [&](auto& ctx) { return MyPair(1, 2); }; 
    bool parsed_some = parse(first, last, ((int_ >> ':' >> int_)[pair]) % ',', pairs); 

    if (parsed_some) { 
     std::cout << "Parsed the following pairs" << std::endl; 
     for (auto& p : pairs) { 
      std::cout << p.mx << ":" << p.my << std::endl; 
     } 
    } 
    return 0; 
} 

나는 내 타입에 기본 생성자를 추가하지 않습니다 (여기 MyPair). 기본 생성자없이 나는 다음과 같은 오류 얻을 :

'MyPair::MyPair': no appropriate default constructor available ...\boost\utility\value_init.hpp 

을하지만 기본 생성자가 내 구조를 변경하지 않습니다. 내가 하나를 추가하려면, 가정, 내가 할 마지막 오류는 다음과 같습니다

binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) TestParsing ...\x3\support\traits\move_to.hpp 

을하지만 수동으로 의미 작용의 속성을 구축 이후가 융합 정의를 만들 필요가 왜 표시되지 않습니다. (이 문제는 해결 될 때까지 현재 하드 코드 된 값을 사용하고 적절한 값을 얻는다는 점에 유의하십시오.)

Spirit X3을 사용하여 기본 생성자없이 사용자 정의 유형의 속성을 어떻게 구성합니까?

답변

1

마음에 오는 유일한 방법은 MyPair 속성에 바인딩하는 규칙/구문 분석기를 전혀 사용하지 않는 것입니다.

다행히 X3 반복적으로 컨테이너 속성에 바인딩 할 수있을만큼 유연하다 :

auto pair = x3::rule<struct pair_, std::vector<MyPair> > {} 
      = (int_ >> ':' >> int_) 
       [([&](auto& ctx) { 
        auto& attr = x3::_attr(ctx); 
        using boost::fusion::at_c; 
        return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr)); 
       })] 
      ; 

Live On Coliru

#include <boost/spirit/home/x3.hpp> 
#include <iostream> 
#include <vector> 

struct MyPair { 
    MyPair(int x, int y) : mx(x), my(y) {}; 
    int mx; 
    int my; 
}; 

int main() 
{ 
    namespace x3 = boost::spirit::x3; 
    using x3::int_; 

    std::vector<MyPair> pairs; 
    char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first); 

    auto pair = x3::rule<struct pair_, std::vector<MyPair> > {} 
       = (int_ >> ':' >> int_) 
        [([&](auto& ctx) { 
         auto& attr = x3::_attr(ctx); 
         using boost::fusion::at_c; 
         return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr)); 
        })] 
       ; 

    bool parsed_some = parse(first, last, pair % ',', pairs); 

    if (parsed_some) { 
     std::cout << "Parsed the following pairs" << std::endl; 
     for (auto& p : pairs) { 
      std::cout << p.mx << ":" << p.my << std::endl; 
     } 
    } 
} 

인쇄

Parsed the following pairs 
11:22 
33:44 
55:66 
+0

감사합니다. 그러나 나는이 접근법을 적용 할 수 있을지 확신하지 못한다. 내 원하는 출력 "AST"는 대부분 기본이 아닌 구성 가능한 유형의 계층 구조입니다 (예 : ) a ("단순/기본 인수") ... B b (24.8); // 최저 계층 X x (a, c) .... Y y (b); // 가장 낮은 레이어 + 1 레이어 P (x, y) // 최저 + 2 레이어 ... 등등 ..... – senevoldsen

+0

그러면 영혼에 어려움을 겪을 것입니다. 나는 중간 표현으로 파싱하고 그것을 변형시킬 것이다. X3에는 변형을 "자동"으로 만드는 특징이 있습니다. – sehe

+0

다른 중간 표현을 만들어야 할까봐 두려웠습니다. 많은 상용구. 이러한 변환을 자동화하는 방법에 대한 문서에 대한 링크가 있습니까? – senevoldsen