在boost精神语义动作中通过std :: map过滤合成的属性

时间:2013-01-07 22:25:22

标签: c++ boost boost-spirit boost-spirit-qi

我有一个案例,我希望通过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 containers的支持,我想我的印象是,这应该有效。但是我在规则行上遇到编译错误。如果我用经典的无意义[qi::_val = qi::_1]替换语义动作(毫不奇怪),这个错误就消失了。

像往常一样,MSVS10下的编译器错误令人震惊,但这是第一次提到我的代码文件:(在C:\ code \ Compiler2 \ spirit_test.cpp(25)...第25行是规则{{ 1}})

r

2 个答案:

答案 0 :(得分:3)

重新发布评论

尝试qi::_val = phx::ref(myMap)[qi::_1]而不是qi::_val = phx::at(myMap, qi::_1)

答案 1 :(得分:2)

问题是phoenix :: at的返回类型在this header中被定义为container::value_type。在地图的情况下,这是一对。只需专门化地图的结果就可以了(使用参考ildjarn所说的参考)。

#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";
    }
}