在阅读perl6(https://github.com/supernovus/exemel/blob/master/lib/XML/Grammar.pm6)的XML语法时,我在理解下面的标记时遇到了一些困难。
token pident {
<!before \d> [ \d+ <.ident>* || <.ident>+ ]+ % '-'
}
更具体<.ident>地说,ident没有其他定义,所以我假设它是一个保留术语。虽然我在perl6.org上找不到合适的定义。有人知道这是什么意思吗?
2条答案
按热度按时间mepcadol1#
ident
的人准备的。<.ident>
功能/捕获由于
.
,<.ident>
只匹配,它不捕获[1]。对于这个答案的其余部分,我通常会省略.
,因为除了捕获方面之外,它对规则的含义没有任何影响。就像你可以在编程语言中调用(也就是“call”)另一个函数的声明中的一个函数一样,你也可以在另一个规则的声明中调用一个规则/token/regex/方法(以下我通常只使用术语“规则”)。
<foo>
是用于调用名为foo
的规则的语法;所以<ident>
调用一个名为ident
的(方法)。在我写这篇文章的时候,
XML::Grammar
语法本身并没有定义/声明一个名为ident
的规则。这意味着调用最终被分派到一个具有该名称的 * 内置 * 声明。内置的
ident
规则的作用与声明为:官方预定义字符类文档应该提供
<alpha>
和<alnum>
的精确定义。或者,有关的细节也将在本答复的后面部分提供。底线是
ident
匹配一个或多个“字母数字”字符串,除了第一个字符不能是“数字”。因此,
abc
或def123
都匹配,而123abc
不匹配。剩下的答案
对于那些有兴趣了解细节的人,我写了以下几个部分:
*NQP(中级实施)
*
ident
的规格和“规格”*
<ident>
、“字符类”和“标识符”的文档(更正)***
ident
vs Raku * 标识符 *Raku(标准语言和类详细信息)
XML::Grammar
是用户定义的Raku语法。一个Raku语法是一个类。(“语法实际上只是稍微特殊化的类”)。一个Raku rule是一个regex是一个方法:
语法中的规则 call,如
<ident>
,通常是在语法上调用.parse
或类似的结果。.parse
调用根据语法中的规则匹配输入字符串。当在匹配过程中计算
XML::Grammar
中出现的<ident>
时,结果是对XML::Grammar
的示例进行ident
方法(规则)调用(如果.parse
调用只是一个类型对象,则会创建其调用对象的示例)。因为
XML::Grammar
本身并没有定义一个同名的规则/方法,所以ident
调用是根据标准的方法解析,呃,规则来调度的。(我在这里使用的“规则”一词是通用的非Raku特定意义上的。啊,语言。)在Raku中,任何使用
grammar foo { ... }
形式的声明创建的类都会自动从Grammar
类继承,而Grammar
类又从Match
类继承:ident
在Match
类中。Rakudo(高级实现)
在Rakudo编译器中,the
Match
classdoes
的作用是NQPMatchRole
。这个
NQPMatchRole
是ident
的最高级别实现。NQP(中级实现)
NQPMatchRole
是用nqp语言编写的,nqp语言是Raku的一个子集,用于引导完整的Raku,也是NQP的核心,一个编译器工具包。从
ident
声明中提取并重新格式化最突出的代码,first 字符的匹配归结为:如果 * 第一个 * 字符是 *
_
(95
是下划线的ASCII码/ Unicode码点)* 或 * 匹配NQP中定义的字符类CCLASS_ALPHABETIC
的字符,则匹配。另一个突出的代码是:
这匹配字符类
CCLASS_WORD
中的零个或多个 * 后续 * 字符。search of NQP for
CCLASS_ALPHABETIC
显示了几个匹配项。最有用的似乎是an NQP test file。虽然这个文件清楚地表明CCLASS_WORD
是CCLASS_ALPHABETIC
的超集,但它并没有清楚地表明这些类实际上匹配什么。NQP的目标是多个“后端”或具体的虚拟机。考虑到Rakudo/NQP文档/测试相对缺乏这些规则和字符类实际匹配的内容,人们必须查看它的一个后端来验证什么是什么。
MoarVM(底层实现)
MoarVM是唯一官方支持的后端。
search of MoarVM for
CCLASS
显示了几个匹配项。重要的一个似乎是ops.c,它包含一个
switch (cclass)
语句,该语句又包含对应于NQP类似命名的常量的MVM_CCLASS_ALPHABETIC
和MVM_CCLASS_WORD
的情况。根据代码的注解:
CCLASS_ALPHABETIC
当前匹配的字符与完整的Raku或NQP<:L>
规则完全相同,即Unicode将这些字符归类为“字母”。我认为这意味着
<alpha>
等效于CCLASS_ALPHABETIC
和_
(下划线)的并集。CCLASS_WORD
匹配相同的加上<:Nd>
,即十进制数字(在任何人类语言中,不仅仅是英语)。我认为这意味着Raku / NQP
<alnum>
规则等价于CCLASS_WORD
。ident
的规格和“规格”Raku的 * 官方 * 规范体现在 roast 中[2]。
search of roast for
ident
显示了几个匹配项。大多数使用
<ident>
只是偶然的,作为测试其他东西的一部分。规范要求它们按照图示工作,但是通过查看附带的用法,您不会理解<ident>
应该做什么。三个测试清楚地测试了
<ident>
本身。其中一个基本上是多余的,剩下两个。我没有看到这两个匹配的6.c
和6.c.errata
版本之间的变化:来自S 05-质量/单位吨:
ok
测试它的第一个参数返回True
。此调用测试<ident>
跳过2+3
并匹配ab2
。来自S 05-mass/charsets.t:
is
测试它的第一个参数是否与第二个参数匹配。这个调用测试ident
规则从由前256个Unicode码点(拉丁语1字符集)组成的字符串中匹配什么。下面是这个测试的一个变体,它更清楚地显示了发生的匹配:
打印:
但是
<ident>
将匹配比Latin-1中的100个左右字符多得多的字符。因此,虽然上述测试涵盖了<ident>
* 官方指定/测试 * 的匹配,但它们显然没有涵盖全貌。因此,让我们来看看official speculation,它可能被认为与“规范”有关。
首先,我们注意到顶部的警告:
本警告中的术语“specs”是“specification”的缩写。正如已经解释过的,* 官方 * 规范测试套件是 roast,而不是任何人类语言的赘言。
(Some人们仍然认为这些历史上的设计文档也是“规格”,并称它们为“规格”,但官方的观点是,“规格”,适用于设计文档,应被视为“投机”的缩写,以强调它们不是完全依赖的东西。
search for
ident
in design.raku.org显示了几个匹配项。最有用的匹配位于S 05的 * 预定义子规则 * 部分:
以下是任何文法或正则表达式的一些预定义子规则:
呃...
<ident>
、“字符类”和“标识符”文档(更正)来自官方文档中的预定义字符类:
这在三个方面具有误导性:
ident
不是字符类。字符类匹配该字符类中的 * 单个 * 字符;如果与量词一起使用,它们只匹配一串这样的字符,每个字符可以是该类中的任何字符。相反,<ident>
匹配特定的字符模式。它可能是一个字符,但你不能控制它;规则是贪婪的,匹配尽可能多的字符符合模式。如果你应用一个量词,它控制整个规则的重复,而不是规则的单个匹配中包含多少个字符。*所有内置规则均为默认规则。我认为默认注解是为了强调如果您不喜欢内置模式,可以编写自己的
ident
规则。这对所有规则都是正确的,尽管覆盖内置的规则(如<lower>
(<lower>
)等规范字符类)通常意义不大。ident
不**匹配 * 标识符 *!或者,更准确地说,对于大多数Raku标识符,它本身并不这样做。有关详细信息,请参阅下一节。ident
vs Raku * 标识符 *在NQP的Grammar.nqp中定义的nqp语法中,有:
在Raku的语法中,Rakudo的Grammar.nqp中定义了一些代码,它们看起来略有不同,但效果完全相同:
所以
<identifier>
匹配一个包含一个或多个<ident>
s的模式,其中<apostrophe>
s介于两者之间。ident
方法在NQPMatchRole
中,这意味着它是一个内置的,是用户语法的规则命名空间的一部分。但是
identifier
方法不是由Raku或nqp导出的。所以它们不是用户语法的规则命名空间的一部分。如果我们编写自己的
indentifier
令牌,我们可以看到它的运行情况:显示:
总结上述和其他一些考虑:
<ident>
只匹配<identifier>
匹配的 * 部分 *(尽管它们对于简单名称是相同的)。以is-prime
为例。这是一个Raku标识符,但包含 * 两个 *<ident>
匹配项(is
和prime
)。<identifier>
只匹配“Raku identifiers”的 * 部分 *(尽管它们对于简单名称是相同的)。以infix:<+>
为例。这有时被称为Raku标识符,但需要<identifier>
匹配和:<+>
匹配。Foo-Bar::Baz-Qux
,它包含 * 两个 *<identifier>
匹配(每个匹配又包含两个<ident>
匹配)。脚注
[1]如果您不确定捕获是什么,请参阅捕获、命名捕获和子规则。
[2]Raku的官方规范是一个名为roast的测试套件--RepositoryOfAllSspecificationTests。roast的特定分支的最新版本定义了Raku的特定版本。当我第一次写这个答案的时候,只有两个官方的分支/版本的烤,因此是Raku。第一个是
6.c
,也就是6.Christmas
。这是cut on Christmas day 2015,从那天起就被故意冻结了。第二个是6.c.errata
,它保守地添加了对6.c
的修正,这些修正被认为足够重要,并且向后兼容,可以包含在(当时)当前的官方推荐版本中。一个“正式兼容的”Raku编译器通过了某个正式的roast分支。Rakudo编译器(然后)通过了6.c.errata
。如果您阅读了所有涉及某个特性的测试,比如roast的6.c.errata
分支,那么您就已经阅读了该特性在Raku语言的6.c.errata
版本中的 * 官方指定 * 含义的完整定义。tvz2xvvm2#
通常,查找文档的位置是Perl6 documentation。这是正则表达式的一部分,可以在字符类的定义中找到。它匹配Perl6标识符。
ident
前面的.
所做的是抑制捕获。