提升精神罗马数字解析器示例

时间:2011-08-24 17:10:11

标签: c++ boost boost-spirit

尝试学习提升精神,文档中给出的例子让我有些困惑。

参考此代码:

http://www.boost.org/doc/libs/1_46_1/libs/spirit/example/qi/roman.cpp

特别是这段语法:

        start = eps             [_val = 0] >>
            (
                +lit('M')       [_val += 1000]
                ||  hundreds    [_val += _1]
                ||  tens        [_val += _1]
                ||  ones        [_val += _1]
            )

有人可以向我解释为什么它是+亮('M')而不是*亮('M')。因为毕竟不能有零个或多个M与一个或多个M?

4 个答案:

答案 0 :(得分:2)

Spirit中的a || b运算符表示abb表示aa表示M。在运算符的meaing中,没有M的情况是隐式的(因为*lit('M')的匹配可能存在,也可能不存在)。另外,在M的情况下,如果有 _val,您是否会说匹配第一条规则?无论如何它都是有效的,{{1}}将增加1000。

答案 1 :(得分:0)

+lit('M')*lit('M')都是正确的。但是在我看来,前者比后者(语义上)更具可读性,因为如果1000匹配,前者说添加 _valone,并反复做。另一方面,后者难以阅读,因为人们可以将其视为添加 1000_val,即使对于错误的零匹配也是如此。 1000未添加_val以进行零次匹配,但解析器*lit('M')似乎也匹配零匹配(似乎有点令人困惑)。

所以+lit('M')更可取。


好的。我看了你的评论。 CCLLIX不是有效的罗马数字。你认为它的价值是什么? 309?如果是这样,那么CCCIX会有什么价值?它太309了,它是正确的。你错了。因此,当您使用*lit('M')时,解析器会停止。另请注意,即使您使用+lit('M')进行此错误输入,解析器也会停止。

答案 2 :(得分:0)

它是(一个或多个Ms)或数百或数十个OR。 (零个或多个Ms)或数百个或数十个OR将匹配没有Ms aka空字符串并毫无意义地添加1000。

答案 3 :(得分:0)

在Qi中匹配表达式A || B意味着只匹配A,或仅匹配BA followed by B。因此,在您的情况下,+lit('M') || hundreds表示+lit('M'),或hundreds+lit('M')followed by hundreds。因此,语法允许匹配任何甚至不以M开头的罗马数字。