使用boost::spirit::x3编写通用字符串分组解析规则遇问题
问题描述
我正尝试使用boost::spirit::x3编写符合需求的通用解析规则,需求如下:
- 输入
"string,string",输出[string, string] - 输入
"string.string,string",输出[string.string, string] - 输入
"string.0.string.1.string,string",输出[string.0.string.1.string, string]
我尝试了两条规则,但都无法满足需求:
auto myRule = +x3::lexeme[ +x3::alnum >> -x3::char_('.')] % +x3::char_(',');
我的理解是:+x3::alnum >> -x3::char_('.')允许string、string.string等格式,直到遇到% +x3::char_(',')分隔符auto myRule = +x3::alnum >> +x3::lexeme[ +x3::alnum >> -x3::char_('.')] % +x3::char_(',');
我的理解是:+x3::alnum匹配基础字符串,后续规则匹配带点的格式,直到遇到分隔符
请问我哪里出错了?
问题分析与解决
你的规则错误在于对boost::spirit::x3组合逻辑的理解偏差:
第一条规则里,
+x3::alnum >> -x3::char_('.')的逻辑是先匹配一串字母数字,然后可选匹配一个点,再被+包裹后,会变成重复这个组合——这会导致它匹配类似string.string.(末尾带点)的内容,而且遇到逗号时无法正确终止,因为它会尝试继续匹配字母数字,而非识别逗号作为分隔符。第二条规则的结构完全错误,
+x3::alnum >> +[...] % ','的逻辑是先匹配一串字母数字,然后必须匹配多个被逗号分隔的[...]规则,这和你要解析的“逗号分隔的多个带点字符串”的结构完全不符。
正确的规则可以这样写:
// 允许点在任意位置的简单版本 auto element = x3::lexeme[ +(x3::alnum | x3::char_('.')) ]; auto myRule = element % x3::char_(',');
如果需要避免元素开头或结尾出现点(更贴合你的示例需求),可以用更严谨的版本:
auto element = x3::lexeme[ x3::alnum >> *(x3::char_('.') >> x3::alnum) ]; auto myRule = element % x3::char_(',');
解释:
element规则:- 简单版本直接匹配任意字母数字和点的组合,适合允许点出现在任意位置的场景;
- 严谨版本确保元素以字母数字开头,后续是任意数量的“点+字母数字”组合,完全符合你给出的示例格式。
myRule规则:用%分隔符,匹配多个element,用逗号分隔,正好对应你需要的输入格式。
内容的提问来源于stack exchange,提问作者proton
相关产品推荐
相关产品推荐

