C++ 提升精神-修剪最后一个字符和分隔符之间的空格
我是新来的 我有一个格式为“Key:Value\r\nKey2:Value2\r\n”的字符串,正试图对其进行分析。在这种特定的形式下,用Boost-Spirit进行解析非常简单。但是,为了更加稳健,我还需要处理以下情况: “我的密钥:Value\r\n My2ndKey:LongValue\r\n” 在这种情况下,我需要在键/值分隔符之前和之后修剪前导空格和尾随空格,以便得到以下映射: “我的钥匙”、“价值” “My2ndKey”、“LongValue” 为了实现这一点,我使用了qi::hold,但由于不支持boost::multi_-pass迭代器和我尝试使用的嵌入式解析器,因此我出现了编译错误。必须有一个简单的方法来实现这一点 我读了以下文章(以及其他许多关于这个主题的文章): 我正在寻找我的问题的解决方案,这些文章似乎没有完全涵盖这一点。我还想更好地了解这是如何实现的。作为一个小问题,我一直看到“%=”运算符,这对我的情况有用吗?MyRule%=MyRule。。。是否用于递归解析 下面的代码正确地解析了我的字符串,只是没有删除最后一个非空格字符和分隔符之间的空格:(使用的跳过程序是qi::blank_类型(没有EOL的空格) 谢谢C++ 提升精神-修剪最后一个字符和分隔符之间的空格,c++,parsing,boost,boost-spirit,boost-spirit-qi,C++,Parsing,Boost,Boost Spirit,Boost Spirit Qi,我是新来的 我有一个格式为“Key:Value\r\nKey2:Value2\r\n”的字符串,正试图对其进行分析。在这种特定的形式下,用Boost-Spirit进行解析非常简单。但是,为了更加稳健,我还需要处理以下情况: “我的密钥:Value\r\n My2ndKey:LongValue\r\n” 在这种情况下,我需要在键/值分隔符之前和之后修剪前导空格和尾随空格,以便得到以下映射: “我的钥匙”、“价值” “My2ndKey”、“LongValue” 为了实现这一点,我使用了qi::hol
template <typename Iterator, typename Skipper>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>(), Skipper> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {
ItemRule = PairRule >> *(qi::lit(END_OF_CMD) >> PairRule);
PairRule = KeyRule >> PAIR_SEP >> ValueRule;
KeyRule = +(qi::char_ - qi::lit(PAIR_SEP));
ValueRule = +(qi::char_ - qi::lit(END_OF_CMD));
}
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()> KeyRule;
qi::rule<Iterator, std::string()> ValueRule;
};
模板
结构KeyValueParser:qi::grammar{
KeyValueParser():KeyValueParser::基本类型(ItemRule){
ItemRule=PairRule>>*(qi::lit(命令的结尾)>>PairRule);
PairRule=KeyRule>>PAIR\u SEP>>ValueRule;
KeyRule=+(qi::char\uqi::lit(PAIR\u SEP));
ValueRule=+(qi::char_uqi::lit(命令的结尾));
}
qi::规则项规则;
齐:治廉;
qi::规则键规则;
qi::规则值规则;
};
您需要使用KeyRule=qi::raw[+(qi::char\uqi::lit(PAIR\u SEP))];
为了了解原因,让我们尝试研究几种解析字符串
“ab:”
的方法
首先,让我们记住以下解析器/指令是如何工作的:
- :禁用跳过程序时,此指令与主题匹配
- :放弃主题的属性,并返回指向输入流中匹配字符的迭代器对
- :plus解析器尝试匹配其
主题的1倍或更多倍
- :差异解析器首先尝试解析
,如果b
成功,b
失败。当a-b
失败时,它匹配b
a
:匹配任何字符。它是一个字符
:匹配lit(“:”)
,但忽略其属性。它是一个“:”
lexeme[+(char_u-lit(':'))]
:从规则中删除skipper,您就有了一个隐式lexeme。由于没有skipper,它是这样的:':'
失败,char\u
与“a”匹配,当前合成的属性为“a”“->
”:“
失败,字符匹配“”,当前合成属性为“a”
“b”->:”
失败,字符与“b”匹配,当前合成属性为“ab”
“->”:“
失败,字符匹配“”,当前合成属性为“ab”
“:”->”:“
成功,最终合成的属性为“a b”
+(char.-lit(“:”)
:由于它有一个skipper,每个原语分析器在尝试之前都会预先跳过:
“a'->':'
失败,char\u
与“a”匹配,当前合成的属性为“a”
''->在尝试之前跳过此操作:'
。
“b”->:”
失败,字符与“b”匹配,当前合成属性为“ab”
''->在尝试之前跳过此操作:'
。
“:”->”:“
成功,最终合成的属性为“ab”
raw[+(char:)]
:主题与2.
完全相同。raw指令忽略“ab”
并返回从'a'
到'b'
的迭代器对。由于规则的属性是std::string
,因此将从该迭代器对构造字符串,从而生成所需的“a b”
您需要使用KeyRule=qi::raw[+(qi::char\uqi::lit(PAIR\u SEP))];
为了了解原因,让我们尝试研究几种解析字符串“ab:”
的方法
首先,让我们记住以下解析器/指令是如何工作的:
- :禁用跳过程序时,此指令与主题匹配
- :放弃主题的属性,并返回指向输入流中匹配字符的迭代器对
- :plus解析器尝试匹配其
主题的1倍或更多倍
- :差异解析器首先尝试解析
b
,如果b
成功,a-b
失败。当b
失败时,它匹配a
字符
:匹配任何字符。它是一个
lit(“:”)
:匹配“:”
,但忽略其属性。它是一个
lexeme[+(char_u-lit(':'))]
:从规则中删除skipper,您就有了一个隐式lexeme。由于没有skipper,它是这样的:
“a'->':'
失败,char\u
与“a”匹配,当前合成的属性为“a”
“->”:“
失败,字符匹配“”,当前合成属性为“a”
“b”->:”
失败,字符与当前合成器的“b”匹配