2013-01-07 2 views
1

std :: map을 통해 규칙 내에서 합성 된 속성으로 제공되는 값을 필터링하려는 경우가 있습니다.부스트 영 의미 론적 동작에서 std :: map을 통해 합성 된 속성 필터링

  • 지도는 사전 생성되어 파싱 중에 변경되지 않습니다.
  • 지도의 특성과 실제 파서는 실제 요소 수가 상당히 클 수 있지만 조회가 실패하지 않아야 함을 의미합니다.
  • 이 문제 (기호 표 사용)에 가장 적합한 일반적인 방법은 isn ' 실제 사례에 적절하다. 실제 문제에서 룩업은 구문 분석에서 훨씬 나중에 (다소 제거 된 규칙에서) 명백하지 않은 속성을 기반으로하는 조건부 조건입니다.

내 시도 :

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/foreach.hpp> 
#include <string> 
#include <iostream> 
#include <vector> 
#include <map> 

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

int main() { 

    std::map<unsigned int, unsigned int> myMap; 
    myMap[1] = 100; myMap[2] = 200; myMap[3] = 300; 

    std::string test = "1 2 3"; 
    std::vector<unsigned int> results; 

    qi::rule<std::string::iterator, unsigned int()> r 
         = qi::uint_ [qi::_val = phx::at(myMap, qi::_1)]; 

    qi::parse(test.begin(), test.end(), (r % " "), results); 

    BOOST_FOREACH(unsigned int &x, results) { 
     std::cout << x << "\n"; 
    } 
} 

나는이 일을해야한다고 인해 stl containers의 피닉스 지원, 인상이었다고 생각한다. 하지만 규칙 라인에서 컴파일 오류가 발생합니다. 시멘틱 액션을 클래식 무의미한 [qi::_val = qi::_1]으로 대체하면이 오류가 사라집니다 (놀라운 것은 아님).

MSVS10에서의 컴파일러 오류는 평소와 같이 놀랍게 길지만 여기에 내 코드 파일에 대한 첫 번째 언급이 있습니다. (C : \ code \ Compiler2 \ spirit_test.cpp (25) ...) 행 25는 규칙 r입니다.)

C:\boost_1_50_0\boost/spirit/home/qi/nonterminal/rule.hpp(191) : see reference to function template instantiatio 
n 'void boost::spirit::qi::rule<Iterator,T1>::define<boost::mpl::false_,Expr>(boost::spirit::qi::rule<Iterator,T1> &,con 
st Expr &,boost::mpl::true_)' being compiled 
     with 
     [ 
      Iterator=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>>, 
      T1=unsigned int (void), 
      Expr=boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,boost::proto::argsns_::list2<const boo 
st::spirit::terminal<boost::spirit::tag::uint_> &,const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::p 
roto::tagns_::tag::assign,boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,b 
oost::proto::argsns_::term<boost::spirit::attribute<0>>,0>,boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost 
::phoenix::detail::tag::function_eval,boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns 
_::tag::terminal,boost::proto::argsns_::term<boost::phoenix::stl::at_impl>,0>,boost::phoenix::actor<boost::proto::exprns 
_::basic_expr<boost::proto::tagns_::tag::terminal,boost::proto::argsns_::term<boost::reference_wrapper<std::map<unsigned 
int,unsigned int>>>,0>>,boost::phoenix::actor<boost::spirit::argument<0>>>,3>>>,2>> &>,2> 
     ] 
     C:\code\Compiler2\spirit_test.cpp(25) : see reference to function template instantiation 'boost::spirit::qi 
::rule<Iterator,T1>::rule<boost::proto::exprns_::expr<Tag,Args,Arity>>(const Expr &,const std::string &)' being compiled 

     with 
     [ 
      Iterator=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>>, 
      T1=unsigned int (void), 
      Tag=boost::proto::tagns_::tag::subscript, 
      Args=boost::proto::argsns_::list2<const boost::spirit::terminal<boost::spirit::tag::uint_> &,const boost::ph 
oenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign,boost::proto::argsns_::list2<boost::pro 
to::exprns_::expr<boost::proto::tagns_::tag::terminal,boost::proto::argsns_::term<boost::spirit::attribute<0>>,0>,boost: 
:phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,boost::proto::argsns_::list 
3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,boost::proto::argsns_::term<boost::phoenix::stl: 
:at_impl>,0>,boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,boost::proto::a 
rgsns_::term<boost::reference_wrapper<std::map<unsigned int,unsigned int>>>,0>>,boost::phoenix::actor<boost::spirit::arg 
ument<0>>>,3>>>,2>> &>, 
      Arity=2, 
      Expr=boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,boost::proto::argsns_::list2<const boo 
st::spirit::terminal<boost::spirit::tag::uint_> &,const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::p 
roto::tagns_::tag::assign,boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,b 
oost::proto::argsns_::term<boost::spirit::attribute<0>>,0>,boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost 
::phoenix::detail::tag::function_eval,boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns 
_::tag::terminal,boost::proto::argsns_::term<boost::phoenix::stl::at_impl>,0>,boost::phoenix::actor<boost::proto::exprns 
_::basic_expr<boost::proto::tagns_::tag::terminal,boost::proto::argsns_::term<boost::reference_wrapper<std::map<unsigned 
int,unsigned int>>>,0>>,boost::phoenix::actor<boost::spirit::argument<0>>>,3>>>,2>> &>,2> 
     ] 
C:\boost_1_50_0\boost/proto/transform/default.hpp(154) : error C2440: '=' : cannot convert from 'std::pair<_Ty1,_Ty2>' t 
o 'unsigned int' 
     with 
     [ 
      _Ty1=const unsigned int, 
      _Ty2=unsigned int 
     ] 
     No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 
+0

필자는 phx :: at'을 원하는 것으로 생각하지 않습니다. 이는 하위 요소 연산자를 사용하지 않고 튜플 요소에 액세스하기위한 것입니다. 'qi :: _ val = phx :: at (myMap, qi :: _ 1)'보다는'qi :: _ val = phx :: ref (myMap) [qi :: _ 1]'을 사용해보십시오. – ildjarn

+0

@ildjarn : 참으로 ... 작동합니다! 나는 그것이 std :: map .at ()와 동일하게 동작 할 것이라고 생각했다. – jkerian

+0

아, 나는'phx :: at_c' (Boost.Fusion에서 변형)과'phx :: at'을 섞어 놓았다고 생각합니다. 당신은'phx :: at'에 대해 정확합니다 - 나는 당신이해야 할 일을해야한다고 생각합니다 (아마'qi :: _ val = phx :: at (phx :: ref (myMap), qi :: _ 1)'). 다행히 해결 방법이 도움이됩니다. : -] – ildjarn

답변

3

코멘트

에서 재개시 qi::_val = phx::ref(myMap)[qi::_1]보다는 qi::_val = phx::at(myMap, qi::_1)를 사용해보십시오.

2

phoenix :: at의 반환 유형은 this header으로 정의되어 있으며 container::value_type으로 정의되어 있습니다. 이것은지도의 경우 쌍입니다. 맵에 대한 결과를 특수화하기 만하면 작동합니다 (ildjarn이 지적한 것처럼 ref를 사용).

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/foreach.hpp> 
#include <string> 
#include <iostream> 
#include <vector> 
#include <map> 

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

namespace boost { namespace phoenix { namespace stl { 
    template <typename This, typename Key, typename Value, typename Compare, typename Allocator, typename Index> 
     struct at_impl::result<This(std::map<Key,Value,Compare,Allocator>&, Index)> 
     { 
      typedef Value & type; 
     }; 
    template <typename This, typename Key, typename Value, typename Compare, typename Allocator, typename Index> 
     struct at_impl::result<This(std::map<Key,Value,Compare,Allocator> const&, Index)> 
     { 
      typedef Value const& type; 
     }; 
}}} 

int main() { 

    std::map<unsigned int, unsigned int> myMap; 
    myMap[1] = 100; myMap[2] = 200; myMap[3] = 300; 

    std::string test = "1 2 3"; 
    std::vector<unsigned int> results; 

    qi::rule<std::string::iterator, unsigned int()> r 
         = qi::uint_ [qi::_val = phx::at(phx::cref(myMap), qi::_1)]; 

    qi::parse(test.begin(), test.end(), (r % " "), results); 

    BOOST_FOREACH(unsigned int &x, results) { 
     std::cout << x << "\n"; 
    } 
} 
+0

+1, 대부분 고통없는 해결 방법. : -] – ildjarn

+1

const- 정확성이있는 라이브 데모는 http://liveworkspace.org/code/1oAmHB를 참조하십시오. – sehe