<.ident> perl6语法中的函数/捕获

Mik*_*kel 5 regex grammar perl6

在阅读perl6的Xml语法时(https://github.com/supernovus/exemel/blob/master/lib/XML/Grammar.pm6),我在理解以下令牌时遇到了一些困难.

token pident {
  <!before \d> [ \d+ <.ident>* || <.ident>+ ]+ % '-'
}
Run Code Online (Sandbox Code Playgroud)

更具体地说<.ident>,没有其他身份定义,所以我假设它是一个保留的术语.虽然我无法在perl6.org上找到合适的定义.有谁知道这意味着什么?

rai*_*iph 8

TL;DR我将从一个精确且相对简洁的答案开始。这个答案的其余部分是为那些想要更多地了解一般内置规则和/或ident特别深入研究的人准备的。

<.ident> 功能/捕获

由于., <.ident>only 匹配,它不会捕获[1]。对于这个答案的其余部分,我通常会省略 the.因为除了捕获方面之外,它对规则的含义没有任何影响。

正如您可以在编程语言中调用(又名“调用”)另一个函数的声明中的一个函数一样,您也可以在其中调用规则/令牌/正则表达式/方法(此后我通常只使用术语“规则”)另一条规则的声明。<foo>是用于调用名为 的规则的语法foo;所以<ident>调用一个名为ident.

在我写这篇文章的时候,XML::Grammar语法本身并没有定义/声明一个名为ident. 这意味着调用最终被分派到具有该名称的内置声明。

内置ident规则与声明为完全相同:

token ident {
    [ <alpha> ]
    [ <alnum> ]*
}
Run Code Online (Sandbox Code Playgroud)

官方预定义字符类文档应提供准确的定义<alpha><alnum>。或者,相关详细信息也稍后包含在此答案中。

底线是ident匹配一个或多个“字母数字”字符的字符串,但第一个字符不能是“数字”。

因此两者abcdef123匹配而123abc不会。

这个答案的其余部分

对于那些对值得了解的细节感兴趣的人,我写了以下部分:

  • Raku(标准语言和课程详情)

  • Rakudo(高级实现)

  • NQP(中级实施)

  • MoarVM(低级实现)

  • 的规格和“规格” ident

  • (更正)<ident>,“字符类”和“标识符”的文档

  • identvs 乐标识符

Raku(标准语言和课程详情)

XML::Grammar是用户定义的 Raku 语法。Raku 语法是一个类。(“语法实际上只是稍微专业化的课程”。)

一个乐规则是一个正则表达式是一个方法:

grammar foo { rule ident { ... } }

say foo.^lookup('ident').WHAT; # (Regex)
say Regex ~~ Method;           # True
Run Code Online (Sandbox Code Playgroud)

规则调用,如<ident>语法中的 ,通常作为调用.parse或类似语法的结果而被调用。该.parse呼叫根据语法规则输入字符串相匹配。

当在匹配期间评估发生的<ident>XML::Grammar时,结果是ident对实例的方法(规则)调用XML::Grammar.parse如果它只是一个类型对象,则调用会创建其调用者的实例)。

因为XML::Grammar它本身并没有定义该名称的规则/方法,所以ident根据标准方法解析,呃,规则来分派调用。(我在这里使用的“规则”一词是通用的非 Raku 特定意义上的。啊,语言。)

在 Raku 中,使用表单声明创建的任何类都会grammar foo { ... }自动继承自Grammar该类,而该类又继承自Match该类:

say .^mro given grammar foo {} # ((foo) (Grammar) (Match) (Capture) (Cool) (Any) (Mu))
Run Code Online (Sandbox Code Playgroud)

ident可以在内置Match类中找到。

Rakudo(高级实现)

在Rakudo编译器,Match does角色 NQPMatchRole

NQPMatchRole是找到最高级别实现的ident地方。

NQP(中级实施)

NQPMatchRole是用 nqp 语言编写的,它是 Raku 的一个子集,用于引导完整的 Raku,也是NQP的核心,一个编译器工具包。

摘编和重新格式化刚刚从最突出的代码ident声明,本场比赛的第一个字符归结为:

   nqp::ord($target, $!pos) == 95
|| nqp::iscclass(nqp::const::CCLASS_ALPHABETIC, $target, $!pos)
Run Code Online (Sandbox Code Playgroud)

此匹配,如果第一字符是一个_95在ASCII码/ Unicode的码点用于下划线)匹配NQP定义的字符类的字符称为CCLASS_ALPHABETIC

另一部分显着代码是:

nqp::findnotcclass( nqp::const::CCLASS_WORD
Run Code Online (Sandbox Code Playgroud)

这匹配字符类中的零个或多个后续字符CCLASS_WORD

对 NQPCCLASS_ALPHABETIC搜索显示了多个匹配项。最有用的似乎是NQP 测试文件。虽然此文件明确说明它CCLASS_WORD是 的超集CCLASS_ALPHABETIC,但并没有说明这些类实际匹配什么。

NQP 针对多个“后端”或具体的虚拟机。鉴于 Rakudo/NQP doc/tests 对这些规则和字符类实际匹配的内容的相对缺乏,人们必须查看其后端之一来验证什么是什么。

MoarVM(低级实现)

MoarVM是唯一官方支持的后端。

对 MoarVMCCLASS搜索显示了几个匹配项。

重要的似乎是ops.c,其中包含一个switch (cclass)语句语句又包含对应于 NQP 的类似命名常量的情况MVM_CCLASS_ALPHABETICMVM_CCLASS_WORD对应的情况。

根据代码的注释:

CCLASS_ALPHABETIC当前匹配与完整 Raku 或 NQP<:L>规则完全相同的字符,即 Unicode 分类为“字母”的字符。

我认为这意味着<alpha>相当于CCLASS_ALPHABETIC_(下划线)的并集。

CCLASS_WORD匹配相同的加号<:Nd>,即十进制数字(在任何人类语言中,而不仅仅是英语)。

我认为这意味着 Raku/NQP<alnum>规则等效于CCLASS_WORD.

的规格和“规格” ident

Raku的官方规范体现在[2] 中

一个搜索烤的ident演出几场比赛。

大多数<ident>只是偶然使用,作为测试其他东西的一部分。规范要求它们按所示工作,但您不会<ident>通过查看偶然使用来理解应该做什么。

三项测试清楚地测试<ident>自己。其中一个基本上是多余的,剩下两个。我看到这两个匹配项的6.c6.c.errata版本之间没有变化:

S05-mass/rx.t

ok ('2+3 ab2' ~~ /<ident>/) && matchcheck($/, q/mob<ident>: <ab2 @ 4>/), 'capturing builtin <ident>';
Run Code Online (Sandbox Code Playgroud)

ok测试它的第一个参数返回True. 此调用测试<ident>跳过2+3和匹配ab2.

S05-mass/charsets.t

is $latin-chars.comb(/<ident>/).join(" "), "ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ª µ º ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö øùúûüýþÿ", 'ident chars';
Run Code Online (Sandbox Code Playgroud)

is测试它的第一个参数是否与第二个参数匹配。此调用测试ident规则与由前 256 个 Unicode 代码点(Latin-1 字符集)组成的字符串匹配的内容。

这是此测试的一个变体,它更清楚地显示了发生的匹配:

say ~$_ for $latin-chars ~~ m:g/<ident>/;
Run Code Online (Sandbox Code Playgroud)

印刷:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
_
abcdefghijklmnopqrstuvwxyz
ª
µ
º
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ
ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö
øùúûüýþÿ
Run Code Online (Sandbox Code Playgroud)

但是<ident>将匹配来自 Latin-1 的超过一百个左右的字符。因此,尽管上述测试涵盖哪些<ident>官方指定/测试匹配,他们显然没有涵盖的全貌。

那么让我们来看看官方的猜测,小心翼翼地认为与“规范”有关。

首先,我们注意到顶部的警告:

Note: these documents may be out of date.
For Perl 6 documentation see docs.perl6.org;
for specs, see the official test suite.
Run Code Online (Sandbox Code Playgroud)

此警告中的术语“规格”是“规格”的缩写。正如已经解释过的,官方规范测试套件是烤的,而不是任何人类语言的措辞。

(有些人仍然认为这些历史设计文档也被称为“规范”,并将它们称为“规范”,但官方的观点是“规范”应用于设计文档时,应该被认为是“的缩写”推测”以强调它们不是完全可以依赖的东西。)

一个用于搜索ident在design.raku.org显示了若干场比赛。

最有用的匹配是在S05预定义子规则部分

这些是任何语法或正则表达式的一些预定义子规则:

  • ident ... 匹配一个标识符。

呃...

(更正)<ident>,“字符类”和“标识符”的文档

来自官方文档中的预定义字符类

    Class                             Description
    <ident>                           Identifier. Also a default rule.
Run Code Online (Sandbox Code Playgroud)

这在三个方面具有误导性:

  • ident不是 一个字符类。字符类匹配该字符类中的单个字符;如果与量词一起使用,它们只匹配一串这样的字符,每个字符都可以是该类中的任何字符。相反,<ident>匹配特定的字符模式。它可能是一个角色,但你无法控制它;规则是贪婪的,匹配符合模式的字符数。如果应用量词,它控制整个规则的重复,而不是规则的单个匹配项中包含多少个字符。

  • 所有内置规则都是默认规则。我认为默认注释是为了强调ident如果您不喜欢内置模式,您可以编写自己的规则。这适用于所有规则,尽管覆盖诸如<lower>(小写)之类的规范字符类之类的内置函数通常意义不大。

  • ident符合标识符!或者,更准确地说,对于大多数 Raku 标识符,它本身并没有这样做。有关详细信息,请参阅下一节。

identvs 乐标识符

my @Identifiers = < $bar %hash Foo Foo::Bar your_ident anothers' my-ident >; 
say (~$/ if m/^<ident>$/ for @Identifiers); # (Foo your_ident)
say (~$/ if m/ <ident> / for @Identifiers); # (bar hash Foo Foo your_ident anothers my)
Run Code Online (Sandbox Code Playgroud)

在 NQP 的Grammar.nqp 中定义的 nqp语法中,有:

token identifier { <.ident> [ <[\-']> <.ident> ]* }
Run Code Online (Sandbox Code Playgroud)

在 Raku 的Grammar.nqp 中定义的 Raku 语法中,有些代码看起来略有不同,但具有完全相同的效果:

token apostrophe { <[ ' \- ]> }
token identifier { <.ident> [ <.apostrophe> <.ident> ]* }
Run Code Online (Sandbox Code Playgroud)

因此<identifier>匹配包含一个或多个<ident>s 且<apostrophe>s 介于两者之间的模式。

ident方法是NQPMatchRole,这意味着它是一个内置的的用户语法的规则命名空间的一部分。

但是这些identifier方法不是由 Raku 或 nqp 导出的。所以它们不是用户语法的规则命名空间的一部分。

如果我们编写自己的indentifier令牌,我们可以看到它的实际效果:

my token identifier { <.ident> [ <[\-']> <.ident> ]* }
my token sigil { <[$@%&]> }
say (~$/ if m/^ <sigil>? <identifier> $/ for @Identifiers)
Run Code Online (Sandbox Code Playgroud)

显示:

($bar %hash Foo your_ident my-ident)
Run Code Online (Sandbox Code Playgroud)

总结上述和其他一些注意事项:

  • <ident>只匹配部分的什么<identifier>比赛(尽管它们是简单的名称相同)。考虑is-prime。这是一个 Raku 标识符,但包含两个 <ident>匹配项(isprime)。

  • <identifier>仅匹配零件“乐标识符”(虽然他们的简单名称相同)的。考虑infix:<+>。这有时被称为 Raku 标识符,但需要<identifier>匹配和匹配:<+>

  • 乐标识符本身只是部分的名称(虽然他们对于最简单的名称相同)。考虑Foo-Bar::Baz-Qux哪个包含两个 <identifier>匹配项(每个又包含两个<ident>匹配项)。

脚注

[1]如果你不知道捕获是什么,看到捕捉命名捕获子规则

[2]乐的官方规范是一种称为烘烤测试套件-所述ř epository ø ˚FLL小号pecification Ť的EST。特定烤肉分支的最新版本定义了特定版本的 Raku。当我第一次写这个答案时,只有两个官方分支/版本的烤肉,因此是 Raku。第一个是6.c又名6.Christmas。这是在 2015 年圣诞节那天剪掉的,从那天起就被故意冻结了。第二个是6.c.errata,它保守地添加了更正6.c被认为足够重要且向后兼容以包含在(当时)当前官方推荐的 Raku 版本中。一个“正式兼容”的 Raku 编译器通过了一些官方的烤肉分支。Rakudo 编译器(当时)通过了6.c.errata. 如果您阅读了所有涉及某个功能的测试,例如,6.c.errata烘焙分支,那么您将阅读该功能在 Raku 语言版本中的官方指定含义的完整定义6.c.errata


jjm*_*elo 7

通常,查找文档的位置是Perl6文档.这是正则表达式的一部分,你可以在字符类的定义中找到它.它匹配Perl6标识符.什么.前面ident所做的是要抑制捕获.

  • 文档提示:截至2018年6月,如果您使用[docs.perl6.org](https://docs.perl6.org/)搜索框搜索某些内容,并且您在下拉菜单中没有获得有用的匹配,你可以添加空格到最后(有时需要4或5),直到你看到"不在索引(尝试网页搜索)".点击它将谷歌文字的单词.在这种情况下,您应该看到"1结果",即[Regexes - Perl 6 Documentation](https://docs.perl6.org/language/regexes),其中显示了一个粗体**`<ident>`**摘录的开头.现在,您可以转到该页面并在页面中搜索该单词. (2认同)