“总是成功”绰绰有余?[乐]

jak*_*kar 5 grammar assertion raku

在节下的语法文档中:

“永远成功”断言

我复制了那里提供的示例,并添加了代码来显示在解析机制的每个阶段生成的表:

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;
Run Code Online (Sandbox Code Playgroud)

结果如下:

[!]
---> !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
Run Code Online (Sandbox Code Playgroud)

我预计表@!numbers 中只有 3 次推送,但我得到了 4 次。我对排除方法“TOP”中表 @!n​​umbers 的最后一个值感到困惑。

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

最后一个“Always Succeed”断言从何而来?

rai*_*iph 6

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

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

在您的代码中,Ais<.succ>减少到<?>,始终匹配。有4次尝试,因此A匹配4次。相反B,即<digit>+,在第四次尝试中失败,因此只匹配3次。