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

Difference in capturing and non-capturing regex scope in Perl 6 / Raku

尽管文档声明将 token/rule/regex 调用为 <.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'。这是预期的行为还是潜在的错误?

根据 S05 的意图

根据the relevant speculation/design doc的意图包括:

<foo ...>

This form always gives preference to a lexically scoped regex declaration, dispatching directly to it as if it were a function. If there is no such lexical regex (or lexical method) in scope, the call is dispatched to the current grammar, assuming there is one.

...

A leading . explicitly calls a method as a subrule; the fact that the initial character is not alphanumeric also causes the named assertion to not capture what it matches.

...

A call to <foo> will fail if there is neither any lexically scoped routine of that name it can call, nor any method of that name that be reached via method dispatch. (The decision of which dispatcher to use is made at compile time, not at run time; the method call is not a fallback mechanism.)

表单示例

  • <bar>如上解释。它优先解析为名为 &bar 的早期绑定 lexical (my/our) routine/rule。否则它会解析为后期绑定尝试调用名为 barhas (has) method/rule。如果成功,它会将匹配存储在名为 bar.

    的捕获下
  • <.bar> 调用 has (has) method/rule 如果找到一个名为 bar .它不捕获。

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

  • <&bar><.&bar> 意思相同。他们调用一个名为 &bar 的词法例程并执行 not 捕获。做同样的事情,但捕获,使用 <bar=&bar><bar=.&bar>.

(如果您阅读上面链接的 speculation/design 文档并进行尝试,您会发现文档提到的大部分设计细节已经在 Rakudo 中实现,即使它们不是正式的 supported/roasted/documented.)

范围示例

首先是常见的情况:

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」