在阅读perl6(https://github.com/supernovus/exemel/blob/master/lib/XML/Grammar.pm6)的Xml语法时,我在理解以下标记时遇到了一些困难。
token pident {
<!before \d> [ \d+ <.ident>* || <.ident>+ ]+ % '-'
}
更具体地说,,没有ident的其他定义,因此我假设它是保留术语。虽然我找不到在perl6.org上找到合适的定义。有人知道这意味着什么吗?
最佳答案
TL; DR 我将从一个准确而相对简洁的答案开始。该答案的其余部分适用于那些希望全面了解内置规则和/或特别要深入研究ident
的人员。
由于.
,<.ident>
仅匹配,因此无法捕获[1]。对于此答案的其余部分,我通常会省略.
,因为它除了捕获方面对规则的含义没有影响。
正如您可以在编程语言中在另一个函数的声明中调用(也称为“调用”)一个函数一样,您也可以在其中调用规则/ token /正则表达式/方法(此后我通常只使用术语“规则”)另一条规则的声明。 <foo>
是用于调用名为foo
的规则的语法;因此<ident>
调用了一个名为ident
的(方法)。
在撰写本文时,XML::Grammar
语法本身并未定义/声明一个名为ident
的规则。这意味着该调用最终被调度到具有该名称的内置声明中。
内置的ident
规则的作用与声明为:
token ident {
[ <alpha> ]
[ <alnum> ]*
}
official Predefined character classes doc应该提供
<alpha>
和<alnum>
的精确定义。或者,相关详细信息也将包含在此答案的后面。底线是
ident
与一个或多个“字母数字”字符的字符串匹配,但第一个字符不能为“数字”。因此,
abc
或def123
都匹配,而123abc
不匹配。这个答案的其余部分
对于那些有兴趣详细了解的人,我写了以下部分:
ident
的规范和“规范” <ident>
,“字符类”和“标识符”的ident
与Raku标识符 Raku(标准语言和类(class)详细信息)
XML::Grammar
是用户定义的Raku语法。 Raku语法是一门课。 ("Grammars are really just slightly specialized classes"。)Raku rule是正则表达式是一种方法:
grammar foo { rule ident { ... } }
say foo.^lookup('ident').WHAT; # (Regex)
say Regex ~~ Method; # True
通常,由于在语法上调用了
<ident>
或类似命令,因此会调用规则调用(如.parse
)。 .parse
调用根据语法规则匹配输入字符串。在比赛期间评估
<ident>
中XML::Grammar
的出现时,结果是对ident
实例的XML::Grammar
方法(规则)调用(如果.parse
调用只是一个类型对象,则将创建其invocant的实例)。由于
XML::Grammar
本身并未定义该名称的规则/方法,因此ident
调用而是根据标准方法解析规则来分派(dispatch)的。 (我在这里使用的是非Raku的一般意义上的“规则”一词。啊,语言。)在Raku中,使用
grammar foo { ... }
形式的声明创建的任何类都会自动继承自Grammar
类,而Match
类又继承自ident
类:say .^mro given grammar foo {} # ((foo) (Grammar) (Match) (Capture) (Cool) (Any) (Mu))
在内置的
Match
类中可以找到Match
。Rakudo(高级实现)
在Rakudo编译器中,the
does
class NQPMatchRole
到role NQPMatchRole
。此
ident
是NQPMatchRole
的最高级别实现的位置。NQP(中级实现)
ident
用nqp语言编写,它是Raku的一个子集,用于引导整个Raku,它是编译器工具包NQP的核心。仅从the
_
declaration中摘录并重新格式化最突出的代码,第一个字符的匹配可归结为: nqp::ord($target, $!pos) == 95
|| nqp::iscclass(nqp::const::CCLASS_ALPHABETIC, $target, $!pos)
如果第一个字符是
95
(CCLASS_ALPHABETIC
是下划线的ASCII代码/Unicode代码点)或与NQP中定义的称为CCLASS_WORD
的字符类匹配的字符,则此匹配。显着代码的另一位是:
nqp::findnotcclass( nqp::const::CCLASS_WORD
这与字符类
CCLASS_ALPHABETIC
中的零个或多个后续字符匹配。search of NQP for
CCLASS_WORD
显示多个匹配项。最有用的似乎是an NQP test file。尽管此文件清楚表明CCLASS_ALPHABETIC
是CCLASS
的超集,但并不清楚这些类实际上匹配什么。NQP针对多个“后端”或具体的虚拟机。鉴于Rakudo/NQP doc/测试相对缺乏这些规则和字符类的实际匹配性,因此必须查看其后端之一以验证什么。
MoarVM(低级别实现)
MoarVM是唯一受官方支持的后端。
search of MoarVM for
switch (cclass)
显示多个匹配项。重要的一个似乎是ops.c,而includes a
MVM_CCLASS_ALPHABETIC
statement则包括MVM_CCLASS_WORD
和CCLASS_ALPHABETIC
的情况,这些情况与NQP的类似命名常量相对应。根据代码的注释:
<:L>
当前与完全Raku或NQP <alpha>
规则完全相同的字符匹配,即Unicode字符已分类为“字母”。我认为这意味着
CCLASS_ALPHABETIC
等于_
和CCLASS_WORD
的并集(下划线)。<:Nd>
与<alnum>
相同,即十进制数字(以任何人类语言,而不仅仅是英语)。我认为这意味着Raku/NQP
CCLASS_WORD
规则等效于ident
。ident
的规范和“规范”Raku的官方规范体现在烤[2]中。
search of roast for
<ident>
显示多个匹配项。大多数测试只是偶然地使用
<ident>
,作为测试其他内容的一部分。规范要求它们按所示方式工作,但是通过查看附带用法,您将无法理解<ident>
应该做什么。三个测试清楚地测试了
6.c
本身。其中之一本质上是多余的,剩下两个。我发现这两个匹配项的6.c.errata
和ok
版本之间没有任何变化:从S05-mass/rx.t:
ok ('2+3 ab2' ~~ /<ident>/) && matchcheck($/, q/mob<ident>: <ab2 @ 4>/), 'capturing builtin <ident>';
True
测试其第一个参数是否返回<ident>
。此调用测试2+3
跳过ab2
并匹配is
。从S05-mass/charsets.t:
is $latin-chars.comb(/<ident>/).join(" "), "ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ª µ º ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö øùúûüýþÿ", 'ident chars';
ident
测试其第一个参数与第二个参数匹配。此调用从由前256个Unicode代码点(拉丁1字符集)组成的字符串中测试<ident>
规则与什么匹配。这是此测试的一种变体,可以更清楚地显示发生的匹配:
say ~$_ for $latin-chars ~~ m:g/<ident>/;
打印:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
_
abcdefghijklmnopqrstuvwxyz
ª
µ
º
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ
ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö
øùúûüýþÿ
但是
<ident>
匹配的内容不仅仅来自Latin-1中的一百多个字符。因此,尽管以上测试涵盖了ident
官方指定/测试的匹配项,但它们显然并未涵盖全部内容。因此,让我们仔细考虑一下可能与“规范”有关的official speculation。
首先,我们在顶部注意警告:
Note: these documents may be out of date.
For Perl 6 documentation see docs.perl6.org;
for specs, see the official test suite.
该警告中的术语“规范”是“规范”的缩写。如前所述,官方规范测试套件是烤制的,不是任何人类语言的措辞。
(有些人仍然将这些历史设计文档也视为“规范”,并将它们称为“规范”,但官方认为,适用于设计文档的“规范”应被视为“规范”的简称)。投机”以强调它们不是完全值得依赖的东西。)
search for
<ident>
in design.raku.org显示多个匹配项。最有用的匹配项是the Predefined Subrules section of S05:
喔...
(更正)
ident
,“字符类”和“标识符”的文档从Predefined character classes in the official doc:
Class Description
<ident> Identifier. Also a default rule.
这在三种方式上具有误导性:
<ident>
是而不是 a character class。字符类与该字符类中的单个字符匹配;如果与量词一起使用,它们仅匹配一串这样的字符,每个字符都可以是该类中的任何字符。相反,ident
与特定的字符模式匹配。它可能是一个字符,但您无法控制。规则是贪婪的,匹配符合模式的字符数。如果应用量词,则它控制整个规则的重复,而不是规则的单个匹配中包含多少个字符。 <lower>
规则。这对于所有规则都是正确的,尽管通常覆盖诸如ident
(小写)之类的规范字符类之类的内置插件的意义要小得多。 ident
是否而不是匹配标识符!或者,更准确地说,对于大多数Raku标识符而言,它并不是单独这样做的。有关详细信息,请参见下一部分。 <identifier>
与Raku标识符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)
在NQP的Grammar.nqp中定义的nqp语法中,有:
token identifier { <.ident> [ <[\-']> <.ident> ]* }
在Rakudo的Grammar.nqp中定义的Raku语法中,代码看起来有些不同,但效果完全相同:
token apostrophe { <[ ' \- ]> }
token identifier { <.ident> [ <.apostrophe> <.ident> ]* }
因此,
<ident>
与包含一个或多个<apostrophe>
以及介于两者之间的ident
的模式匹配。NQPMatchRole
方法位于identifier
中,这意味着它是内置的,属于用户语法的规则 namespace 。但是
indentifier
方法是akut或nqp导出的而不是。因此,它们不是用户语法的规则命名空间的而不是的一部分。如果我们编写自己的
<ident>
token ,我们可以看到它的作用:my token identifier { <.ident> [ <[\-']> <.ident> ]* }
my token sigil { <[$@%&]> }
say (~$/ if m/^ <sigil>? <identifier> $/ for @Identifiers)
显示:
($bar %hash Foo your_ident my-ident)
总结以上内容和其他一些注意事项:
<identifier>
仅匹配is-prime
匹配的部分内容(尽管简单名称相同)。考虑<ident>
。这是Raku标识符,但包含两个is
匹配项(prime
和<identifier>
)。 infix:<+>
仅匹配“Raku标识符”的一部分(尽管简单名称相同)。考虑<identifier>
。有时将其称为Raku标识符,但需要:<+>
匹配和Foo-Bar::Baz-Qux
匹配。 <identifier>
匹配项的<ident>
(每个依次包含两个6.c
匹配项)。 脚注
[1]如果不确定是什么捕获,请参阅Capturing,Named captures和Subrules。
[2] Raku的官方规范是一个称为roast的测试套件- R 知识库 O f ll S 规范化 T ests。 roast特定分支的最新版本定义了Raku的特定版本。当我第一次写这个答案时,只有两个正式的分支机构/版本的烤肉,因此也只有Raku。第一个是
6.Christmas
aka 6.c.errata
。这是cut on Christmas day 2015,自那天以来一直故意卡住。第二个是6.c
,它保守地添加了对6.c.errata
的修正,该修正被认为足够重要并且向后兼容,可以包含在(当时)当前的官方推荐版本的Raku中。一个“官方兼容的” Raku编译器通过了一些正式的烘烤程序。 Rakudo编译器(然后)传递了6.c.errata
。如果您阅读了例如roast的6.c.errata
分支中涉及某个功能的所有测试,那么您将已经阅读了Raku语言的ojit_code版本对该功能的正式指定含义的完整定义。关于regex - Perl6语法中的<.ident>函数/捕获,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50676007/