C++11 如何定义此boost spirit规则的AST?

C++11 如何定义此boost spirit规则的AST?,c++11,boost-spirit,C++11,Boost Spirit,我有一个更复杂的规则,但这个规则足以解决这个问题(我希望)。考虑规则: result = double_ >> *(char_ > int_); 其中,结果是根据命名空间ast中的结构结果声明的: qi::rule<Iterator, ast::result(), qi::space_type> result; 除了 BOOST_FUSION_ADAPT_STRUCT( ast::result, (double, first), (ast::seco

我有一个更复杂的规则,但这个规则足以解决这个问题(我希望)。考虑规则:

result = double_ >> *(char_ > int_);
其中,结果是根据命名空间ast中的结构结果声明的:

qi::rule<Iterator, ast::result(), qi::space_type> result;
除了

BOOST_FUSION_ADAPT_STRUCT(
  ast::result,
  (double, first),
  (ast::second_type, second)
)
但这给了我编译错误:

error: no matching function for call to 'std::pair<char, int>::pair(const char&)'
错误:调用'std::pair::pair(const char&')没有匹配的函数
这个规则很简单,创建结果将存储在其中的AST结构也应该很简单。。。但是怎么做呢

以下是我尝试的完整测试程序:

 #include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>

namespace ast
{

using second_type = std::vector<std::pair<char, int>>;

struct result
{
  double first;
  second_type second;

  friend std::ostream& operator<<(std::ostream& os, result const& result);
};

std::ostream& operator<<(std::ostream& os, second_type::value_type val)
{
  return os << val.first << ' ' << val.second;
}

std::ostream& operator<<(std::ostream& os, result const& result)
{
  os << result.first;
  for (auto& i : result.second)
      os << ' ' << i;
  return os;
}

} // namespace ast

BOOST_FUSION_ADAPT_STRUCT(
  ast::result,
  (double, first),
  (ast::second_type, second)
)

namespace client
{

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
class test_grammar : public qi::grammar<Iterator, ast::result(), qi::space_type>
{
 private:
  qi::rule<Iterator, ast::result(), qi::space_type> result;

 public:
  test_grammar() : test_grammar::base_type(result, "result_grammar")
  {
    using qi::double_;
    using qi::char_;
    using qi::int_;

    result = double_ >> *(char_ > int_);
  }
};

} // namespace client

int main()
{
  std::string const input{"3.4 a 5 b 6 c 7"};
  using iterator_type = std::string::const_iterator;
  using test_grammar = client::test_grammar<iterator_type>;
  namespace qi = boost::spirit::qi;

  test_grammar program;
  iterator_type iter{input.begin()};
  iterator_type const end{input.end()};
  ast::result out;
  bool r = qi::phrase_parse(iter, end, program, qi::space, out);

  if (!r || iter != end)
  {
    std::cerr << "Parsing failed." << std::endl;
    return 1;
  }
  std::cout << "Parsed: " << out << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
名称空间ast
{
使用第二种类型=std::vector;
结构结果
{
双优先;
第二类;

friend std::ostream&operator我做了以下更改:

#include <boost/fusion/tuple.hpp>

using second_type = std::vector<boost::fusion::tuple<char, int>>;

std::ostream& operator<<(std::ostream& os, second_type::value_type val)
{
    return os << boost::fusion::get<0>(val) << ' ' << boost::fusion::get<1>(val);
}
#包括
使用第二种类型=std::vector;

std::ostream&operatorsirgue更改了AST以适应默认的合成属性。代价是,确实使AST复杂化了

但是,您可以通过调整
std::pair
来利用属性兼容性规则。事实上,这非常简单,只需包含1个标头:

#include <boost/fusion/include/std_pair.hpp>

如果你想走这条路,你最好包括Fusion的
io.hpp
:谢谢!你基本上说的和sehe是一样的,也就是说,std::pair不受支持(不包括头)。如果不是因为文档简单地说明std::pair确实有效,而不提及标题,我会尝试完全这样做。我认为这是spirit文档的一个普遍问题;它似乎完全忽略了一个事实,即除非包含正确的标题,否则事情不会起作用,而从不谈论(那些标题)标题:/。
#include <boost/fusion/include/std_pair.hpp>
Parsed: 3.4 a 5 b 6 c 7