對於那些不遵循POJ(JVM 上的Pascal)的人來說,它是一個將子集 從Pascal 轉換為JASM 的編譯器( Java Assembly),以便我們可以使用JVM 作為執行環境。
在上一篇文章中,我們解決了一些重要的錯誤,特別是在程式集的生成。在這篇文章中,我們將討論如何正確產生嵌套句子的程序集。
當我們為 JVM 進行編譯時,有必要詳細說明這個令人難以置信的虛擬機器的各個點的功能。因此,我多次詳細介紹 JVM 的內部功能及其一些指令(操作碼)。
正確處理巢狀句子的必要功能之一是解析器中可能具有多個上下文。這是因為,如果 解析器 只假定一個上下文,則會產生 標籤 並跳轉的嵌套控制語句(如if、for 、while 和repeat) 將錯誤地產生跳轉尋址。
處理上下文有兩種方法,分別是:
通常我會使用遞迴解析器方法。然而,為了使用 ANTLR 實作遞歸解析器,由於 POJ 中語法的結構方式,需要將程式碼直接注入語法中,但不建議此方法。因此,我們選擇了堆疊上下文的方法。
由於已經有一個堆疊實作來監視解析器在JVM 中堆疊/取消堆疊的類型,為了不必為特定類型建立另一個堆疊,我們決定建立一個stack此PR 中的通用。除了稍後能夠利用此實作之外,我仍然可以重構舊程式碼並刪除現有的特定 stack.
在此提交中,解析器已更改為正確堆疊/取消堆疊函數上下文。基本上,在函數的 解析器 的開頭,上下文是堆疊的,而在最後,上下文是未堆疊的。
if、for、while 和 repeat 等控制語句可以正常運作。然而,如果有嵌套句子,POJ 不會儲存上下文,最終會錯誤地產生 labels 並跳轉。這裡和這裡討論了程式集的產生如何適用於這些控制語句。
對於下面的範例,其中包含嵌套在另一個 if 中的範例,POJ 錯誤地產生了 標籤 和必要的跳轉:
program NestedIfs; begin if (1 > 2) then if (2 > 3 ) then writeln('1 > 2 and 2 > 3') else writeln('1 > 2 and 2 <= 3') else writeln('1 <= 2'); end.
這個錯誤是已知的,我選擇在解析器支援上下文時解決它。
在此提交中,建立了 LabelsContext 結構,其中包含以下 標籤:
為了驗證程序集的正確生成,創建了測試來驗證嵌套if's、嵌套repeat's、嵌套while以及for's 巢狀。此處建立測試是為了驗證在遞歸函數的情況下程序集的產生。此外,有必要更新所有現有測試的預期程序集。最後,在此 PR 中,解析器 已更新為使用新的上下文結構。
以下是這些變更的完整 PR。這裡我們有commit ,其中包含if 句子正確運行的更改,這裡commit 指的是repeat,這裡commit 指的是while,這裡commit 指的是for。
在下一篇文章中我們將討論資料輸入。現在不久我們就完成了這個專案的目標之一:從標準輸入讀取一個數字併計算其階乘。
包含項目完整程式碼和文件的儲存庫位於此處。
以上是嵌套句子的詳細內容。更多資訊請關注PHP中文網其他相關文章!