命名语法规则的元对象规则是什么

What's the meta-object rule for naming grammar rules

this issue, some token names clash with method names in the class hierarchy of Grammar (which includes Match, Capture, Cool, Any and obviously My.). For instance, `Mu.item

所示
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

item is part of Anys methods, too;我没有在其他 classes 中找到任何其他方法,其名称通常失败,但是没有定义 subs(item 除外);大多数是多重或实际上定义为 method.

当像 BUILDTWEAK 这样的子方法用于标记名称时也会发生这种情况,但这种情况下的错误是不同的:

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」␤»  

语法的 class 层次结构中的其他一些方法也是如此,例如 rand 或者,一般来说,大多数方法都是这样定义的。

有问题的名称似乎有一个共同点,即它们被声明为 sub,但情况并非总是如此:最初导致整个问题的 CREATE 被声明为一个method。所以我完全不清楚要避免使用哪些名称,以及可以合法使用哪些名称。有人可以澄清一下吗?

这几乎完全是关于多个尴尬的错误。

item

参见 RT#127945 -- Mu methods cannot be used as grammar tokens due to default Actions class. Also token name confilct with internal name ?。不幸的是,这并不容易修复。

此错误及其影响的解释如下。

根据 the Actions mechanism,如果语法规则匹配,.parse 调用会立即尝试调用相应命名的操作方法。

如果您没有显式地将操作 class/object 传递给 .parse 方法,那么它将使用默认值,即 Mu。然后,当语法中的规则匹配时,它会查找具有相同名称的 Mu 方法。如果找不到,则一切正常。但是,如果它找到一个,则它会在 Mu 上调用该方法,并将当前 Match 对象作为第一个也是唯一的参数。在几乎所有情况下,情况都会很糟糕。 item 就是一个例子。

如果你告诉.parse方法使用特定的动作class/object,另一个问题出现了:

grammar g           { rule all { all } };
class actions       { }
g.parse: 'all',
         rule    => 'all',
         actions => actions, 

这会产生与 item 类似的错误,只是这次 all 方法来自 Any。这是因为操作 class 的 MRO 包括 Any:

say class actions   { }.^mro ; # ((actions) (Any) (Mu))

您可以通过使用 is Mu:

声明您的操作 classes 来消除这种问题
grammar g           { rule all { all } };
class actions is Mu { }
g.parse: 'all',
         rule    => 'all',
         actions => actions, 

这很好用,因为现在操作仅继承自 Mu -- 而 Mu 没有 all 方法。

如果你能从无到有继承就好了,但你不能; is Mu 尽可能少。

关于第一个错误,我们可以得出什么结论?

因为较新版本的 Perl 6 and/or Rakudo 可能会附带新的 Mu 方法,防御此错误最安全的做法是始终声明一个操作 class 和始终声明一个方法对应于语法中的每个规则。如果你这样做,你不需要遵循任何命名规则来避免这个错误。

TWEAK

如果找不到现有的,我会提交一个关于此的 RT 错误。

打高尔夫球:

grammar g { rule TWEAK {} }

这在 编译时 爆炸(在解析语法声明的右花括号后立即)。所以这绝对不是与 item 错误相同的错误——因为后者是由于 运行-time 动作机制仅在规则匹配。

这不爆炸:

grammar g { method TWEAK {} }

也许,作为 creating/finalizing 语法包的一部分,一些代码内省 and/or 以一种可以正常工作的方式操纵在新语法包中找到的任何 TWEAK “方法”这是一个普通的方法,但如果不是这样就会爆炸。

However, other submethods like FALLBACK have no problem at all

TWEAKBUILD 方法或 class 中的子方法是标准对象构造的一部分。它们扮演的角色与 FALLBACK(如果缺少方法时调用)完全不同。

关于第二个错误,我们可以得出什么结论?

TWEAKBUILD 显然有一些非常具体的问题,它们很可能是仅有的两个出现问题的规则名称。因此,只要避免使用这两个名称,您就有望摆脱这个错误。

不小心使用了内置规则名称

参见 RT#125518 -- Grammar 'ident' override behaviour

您只需指定自己的版本即可覆盖内置规则。

As “如果您不小心将 [规则] 声明为与内置规则同名,肯定会造成混淆。”。

所以关键问题是,了解 内置 规则的权威来源是什么?鉴于这些规则可能会随着时间的推移而发生变化,人们该如何管理它们?

(是的,非常模糊,我知道。另外,我认为 Perl 6 的内置函数必须扩展 NQP,这似乎很可能是相关的。此外,每种整体语言中都有多种俚语,也许这是相关的。我计划在以后的编辑中更全面地讨论这个问题。)

其他相关错误

另见莫里茨的回答。

另请注意,语法中的 FALLBACK 标记执行与 类 中的 FALLBACK method 类似的功能。当在语法中遇到未知标记时,使用标记名称调用它。

稍微改变一下你的例子:

grammar g { 
  token TOP { <blah> }; 
  token FALLBACK($name) { {note "$name called" } 'defined' } 
}; 
say g.parse('defined')

生产

blah called
「defined」
blah => 「defined」

规则似乎是"if the grammar engine itself calls a method, you cannot redefine it as a regex/token"。

遗憾的是,没有关于此的文档,很可能它非常依赖于实现。