use*_*601 8 grammar perl6 raku
将变量传递给tokenor regex或rule相当简单。例如,输出
grammar Foo {
token TOP { (.) {} <bar($0)> }
token bar($s) { {say ~$s} .+ }
}
Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
很简单x。但是当使用原型时,事情变得很糟糕。例如,1让我们做一个简单的原型来区分字符为字母或数字的其余部分:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
这枚炸弹声称expected 1 argument but got 2为bar。好的,在普通方法中,我们必须在proto声明中指定args,所以我们只声明一下:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar ($s) { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
现在我们得到相反的结果:expected 2 arguments but got 1。嗯,也许这意味着原始声明正在消耗该值,并且没有传递任何东西。因此,我尝试将其插入:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar (|) { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
同样的错误在这里。它声称expected 2 arguments, but got 1。2 不知何故,使用proto占用了争论。目前,我发现的唯一解决方案是使用动态变量,这使我认为可能存在一些隐藏步骤,其中变量没有从原型传递到候选对象。
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar ($*s) { * }
token bar:sym<a> { {say ~$*s} <alpha>+ }
token bar:sym<1> { {say ~$*s} <digit>+ }
}
Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
但这似乎并不是一个非常直观的步骤。一个人将如何以一种非动态的方式将变量直接传递给原型,以使其被候选人接收?
[1]请注意,以上所有代码都集中于传递变量。实际使用的令牌与我的真实代码不相似。
[2]我也开始怀疑这是否通常是LTA错误消息。虽然我认为它是基于第一个arg = invocant的,但仍然感觉不佳。也许应该说出“期望的主诉者和一个论点,只有被接受的主诉者”之类的话。
TL; DR
这是一个错误。参见[BUG]在Rakudo中未正确调用带参数的Proto正则表达式(可能是NYI)。
我有一种替代方法,可用于传递非动态参数。但请看下一点。
您的后续评论解释了您从中获得的收益,这表明动态变量替代方案可能会更好。我也要讨论。
proto token...在不带后缀的情况下切换到proto method...和切换到token foo:sym<...>s :multi token:sym<...>
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto method bar ($s) {*}
multi token bar ($s where /<alpha>+/) { {say 'alpha start ', $s} .. }
multi token bar ($s where /<digit>+/) { {say 'digit start ', $s} .. }
}
say Foo.parse("xyz")
Run Code Online (Sandbox Code Playgroud)
显示:
alpha start ?x?
?xyz?
0 => ?x?
bar => ?yz?
Run Code Online (Sandbox Code Playgroud)
在我的实际代码中,传递了该变量以阻止某些匹配(主要是为了避免某些类型的递归)
听起来您可以有一个动态变量(例如$*nope),将其设置为所需的任何值,然后系统地使用它。也许是一对。动态变量正是用于此类事情。除了在意识形态上与动态变量不符(在某种程度上,它们被无意用作不受约束的全局变量,这是个坏消息),还有什么不喜欢的呢?