boost spirit 重复解析器行为异常

boost spirit repetition parser behaves unexpectedly

在 windows 7
下使用 boost 1.57 spirit::qi 我正在研究 ipv6 解析器,一定是误解了重复解析器指令的工作原理。 鉴于以下(简化)

ipv6part = repeat(1, 4)[xdigit];

ipv6address =
-(repeat(1,4)[ipv6part >> lit(':')] >> ipv6part) >> 
    lit("::") >> ipv6part >> lit(':') >> ipv6part
| ...

我希望匹配以下地址:

1111:5555::ffff:eeee
1111:2222:5555::ffff:eeee
1111:2222:3333:5555::ffff:eeee
1111:2222:3333:4444:5555::ffff:eeee

然而,当我测试时,唯一的匹配是重复子句中的最大值:

1111:2222:3333:4444:5555::ffff:eeee

现在,明确指定每个组合匹配所有情况:

ipv6address =
-(repeat(1)[ipv6part >> lit(':')] >> ipv6part) >> 
    lit("::") >> ipv6part >> lit(':') >> ipv6part
| -(repeat(2)[ipv6part >> lit(':')] >> ipv6part) >> 
    lit("::") >> ipv6part >> lit(':') >> ipv6part
| -(repeat(3)[ipv6part >> lit(':')] >> ipv6part) >> 
    lit("::") >> ipv6part >> lit(':') >> ipv6part
| -(repeat(4)[ipv6part >> lit(':')] >> ipv6part) >> 
    lit("::") >> ipv6part >> lit(':') >> ipv6part
| ...

但这看起来很愚蠢;这不可能是对的。

似乎 repeat(N,M) 在解析的其余部分失败时不会回溯。 因此,如果输入是 11:22:55::ff:ee,则重复部分需要 11:22:55: 离开 :ff:ee 失败了。

从文档中我不太确定这是否是有意为之的行为,但解决方法是不要将冒号作为重复中的最后一个字符,这样可以避免拆分 ' 的问题::',像这样

ipv6address =
-(ipv6part >> repeat(1,4)[lit(':') >> ipv6part]) >> lit("::") >> ipv6part >> lit(':') >> ipv6part