【问题标题】:What's the meta-object rule for naming grammar rules命名语法规则的元对象规则是什么
【发布时间】:2018-05-26 17:48:07
【问题描述】:

this issue 中所示,一些标记名称与语法的类层次结构中的方法名称冲突(包括MatchCaptureCoolAny,显然还有My。)。比如`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;我在其他类中没有找到任何其他名称通常失败的方法,但是没有定义任何子类(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」␤»  

同样适用于 Grammar 类层次结构中的一些其他方法,例如 rand,或者一般来说,大多数方法都这样定义。

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

【问题讨论】:

  • 对于将来阅读本文的其他人,根据 JJ 对我的回答的评论,在他的问题标题中,“规则”一词用于英语意义,“规则”一词用于 P6 意义(即语法中的规则/令牌/正则表达式/方法)并且元对象是,我认为,Rakudo 的Perl6::Metamodel::GrammarHow,也许还有一些类似的 nqp 元对象。
  • @raiph 补充了一些解释:如上所述,item 也是 Any 的一部分,但测试的其他功能实际上都不是subs,因此可能只有Mu 方法或 Mu subs 失败。这就是我想知道的。
  • 对此没有简单的答案。至少存在三个独立的错误,每个错误对规则命名都有其自身的复杂影响。 Moritz 和 Lizmat 确认了一个听起来不像是我在回答中提到的三个问题的重复问题,因此很可能至少存在四个与规则命名相关的错误/问题,并且可能会出现更多问题。请放弃修复这一特定错误巢的想法,通过记录如何通过荒谬复杂的命名规则来避免它们。你会浪费你和其他人的时间。如果您不相信,请仔细阅读我的回答。
  • 好的。我不确定,我觉得我需要强调这是疯狂的复杂,​​远远超出了任何文档工作所能解决的范围。感谢您对我们沟通的耐心等待。 :)
  • /o\ 情况变得更糟。 TWEAK 错误会导致编译时错误。我现在看到我认为可能涵盖它的错误并没有被写为编译时错误。也许莫里茨的。调查和答案重写继续......

标签: grammar raku meta-object-protocol


【解决方案1】:

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

稍微改变一下你的例子:

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

生产

blah called
「defined」
blah => 「defined」

【讨论】:

  • 不错!投赞成票。 :) 我无法从 JJ 的问题标题中看出他真正追求的是什么,所以我只是写了一本书......
  • 这只是一个太大的评论,不适合 SO 的评论格式 :-)
  • 我的书本长度“答案”的原始版本一开始就说这不是答案,但不适合评论。然后我想出了足够的删除那个位。我找到了您提交的Grammar 'ident' override behaviour,但我仍然想知道这是否也是其中的一部分。唔。可能不会。
  • RT 涉及覆盖内置规则“ident”。如果您不小心声明了与内置规则同名的令牌,肯定会引起混乱。
【解决方案2】:

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

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,如果语法规则匹配,.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 错误。

打高尔夫球:

grammar g { rule TWEAK {} }

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

这不会爆炸:

grammar g { method TWEAK {} }

也许,作为创建/完成语法包的一部分,一些代码会自省和/或操作在新语法包中找到的任何TWEAK“方法”,如果它是一个普通方法则可以正常工作,但如果是不是。

但是像FALLBACK这样的其他子方法完全没有问题

TWEAKBUILD 类中的方法或子方法是标准对象构造的一部分。他们扮演的角色与FALLBACK(如果缺少方法,则会被调用)截然不同。

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

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

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

RT#125518 -- Grammar 'ident' override behaviour

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

As dwarring notes “如果你不小心声明了与内置规则同名的[规则],肯定会引起混乱。”。

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

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

其他相关错误

另请参阅 Moritz 的回答。

【讨论】:

  • 想不出更好的方法来命名这个词。这是一条规则,因为它说明了如何命名语法类方法(规则、正则表达式、标记)。它是元对象,因为它指的是类的构造。如果您认为它没有帮助,我可以删除元对象,但我当时真的想不出更好的方法。另外,是的,我的意思是它们被声明为 subs,而不是方法。其中一些不是 Mu 的一部分,而是层次结构中更高级别的其他类。
【解决方案3】:

规则似乎是“如果语法引擎本身调用一个方法,则不能将其重新定义为正则表达式/令牌”。

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 2018-01-26
  • 2021-07-23
  • 1970-01-01
  • 2012-05-30
  • 2016-11-13
相关资源
最近更新 更多