【问题标题】:Attributes composition not working in Boost::spirit属性组合在 Boost::spirit 中不起作用
【发布时间】:2012-09-02 18:22:42
【问题描述】:

documentation 表示如果同时使用 A 和 B,则两个复合规则 (a >> b) 的属性应该是元组。

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

#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]);

只要 A 是 int,它就会一直有效。
来回更改类型并编写自定义规则表明,无论 B 是什么,(a >> b) 的属性都将始终为 A。

均匀

【问题讨论】:

    标签: c++ boost boost-spirit


    【解决方案1】:

    我猜你想这样做:

    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

    编译

    【讨论】:

      【解决方案2】:

      如果你编译这个:

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

      您应该在生成的错误文章中看到属性类型是一个元组:

      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 编译)

      并不能直接解决我们的问题,但至少你知道它确实是 fusion::vector&lt;int,float&gt;

      【讨论】:

      • 虽然我不得不改变'bar'表达式来让我的编译器打印出你正确的类型。但是,“_1”似乎有问题……我会调查的。
      • 我认为您的问题是在 at_c 的实例化点,类型是占位符“_1”的类型,而不是序列。也许写一个函数对象来处理它什么的。
      • 我提供了三个可行的替代方案。另外,相关:Detecting the parameter types in a Spirit semantic action
      猜你喜欢
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多