gpt4 book ai didi

c++ - boost 灵气 : Omit element in Kleene Star parser

转载 作者:太空狗 更新时间:2023-10-29 20:42:05 27 4
gpt4 key购买 nike

我想解析特殊的结构,把剩下的扔掉。但我不想使用 skipper 。

我想获得这些构造的 vector ,所以我使用 Kleene Star 解析器作为主要规则。但是,每当有东西被丢弃时,一个默认构造的元素就会被插入到 vector 中。

这是一个虚构的例子。它只查找字符串 Test 并丢弃其余部分,至少这是计划。但是每次规则 garbage 成功时,它都会将默认构造的项目添加到规则 all 中的 vector 中,输出 7 insteat 1。我如何告诉 Spirit如果规则 item 成功,就添加到 vector 中?

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

}

最佳答案

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

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

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

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

来自 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;
}

}

虽然我不想使用 skipper ,但我最终得到了:

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

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

关于c++ - boost 灵气 : Omit element in Kleene Star parser,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20038186/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com