2013-01-18 4 views
1

Boost.Fusion ASSOC_STRUCT를 반환해야하는 규칙이 있습니다. _val에 규칙의 파서로 구문 분석 된 결과를 할당하려고하는데 작동하지 못합니다. 내가 이야기를 건너 뛰고 관련 코드를 직접 제시 할 것입니다.영의 의미 론적 액션과 융합 데이터 타입을 향상

#include <boost/fusion/include/define_assoc_struct.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/fusion/include/as_vector.hpp> 
#include <boost/spirit/include/qi_symbols.hpp> 
#include <iostream> 
#include <string> 

namespace keys { 
    struct actor_key; 
    struct action_key; 
    struct money_key; 
} 

BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), ActionLine, 
    (int, action, keys::action_key) 
    (int, amount, keys::money_key) 
    (int, actor, keys::actor_key) 
) 

int main() 
{ 
    namespace qi = boost::spirit::qi; 
    using qi::_1; 
    using qi::_2; 
    using qi::_a; 
    using qi::int_; 
    using qi::lit; 
    using boost::spirit::_val; 
    using boost::fusion::as_vector; 

    qi::symbols<char, int> name_parser_; 
    name_parser_.add("name4", 4); 

    std::string input("string1 ($7) string2 name4"); 
    std::string::const_iterator f(input.begin()), l(input.end()); 
    ActionLine expected{0, 7, 4}, result; 

    //The following rule is supposed to parse input of the form 
    //"string1 ($[integer]) string2 [name]" 
    //and return a triple (ActionLine) with the values { 0, value of (int_), value of (name_parser_) } 
    qi::rule<std::string::const_iterator, ActionLine()> action_line_ = 
    lit("string1 ($") >> int_ >> lit(") string2 ") >> name_parser_ 
    // [ _val = ActionLine{0, _1, _2} ]; // this is what I am trying to achieve 
    [ _val = ActionLine{0, 7, 4} ]; //this compiles, but of course is not what I need 

    bool b = 
    qi::parse(f, l, action_line_, result) && 
    as_vector(result) == as_vector(expected); 

    std::cout << "test: " << std::boolalpha << b << std::endl; 
    return 0; 
} 

컴파일러 오류이 예보다 내 실제 응용 프로그램에서 다소 다르다 (g ++ above_file.cpp -std = C + +0 함께 컴파일)하지만 _val = ActionLine의 라인 같은 (이다 {0, _1, _2}) : call :: ActionLine :: ActionLine()과 일치하는 함수가 없으며 _1과 _2를 int로 변환 할 수 없다고 생각합니다.

또한 로컬 int 변수를 추가하여 구문 분석 된 값을 복사하려고했지만 작동하지 않았고 boost :: phoenix :: at (_1,0), boost :: phoenix :: at를 사용하지 않았습니다. (_1,1) (나는 그 아이디어를 여기에서 발견했습니다 boost spirit semantic action parameters)

답변

2

당신이 원하는 것을하기 위해 의미 론적 행동에 phoenix::construct을 사용해야합니다.

#include <boost/fusion/include/define_assoc_struct.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_object.hpp> //CHANGE:you need to include this to use "phoenix::construct" 
#include <boost/fusion/include/as_vector.hpp> 
#include <boost/spirit/include/qi_symbols.hpp> 
#include <iostream> 
#include <string> 

namespace keys { 
    struct actor_key; 
    struct action_key; 
    struct money_key; 
} 

BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), ActionLine, 
    (int, action, keys::action_key) 
    (int, amount, keys::money_key) 
    (int, actor, keys::actor_key) 
) 

int main() 
{ 
    namespace qi = boost::spirit::qi; 
    namespace phx = boost::phoenix; 
    using qi::_1; 
    using qi::_2; 
    using qi::_a; 
    using qi::int_; 
    using qi::lit; 
    using boost::spirit::_val; 
    using boost::fusion::as_vector; 

    qi::symbols<char, int> name_parser_; 
    name_parser_.add("name4", 4); 

    std::string input("string1 ($7) string2 name4"); 
    std::string::const_iterator f(input.begin()), l(input.end()); 
    ActionLine expected{0, 7, 4}, result; 

    //The following rule is supposed to parse input of the form 
    //"string1 ($[integer]) string2 [name]" 
    //and return a triple (ActionLine) with the values { 0, value of (int_), value of (name_parser_) } 
    qi::rule<std::string::const_iterator, ActionLine()> action_line_ = 
    (lit("string1 ($") >> int_ >> lit(") string2 ") >> name_parser_) //CHANGE:the parentheses are important otherwise the semantic action would be attached to name_parser_ 
    [ _val = phx::construct<ActionLine>(0, _1, _2) ]; //CHANGE: you need to use phoenix to use the placeholders _1, _2, etc 

    bool b = 
    qi::parse(f, l, action_line_, result) && 
    as_vector(result) == as_vector(expected); 

    std::cout << "test: " << std::boolalpha << b << std::endl; 
    std::cout << at_key<keys::action_key>(result)<< ", " << at_key<keys::money_key>(result)<< ", " << at_key<keys::actor_key>(result) << std::endl; 

    return 0; 
} 
+0

감사합니다. 나는 그 대답이 피닉스에 대한 더 나은 지식을 요구할 것이라고 생각했다. – engineerX

+0

@ user1097105 두 번째 모습을 본 후에,이 경우 다음을 사용할 수도 있습니다 :'action_line = qi :: attr (0) >> lit ("string1 ($") >> int_ >> lit (") string2")> > name_parser_;'와 같은 의미를가집니다. –