使用 Boost.Spirit 解析 INI 部分时出现问题

问题描述 投票:0回答:1
我正在为一个大学项目研究解析器。我发现了 Boost.Spirit 并决定使用它。在阅读其文档并实现一些基本示例后,我尝试制作一个解析器来解析一个小的 INI 部分。程序的输出是:

程序错误

<section> <try>[Section]\nkey1 = val</try> <key> <try>Section]\nkey1 = valu</try> <success>]\nkey1 = value1\nkey2</success> <attributes>[]</attributes> </key> <fail/> </section> -------------------- Parsing failed --------------------
代码

#include <boost/spirit/include/qi.hpp> #include <iostream> #include <string> using namespace std; namespace client { namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; template <typename Iterator> struct ini_grammar : qi::grammar<Iterator, ascii::space_type> { ini_grammar() : ini_grammar::base_type(section) { using qi::char_; key = +char_("a-zA-Z_0-9"); pair = key >> '=' >> key; section = '[' >> key >> ']' >> '\n' >> *(pair >> '\n') ; BOOST_SPIRIT_DEBUG_NODES((key)(pair)(section)) } qi::rule<Iterator, ascii::space_type> section, pair, key; }; } int main() { using boost::spirit::qi::phrase_parse; using boost::spirit::ascii::space; string ini_section = "[Section]\n" "key1 = value1\n" "key2 = value2\n"; typedef client::ini_grammar<string::const_iterator> ini_grammar; ini_grammar grammar; string::const_iterator iter = ini_section.begin(); string::const_iterator end = ini_section.end(); bool r = phrase_parse(iter, end, grammar, space); if (r == true) { cout << "-------------------------\n"; cout << "Parsing succeeded\n"; cout << "-------------------------\n"; } else { cout << "-------------------------\n"; cout << "Parsing failed\n"; cout << "-------------------------\n"; } return 0; }
对于某些上下文,我读了这个SO

thread。我使用问题中提供的代码作为参考,并尝试使用答案中提供的一些提示。

c++ boost-spirit
1个回答
0
投票
钥匙不应使用船长。这是一个“词位”。

接下来,

'\n'

永远无法匹配,因为你的船长已经吃掉了它。

由于您希望这些规则中的空格无关紧要,而不是换行符,因此请使用

qi::blank

,而不是 
qi::space
。另外,匹配 
qi::eol
 以获得更多可移植性(DOS/UNIX 行结束)。
对于最后的修饰,如果接受空白/空行,则接受多个行结束。

当你这样做时,不要暴露船长的选择,因为这对你的语法至关重要。

我还选择使用

qi::space

/
qi::blank
qi::char_
 保持一致。

住在Coliru

// #define BOOST_SPIRIT_DEBUG #include <boost/spirit/include/qi.hpp> #include <iostream> namespace qi = boost::spirit::qi; namespace client { template <typename Iterator> struct ini_grammar : qi::grammar<Iterator> { ini_grammar() : ini_grammar::base_type(start) { key = +qi::char_("a-zA-Z_0-9"); pair = key >> '=' >> key; section = '[' >> key >> ']' >> +qi::eol >> *(pair >> +qi::eol); start = qi::skip(qi::blank)[section]; BOOST_SPIRIT_DEBUG_NODES((key)(pair)(section)) } private: qi::rule<Iterator> start; qi::rule<Iterator, qi::blank_type> section, pair; qi::rule<Iterator> key; }; } // namespace client int main() { std::string const ini_section = R"([Section] key1 = value1 key2 = value2 )"; using It = std::string::const_iterator; client::ini_grammar<It> grammar; It iter = ini_section.begin(), end = ini_section.end(); bool r = parse(iter, end, grammar); if (r == true) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "-------------------------\n"; } else { std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "-------------------------\n"; } }
打印

------------------------- Parsing succeeded -------------------------
参见

提升精神船长问题

© www.soinside.com 2019 - 2024. All rights reserved.