【问题标题】:Difference in capturing and non-capturing regex scope in Perl 6 / RakuPerl 6 / Raku 中捕获和非捕获正则表达式范围的差异
【发布时间】:2019-09-29 18:25:38
【问题描述】:

虽然文档声明将令牌/规则/正则表达式称为 <.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'。这是预期的行为还是潜在的错误?

【问题讨论】:

    标签: regex module grammar raku


    【解决方案1】:

    S05 的意图

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

    <foo ...>
    

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

    ...

    前导. 显式调用方法作为子规则;初始字符不是字母数字的事实也会导致命名断言无法捕获它匹配的内容。

    ...

    如果既没有可以调用该名称的任何词法范围的例程,也没有可以通过方法分派到达的该名称的任何方法,则对&lt;foo&gt; 的调用将失败。 (使用哪个调度程序的决定是在编译时做出的,而不是在运行时;方法调用不是回退机制。)

    表格示例

    • &lt;bar&gt; 如上所述。它优先解析为名为@9​​87654329@ 的早期绑定词法 (my/our) 例程/规则。否则,它会解析为调用名为bar (has) 方法/规则的后期绑定尝试。如果成功,它将匹配存储在名为 bar 的捕获下。

    • &lt;.bar&gt; 调用一个名为barhas (has) 方法/规则(如果找到)。它不捕获。

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

    • &lt;&amp;bar&gt;&lt;.&amp;bar&gt; 意思相同。他们调用一个名为&amp;bar 的词法例程并进行not 捕获。要执行相同的操作,但要捕获,请使用 &lt;bar=&amp;bar&gt;&lt;bar=.&amp;bar&gt;

    (如果您阅读上面链接的推测/设计文档并尝试一下,您会发现文档中提到的大部分设计细节已经在 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 上,因为捕获(以及返回匹配项的非正则表达式方法)没有很好的记录,这将填补一个巨大的空白。
    • (我也发现对词汇范围的偏好比语法的方法有点......出乎意料,我认为它应该反过来。
    • 短语“语法的方法”有问题。在grammar g { my method foo {} } 中,foo 可以合理地称为“语法的方法”。我知道你的意思。我也没想到。 说,我仍处于我可能/将/应该从惊喜到新猜测的旅程的第一个可能阶段。很明显,它可以走任何一条路,Larry 确保一个可以走任何一条路。但如果是另一种方式呢?我注意到的一件事是,就目前而言,只需将my 添加到现有规则声明中,就可以将规则调用从晚期绑定转变为早期绑定。
    • raiph:没错,虽然我的意思是my rule bar 是在语法的内部范围之外创建的,但优先于该内部范围内的事物。好消息是我现在所做的可能不是最常见的,并且可能会被模块开发人员隔离:我基本上是在创建一个导入令牌的模块,用于明确封装(角色 mixin 是 jnhtn 的最初建议的方法,但我不喜欢方法名称的潜在歧义[即使我知道它可以被清除],并且它不允许在语法之外使用标记)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2018-01-15
    相关资源
    最近更新 更多