在这里提升精神新人。
我有一个字符串形式为“Key:Value \ r \ nKey2:Value2 \ r \ n”,我正在尝试解析它。在这种特定的形式中,用Boost Spirit解析它是微不足道的。但是,为了更加健壮,我还需要处理这样的案例:
“我的密钥:值\ r \ n My2ndKey:长< 4个空格>值\ r \ n”
在这种情况下,我需要修剪键/值分隔符之前和之后的前导和尾随空格,以便得到以下映射:
“我的钥匙”,“价值”
“My2ndKey”,“长< 4个空格>值”
我使用qi :: hold来实现这一点但由于不支持的boost :: multi_pass迭代器和我试图使用的嵌入式解析器,我得到了编译错误。必须有一种简单的方法来实现这一目标。
我阅读了以下文章(以及关于这个主题的许多其他文章):
http://boost-spirit.com/home/articles/qi-example/parsing-a-list-of-key-value-pairs-using-spirit-qi/ http://boost-spirit.com/home/2010/02/24/parsing-skippers-and-skipping-parsers/
Boost spirit parsing string with leading and trailing whitespace
我正在寻找我的问题的解决方案,这些文章似乎没有完全涵盖。我还想更好地了解这是如何实现的。作为一个小小的奖金问题,我一直看到'%='运算符,这对我的情况有用吗? MyRule%= MyRule ...用于递归解析?
下面的代码正确地解析了我的字符串,只是它没有删除最后一个非空格字符和分隔符之间的空格。 :(使用的船长是qi :: blank_type(没有EOL的空间)。
谢谢!
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;
};
答案 0 :(得分:0)
您需要使用KeyRule = qi::raw[ +(qi::char_ - qi::lit(PAIR_SEP)) ];
为了了解原因,让我们尝试研究解析字符串"a b :"
的几种方法。
首先让我们记住以下解析器/指令的工作原理:
lexeme[subject]
:此指令与subject
匹配,同时禁用了跳过者。
raw[subject]
:丢弃subject
的属性并返回指向输入流中匹配字符的迭代器对。
+subject
:加号解析器尝试匹配其subject
的1次或更多次。
a-b
:差异解析器首先尝试解析b
,如果b
成功,则a-b
失败。 b
失败时,它与a
匹配。
char_
:匹配任何字符。这是一个PrimitiveParser
。
lit(':')
:匹配':'
但忽略其属性。这是一个PrimitiveParser
。
lexeme[ +(char_ - lit(':')) ]
:通过从规则中删除队友,您有一个隐含的词汇。由于没有船长,它是这样的:'a' - &gt;
':'
失败,char_
匹配'a',当前合成的属性为“a” '' - &gt;':'
失败,char_
匹配'',当前合成的属性为“a” 'b' - &gt;':'
失败,char_
匹配'b',当前合成的属性为“a b” '' - &gt;':'
失败,char_
匹配'',当前合成的属性为“a b” ':' - &gt;':'
成功,最终合成属性为“a b”
+(char_ - lit(':'))
:由于它有一个队长,因此每个PrimitiveParser在尝试之前都会预先跳过:'a' - &gt;
':'
失败,char_
匹配'a',当前合成的属性为“a” '' - &gt;在尝试':'
之前跳过此选项 'b' - &gt;':'
失败,char_
匹配'b',当前合成的属性为“ab”
'' - &gt;在尝试':'
之前跳过此选项 ':' - &gt;':'
成功,最终合成属性为“ab”
raw[ +(char_ - lit(':') ) ]
:主题与2.
完全相同。 raw指令忽略"ab"
并返回从'a'
到'b'
的迭代器对。由于规则的属性为std::string
,因此会从该迭代器对构造一个字符串,从而生成"a b"
这就是您想要的。