boost :: spirit :: karma生成器规则中的语义动作

时间:2013-08-09 09:14:29

标签: boost boost-spirit boost-spirit-karma

这困扰了我几个小时,我不明白如何让它发挥作用。我只想在每次使用规则时做一些事情,在这个例子中增加一个计数器。如果我没有明确指定规则但在调用boost :: spirit :: karma :: generate时使用它,它就可以工作。但是当我尝试将所有内容放入规则时,它将无法编译,并且我从冗长的错误消息中得不到任何见解。

#include <iostream>
#include <string>

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

int main()
{
    using boost::spirit::karma::eps;
    using boost::spirit::karma::int_;
    using boost::spirit::karma::lit;
    using boost::spirit::karma::eol;
    using boost::phoenix::val;
    using boost::phoenix::ref;
    using boost::spirit::karma::generate;
    using boost::spirit::karma::rule;

    typedef std::back_insert_iterator<std::string> OutputIteratorType;

    std::string s;
    std::back_insert_iterator<std::string> sink(s);
    int lineNum = 0;

    generate(sink, eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol, 123);
    generate(sink, eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol, 123);

    // Will not compile
    //rule<OutputIteratorType, int()> testRule = eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol;
    //generate(sink, testRule, 123);
    //generate(sink, testRule, 123);

    std::cout << s;
    return 0;
}

(上面你可以看到最优雅的boost :: spirit版本,但是使用lambda函数或成员函数都是相同的,“直接方法”有效,“规则方法”没有。 )

不幸的是,我也找不到任何文档或示例或其他资源,我也非常感谢参考。

1 个答案:

答案 0 :(得分:3)

这是boost :: phoenix V2的问题(不要问哪个;-))所以,使用V3会有效。

此外,必须将属性赋予int生成器,并在打印时引用lineNum。

#include <iostream>
#include <string>

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

int main() {
  using boost::spirit::karma::eps;
  using boost::spirit::karma::int_;
  using boost::spirit::karma::lit;
  using boost::spirit::karma::eol;
  using boost::spirit::karma::_1;
  using boost::spirit::karma::_val;
  using boost::phoenix::val;
  using boost::phoenix::ref;
  using boost::spirit::karma::generate;
  using boost::spirit::karma::rule;

  typedef std::back_insert_iterator<std::string> OutputIteratorType;

  std::string s;
  std::back_insert_iterator<std::string> sink(s);
  int lineNum = 0;

  rule<OutputIteratorType, int()> testRule = eps[ref(lineNum) += 10]
      << lit("Line number ") << lit(ref(lineNum)) << lit(": ")
      << int_[_1 = _val] << eol;
  generate(sink, testRule, 123);
  generate(sink, testRule, 123);

  std::cout << s;
  return 0;
}