使用boost::spirit实现简易解析器失败,请求排查问题
问题分析与解决:Boost Spirit解析三个单词到std::tuple失败
你的代码解析失败的核心原因是:+qi::char_会匹配所有字符(包括空格),第一个+qi::char_直接消耗了整个输入字符串"some second last",后续两个+qi::char_没有剩余输入可匹配,导致解析返回失败。
虽然qi::phrase_parse会自动用指定的skipper(这里是qi::ascii::space)跳过解析器之间的空白,但qi::char_本身并不排除skipper匹配的字符,所以必须明确限制要匹配的字符为非空格字符。
修复方案
将解析规则中的+qi::char_替换为匹配非空格字符的规则,有几种可选方式:
+qi::char_("^ "):匹配除空格外的任意字符+qi::graph:匹配所有可见字符(不含空格、换行等空白)+qi::alpha:仅匹配字母(适合纯英文单词场景)
以下是修复后的完整代码:
#include <boost/fusion/include/std_tuple.hpp> #include <boost/spirit/home/qi/parse.hpp> #include <boost/spirit/include/qi.hpp> #include <iostream> #include <string_view> #include <tuple> namespace { using namespace boost::spirit; } int main () { const std::string_view content {"some second last"}; std::tuple<std::string, std::string, std::string> words; auto atInput = content.begin (); const auto endOfInput = content.end (); // 使用+qi::char_("^ ")匹配非空格字符,替换原有的+qi::char_ bool result = qi::phrase_parse (atInput, endOfInput, +qi::char_("^ ") >> +qi::char_("^ ") >> +qi::char_("^ "), qi::ascii::space, words); if (result && atInput == endOfInput) { // 额外检查是否完全消耗输入 const auto& [first, second, last] = words; std::cout << "Parsing succeeded: " << first << " - " << second << " - " << last << std::endl; } else { std::cout << "Error in parsing.\n"; if (atInput != endOfInput) { std::cout << "未消耗的输入: " << std::string(atInput, endOfInput) << std::endl; } } }
额外说明
- 代码中增加了
atInput == endOfInput的检查,确保输入被完全消耗,避免出现部分解析成功但仍有剩余输入的情况。 - 如果你的单词仅包含字母,使用
+qi::alpha会更严谨,避免匹配到数字、符号等非单词字符。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

