提振精神 - 无法获取属性 [英] boost spirit - unable to get attributes

查看:160
本文介绍了提振精神 - 无法获取属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的code:

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <string>
#include <vector>

struct parameter
{
  std::string type;
  std::string name;
};

BOOST_FUSION_ADAPT_STRUCT(
  parameter,
  (std::string, type)
  (std::string, name)
)

inline
std::ostream& operator<<(std::ostream& os, const parameter& param)
{
  os << param.type << ' ' << param.name;

  return os;
}

inline
std::ostream& operator<<(std::ostream& os, const std::vector<parameter>& parameters)
{
  for (const auto& param : parameters)
  {
    os << param;
  }

  return os;
}

struct function
{
  std::vector<parameter> parameters;
};

BOOST_FUSION_ADAPT_STRUCT(
  ::function,
  (std::vector<parameter>, parameters)
)

template <typename Iterator>
struct function_parser : boost::spirit::qi::grammar<Iterator, function(), boost::spirit::qi::ascii::space_type>
{
  function_parser() : function_parser::base_type(start)
  {
    using boost::spirit::qi::alnum;
    using boost::spirit::qi::alpha;

    string %= alpha >> *alnum;
    BOOST_SPIRIT_DEBUG_NODE(string);

    param %= string >> string;
    BOOST_SPIRIT_DEBUG_NODE(param);

    start %= *(param % ',');
    BOOST_SPIRIT_DEBUG_NODE(start);
  }

  boost::spirit::qi::rule<Iterator, std::string()> string;
  boost::spirit::qi::rule<Iterator, parameter, boost::spirit::qi::ascii::space_type> param;
  boost::spirit::qi::rule<Iterator, function(), boost::spirit::qi::ascii::space_type> start;
};

int main()
{
  std::string input_data("int bar, int baz");

  function fn;
  auto itr = input_data.begin();
  auto end = input_data.end();
  function_parser<decltype(itr)> g;
  bool res = boost::spirit::qi::phrase_parse(itr, end, g, boost::spirit::ascii::space, fn);
  if (res && itr == end)
  {
    std::cout << boost::fusion::tuple_open('[');
    std::cout << boost::fusion::tuple_close(']');
    std::cout << boost::fusion::tuple_delimiter(", ");

    std::cout << "Parsing succeeded \n";
    std::cout << "got: " << boost::fusion::as_vector(fn) << std::endl;
  }
  else
  {
    std::cout << "Parsing failed \n";
  }
}

输出

<start>
  <try>int bar, int baz</try>
  <param>
    <try>int bar, int baz</try>
    <string>
      <try>int bar, int baz</try>
      <success> bar, int baz</success>
      <attributes>[[i, n, t]]</attributes>
    </string>
    <string>
      <try>bar, int baz</try>
      <success>, int baz</success>
      <attributes>[[b, a, r]]</attributes>
    </string>
    <success>, int baz</success>
    <attributes>[]</attributes>
  </param>
  <param>
    <try> int baz</try>
    <string>
      <try>int baz</try>
      <success> baz</success>
      <attributes>[[i, n, t]]</attributes>
    </string>
    <string>
      <try>baz</try>
      <success></success>
      <attributes>[[b, a, z]]</attributes>
    </string>
    <success></success>
    <attributes>[]</attributes>
  </param>
  <param>
    <try></try>
    <string>
      <try></try>
      <fail/>
    </string>
    <fail/>
  </param>
  <success></success>
  <attributes>[[[]]]</attributes>
</start>
Parsing succeeded
got: []

为什么没有上市之后的任何参数得到的消息在解析成功了吗?我在做什么错了?

Why there isn't any parameters listed after "got: " message while parsing succeeded? What am I doing wrong?

推荐答案

三个问题:


  1. 您在这儿缺少括号:

  1. You're missing parentheses here:

boost::spirit::qi::rule<Iterator, parameter(), boost::spirit::qi::ascii::space_type> param;
                                           ^^

我同意它吮吸,这显然不是容易提高流浪模板参数诊断。然而,这一个东西,你将能够迅速适应pretty,因为它是惯用的任何语法/规则的定义。

I agree that it sucks that it isn't apparently easy to improve diagnostics for "stray" template arguments. However, this one is something that you will get used to pretty quickly, as it is idiomatic for any grammar/rule definition.

您的功能结构只有一个元素,而且有局限性的break单元素的元组的抽象。这是一个/非常不确定/问题,并应灵V3得到缓解。现在,无论是跳过结构:

Your function struct contains only one element, and there are limitations that "break" the abstraction with single-element tuples. This is a /very wellknown/ issue, and should be relieved in Spirit V3. For now, either skip the struct:

using function = std::vector<parameter>;

或使用'规范'的解决方法:

or use the 'canonical' workaround:

start %= eps >> (params % ',');


  • 您开始规则有虚假克莱尼星号。如果你想允许空参数列表,执行

  • Your start rule has a spurious kleen star. If you want to allow empty param lists, do

    start %= eps >> -(params % ',');
    

    微妙的不同(允许多个连续的

    start %= eps >> (-params % ',');
    


  • <子>的风格剩余元素:(%)= 是多余的规则没有语义动作

  • Remaining element of style: %= is redundant on rules without semantic actions

    看它的 住在Coliru

    See it Live On Coliru

    输出:

    <start>
      <try>int bar, int baz</try>
      <param>
    
        <!-- snip -->
        <attributes>[[[i, n, t], [b, a, z]]]</attributes>
      </param>
      <success></success>
      <attributes>[[[[[i, n, t], [b, a, r]], [[i, n, t], [b, a, z]]]]]</attributes>
    </start>
    Parsing succeeded 
    got: [int bar; int baz; ]
    

    全code

    #define BOOST_SPIRIT_DEBUG
    #include <boost/fusion/include/adapt_struct.hpp>
    #include <boost/fusion/include/io.hpp>
    #include <boost/spirit/include/qi.hpp>
    
    #include <iostream>
    #include <string>
    #include <vector>
    
    struct parameter
    {
        std::string type;
        std::string name;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(
        parameter,
        (std::string, type)
        (std::string, name)
    )
    
    inline std::ostream& operator<<(std::ostream& os, const parameter& param) { return os << param.type << ' ' << param.name;  }
    inline std::ostream& operator<<(std::ostream& os, const std::vector<parameter>& parameters) {
      for (const auto& param : parameters) { os << param << "; "; }
      return os;
    }
    
    struct function
    {
        std::vector<parameter> parameters;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(
        ::function,
        (std::vector<parameter>, parameters)
    )
    
    template <typename Iterator>
    struct function_parser : boost::spirit::qi::grammar<Iterator, function(), boost::spirit::qi::ascii::space_type>
    {
        function_parser() : function_parser::base_type(start)
        {
            using boost::spirit::qi::alnum;
            using boost::spirit::qi::alpha;
    
            string %= alpha >> *alnum;
            BOOST_SPIRIT_DEBUG_NODE(string);
    
            param %= string >> string;
            BOOST_SPIRIT_DEBUG_NODE(param);
    
            start = boost::spirit::qi::eps >> (param % ',');
            BOOST_SPIRIT_DEBUG_NODE(start);
        }
    
        boost::spirit::qi::rule<Iterator, std::string()> string;
        boost::spirit::qi::rule<Iterator, parameter(), boost::spirit::qi::ascii::space_type> param;
        boost::spirit::qi::rule<Iterator, function(), boost::spirit::qi::ascii::space_type> start;
    };
    
    int main()
    {
        std::string input_data("int bar, int baz");
    
        function fn;
        auto itr = input_data.begin();
        auto end = input_data.end();
        function_parser<decltype(itr)> g;
        bool res = boost::spirit::qi::phrase_parse(itr, end, g, boost::spirit::ascii::space, fn);
        if (res && itr == end)
        {
            std::cout << boost::fusion::tuple_open('[');
            std::cout << boost::fusion::tuple_close(']');
            std::cout << boost::fusion::tuple_delimiter(", ");
    
            std::cout << "Parsing succeeded \n";
            std::cout << "got: " << boost::fusion::as_vector(fn) << std::endl;
            //std::cout << "got: " << fn << std::endl;
        }
        else
        {
            std::cout << "Parsing failed \n";
        }
    }
    

    这篇关于提振精神 - 无法获取属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆