跳轉到內容

鸚鵡虛擬機器/編譯器構建

來自華夏公益教科書

高階語言編譯器

[編輯 | 編輯原始碼]

現在我們已經瞭解了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 鸚鵡內部
華夏公益教科書