2012-09-02 76 views
1

documentation说如果使用A和B,则两个合成规则(a >> b)的属性应该是元组。属性组合不起作用Boost :: spirit

假设这我试图读出这样一个元组的第一个属性。但它失败:
(我尝试解析整数存储在“我”)

#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> 

template <typename ForwardIterator> class TestGrammar 
: public boost::spirit::qi::grammar<ForwardIterator, boost::spirit::ascii::space_type> 
{ 
    boost::spirit::qi::rule<ForwardIterator, boost::spirit::ascii::space_type> foo_; 
public: 
    TestGrammar(void) : TestGrammar::base_type(foo_) 
    { 
     int i; 
     foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_) 
         [boost::phoenix::ref(i) = boost::phoenix::at_c<0>(boost::spirit::_1)]); 
    } 
}; 

int main(void) 
{ 
    TestGrammar<std::string::iterator> g; 

    return 0; 
} 

写作:

foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_) 
        [boost::phoenix::ref(i) = boost::spirit::_1]); 

总会的工作,虽然只要是int。
来回更改类型并编写自定义规则显示(a >> b)的属性始终为A,而不管B是什么。

即使

回答

2

我想你想做到这一点:

int i; 
float f; 
foo_ = (boost::spirit::qi::int_ >> boost::spirit::qi::float_) 
      [ boost::phoenix::ref(i) = boost::spirit::_1, 
       boost::phoenix::ref(f) = boost::spirit::_2 ]; 

如果你真的想用序列,尝试:

foo_ = qi::attr_cast<>(qi::int_ >> qi::float_) 
       [ boost::phoenix::ref(i) = phx::at_c<0>(qi::_1), 
        boost::phoenix::ref(f) = phx::at_c<1>(qi::_1) ] 

或者与助手规则:

helper = qi::int_ >> qi::float_; 
foo_ = helper 
       [ boost::phoenix::ref(i) = phx::at_c<0>(qi::_1), 
        boost::phoenix::ref(f) = phx::at_c<1>(qi::_1) ] 
    ; 

全部三个版本编译在http://liveworkspace.org/code/518f2bd03e1fed7ed734d62071a88eab

+0

谢谢! :) 这样可行。 – iolo

1

如果你编译如下:

1>e:\work\test\spiritprob\spiritprob\spiritprob.cpp(14) : error C2065: 'bar' : undeclared identifier 
1>  e:\boost\boost_1_44_0\boost_1_44_0\boost\spirit\home\support\action_dispatch.hpp(29) : see reference to function template instantiation 'void TestDelegate::operator()<Attribute,Context,bool>(const T &,const U &,const V &) const' being compiled 
1>  with 
1>  [ 
1>   Attribute=boost::fusion::vector2<int,float>, 
1>   Context=boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type &,boost::fusion::nil>,boost::fusion::vector0<>>, 
1>   T=boost::fusion::vector2<int,float>, 
1>   U=boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type &,boost::fusion::nil>,boost::fusion::vector0<>>, 
1>   V=bool 
1>  ] 

(编译与Visual Studio 2008:

struct TestDelegate 
{ 
    template <typename T, typename U, typename V> 
    void operator()(T const& t, U const& u, V const& v) const { 
     bar; 
    } 
}; 

template <typename ForwardIterator> class TestGrammar 
: public boost::spirit::qi::grammar<ForwardIterator, boost::spirit::ascii::space_type> 
{ 
    boost::spirit::qi::rule<ForwardIterator, boost::spirit::ascii::space_type> foo_; 
public: 
    TestGrammar(void) : TestGrammar::base_type(foo_) 
    { 
     //int i; 
     TestDelegate test_delegate; 
     //foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_) 
     //    [boost::phoenix::ref(i) = boost::phoenix::at_c<0>(boost::spirit::_1)]); 
     foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_) 
         [test_delegate]); 
    } 
}; 

int main(void) 
{ 
    TestGrammar<std::string::iterator> g; 

    return 0; 
} 

你应该得到的错误文章,属性类型是一个元组看)

不直接解决我们的问题,但至少你知道它确实是c青梅作为一个fusion::vector<int,float>

+0

尽管我不得不改变'bar'表达式来让我的编译器打印出你是对的类型。但是,然后似乎有一个'_1'的问题,而不是...我会调查。 – iolo

+0

我认为你的问题是,在at_c的实例化处,类型是占位符'_1'的类型,而不是序列。也许写一个函数对象来处理它或某事。 – Pete

+0

我提供了三种替代方案。此外,相关:[在Spirit语义动作中检测参数类型](http://stackoverflow.com/questions/9404189/detecting-the-parameter-types-in-a-spirit-semantic-action) – sehe