鹦鹉虚拟机/高级 PGE
本章中的信息可能会在创建关于 Perl 6 的书籍时得到更详细的介绍 |
我们已经了解了使用 PGE 和 NQP 进行解析器构建的一些基础知识。在本章中,我们将更深入地了解我们尚未见过的语法引擎的一些功能。一些更高级的功能,例如内联 PIR 代码、断言、函数调用和内置标记类型,将使编译器设计者的生活更加轻松,但对于大多数基本任务来说是不必要的。
PGE 是 Perl 6 语法规则引擎 的实现,最终将在 Parrot 上的 Perl6 实现“Rakudo”中直接使用。Perl 6 语法规则规范丰富多样,涵盖它的所有方面超出了本书的范围。我们将介绍 PGE 的基础知识以及它对构建编译器最有用的部分,但我们不可能涵盖它所有高级细节。 |
正则表达式 是一种允许回溯的高级匹配操作。标记 是一种不允许回溯的低级匹配操作。原型 像正则表达式,但允许多重调度。将原型声明视为几种函数可以匹配的原型或签名。
PIR 可以直接嵌入到 PGE 语法文件和 NQP 文件中。这对于弥合 NQP 由于其局限性而无法处理的一些差距非常重要。有时将一些主动处理插入语法也很有用,以便能够以更智能的方式指导解析器。
在 NQP 中,可以使用 PIR
语句内联 PIR 代码,后跟一个 PIR 代码的引号字符串。如果你觉得它看起来更好,这个引号字符串可以采用类似 perl 的“qw< ... >”类型的引号形式。
在 PGE 中,可以使用双大括号“{{ ... }}”插入内联 PIR。进入 PIR 模式后,可以通过调用 $Px = find_global "$/"
(其中 $Px
是任何有效的 PIR 寄存器,x 是一个数字)访问当前匹配对象。
PGE 已经定义了某些规则的基本默认值,以帮助解析。但是,如果你不喜欢默认行为,可以将其重新定义为其他内容。
函数 或 子例程 是现代编程实践中不可或缺的一部分。因此,对它们的 支持是 PAST 系统的一部分,并且相对容易实现。我们将首先介绍一些必要的背景信息,然后讨论如何将所有部分整合在一起以创建一个具有可用子例程的系统。
在 Parrot 中,控制流,尤其是子例程的返回操作,是作为特殊的控制异常实现的。为什么它作为异常而不是作为基本的 .return()
PIR 语句来实现有点复杂。许多语言允许嵌套词法范围,其中在“内部”范围中定义的变量不能被“外部”范围中的语句看到、访问或修改。在大多数编译器中,这种行为由编译器直接强制执行,并且在代码转换为汇编和机器语言时不可见。但是,PIR 就像 Parrot 系统的汇编语言,在这个级别上无法隐藏任何东西。所有局部变量对于整个子例程都是局部的,并且不能局限于子例程的单个部分。为了实现嵌套范围,Parrot 而是使用嵌套子例程
可以使用“return”PAST.op 类型使函数返回值。返回值系统基于控制异常。如前所述,异常将控制流移动到称为“异常处理程序”的指定位置。就返回异常而言,处理程序是原始函数调用后的代码。返回值(目前,return PAST 节点只允许单个返回值)作为异常数据项传递,并由控制异常处理程序检索。
所有这些细节通常对程序员隐藏,你可以像预期的那样对待 return PAST 节点。如果存在,你将一个返回值传递给 return PAST 节点。当前函数结束,其范围被销毁。控制流返回调用函数,并使函数的返回值可用。
可以使用 <FUNC( )>
格式从规则中调用函数。
使用 <. >
形式创建不捕获其内容的匹配对象。
形如 <$ >
的规则(可以是字符串或其他数据)将被转换为正则表达式,然后运行。
形如 <[ ]>
的规则包含自定义字符类。带有 <-[ ]>
的规则是补充字符类。
<?before>
,<!before>
<?after>
,<!after>
<?same>
,<!same>
<.ws>
<?at()>
,<!at()>
您可以指定一个部分匹配,它尝试尽可能多地匹配并且从不失败,使用 <* >
形式。
您可以使用 <~~ >
规则递归回到当前匹配规则的子规则。