Perl 6 / Raku 中捕获和非捕获正则表达式范围的区别

6
尽管文档说明使用<.foo>代替<foo>来调用标记/规则/正则表达式将使它们不捕获,但似乎在范围方面存在差异,但我不确定这是否是有意的。
以下是一个简化的测试。在一个模块文件中:
unit module Foo;
my token y           {     y  }
my token a is export { x  <y> }
my token b is export { x <.y> }

在另一个脚本文件中:

grammar A {
  use Foo;
  token TOP { <a> }
}

grammar B {
  use Foo;
  token TOP { <b> }
}

如果我们调用A.parse("xy")一切都会按预期运行,但是调用B.parse("xy")会导致错误No such method 'y' for invocant of type 'B'。这是预期的行为还是潜在的错误?

1个回答

6

S05规范的意图

根据相关的推测/设计文档,S05规范的意图包括:

<foo ...>

该表单总是优先使用词法作用域的正则表达式声明,直接调用它,就像调用函数一样。如果当前范围中没有这样的词法正则表达式(或词法方法),则将调用分派给当前语法,假设有一个。

...

前导 . 明确地将方法调用为子规则;初始字符不是字母数字也使命名断言未捕获其匹配内容。

...

如果既没有任何具有该名称的词法作用域例程可供调用,也没有可以通过方法调度到达的该名称的任何方法,则对<foo>的调用将失败。(使用哪个分派程序的决定是在编译时做出的,而不是在运行时;方法调用不是后备机制。)


表格形式的示例

  • 如上所述,<bar>首选解析为早期绑定的词法(my/our)程序/规则&bar。否则,它会尝试晚期绑定以调用名为barhas (has) 方法/规则。如果成功,它将在名为bar的捕获下存储匹配项。

  • <.bar>如果找到一个名为barhas(has)方法/规则,则调用该方法/规则。它不捕获。

  • 如果找到一个名为barhas(has)方法/规则,则调用该方法/规则。如果成功,则在名为bar的捕获下存储匹配项。换句话说,它与<bar>相同,只是尝试调用名为.barhas方法;它不会首先尝试解析为词法&bar

  • <&bar><.&bar>意思相同。它们调用名为&bar的词法程序,并且不捕获。要执行相同的操作,但要捕获,请使用<bar=&bar><bar=.&bar>

(如果您阅读上面链接的推测/设计文档并尝试这些内容,您会发现Rakudo中已经实现了该文档提到的大多数设计细节,即使它们没有得到官方支持/烤制/记录。)


范围示例

首先是常见情况:

grammar c {
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

显示:

has rule
「a」
 bar => 「a」

has声明符是可选的,而且省略它们是惯用法。)
现在引入一个规则,它在语法块中具有词汇作用域:
grammar c {
  my  rule bar { . { say 'inner my rule' } }
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

显示:

inner my rule
「a」
 bar => 「a」

即使在语法块之外声明的词汇规则,也优先于已有的规则。
my rule bar { . { say 'outer my rule' } }
grammar c {
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

显示:

outer my rule
「a」
 bar => 「a」

太棒了!(它几乎可以稍微修改一下就可以放到 Perldoc 上,因为捕获(和返回匹配项的非正则表达式方法)没有得到很好的记录,这将填补一个巨大的空白。) - user0721090601
我发现在编程中更倾向于词法作用域而不是语法方法有点出乎意料,我认为应该反过来。 - user0721090601
“语法方法”这个说法有问题。在 grammar g { my method foo {} } 中,foo 可以合理地被称为“语法方法”。我知道你的意思。我也没有想到过。话虽如此,我仍然处于从惊讶到新推测的第一阶段。显然,它可以朝任何方向发展,Larry 确保了可以朝任何方向发展。但如果是另一种方式呢?我注意到的一件事是,按照现有的规定,只需在现有的规则声明中添加一个 my 就可以将规则调用从后期绑定转换为早期绑定。 - raiph
raiph: 是的,尽管我的意思是my rule bar是在语法的内部作用域之外创建的,但它优先于该内部作用域中的内容。好处是我现在做的可能不是最常见的,而且很可能只限于模块开发人员:我基本上创建了一个导入令牌的模块,以进行明确的封装(角色混合是jnhtn最初建议的方法,但我不喜欢那里潜在的歧义方法名称[尽管我知道它可以被澄清],并且它不允许在语法之外使用令牌)。 - user0721090601
这是与您的帮助相关的结果:https://github.com/alabamenhu/Intl-CLDR/blob/master/lib/Intl/CLDR/Numbers/Finder.pm6 - user0721090601

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接