Perl 6 / Raku中捕获和不捕获正则表达式作用域的差异

use*_*601 5 regex grammar module perl6 raku

尽管文档指出将令牌/规则/正则表达式作为<.foo>代替而不是<foo>使其不被捕获,但似乎范围有所不同,但我不确定是否打算这样做。

这是一个简化的测试。在模块文件中:

unit module Foo;
my token y           {     y  }
my token a is export { x  <y> }
my token b is export { x <.y> }
Run Code Online (Sandbox Code Playgroud)

在另一个脚本文件中:

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

grammar B {
  use Foo;
  token TOP { <b> }
}
Run Code Online (Sandbox Code Playgroud)

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

rai*_*iph 6

根据S05的意图

根据有关推测/设计文档的意图包括:

<foo ...>
Run Code Online (Sandbox Code Playgroud)

这种形式总是优先考虑一个词法范围的regex声明,就像它是一个函数一样直接分派给它。如果范围内没有这样的词法正则表达式(或词法方法),则假设存在一个调用,则将调用分配给当前语法。

...

领导.明确地将方法称为子规则。初始字符不是字母数字的事实也导致命名的断言无法捕获其匹配的内容。

...

<foo>如果无法调用该名称的任何词法范围的例程,也无法通过方法分派访问该名称的任何方法,则对to的调用将失败。(使用哪个调度程序的决定是在编译时决定的,而不是在运行时决定的;方法调用不是回退机制。)

表格范例

  • <bar>如上所述。它优先解析为名为的早期绑定词法my/ our)例程/规则&bar。否则,它将解析为延迟尝试调用名为的hashas)方法/规则bar。如果成功,则将匹配项存储在名为的捕获下bar

  • <.bar>调用具有has命名)方法/规则bar,如果它发现之一。它不会捕获。

  • <bar=.bar>调用具有has命名)方法/规则bar,如果它发现之一。如果成功,则将匹配项存储在名为的捕获下bar。换句话说,它与<bar>仅尝试调用名为的has方法的方法相同.bar。它并不首先尝试解析为词汇&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';
Run Code Online (Sandbox Code Playgroud)

显示:

has rule
?a?
 bar => ?a?
Run Code Online (Sandbox Code Playgroud)

has声明符是可选的,排除它们是惯用法。)

现在引入一个词法范围为语法块的规则:

grammar c {
  my  rule bar { . { say 'inner my rule' } }
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';
Run Code Online (Sandbox Code Playgroud)

显示:

inner my rule
?a?
 bar => ?a?
Run Code Online (Sandbox Code Playgroud)

即使是一个词法规则中声明语法积木的优先级高于具有规则:

my rule bar { . { say 'outer my rule' } }
grammar c {
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';
Run Code Online (Sandbox Code Playgroud)

显示:

outer my rule
?a?
 bar => ?a?
Run Code Online (Sandbox Code Playgroud)