Отфильтруйте синтезированный атрибут через std :: map в семантическом действии буст-духа

У меня есть случай, когда я хотел бы отфильтровать значение, которое появляется как синтезированный атрибут внутри правила через std :: map.

Карта предварительно сгенерирована и не будет изменяться во время анализа.Природа карты и реального синтаксического анализатора означает, что поиск никогда не должен завершиться ошибкой (хотя фактическое количество элементов может быть довольно большим)Обычный подход, идеально подходящий для этой проблемы (используйте таблицу символов), не подходит для реального случая. В реальной проблеме поиск является условным, основанным на атрибуте, который не будет очевиден намного позже при разборе (в несколько удаленном правиле).

Моя попытка:

#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 контейнеры, что это должно работать. Но я получаю ошибку компиляции в строке правила. Эта ошибка исчезнет, если я заменю семантическое действие на классическое бессмысленное[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

Ответы на вопрос(2)

Ваш ответ на вопрос