跳转到内容

鹦鹉虚拟机/编译器构建

来自维基教科书,开放世界中的开放书籍

高级语言编译器

[编辑 | 编辑源代码]

现在我们已经了解了NQP和PGE,我们有了开始编写我们最喜欢的语言编译器的工具。让我们回顾一下创建编译器的步骤

  1. 使用PGE编写语法
  2. 使用NQP编写动作
  3. 动作创建PAST树
  4. PCT将PAST转换为PIR
  5. 鹦鹉将PIR转换为字节码。

在步骤5之后,如果我们一切都做对了,我们应该有一个可以工作的编译器。当然,在我们到达步骤5之前还有很多工作要做。幸运的是,步骤4和5由构建过程自动完成,因此我们只需要关注1、2和3。在教程部分,我们将提供一些语言构建教程,你可以参考。

创建PAST树

[编辑 | 编辑源代码]

PAST节点是你的NQP动作方法必须创建的对象。PCT会在你创建这些节点后自动将它们插入到树中。PAST节点是具有数组和哈希组件的复杂对象。数组存储对子节点引用的列表,而哈希存储有关节点本身的信息。创建PAST树意味着我们创建低层规则的节点,并将它们插入到高层规则的数组中。在创建过程中,我们为每个规则设置必要的选项,以便PCT可以生成相应的代码。

附录中提供了有关各种PAST节点类型的参考。

PAST::Node是其他PAST节点类型派生的基类。其他类型是PAST::Stmts、PAST::Val、PAST::Var、PAST::Op和PAST::Block。

PAST::Op

PAST::Op节点是需要执行的操作。

PAST::Val

PAST::VAL节点是常量值,如整数或字符串

PAST::Var

PAST::Var节点是变量

PAST::Block

PAST::Block节点用于词法作用域变量和定义子例程。它们将其他节点放在一起。

PAST::Stmts

PAST::Stmts节点只是其他节点的组,除了基本的组织之外不执行任何任务。

创建好必要的节点后,可以使用关键字make将它插入到解析树中。

匹配对象

[编辑 | 编辑源代码]

匹配对象是一个包含哈希的特殊对象。匹配对象哈希包含有关匹配规则的信息。哈希中的每个元素都以规则中的一个子规则命名。例如,如果我们有以下规则

rule sentence { 
  <adjective> <noun> <adverb> <verb>
}

那么匹配规则将包含条目“形容词”、“名词”、“副词”和“动词”。这些键的哈希值是使用make命令从子规则返回的值(如果有)。所以,我们将有以下字段

$<adjective>
$<noun>
$<adverb>
$<verb>

然后,我们将使用这些字段的值来为sentence规则生成和make一个节点。如果这些字段中的每一个都返回它们自己的PAST节点,我们应该将它们推入

我们将在这里展示一些非常小的示例,以演示基本的编译器构建方法。教程部分提供了更高级的教程。

示例:基本计算器

[编辑 | 编辑源代码]
问题

我们想创建一个基本的计算器程序,它可以对整数执行加法和减法。计算器应将结果打印到屏幕上。

解决方案
我们首先运行mk_language_shell.pl来创建一个基本的语言框架。这还会生成一个名为say的内置函数。我们将使用say函数将结果打印到屏幕上。我们将使用基本的自顶向下解析器,我们不会使用操作表。

我们为我们的计算器创建一个基本语法

rule TOP {
  <expression>
  {*}
}

rule expression {
  <term> <operation> <term>
  {*}
}

token operation { '+' | '-' }

token term { \d+ }

现在我们需要创建两个动作,一个用于TOP,另一个用于表达式。TOP方法应该获取解析表达式的值并将其传递给say函数。表达式函数应该生成必要的PIR操作,并将term值插入这些操作中。这是一个基本的动作文件来完成这项工作

method TOP($/) {
  my $past := PAST::Op.new(:pasttype('inline'));
  my $expr := $( $<expression> );
  $past.inline('say(%0)');
  $past.unshift($expr);
  make $past;
}

method expression($/) {
  my $left := $( $<term>[0] );
  my $right := $( $<term>[1] );
  my $op := $( $<operation> );
  my $pirop := "sub_n";
  if $op eq "+" {
    my $pirop := "add_n";
  }
  my $past := PAST::Op.new(:pasttype('pirop'), :pirop($pirop));
  $past.unshift($left);
  $past.unshift($right);
  make $past;
}


上一个 鹦鹉虚拟机 下一个
高级PGE 鹦鹉内部
华夏公益教科书