2010-12-01 3 views
1

다음과 같은 영혼 문법을 사용합니다. push_back(at_c<0>(qi::_val), qi::_1) 표준을 사용하여 struct myresult에 AST 노드의 벡터를 만들려고하는데 컴파일 오류가 발생합니다 (아래 참조).boost spirit grammar (phoenix push_back은 컴파일 오류가 발생 함)에서 결과 얻기

typedef vector<ZLS::ASTNode*> vector_astnode_t; 

struct myresult { 
vector_astnode_t turtle_commands; 
}; 

BOOST_FUSION_ADAPT_STRUCT 
(
myresult, 
(vector_astnode_t, turtle_commands) 
); 


namespace spirit = boost::spirit; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 
namespace phoenix = boost::phoenix; 


struct debugprint { 
    string _name; 
    debugprint(string n) : _name(n) {} 

    void operator()(int const& i, qi::unused_type, qi::unused_type) const { 
     cout << _name << std::endl; 
    } 
    void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const { 
     cout << _name << std::endl; 
    }  

    // todo: more of these for each type 

}; 


template <typename Iterator> 
struct lsystem_parser : qi::grammar<Iterator, myresult() > { 
    lsystem_parser(ZLS::Context* ctx) 
    : lsystem_parser::base_type(start) 
    , _ctx(ctx) 
    { 
     using qi::char_; 
     using qi::float_; 
     using qi::eps; 
     using qi::lit; 
     using qi::_1; 
     using qi::_val; 
     using phoenix::ref; 
     using phoenix::push_back; 
     using phoenix::at_c; 

     float_parameters = '(' >> (float_ >> *(',' >> float_)) >> ')'; 

     /// turtle grammar /// 
     draw_forward = (char_('F') [ _val = new ZLS::ASTDrawForward(_ctx,0)]) 
            [debugprint("draw_forward")]; 

     move_forward = (char_('f') [ _val = new ZLS::ASTMoveForward(_ctx,0)]) 
            [debugprint("move_forward")]; 

     turn_left = (char_('+') [ _val = new ZLS::ASTTurnLeft(_ctx,0)]) 
            [debugprint("turn_left")]; 

     turn_right = (char_('-') [ _val = new ZLS::ASTTurnRight(_ctx,0)]) 
            [debugprint("turn_right")]; 

     push_state = (char_('[') [ _val = new ZLS::ASTPushState(_ctx)]) 
            [debugprint("push_state")]; 

     pop_state = (char_(']') [ _val = new ZLS::ASTPopState(_ctx) ]) 
            [debugprint("pop_state")]; 

     turtle_commands = (draw_forward 
         | move_forward 
         | turn_left  
         | turn_right  
         | push_state  
         | pop_state);  

     // >>>> THIS IS WHAT IS CAUSING THE ERROR <<<<< 
     start = *turtle_commands[ push_back(at_c<0>(qi::_val), qi::_1) ]; 
    } 
    qi::rule< Iterator, myresult() > start; 
    qi::rule< Iterator, vector<float> > float_parameters; 

    qi::rule< Iterator, ZLS::ASTNode* > draw_forward; 
    qi::rule< Iterator, ZLS::ASTNode* > move_forward; 
    qi::rule< Iterator, ZLS::ASTNode* > turn_left; 
    qi::rule< Iterator, ZLS::ASTNode* > turn_right; 
    qi::rule< Iterator, ZLS::ASTNode* > push_state; 
    qi::rule< Iterator, ZLS::ASTNode* > pop_state; 
    qi::rule< Iterator, ZLS::ASTNode* > turtle_commands; 

    ZLS::Context* _ctx; 

}; 

다음은 엑스 코드에서 반환되는 실제 오류입니다 :

container.hpp:492: error: no matching function for call to 'std::vector<ZLS::ASTNode*, std::allocator<ZLS::ASTNode*> >::push_back(const boost::fusion::unused_type&)' 
stl_vector.h:600: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = ZLS::ASTNode*, _Alloc = std::allocator<ZLS::ASTNode*>] 
container.hpp:492: error: return-statement with a value, in function returning 'void' 

편집 : 다음은되어 컴파일하고 작품을 수정 정신 문법. 당신은 직접 세만 틱 액션의 내부 operator new을 사용할 수 없습니다 turtle_commands = ... [_val = _1]

template <typename Iterator> 
struct lsystem_parser : qi::grammar<Iterator, vector_astnode_t() > { 
    lsystem_parser(ZLS::Context* ctx) 
    : lsystem_parser::base_type(start) 
    , _ctx(ctx) 
    { 
     using qi::char_; 
     using qi::float_; 
     using qi::eps; 
     using qi::lit; 
     using qi::_1; 
     using qi::_val; 
     using phoenix::ref; 
     using phoenix::push_back; 
     using phoenix::at_c; 
     using phoenix::new_; 

     float_parameters = '(' >> (float_ >> *(',' >> float_)) >> ')'; 

     /// turtle grammar /// 
     draw_forward = (char_('F') [ _val = new_<ZLS::ASTDrawForward>(_ctx, (ZLS::ASTNode*)0)]) 
             [debugprint("draw_forward")]; 

     move_forward = (char_('f') [ _val = new_<ZLS::ASTMoveForward>(_ctx, (ZLS::ASTNode*)0)]) 
             [debugprint("move_forward")]; 

     turn_left  = (char_('+') [ _val = new_<ZLS::ASTTurnLeft>(_ctx, (ZLS::ASTNode*)0)]) 
             [debugprint("turn_left")]; 

     turn_right  = (char_('-') [ _val = new_<ZLS::ASTTurnRight>(_ctx, (ZLS::ASTNode*)0)]) 
             [debugprint("turn_right")]; 

     push_state  = (char_('[') [ _val = new_<ZLS::ASTPushState>(_ctx)]) 
             [debugprint("push_state")]; 

     pop_state  = (char_(']') [ _val = new_<ZLS::ASTPopState>(_ctx) ]) 
             [debugprint("pop_state")]; 

     turtle_commands = (draw_forward 
         | move_forward 
         | turn_left  
         | turn_right  
         | push_state  
         | pop_state)[_val = _1];   


     start = *turtle_commands >> qi::eps; 
    } 
    qi::rule< Iterator, vector_astnode_t() > start; 
    qi::rule< Iterator, vector<float> > float_parameters; 

    qi::rule< Iterator, ZLS::ASTNode*() > draw_forward; 
    qi::rule< Iterator, ZLS::ASTNode*() > move_forward; 
    qi::rule< Iterator, ZLS::ASTNode*() > turn_left; 
    qi::rule< Iterator, ZLS::ASTNode*() > turn_right; 
    qi::rule< Iterator, ZLS::ASTNode*() > push_state; 
    qi::rule< Iterator, ZLS::ASTNode*() > pop_state; 
    qi::rule< Iterator, ZLS::ASTNode*() > turtle_commands; 

    ZLS::Context* _ctx; 

}; 

답변

2

에 다음과 같은 의미 조치를 피닉스 new_ 연산자를 사용하고 추가하는 등주의 대신 phoenix::new_<>를 사용하는 몇 가지 미묘한 변화가있다.

또한 규칙에 대한 속성은 함수 표기법 구문을 사용하여 지정됩니다. 따라서 다음과 같이 규칙 선언을 변경해야합니다.

qi::rule< Iterator, ZLS::ASTNode*()> draw_forward; 

다음은 추가 팁입니다. 시작 규칙을

start = *turtle_commands >> qi::eps; 

으로 변경하면 의미 작업이 모두 수행되지 않을 수 있습니다. 규칙을 (파서) 시퀀스로 변환하면 시퀀스에 대한 속성 전파 규칙을 활용하여 융합 시퀀스의 첫 번째 요소 (vector_astnode_t turtle_commands)를 파서 시퀀스의 첫 번째 요소 (*turtle_commands)에 직접 매핑 할 수 있습니다.

불완전한 예제를 컴파일 할 수 없으므로 더 많은 문제가 숨겨져있을 수 있습니다.

관련 문제