绰绰有余"Always succeed"? [乐]

More than enough "Always succeed"? [ RAKU ]

在语法文档的第 :

部分下

"Always succeed" assertion

我重现了此处提供的示例,并添加了代码以显示在解析机制的每个阶段生成的 table:

use v6.d;

grammar Digifier {
    rule TOP { [ <.succ> <digit>+ ]+ }
    token succ   { <?> }
    token digit { <[0..9]> }
}

class Letters {
    has @!numbers;

    method digit ($/) { @!numbers.tail ~= <a b c d e f g h i j>[$/]; say '---> ' ~ @!numbers }
    method succ  ($/) { @!numbers.push: '!'; say @!numbers }
    method TOP   ($/) { make @!numbers[^(*-1)] }
}

say 'FINAL ====> ' ~ Digifier.parse('123 456 789', actions => Letters.new).made;

结果如下:

[!]
---> !b
---> !bc
---> !bcd
[!bcd !]
---> !bcd !e
---> !bcd !ef
---> !bcd !efg
[!bcd !efg !]
---> !bcd !efg !h
---> !bcd !efg !hi
---> !bcd !efg !hij
[!bcd !efg !hij !]

FINAL ====> !bcd !efg !hij

我预计 table @!numbers 中只有 3 次推送,但我得到了 4 次。 我对在方法 "TOP".

中需要排除 table @!numbers 的最后一个值感到困惑

是的,我知道代码产生了正确的结果,但为什么呢?

最后一个 "Always Succeed" 断言来自哪里?

一个量化组,例如[ A B ]+,实际上是一个循环,重复尝试匹配A,如果匹配,则尝试匹配B

除非它是一个无限循环——在这种情况下你的程序会挂起——它最终会匹配 N 次然后继续。如果 A always 匹配,但你的程序 没有 挂起,那么这一定意味着 B 最终失败了。如果是这样,A 肯定比 B.

多匹配一次

在您的代码中,A<.succ>,后者缩减为 <?>,始终匹配。有 4 次尝试,因此 A 匹配 4 次。相比之下 B,即 <digit>+,在第四次尝试时失败,因此仅匹配 3 次。