gpt4 book ai didi

c++ - Boost Spirit - 跳过键值对之间不需要的行

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:14:33 25 4
gpt4 key购买 nike

我有一个键值对列表,以 EOL 分隔。我让 Boost Spirit 对格式正确的行执行我想要的操作(即 "MyKey : MyValue\r\n MyKey2 : MyValue2")。

现在我的问题是我想跳过不符合要求的行。例如:

This is some title line! 
Key1:Value1
Some more gibberish to skip
Key2:Value2

我想出了以下我认为可行的代码,但生成的 map 是空的并且解析失败。

  • 在我的 KeyRule 中,我添加了“- qi::eol”以避免在遇到第一个 KeyValue 分隔符之前耗尽无效行。
  • 在我的 ItemRule 中,两个 PairRule 都是可选的,eol 为 1 或更多以解决多个断线。

我阅读了以下线程: Why does parsing a blank line with Spirit produce an empty key value pair in map?它通过自定义 skipper 跳过注释行(以#开头),但在我的在这种情况下,我想跳过任何不包含键值分隔符 : 的行。必须有一些优雅的东西。

#include <iostream>
#include <string>
#include <map>

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

namespace qi = boost::spirit::qi;

template <typename Iterator, typename Skipper = qi::blank_type>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>(), Skipper> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {
ItemRule = -PairRule >> *(+qi::eol >> -PairRule) >> -qi::eol;
PairRule = KeyRule >> ':' >> ValueRule;
KeyRule = qi::raw[+(qi::char_ - ':' - qi::eol)];
ValueRule = qi::raw[+(qi::char_ - qi::eol)];
}
qi::rule<Iterator, std::map<std::string, std::string>(), Skipper> ItemRule;
qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> PairRule;
qi::rule<Iterator, std::string(), Skipper> KeyRule;
qi::rule<Iterator, std::string(), Skipper> ValueRule;
};

int main() {
const std::string input = " Line To Skip! \r\n My Key : Value \r\n My2ndKey : Long Value \r\n";

std::string::const_iterator iter = input.begin(), end = input.end();

KeyValueParser<std::string::const_iterator> parser;
typedef std::map<std::string, std::string> MyMap;
MyMap parsed_map;

bool result = qi::phrase_parse(iter, end, parser, qi::blank, parsed_map);

if (result && (iter == end)) {
std::cout << "Success." << std::endl;
for (MyMap::const_iterator pIter = parsed_map.begin(); pIter != parsed_map.end(); ++pIter) {
std::cout << "\"" << pIter->first << "\" : \"" << pIter->second << "\"" << std::endl;
}
} else {
std::cout << "Something failed. Unparsed: ->|" << std::string(iter, end) << "|<-" << std::endl;
}

getchar();
return 0;
}

最佳答案

我能想到的最优雅的方法是解析键值对/可选地/,然后是任何乱码,直到行尾。

你可以这样写:

ItemRule  = -PairRule % (*~char_("\r\n") >> eol);

唯一需要注意的是,在乱码行中,将插入“默认”对(空键和值),因此您必须删除该后解析。

一种等效的写法(但不太优雅)是:

ItemRule  = (hold[PairRule] | omit[ *~char_("\r\n") ]) % eol;

演示

这是一个完整的演示。注意,我还将 skipper 知识移到了语法中(这对于语法的正确操作至关重要)。

最后,我使用 BOOST_SPIRIT_DEBUG 来打印调试输出。

Live On Coliru

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <map>

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>()> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {

using namespace qi;

ItemRule = skip(blank) [ -PairRule % (*~char_("\r\n") >> eol) ];
ItemRule = skip(blank) [ hold[PairRule] | omit[ *~char_("\r\n") ] ] % eol;
PairRule = KeyRule >> ':' >> ValueRule;
KeyRule = +~char_("\r\n:");
ValueRule = +~char_("\r\n");

BOOST_SPIRIT_DEBUG_NODES((ItemRule)(PairRule)(KeyRule)(ValueRule))
}
private:
qi::rule<Iterator, std::map<std::string, std::string>()> ItemRule;
qi::rule<Iterator, std::pair<std::string, std::string>(), qi::blank_type> PairRule;
// lexemes
qi::rule<Iterator, std::string()> KeyRule, ValueRule;
};

int main() {
const std::string input = R"(
Line To Skip!
My Key : Value
Some more gibberish to skip
My2ndKey : Long Value
)";

std::string::const_iterator iter = input.begin(), end = input.end();

KeyValueParser<std::string::const_iterator> parser;
std::map<std::string, std::string> parsed_map;

bool result = qi::parse(iter, end, parser, parsed_map);

if (result && (iter == end)) {
std::cout << "Success.\n";

// drop empty lines:
parsed_map.erase("");

for (auto& p : parsed_map)
std::cout << "\"" << p.first << "\" : \"" << p.second << "\"\n";
} else {
std::cout << "Something failed. Unparsed: ->|" << std::string(iter, end) << "|<-\n";
}
}

打印

Success.
"My Key " : "Value "
"My2ndKey " : "Long Value "

带有调试信息

<ItemRule>
<try>\n Line To Skip! \n M</try>
<PairRule>
<try>\n Line To Skip! \n M</try>
<KeyRule>
<try>\n Line To Skip! \n M</try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> Line To Skip! \n My</try>
<KeyRule>
<try>Line To Skip! \n My </try>
<success>\n My Key : Value \nS</success>
<attributes>[[L, i, n, e, , T, o, , S, k, i, p, !, ]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My Key : Value \nSo</try>
<KeyRule>
<try>My Key : Value \nSome</try>
<success>: Value \nSome more g</success>
<attributes>[[M, y, , K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Value \nSome more gib</try>
<success>\nSome more gibberish</success>
<attributes>[[V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\nSome more gibberish</success>
<attributes>[[[M, y, , K, e, y, ], [V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try>Some more gibberish </try>
<KeyRule>
<try>Some more gibberish </try>
<success>\n My2ndKey : Long </success>
<attributes>[[S, o, m, e, , m, o, r, e, , g, i, b, b, e, r, i, s, h, , t, o, , s, k, i, p]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My2ndKey : Long </try>
<KeyRule>
<try>My2ndKey : Long V</try>
<success>: Long Value \n</success>
<attributes>[[M, y, 2, n, d, K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Long Value \n</try>
<success>\n</success>
<attributes>[[L, o, n, g, , , , , V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\n</success>
<attributes>[[[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try></try>
<KeyRule>
<try></try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<success></success>
<attributes>[[[[], []], [[M, y, , K, e, y, ], [V, a, l, u, e, ]], [[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]]</attributes>
</ItemRule>

关于c++ - Boost Spirit - 跳过键值对之间不需要的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35585383/

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