Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 提升灵气:省略Kleene星分析器中的元素_C++_Boost_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 提升灵气:省略Kleene星分析器中的元素

C++ 提升灵气:省略Kleene星分析器中的元素,c++,boost,boost-spirit,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Spirit Qi,我想解析特殊的构造,然后扔掉其余的。但我不想用船长 我想得到这些结构的向量,所以我使用Kleene星形解析器作为主要规则。但是,每当有东西被扔掉时,一个默认的构造元素就会被插入到向量中 下面是一个虚构的例子。它只是查找字符串Test,然后扔掉其余的,至少这是计划。但每次规则垃圾成功时,它都会向规则all中的向量添加一个默认构造项,输出值为7,而不是1。如果规则项成功,我如何告诉Spirit只添加到向量 #define BOOST_SPIRIT_USE_PHOENIX_V3 #include &

我想解析特殊的构造,然后扔掉其余的。但我不想用船长

我想得到这些结构的向量,所以我使用Kleene星形解析器作为主要规则。但是,每当有东西被扔掉时,一个默认的构造元素就会被插入到向量中

下面是一个虚构的例子。它只是查找字符串
Test
,然后扔掉其余的,至少这是计划。但每次规则
垃圾
成功时,它都会向规则
all
中的向量添加一个默认构造项,输出值为7,而不是1。如果规则
成功,我如何告诉Spirit只添加到向量

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

namespace qi = boost::spirit::qi;

struct container {
  std::string name;
  bool        dummy;
};
BOOST_FUSION_ADAPT_STRUCT(::container,
                          (std::string, name)
                          (bool, dummy))

int main() {
  typedef std::string::const_iterator iterator;

  qi::rule<iterator, std::vector<container>()> all;
  qi::rule<iterator, container()> item;
  qi::rule<iterator, std::string()> string_rule;
  qi::rule<iterator> garbage;

  all = *(garbage | item);
  garbage = qi::char_ - qi::lit("Test");
  string_rule = qi::string("Test");
  item = string_rule >> qi::attr(true);

  std::vector<container> ast;

  std::string input = "blaTestbla";

  iterator first = input.begin();
  iterator last = input.end();

  bool result = qi::parse(first, last, all, ast);
  if (result) {
    result = first == last;
  }

  if (result) {
    std::cout << "Parsed " << ast.size() << " element(s)" << std::endl;
  } else {
    std::cout << "failure" << std::endl;
  }

}
#定义提升(精神)使用(凤凰)
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
结构容器{
std::字符串名;
布尔假人;
};
BOOST\u FUSION\u ADAPT\u结构(::容器,
(std::字符串,名称)
(傻瓜)
int main(){
typedef std::string::const_迭代器迭代器;
齐:统治一切;
qi::规则项;
qi::规则字符串\规则;
规则垃圾;
全部=*(垃圾|项);
垃圾=qi::char_uqi::lit(“测试”);
string_rule=qi::string(“测试”);
item=string\u rule>>qi::attr(true);
std::载体ast;
std::string input=“blaTestbla”;
迭代器first=input.begin();
迭代器last=input.end();
bool result=qi::parse(first、last、all、ast);
如果(结果){
结果=第一个==最后一个;
}
如果(结果){
std::cout快速修复(不一定是最有效的)是

它打印:

Parsed 3 element(s)

请参见

由于sehe的回答或多或少是出于教育目的,我们现在有几种解决方案:

*garbage >> -(item % *garbage) >> *garbage

*garbage >> *(item >> *garbage)

all = *(garbage | item[phx::push_back(qi::_val,qi::_1)]);
以及cv_和_he的解决方案:

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

namespace qi = boost::spirit::qi;

struct container {
  std::string name;
  bool        dummy;
};
BOOST_FUSION_ADAPT_STRUCT(::container,
                          (std::string, name)
                          (bool, dummy))

struct container_vector {   //ADDED
    std::vector<container> data;
};

namespace boost{ namespace spirit{ namespace traits //ADDED
{
    template <>
    struct is_container<container_vector> : boost::mpl::true_ {};

    template <>
    struct container_value<container_vector> {
        typedef optional<container> type;
    };

    template <>
    struct push_back_container<container_vector,optional<container> > {
        static bool call(container_vector& cont, const optional<container>& val) {
            if(val)
                cont.data.push_back(*val);
            return true;
        }
    };
}}}

int main() {
  typedef std::string::const_iterator iterator;

  qi::rule<iterator, container_vector()> all; //CHANGED
  qi::rule<iterator, container()> item;
  qi::rule<iterator, std::string()> string_rule;
  qi::rule<iterator> garbage;

  all = *(garbage | item);
  garbage = qi::char_ - qi::lit("Test");
  string_rule = qi::string("Test");
  item = string_rule >> qi::attr(true);

  container_vector ast;     //CHANGED

  std::string input = "blaTestbla";

  iterator first = input.begin();
  iterator last = input.end();

  bool result = qi::parse(first, last, all, ast);
  if (result) {
    result = first == last;
  }

  if (result) {
    std::cout << "Parsed " << ast.data.size() << " element(s)" << std::endl;   //CHANGED 
  } else {
    std::cout << "failure" << std::endl;
  }

}

最后一个解决方案在我使用Linux内核的c文件和我的生产规则进行的非科学测试中是最快的(1-2%)。

谢谢,但它应该只找到一个元素。但是你的回答让我思考了一下;我的问题是
>
的不同传播类型。这导致了规则
*垃圾>>-(item%*垃圾)>>*垃圾
或更短的
*垃圾>>*(item>>*垃圾)
,可以得到想要的结果。@Mike干杯,这正是我想让你开始的。:-D(好吧,再多一些文本,因为不允许只笑一个微笑)@MikeM你可能应该把它作为一个答案(并接受它)除非sehe编辑他的答案。就目前情况而言,接受的答案不起作用。这是一个可能过于复杂的备选方案。最简单的方法是使用语义动作:
all=*(垃圾|项[phx::push_back(qi:| val,qi:|1)])
@cv_和他感谢你完全不同的方法。我还添加了答案。这仍然是一个令人印象深刻的答案。我忘记了其中一些事情。我会再次+1。
#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

namespace qi = boost::spirit::qi;

struct container {
  std::string name;
  bool        dummy;
};
BOOST_FUSION_ADAPT_STRUCT(::container,
                          (std::string, name)
                          (bool, dummy))

struct container_vector {   //ADDED
    std::vector<container> data;
};

namespace boost{ namespace spirit{ namespace traits //ADDED
{
    template <>
    struct is_container<container_vector> : boost::mpl::true_ {};

    template <>
    struct container_value<container_vector> {
        typedef optional<container> type;
    };

    template <>
    struct push_back_container<container_vector,optional<container> > {
        static bool call(container_vector& cont, const optional<container>& val) {
            if(val)
                cont.data.push_back(*val);
            return true;
        }
    };
}}}

int main() {
  typedef std::string::const_iterator iterator;

  qi::rule<iterator, container_vector()> all; //CHANGED
  qi::rule<iterator, container()> item;
  qi::rule<iterator, std::string()> string_rule;
  qi::rule<iterator> garbage;

  all = *(garbage | item);
  garbage = qi::char_ - qi::lit("Test");
  string_rule = qi::string("Test");
  item = string_rule >> qi::attr(true);

  container_vector ast;     //CHANGED

  std::string input = "blaTestbla";

  iterator first = input.begin();
  iterator last = input.end();

  bool result = qi::parse(first, last, all, ast);
  if (result) {
    result = first == last;
  }

  if (result) {
    std::cout << "Parsed " << ast.data.size() << " element(s)" << std::endl;   //CHANGED 
  } else {
    std::cout << "failure" << std::endl;
  }

}
start = qi::skip(garbage.alias())[*item];