perl6 语法,不确定示例中的某些语法
perl6 grammar , not sure about some syntax in an example
我还在学习 perl6,我正在阅读此页面上的语法示例:http://examples.perl6.org/categories/parsers/SimpleStrings.html; regex的文档看了好几遍,还是有些语法没看懂
token string { <quote> {} <quotebody($<quote>)> $<quote> }
问题一:令牌中的这个“{}”是做什么用的?捕获标记为 <()>,嵌套结构为 tilda '(' ~ ')';但是 {} 是什么?
token quotebody($quote) { ( <escaped($quote)> | <!before $quote> . )* }
问题 2a:<> 中的 escaped($quote) 将是一个正则表达式函数,对吗?它需要 $quote 作为参数和 returns 另一个正则表达式 ?
问题 2b:如果我想表示 "char that is not before quote",我应该使用“.”而不是“”。 ??
token escaped($quote) { '\' ( $quote | '\' ) } # I think this is a function;
{}
是一个空代码块。它是语法的过程性(而不是声明性)元素。你可以把常规的 Perl 6 代码放在那里让它做一些事情。
在这种模式下,它正在做另一项工作。它提供了一个序列点,语法引擎知道它需要做各种事情才能继续。这包括填写捕获变量的值(例如 $<quote>
)。该模式的下一部分需要确保 $<quote>
有它的值,所以它需要一些东西来确保该值可用。
$<quote>
其实就是单元素访问Match对象$/
。作为一个类似散列的东西,它实际上是 $/<quote>
,其中尖括号之间的东西是 "key"。 Perl 6 有点聪明,所以它可以让你放弃 /
以获得 $<quote>
。 </code> 等其他匹配变量也是类似的快捷方式。</p>
<p>对于您的最后一个问题,查看您尝试匹配的一些示例数据会有所帮助。 Perl 6 语法有许多匹配平衡文本的特性,这可能使任务变得微不足道。例如,参见 <a href="https://docs.perl6.org/language/regexes#Tilde_for_nesting_structures" rel="nofollow noreferrer">Tilde for nesting structures</a> in the <a href="https://docs.perl6.org/language/regexes" rel="nofollow noreferrer">Regexp documentation</a>:</p>
<pre><code> / '(' ~ ')' <expression> /
这是 REPL 中的一个简短示例。有一个字符串,其中包含一些引用的文本:
$ perl6
To exit type 'exit' or '^D'
> my $s = Q/abcdf "Hello" xyz/
abcdf "Hello" xyz
正则表达式中的 ~
位于分隔符之间。结束定界符之后的内容是您希望 ~
所在的内容:
> $s ~~ m/ '"' ~ '"' .+ /
「"Hello"」
您可以匹配开头的内容并捕获它(现在它在 [=25=]
中),这样您就可以使用与结束分隔符完全相同的内容:
> $s ~~ m/ (<["']>) ~ [=13=] .+ /
「"Hello"」
0 => 「"」
对于that particular example 我认为有一个更简单的方法。匹配转义引号或任何不是引号的内容,而不是环顾四周和任何字符。这还不算费脑筋。
TL;DR @briandfoy 提供了 。但这里有他没有提到的龙。还有漂亮的蝴蝶。这个答案有深度。
Question 1: what is this {}
in the token doing?
是代码块1,2,3,4.
它是一个空的,插入纯粹是为了强制 quotebody($<quote>)
中的 $<quote>
计算为正则表达式开头的 <quote>
捕获的值。
为什么 $<quote>
不 包含正确的值而不插入代码块的原因是 Rakudo Perl 6 编译器限制或与 [=324= 相关的错误].
"Publication" 匹配变量的 Rakudo
Moritz Lenz 在 a Rakudo bug report 中指出 "the regex engine doesn't publish match variables unless it is deemed necessary".
"regex engine" 他指的是 NQP 中的 regex/grammar 引擎,Rakudo Perl 6 编译器的一部分。3
通过"match variables",他的意思是存储捕获的匹配结果的变量:
当前匹配变量$/
;
编号子匹配变量[=23=]
、</code>等;</p></li>
<li><p><em>named</em> 形式的子匹配变量 <code>$<foo>
.
"publish" 他的意思是 regex/grammar 引擎会做它需要做的事情,以便在正则表达式(标记也是正则表达式)中提及的任何变量都会计算出它们的值应该在他们应该拥有的时候拥有。在给定的正则表达式中,匹配变量应该包含一个Match
object对应于在处理该正则表达式的任何给定阶段为它们捕获的内容,或者Nil
如果什么都没有被捕获。
"deemed necessary" 他的意思是 regex/grammar 引擎在匹配过程中的每一步之后对是否值得进行发布工作做出保守的判断。 "conservative" 我的意思是引擎经常避免发布,因为它会减慢速度并且通常是不必要的。不幸的是,有时对于 实际需要发布的时间过于乐观。因此,程序员有时需要通过显式插入代码块来强制发布匹配变量(以及其他变量的其他技术5)进行干预。随着时间的推移,regex/grammar 引擎可能会在这方面有所改进,从而减少需要手动干预的情况。如果您希望帮助推进这一点,请针对现有的相关错误创建对您重要的测试用例。5
"Publication" 的 $<quote>
的值
命名捕获 $<quote>
就是这种情况。
据我所知,所有子匹配变量在直接写入正则表达式而没有周围构造时都正确地引用了它们捕获的值。这有效:
my regex quote { <['"]> }
say so '"aa"' ~~ / <quote> aa $<quote> /; # True
我认为6 $<quote>
得到了正确的值,因为它被解析为 regex 俚语 结构。4
相比之下,如果 {}
从
中删除
token string { <quote> {} <quotebody($<quote>)> $<quote> }
那么 quotebody($<quote>)
中的 $<quote>
将 而不是 包含由 <quote>
.
捕获的值
我认为这是因为 $<quote>
在这种情况下被解析为 main 俚语结构。
Question 2a: escaped($quote)
inside <>
would be a regex function, right? And it takes $quote
as an argument
这是一个很好的近似值。
更具体地说,<foo(...)>
形式的正则表达式原子是 方法 foo
.
的调用
所有正则表达式——无论是用 token
、regex
、rule
、/.../
还是任何其他形式声明的——都是方法。但是用 method
声明的方法是 而不是 正则表达式:
say Method ~~ Regex; # False
say WHAT token { . } # (Regex)
say Regex ~~ Method; # True
say / . / ~~ Method; # True
当遇到 <escaped($quote)>
正则表达式原子时,regex/grammar 引擎不知道或不关心 escaped
是否是正则表达式,也不关心 。它只是调用方法分派,调用者设置为 Match
对象,该对象由封闭的正则表达式构造。
调用将控制权交给最终 运行 方法的任何内容。通常会发现 regex/grammar 引擎只是递归地回调自身,因为通常这是一个正则表达式调用另一个正则表达式的问题。但不一定如此。
and returns another regex
不,<escaped($quote)>
形式的正则表达式原子不会 return 另一个正则表达式。
相反,它调用一个 will/should return 一个 Match
对象的方法。
如果调用的方法是正则表达式,P6 将确保正则表达式自动生成并填充 Match
对象。
如果调用的方法不是正则表达式,而只是普通方法,则该方法的代码应该已手动创建并return编辑了一个 Match
对象。 Moritz 在他对 SO 问题 Can I change the Perl 6 slang inside a method?.
的回答中展示了一个例子
Match
对象被 return 编辑到驱动正则表达式匹配/语法分析的 "regex/grammar engine"。3
然后引擎根据结果决定下一步做什么:
如果匹配成功,引擎会更新与调用正则表达式对应的整体匹配对象。更新可能包括将 returned Match
对象保存为调用正则表达式的子匹配捕获。这就是 match/parse 树 的构建方式。
如果匹配不成功,引擎可能回溯,撤销之前的更新;因此解析树可能会随着匹配的进行而动态增长和收缩。
Question 2b: If I want to indicate "char that is not before quote", should I use . <!before $quote>
instead of <!before $quote> .
??
是的。
但这不是 quotebody
正则表达式所需要的,如果这就是您所说的。
关于后一个主题,在@briandfoy 的回答中,他建议使用 "Match ... anything that's not a quote" 构造,而不是进行负面展望 (<!before $quote>
)。他的观点是匹配 "not a quote" 比 "are we not before a quote? then match any character".
更容易理解
但是,当引号是一个变量,其值设置为开始引号的捕获时,执行此操作决不是直截了当的。这种复杂性是由于 Rakudo 中的错误。我已经找到了我认为最简单的解决方法,但我认为最好还是坚持使用 <!before $quote> .
unless/until 这些长期存在的 Rakudo 错误已修复。5
token escaped($quote) { '\' ( $quote | '\' ) } # I think this is a function;
是一个token,这是一个Regex
,这是一个Method
,这是一个Routine
:
say token { . } ~~ Regex; # True
say Regex ~~ Method; # True
say Method ~~ Routine; # True
正则表达式主体({ ... }
位)内的代码(在本例中,代码是 token { . }
中唯一的 .
,它是匹配的正则表达式原子单个字符)写在 P6 正则表达式 "slang" 中,而 method
例程主体中使用的代码写在主 P6 "slang".4
使用~
regex tilde (~
) operator 是专门为这个问题所涉及的示例中的那种解析而设计的。它读起来更好,因为它可以立即识别并将开头和结尾的引号放在一起。更重要的是,它可以在发生故障时提供人类可理解的错误消息,因为它可以说明它正在寻找的结束定界符。
但是,如果您在正则表达式 ~
运算符(在它的任一侧)旁边的正则表达式中插入代码块(其中有或没有代码),则必须考虑一个关键问题。您将需要对代码块进行分组,除非您特别希望波浪号将代码块视为它自己的原子。例如:
token foo { <quote> ~ $<quote> {} <quotebody($<quote>) }
将匹配一对 <quote>
,它们之间没有任何内容。 (然后尝试匹配<quotebody...>
。)
相比之下,这里有一种方法可以在 String::Simple::Grammar
语法中复制 string
标记的匹配行为:
token string { <quote> ~ $<quote> [ {} <quotebody($<quote>) ] }
脚注
1 2002 年,Larry Wall 写了 "It needs to be just as easy for a regex to call Perl code as it is for Perl code to call a regex.". Computer scientists note that you can't have procedural code in the middle of a traditional regular expression. But Perls long ago led the shift to non-traditional regexes and P6 has arrived at the logical conclusion -- a simple {...}
is all it takes to insert arbitrary procedural code in the middle of a regex. The language design and regex/grammar engine implementation3 ensure that traditional style purely declarative regions within a regex are recognized, so that formal regular expression theory and optimizations can be applied to them, but nevertheless arbitrary regular procedural code can also be inserted. Simple uses include matching logic and debugging。但天空是极限。
2 正则表达式的第一个程序元素(如果有的话)终止所谓的正则表达式的 "declarative prefix"。插入空代码块 ({}
) 的一个常见原因是在正则表达式中为给定 longest alternation 提供所需的匹配语义时故意终止正则表达式的声明性前缀。 (但这不是将其包含在您试图理解的令牌中的原因。)
3 笼统地说,NQP is to P6 what PCRE中的正则表达式/语法引擎是P5.
一个关键的区别是正则表达式语言,连同它相关的 regex/grammar 引擎,以及它与之合作的主要语言,在 Rakudo 的情况下是 Perl 6,在控制方面是平等的.这是 Larry Wall's original 2002 vision for integration between regexes and "rich languages" 的实现。每个 language/run-time 都可以调用对方并通过高级 FFI 进行通信。因此,它们可以看起来、可以表现为,而且实际上是一个由合作语言和合作 运行 次的单一系统。
(P6 的设计使得 所有 语言都可以明确设计或改装,以 "rich" 方式通过两个互补的 P6 FFIs: the metamodel FFI 6model and/or the C calling convention FFI NativeCall.)
4 P6 语言实际上是一起使用的子语言(又名俚语)的集合。当您阅读或编写 P6 代码时,您正在阅读或编写源代码,这些源代码以一种俚语开头,但其中有一些部分是用其他俚语编写的。文件的第一行使用主要俚语。假设这类似于英语。正则表达式是用另一种俚语编写的;让我们说这就像西班牙语。所以在 the grammar String::Simple::Grammar
的情况下,代码以英语开始(use v6;
语句),然后递归为西班牙语(在 rule TOP {
的 {
之后),即 ^ <string> $
位,然后 returns 返回英文(评论开始 # Note ...
)。然后它递归回 <quote> {} <quotebody($<quote>)> $<quote>
的西班牙语,在该西班牙语的中间,在 {}
代码块处,它再次递归到 另一个级别 的英语。这就是英语中的西班牙语中的英语。当然,代码块是空的,所以它就像 writing/reading 没有英文,然后立即回到西班牙语,但重要的是要理解 languages/run-times 的这种递归堆叠是 P6 的工作方式,既单人整体language/run-time与其他非P6合作时languages/run-times.
5 在应用两个潜在改进的过程中,我遇到了几个错误,列在这个脚注的末尾。 (在 briandfoy 的回答和这个回答中都提到了。)两个 "improvements" 是使用 ~
结构,"not a quote" 结构而不是使用 <!before foo> .
。最终结果,加上相关错误的提及:
grammar String::Simple::Grammar {
rule TOP {^ <string> $}
token string {
:my $*not-quote;
<quote> ~ $<quote>
[
{ $*not-quote = "<-[$<quote>]>" }
<quotebody($<quote>)>
]
}
token quote { '"' | "'" }
token quotebody($quote) { ( <escaped($quote)> | <$*not-quote> )* }
token escaped($quote) { '\' ( $quote | '\' ) }
}
如果有人知道更简单的方法,我很乐意在下面的评论中听到。
我最终在 RT 错误数据库中搜索了所有正则表达式错误。我知道 SO 不是错误数据库,但我认为我有理由注意以下内容。 aiui前两个直接交互匹配变量发布的问题
"the < >
regex call syntax looks up lexicals only in the parent scope of the regex it is used in, and not in the scope of the regex itself." rt #127872
Backtracking woes as they relate to passing arguments in regex calls
看起来有很多讨厌的线程错误。大多数归结为几个正则表达式功能在幕后使用 EVAL
并且 EVAL
还不是线程安全的。幸运的是官方文档提到了这些。
6 这个问题和我的回答将我推向了我对 P6 雄心勃勃和复杂方面的理解的外部极限。我计划很快更深入地了解 nqp 和完整 P6 之间的精确交互,以及它们的正则表达式俚语和主要俚语之间的交接,如上面脚注中所讨论的。 (我目前的希望主要寄托在刚刚购买 commaide 上。)我会更新这个答案 if/when 我有一些结果。
我还在学习 perl6,我正在阅读此页面上的语法示例:http://examples.perl6.org/categories/parsers/SimpleStrings.html; regex的文档看了好几遍,还是有些语法没看懂
token string { <quote> {} <quotebody($<quote>)> $<quote> }
问题一:令牌中的这个“{}”是做什么用的?捕获标记为 <()>,嵌套结构为 tilda '(' ~ ')';但是 {} 是什么?
token quotebody($quote) { ( <escaped($quote)> | <!before $quote> . )* }
问题 2a:<> 中的 escaped($quote) 将是一个正则表达式函数,对吗?它需要 $quote 作为参数和 returns 另一个正则表达式 ?
问题 2b:如果我想表示 "char that is not before quote",我应该使用“.”而不是“”。 ??
token escaped($quote) { '\' ( $quote | '\' ) } # I think this is a function;
{}
是一个空代码块。它是语法的过程性(而不是声明性)元素。你可以把常规的 Perl 6 代码放在那里让它做一些事情。
在这种模式下,它正在做另一项工作。它提供了一个序列点,语法引擎知道它需要做各种事情才能继续。这包括填写捕获变量的值(例如 $<quote>
)。该模式的下一部分需要确保 $<quote>
有它的值,所以它需要一些东西来确保该值可用。
$<quote>
其实就是单元素访问Match对象$/
。作为一个类似散列的东西,它实际上是 $/<quote>
,其中尖括号之间的东西是 "key"。 Perl 6 有点聪明,所以它可以让你放弃 /
以获得 $<quote>
。 </code> 等其他匹配变量也是类似的快捷方式。</p>
<p>对于您的最后一个问题,查看您尝试匹配的一些示例数据会有所帮助。 Perl 6 语法有许多匹配平衡文本的特性,这可能使任务变得微不足道。例如,参见 <a href="https://docs.perl6.org/language/regexes#Tilde_for_nesting_structures" rel="nofollow noreferrer">Tilde for nesting structures</a> in the <a href="https://docs.perl6.org/language/regexes" rel="nofollow noreferrer">Regexp documentation</a>:</p>
<pre><code> / '(' ~ ')' <expression> /
这是 REPL 中的一个简短示例。有一个字符串,其中包含一些引用的文本:
$ perl6
To exit type 'exit' or '^D'
> my $s = Q/abcdf "Hello" xyz/
abcdf "Hello" xyz
正则表达式中的 ~
位于分隔符之间。结束定界符之后的内容是您希望 ~
所在的内容:
> $s ~~ m/ '"' ~ '"' .+ /
「"Hello"」
您可以匹配开头的内容并捕获它(现在它在 [=25=]
中),这样您就可以使用与结束分隔符完全相同的内容:
> $s ~~ m/ (<["']>) ~ [=13=] .+ /
「"Hello"」
0 => 「"」
对于that particular example 我认为有一个更简单的方法。匹配转义引号或任何不是引号的内容,而不是环顾四周和任何字符。这还不算费脑筋。
TL;DR @briandfoy 提供了
Question 1: what is this
{}
in the token doing?
是代码块1,2,3,4.
它是一个空的,插入纯粹是为了强制 quotebody($<quote>)
中的 $<quote>
计算为正则表达式开头的 <quote>
捕获的值。
为什么 $<quote>
不 包含正确的值而不插入代码块的原因是 Rakudo Perl 6 编译器限制或与 [=324= 相关的错误].
"Publication" 匹配变量的 Rakudo
Moritz Lenz 在 a Rakudo bug report 中指出 "the regex engine doesn't publish match variables unless it is deemed necessary".
"regex engine" 他指的是 NQP 中的 regex/grammar 引擎,Rakudo Perl 6 编译器的一部分。3
通过"match variables",他的意思是存储捕获的匹配结果的变量:
当前匹配变量
$/
;编号子匹配变量
[=23=]
、</code>等;</p></li> <li><p><em>named</em> 形式的子匹配变量 <code>$<foo>
.
"publish" 他的意思是 regex/grammar 引擎会做它需要做的事情,以便在正则表达式(标记也是正则表达式)中提及的任何变量都会计算出它们的值应该在他们应该拥有的时候拥有。在给定的正则表达式中,匹配变量应该包含一个Match
object对应于在处理该正则表达式的任何给定阶段为它们捕获的内容,或者Nil
如果什么都没有被捕获。
"deemed necessary" 他的意思是 regex/grammar 引擎在匹配过程中的每一步之后对是否值得进行发布工作做出保守的判断。 "conservative" 我的意思是引擎经常避免发布,因为它会减慢速度并且通常是不必要的。不幸的是,有时对于 实际需要发布的时间过于乐观。因此,程序员有时需要通过显式插入代码块来强制发布匹配变量(以及其他变量的其他技术5)进行干预。随着时间的推移,regex/grammar 引擎可能会在这方面有所改进,从而减少需要手动干预的情况。如果您希望帮助推进这一点,请针对现有的相关错误创建对您重要的测试用例。5
"Publication" 的 $<quote>
的值
命名捕获 $<quote>
就是这种情况。
据我所知,所有子匹配变量在直接写入正则表达式而没有周围构造时都正确地引用了它们捕获的值。这有效:
my regex quote { <['"]> }
say so '"aa"' ~~ / <quote> aa $<quote> /; # True
我认为6 $<quote>
得到了正确的值,因为它被解析为 regex 俚语 结构。4
相比之下,如果 {}
从
token string { <quote> {} <quotebody($<quote>)> $<quote> }
那么 quotebody($<quote>)
中的 $<quote>
将 而不是 包含由 <quote>
.
我认为这是因为 $<quote>
在这种情况下被解析为 main 俚语结构。
Question 2a:
escaped($quote)
inside<>
would be a regex function, right? And it takes$quote
as an argument
这是一个很好的近似值。
更具体地说,<foo(...)>
形式的正则表达式原子是 方法 foo
.
所有正则表达式——无论是用 token
、regex
、rule
、/.../
还是任何其他形式声明的——都是方法。但是用 method
声明的方法是 而不是 正则表达式:
say Method ~~ Regex; # False
say WHAT token { . } # (Regex)
say Regex ~~ Method; # True
say / . / ~~ Method; # True
当遇到 <escaped($quote)>
正则表达式原子时,regex/grammar 引擎不知道或不关心 escaped
是否是正则表达式,也不关心 Match
对象,该对象由封闭的正则表达式构造。
调用将控制权交给最终 运行 方法的任何内容。通常会发现 regex/grammar 引擎只是递归地回调自身,因为通常这是一个正则表达式调用另一个正则表达式的问题。但不一定如此。
and returns another regex
不,<escaped($quote)>
形式的正则表达式原子不会 return 另一个正则表达式。
相反,它调用一个 will/should return 一个 Match
对象的方法。
如果调用的方法是正则表达式,P6 将确保正则表达式自动生成并填充 Match
对象。
如果调用的方法不是正则表达式,而只是普通方法,则该方法的代码应该已手动创建并return编辑了一个 Match
对象。 Moritz 在他对 SO 问题 Can I change the Perl 6 slang inside a method?.
Match
对象被 return 编辑到驱动正则表达式匹配/语法分析的 "regex/grammar engine"。3
然后引擎根据结果决定下一步做什么:
如果匹配成功,引擎会更新与调用正则表达式对应的整体匹配对象。更新可能包括将 returned
Match
对象保存为调用正则表达式的子匹配捕获。这就是 match/parse 树 的构建方式。如果匹配不成功,引擎可能回溯,撤销之前的更新;因此解析树可能会随着匹配的进行而动态增长和收缩。
Question 2b: If I want to indicate "char that is not before quote", should I use
. <!before $quote>
instead of<!before $quote> .
??
是的。
但这不是 quotebody
正则表达式所需要的,如果这就是您所说的。
关于后一个主题,在@briandfoy 的回答中,他建议使用 "Match ... anything that's not a quote" 构造,而不是进行负面展望 (<!before $quote>
)。他的观点是匹配 "not a quote" 比 "are we not before a quote? then match any character".
但是,当引号是一个变量,其值设置为开始引号的捕获时,执行此操作决不是直截了当的。这种复杂性是由于 Rakudo 中的错误。我已经找到了我认为最简单的解决方法,但我认为最好还是坚持使用 <!before $quote> .
unless/until 这些长期存在的 Rakudo 错误已修复。5
token escaped($quote) { '\' ( $quote | '\' ) } # I think this is a function;
是一个token,这是一个Regex
,这是一个Method
,这是一个Routine
:
say token { . } ~~ Regex; # True
say Regex ~~ Method; # True
say Method ~~ Routine; # True
正则表达式主体({ ... }
位)内的代码(在本例中,代码是 token { . }
中唯一的 .
,它是匹配的正则表达式原子单个字符)写在 P6 正则表达式 "slang" 中,而 method
例程主体中使用的代码写在主 P6 "slang".4
使用~
regex tilde (~
) operator 是专门为这个问题所涉及的示例中的那种解析而设计的。它读起来更好,因为它可以立即识别并将开头和结尾的引号放在一起。更重要的是,它可以在发生故障时提供人类可理解的错误消息,因为它可以说明它正在寻找的结束定界符。
但是,如果您在正则表达式 ~
运算符(在它的任一侧)旁边的正则表达式中插入代码块(其中有或没有代码),则必须考虑一个关键问题。您将需要对代码块进行分组,除非您特别希望波浪号将代码块视为它自己的原子。例如:
token foo { <quote> ~ $<quote> {} <quotebody($<quote>) }
将匹配一对 <quote>
,它们之间没有任何内容。 (然后尝试匹配<quotebody...>
。)
相比之下,这里有一种方法可以在 String::Simple::Grammar
语法中复制 string
标记的匹配行为:
token string { <quote> ~ $<quote> [ {} <quotebody($<quote>) ] }
脚注
1 2002 年,Larry Wall 写了 "It needs to be just as easy for a regex to call Perl code as it is for Perl code to call a regex.". Computer scientists note that you can't have procedural code in the middle of a traditional regular expression. But Perls long ago led the shift to non-traditional regexes and P6 has arrived at the logical conclusion -- a simple {...}
is all it takes to insert arbitrary procedural code in the middle of a regex. The language design and regex/grammar engine implementation3 ensure that traditional style purely declarative regions within a regex are recognized, so that formal regular expression theory and optimizations can be applied to them, but nevertheless arbitrary regular procedural code can also be inserted. Simple uses include matching logic and debugging。但天空是极限。
2 正则表达式的第一个程序元素(如果有的话)终止所谓的正则表达式的 "declarative prefix"。插入空代码块 ({}
) 的一个常见原因是在正则表达式中为给定 longest alternation 提供所需的匹配语义时故意终止正则表达式的声明性前缀。 (但这不是将其包含在您试图理解的令牌中的原因。)
3 笼统地说,NQP is to P6 what PCRE中的正则表达式/语法引擎是P5.
一个关键的区别是正则表达式语言,连同它相关的 regex/grammar 引擎,以及它与之合作的主要语言,在 Rakudo 的情况下是 Perl 6,在控制方面是平等的.这是 Larry Wall's original 2002 vision for integration between regexes and "rich languages" 的实现。每个 language/run-time 都可以调用对方并通过高级 FFI 进行通信。因此,它们可以看起来、可以表现为,而且实际上是一个由合作语言和合作 运行 次的单一系统。
(P6 的设计使得 所有 语言都可以明确设计或改装,以 "rich" 方式通过两个互补的 P6 FFIs: the metamodel FFI 6model and/or the C calling convention FFI NativeCall.)
4 P6 语言实际上是一起使用的子语言(又名俚语)的集合。当您阅读或编写 P6 代码时,您正在阅读或编写源代码,这些源代码以一种俚语开头,但其中有一些部分是用其他俚语编写的。文件的第一行使用主要俚语。假设这类似于英语。正则表达式是用另一种俚语编写的;让我们说这就像西班牙语。所以在 the grammar String::Simple::Grammar
的情况下,代码以英语开始(use v6;
语句),然后递归为西班牙语(在 rule TOP {
的 {
之后),即 ^ <string> $
位,然后 returns 返回英文(评论开始 # Note ...
)。然后它递归回 <quote> {} <quotebody($<quote>)> $<quote>
的西班牙语,在该西班牙语的中间,在 {}
代码块处,它再次递归到 另一个级别 的英语。这就是英语中的西班牙语中的英语。当然,代码块是空的,所以它就像 writing/reading 没有英文,然后立即回到西班牙语,但重要的是要理解 languages/run-times 的这种递归堆叠是 P6 的工作方式,既单人整体language/run-time与其他非P6合作时languages/run-times.
5 在应用两个潜在改进的过程中,我遇到了几个错误,列在这个脚注的末尾。 (在 briandfoy 的回答和这个回答中都提到了。)两个 "improvements" 是使用 ~
结构,"not a quote" 结构而不是使用 <!before foo> .
。最终结果,加上相关错误的提及:
grammar String::Simple::Grammar {
rule TOP {^ <string> $}
token string {
:my $*not-quote;
<quote> ~ $<quote>
[
{ $*not-quote = "<-[$<quote>]>" }
<quotebody($<quote>)>
]
}
token quote { '"' | "'" }
token quotebody($quote) { ( <escaped($quote)> | <$*not-quote> )* }
token escaped($quote) { '\' ( $quote | '\' ) }
}
如果有人知道更简单的方法,我很乐意在下面的评论中听到。
我最终在 RT 错误数据库中搜索了所有正则表达式错误。我知道 SO 不是错误数据库,但我认为我有理由注意以下内容。 aiui前两个直接交互匹配变量发布的问题
"the
< >
regex call syntax looks up lexicals only in the parent scope of the regex it is used in, and not in the scope of the regex itself." rt #127872Backtracking woes as they relate to passing arguments in regex calls
看起来有很多讨厌的线程错误。大多数归结为几个正则表达式功能在幕后使用
EVAL
并且EVAL
还不是线程安全的。幸运的是官方文档提到了这些。
6 这个问题和我的回答将我推向了我对 P6 雄心勃勃和复杂方面的理解的外部极限。我计划很快更深入地了解 nqp 和完整 P6 之间的精确交互,以及它们的正则表达式俚语和主要俚语之间的交接,如上面脚注中所讨论的。 (我目前的希望主要寄托在刚刚购买 commaide 上。)我会更新这个答案 if/when 我有一些结果。