提振精神琪:在克林星分析器忽略元素 [英] Boost Spirit Qi: Omit element in Kleene Star parser

查看:191
本文介绍了提振精神琪:在克林星分析器忽略元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要解析特殊构造和扔剩下的路程。但我不希望使用的队长。

我要得到这些结构的载体,所以我用一个克莱尼明星解析器为主要原则。但是,每次的东西被扔掉,一个默认构造元件被插入到载体中。

下面是一个由例子。它只是查找字符串测试并引发休息了,至少这是该计划。但每一次的规则垃圾成功增加了一个默认的构造项向量在规则所有,给人一种输出7 insteat 1.我怎么能告诉灵刚添加到向量如果规则项目成功?

 的#define BOOST_SPIRIT_USE_PHOENIX_V3#包括LT&;升压/配置/ warning_disable.hpp>
#包括LT&;升压/精神/有/ qi.hpp>#包括LT&;升压/融合/调整/ struct.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>#包括LT&;&iostream的GT;
#包括LT&;串GT;
#包括LT&;矢量>命名空间补气=的boost ::精神::补气;结构容器{
  性病::字符串名称;
  布尔假;
};
BOOST_FUSION_ADAPT_STRUCT(::容器,
                          (标准::字符串,名称)
                          (BOOL,假人))诠释主(){
  的typedef的std ::字符串::为const_iterator迭代器;  齐::规则<迭代器的std ::矢量<集装箱内容GT;()>所有;
  齐::规则<迭代器,容器()>项目;
  齐::规则<迭代器,标准::字符串()> string_rule;
  齐::规则<&迭代器GT;垃圾;  所有= *(垃圾|项目);
  垃圾气= :: char_ - 气::亮起(测试);
  string_rule =齐::字符串(测试);
  项目= string_rule>>齐:: ATTR(真);  的std ::矢量<集装箱内容GT; AST;  性病::字符串输入=blaTestbla;  迭代器首先= input.begin();
  最后迭代器= input.end();  布尔结果=齐::解析(第一个,最后,全部,AST);
  如果(结果){
    结果=倒数第一==;
  }  如果(结果){
    性病::法院LT&;< 经分析<< ast.size()&所述;&下; 元素(多个)&所述;&下;的std :: ENDL;
  }其他{
    性病::法院LT&;< 失败<<的std :: ENDL;
  }}


解决方案

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

  *垃圾>> - (项目%*垃圾)>> *垃圾*垃圾>> *(项目>> *垃圾)所有= *(垃圾|项[PHX ::的push_back(气:: _ VAL,补气:: _ 1)]);

和来自cv_and_he解决方案:

 的#define BOOST_SPIRIT_USE_PHOENIX_V3#包括LT&;升压/配置/ warning_disable.hpp>
#包括LT&;升压/精神/有/ qi.hpp>#包括LT&;升压/融合/调整/ struct.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>#包括LT&;&iostream的GT;
#包括LT&;串GT;
#包括LT&;矢量>命名空间补气=的boost ::精神::补气;结构容器{
  性病::字符串名称;
  布尔假;
};
BOOST_FUSION_ADAPT_STRUCT(::容器,
                          (标准::字符串,名称)
                          (BOOL,假人))结构container_vector {// ADDED
    的std ::矢量<集装箱内容GT;数据;
};名字空间boost {空间{精神特质空间// ADDED
{
    模板<>
    结构is_container< container_vector> :提高:: MPL :: true_ {};    模板<>
    结构container_value< container_vector> {
        typedef的可选<集装箱>类型;
    };    模板<>
    结构push_back_container< container_vector,可选<集装箱> > {
        静态布尔调用(container_vector&安培;续,常量可选<集装箱>&放大器; VAL){
            如果(VAL)
                cont.data.push_back(* VAL);
            返回true;
        }
    };
}}}诠释主(){
  的typedef的std ::字符串::为const_iterator迭代器;  齐::规则<迭代器,container_vector()>所有; // CHANGED
  齐::规则<迭代器,容器()>项目;
  齐::规则<迭代器,标准::字符串()> string_rule;
  齐::规则<&迭代器GT;垃圾;  所有= *(垃圾|项目);
  垃圾气= :: char_ - 气::亮起(测试);
  string_rule =齐::字符串(测试);
  项目= string_rule>>齐:: ATTR(真);  container_vector AST; // CHANGED  性病::字符串输入=blaTestbla;  迭代器首先= input.begin();
  最后迭代器= input.end();  布尔结果=齐::解析(第一个,最后,全部,AST);
  如果(结果){
    结果=倒数第一==;
  }  如果(结果){
    性病::法院LT&;< 经分析<< ast.data.size()&所述;&下; 元素(多个)&所述;&下;的std :: ENDL; // CHANGED
  }其他{
    性病::法院LT&;< 失败<<的std :: ENDL;
  }}

虽然我不想用我的船长结束了:

 开始=齐::跳过(garbage.alias())[*项目];

这最后的解决方案是使用Linux内核的c文件,我的生产规则,我不科学的测试速度最快的(1-2%)。

I want to parse special constructs and throw the rest away. But I don't want to use a skipper.

I want to get a vector of these constructs, so I use a Kleene Star parser as main rule. But, everytime something gets thrown away, a default constructed element is inserted into the vector.

Here is a made up example. It just looks for the string Test and throws the rest away, at least this is the plan. But every time the rule garbage succeeds it adds a default constructed item to the vector in the rule all, giving an output of 7 insteat of 1. How can I tell Spirit to just add to the vector if the rule item succeeds?

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

}

解决方案

Since sehe's answer was more or less for educational purposes, we have now several solutions:

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

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

all = *(garbage | item[phx::push_back(qi::_val,qi::_1)]);

And the solution from cv_and_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;
  }

}

Although I didn't want to use a skipper I ended up with:

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

This last solution was the fastest (by 1-2%) in my unscientific tests using the c-files of the Linux kernel with my production rules.

这篇关于提振精神琪:在克林星分析器忽略元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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