在 Perl 6 规则中,.parse 锚定还是 :sigspace 首先?

Does .parse anchor or :sigspace first in a Perl 6 rule?

我有两个问题。我展示的行为是否正确,如果正确,是否在某处记录?

我在玩语法 TOP 方法。声明为 rule,它意味着字符串开头和结尾的锚点以及 :sigspace:

grammar Number {
    rule TOP { \d+ }
    }

my @strings = '137', '137 ', ' 137 ';

for @strings -> $string {
    my $result = Number.parse( $string );
    given $result {
        when Match { put "<$string> worked!" }
        when Any   { put "<$string> failed!" }
        }
    }

在没有空格或只有尾随空格的情况下,字符串被解析。使用前导空格,它失败了:

<137> worked!
<137 > worked!
< 137 > failed!

我认为这意味着 rule 先应用 :sigspace 然后再应用锚点:

grammar Foo {
    regex TOP { ^ :sigspace \d+ $ }
    }

我希望 rule 允许前导空格,如果您切换顺序就会发生这种情况:

grammar Foo {
    regex TOP { :sigspace ^  \d+ $ }
    }

我可以在 rule 中为字符串的开头添加一个显式标记:

grammar Number {
    rule TOP { ^ \d+ }
    }

现在一切正常:

<137> worked!
<137 > worked!
< 137 > worked!

我没有任何理由认为它应该是这样或那样。 Grammars docs 说发生了两件事,但文档没有说明这些效果适用的顺序:

Note that if you're parsing with .parse method, token TOP is automatically anchored

When rule instead of token is used, any whitespace after an atom is turned into a non-capturing call to ws.


我认为答案是规则实际上并没有固定在模式意义上。这就是 .parse 的工作方式。光标必须从位置 0 开始,到字符串的最后一个位置结束。那是模式之外的东西。

该行为是有意为之的,是这些语言功能的结晶:

  • Sigspace 忽略第一个原子前的空格。

    来自设计文档1S05: Regexes and Rules, line 348,已强调):

    The new :s (:sigspace) modifier causes certain whitespace sequences to be considered "significant"; they are replaced by a whitespace matching rule, . Only whitespace sequences immediately following a matching construct (atom, quantified atom, or assertion) are eligible. Initial whitespace is ignored at the front of any regex, to make it easy to write rules that can participate in longest-token-matching alternations. Trailing space inside the regex delimiters is significant.

    这意味着:

    rule TOP { \d+ }
                  ^-------- <.ws> automatically inserted
    
    rule TOP { ^ \d+ $ }
                ^---^-^---- <.ws> automatically inserted
    
  • 正则表达式是 first-class 具有词法作用域的编译代码。

    A regex/rule 不是可以稍后将字符连接到它以改变其行为的字符串。它是一个 self-contained 例程,它在编译时被解析并确定其行为。

    正则表达式修饰符,如 :sigspace,包括由 rule 关键字隐式添加的修饰符,仅适用于它们的词法范围 - 即它们在编译时出现的源代码片段。 S05, line 6291:

    The :i, :m, :r, :s, :dba, :Perl5, and Unicode-level modifiers can be placed inside the regex (and are lexically scoped)
  • rule TOP的锚定由.parse在运行时间完成。

    S05, line 44231:

    The .parse and .parsefile methods anchor to the beginning and ending of the text, and fail if the end of text is not reached. (The TOP rule can check against $ itself if it wishes to produce its own error message.)

    即锚定到字符串的开头并不是规则 TOP 固有的,并且不会影响 TOP 的词法范围的解析和编译方式。当调用方法 .parse 时完成。

    必须这样,因为同一个文法可以用不同的起始规则代替TOP,使用.parse(..., rule => ...).

所以当你写

rule TOP { \d+ }

编译为

regex TOP { :r \d+ <.ws> }

并且当您 .parse 该语法时,它有效地调用了正则表达式代码 ^ <TOP> $,锚点不是 TOP 词法范围的一部分,而是一个范围只是 调用 例程 TOP。合并后的行为就像规则 TOP 被写成:

regex TOP { ^ [:r :s \d+] $ }

1) 设计文档通常不会被视为是或不是 Perl 6 语言的一部分的福音,但 S05 在这方面非常准确,除了它提到一些尚未实现但已计划的功能。任何想要真正理解 Perl 6 的复杂性的人 regexes/grammars,通过至少从头到尾阅读完整的 S05 一次,IMO 是否会得到很好的服务。

没有两个正则表达式效果。 rule 适用于 :sigspace。之后,语法被定义。当您调用 .parse 时,它从字符串的开头开始到结尾(或失败)。锚定不是语法的一部分。这是 .parse 如何应用语法的一部分。

我的主要问题是文档中某些内容的措辞方式很奇怪。他们在技术上并没有错,但他们也倾向于假设 reader 可能不知道的事情。在这种情况下,关于锚定 TOP 的随意评论并不像看起来那么特别。传递给 .parse 的任何规则都以相同的方式锚定。除了调用 .parse.

:rule 的默认值外,该规则名称没有特殊行为