自制操作系統Antz(14)——實現內置編程語言(詞法解析器)


AntzScript

🎓 The language executed in the Antz system.

基於以實現的內置vim,接下來需要實現Antz系統中內置語言AntzScript。

Antz系統更新地址

Antz項目地址

AntzScript項目地址

vim

一、概述

1. 解釋器與編譯器

1.1 解釋器

解釋器根據程序中的算法執行運算。簡單地說,它是一種用於執行程序的軟件。

1.2 編譯器

編譯器能將某種語言寫成的程序轉換為另一種語言的程序。通常它會將源程序轉換為機器語言程序。編譯器轉換程序的行為稱為編譯,轉換前的程序稱為源程序。

  • Java虛擬機為了提高性能,會在執行過程中通過編譯器將一部分Java二進制代碼直接轉換為機器語言使用。

過去的編譯器編譯過程非常費時,不過由於編譯后實際執行的是機器語言,因此執行速度很快。而解釋器,會在程序輸入的同時立即執行,執行速度較慢。這就是兩者的基本區別。

在為Antz制作內置腳本語言時,因為是直接執行,處理器屬於解釋器,不過,為了提高性能,該解釋器內部將采用編譯器。

基本流程如下

2. Token

語言處理器的第一個組成部分是詞法分析器(lexer)。程序的源代碼最初只是一長串字符串,這樣的字符串很難處理,語言處理器通常會首先將字符串中的字符以解析單元分組,切割成多個Token,這就是詞法分析。

解析結果

Token類中需要對源代碼分割成最小單元,並解析出變量類型數值量符號標識符

Token
Token中k代表單元含義,lexeme代表其在代碼中的內容。kindMap是一個提前預置關系轉換符表。在需要添加其他關鍵字時可以直接在KindMap中添加。

詞法解析器的實現方法有手工構造法和正則表達式的方法。

手工構造法-狀態圖

這種方法較為復雜,需要大量的代碼,而正則表達式的方法較為便捷。

二、實現詞法解析

借助正則表達式庫能簡單地實現詞法分析器。下表列出的記號在大多數情況下都能使用。例如,.*\.java指的是以.java結束的任意長度的字符串模式。.*\.由兩部分組成,.*表示由任意字符組成的任意長度的字符串模式,\.表示與句點字符相匹配的字符串模式。(java|javax)\..*則表示由java.javax.起始的任意長度的字符串模式。

元字符 含義
. 與任意字符匹配
[0-9] 與0至9中的某個數字匹配
[^0-9] 與0至9這些數字之外的的某個字符匹配
pattern* 模式pattern至少重復出現0次
pattern+ 模式pattern至少重復出現1次
pattern? 模式pattern出現0次或1次
pattern1 pattern2
() 將括號內視為一個完整的模式
\c 與單個字符c(元字符*或.等)匹配

整型字面量的匹配

[0-9]+

標識符的匹配

[A-Z_a-z][A-Z_a-z0-9]*
  • 以字母、下划線開頭,之后僅包含有字母、數字、下划線的就是標識符的定義規則。
[A-Z_a-z][A-Z_a-z0-9]*|==|<=|>=|&&|\|\||\p{Punct}

最后的\p{Punct}表示與任意一個符號字符匹配。模式\|\|將會匹配||。由於|是正則表達式的元字符,因此在使用時必須添加反斜線轉義。

最后需要定義的是字符串字面量。由於不得不處理各種轉義字符,字符串字面量的定義略微復雜。

"(\\"|\\\\|\\n|[^"])*"

首先,從整體上看,這是一個"(pattern)*"形式的模式,即雙引號內是一個與pattern重復出現至少0次的結果匹配的字符串。其中,模式pattern與\"\\\n匹配,同時也與除"之外任意一個字符匹配。

所以我們可以得到一個下圖的匹配規則regexPat。

ArrayList<Token> tokens是詞法解析器Lexer中已解析的Token

源碼source作為參數傳入Lexeradd方法中。

在創建Token時,單元作為構造函數的參數。同時變量,數字值等單元我們無法通過KindMap類來判斷k值,所以需要在這里判斷。

判斷是否是變量類型
判斷是否是數值類型
判斷是否是字符串類型

三、效果

測試代碼
Token解析

將源代碼轉換為了相應的Token單元,這就是詞法解析的主要工作了。

接下來按照源代碼獲得轉換后的直譯代碼。

效果圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM