如this issue所示,某些标记名称与语法的类层次结构中的方法名称冲突(包括Match,Capture,Cool,{{3}显然Any。)。例如,My
grammar g {
token TOP { <item> };
token item { 'defined' }
};
say g.parse('defined');
发出如下错误:
Too many positionals passed; expected 1 argument but got 2
in regex item at xxx
`Mu.item;我还没有在其他类中找到其名称通常失败的其他方法,但之后没有定义任何子类(item
除外);大多数是multis或实际定义为method
。
当TWEAK
BUILD
的{{1}}等子方法用于令牌名称时,也会发生这种情况,但这种情况下的错误不同:
Cannot find method 'match': no method cache and no .^find_method
at xxx
然而,像FALLBACK
这样的其他子方法完全没有问题:
grammar g {
token TOP { <FALLBACK> };
token FALLBACK { 'defined' }
};
say g.parse('defined') # OUTPUT: «「defined」 FALLBACK => 「defined」»
并且同样用于语法的类层次结构中的其他一些方法,例如item
is part of Any
s methods, too,或者一般来说,大多数方法都是这样定义的。
有问题的名称似乎有一个共同点,即它们被声明为sub
,但情况并非总是如此:rand
,它最初导致整个问题,被声明为{ {1}}。因此,我不清楚要避免哪些名称,以及哪些名称可以合法使用。有人可以澄清吗?
答案 0 :(得分:6)
另请注意,语法中的FALLBACK标记与类中的FALLBACK method执行类似的功能。当在语法中遇到未知令牌时,使用令牌名称调用它。
稍微改变你的例子:
{PA1, PA2}
可生产
grammar g {
token TOP { <blah> };
token FALLBACK($name) { {note "$name called" } 'defined' }
};
say g.parse('defined')
答案 1 :(得分:5)
这几乎完全是关于多个尴尬的错误。
item
等。见RT#127945 -- Mu
methods cannot be used as grammar tokens due to default Actions class。 token name confilct with internal name ?也是the Actions mechanism。不幸的是,这不容易解决。
对此错误及其影响的解释如下。
Per RT#125518 -- Grammar 'ident' override behaviour,如果语法规则匹配,.parse
调用会立即尝试调用相应命名的操作方法。
如果未将动作类/对象显式传递给.parse
方法,则它使用默认值Mu
。然后,当您的语法中的规则匹配时,它会查找具有相同名称的Mu
方法。如果找不到,一切都很好。但是如果找到一个,那么它会在Mu
上调用该方法,并将当前Match
对象作为第一个也是唯一的参数。在几乎所有情况下都会变坏。 item
就是一个例子。
如果做告诉.parse
方法使用特定的动作类/对象,则会出现另一个问题:
grammar g { rule all { all } };
class actions { }
g.parse: 'all',
rule => 'all',
actions => actions,
这会产生与item
类似的错误,但这次all
方法来自Any
。这是因为动作类的MRO包含Any
:
say class actions { }.^mro ; # ((actions) (Any) (Mu))
您可以通过is Mu
声明您的行动课程来消除这种皱纹:
grammar g { rule all { all } };
class actions is Mu { }
g.parse: 'all',
rule => 'all',
actions => actions,
这很好用,因为现在这些操作只从Mu
继承而且Mu
没有all
方法。
如果你能从无所不能中继承,那就太棒了,但你做不到; is Mu
尽可能少。
关于第一个错误我们能得出什么结论?
因为较新版本的Perl 6和/或Rakudo可能附带新的Mu
方法,所以要防范此错误最安全的做法是始终声明一个操作类并始终声明一个对应于每个单独的方法统治你的语法。如果这样做,您不需要遵循任何命名规则来避免此错误。
TWEAK
等。如果我找不到现有的错误,我会提交RT错误。
Golfed:
grammar g { rule TWEAK {} }
这会在编译时(在解析语法声明的结束大括号后立即)爆发。所以这绝对不是item
bug的错误 - 因为后者是由运行时动作机制引起的,只有在规则匹配后才会启动。
这不会爆炸:
grammar g { method TWEAK {} }
也许,作为创建/完成语法包的一部分,一些代码内省和/或操纵在新语法包中找到的任何TWEAK
“方法”,如果它是一种普通的方法但是很好如果不是的话。
类中的然而,像
FALLBACK
这样的其他子方法根本没有问题
TWEAK
和BUILD
方法或子方法是标准对象构造的一部分。他们扮演的角色与FALLBACK
的角色非常不同(如果缺少方法,则会调用它)。
关于第二个错误我们能得出什么结论?
TWEAK
和BUILD
显然有一些非常具体的内容,它们可能是唯一有两个规则名称的问题。所以,只要避免这两个名字,你就可以清楚地知道这个错误了。
请参阅dwarring notes。
您只需指定自己的版本即可覆盖内置规则。
作为{{3}}“如果您不小心声明[规则]与内置规则同名,那肯定会引起混淆。”。
因此,关键问题是,了解内置规则的确切来源是什么?如果管理事物可能会随着时间的推移发生变化,那么管理事物的方式是什么?
(是的,非常模糊,我知道。另外,我认为Perl 6的内置插件必须扩展NQP,这看起来可能是相关的。而且,每种整体语言都有多个俚语,也许这是相关的。我计划在稍后的编辑中更全面地讨论这个问题。)
另见莫里茨的回答。
答案 2 :(得分:4)
规则似乎是“如果语法引擎本身调用方法,则不能将其重新定义为正则表达式/令牌”。
可悲的是,没有关于此的文档,而且很可能是依赖于实现。