在翻譯完CUCU編譯器的三篇文章之後,一直有自己嘗試去寫個編譯器的念頭,最近的課餘時間暫且擱置JOS實驗,嘗試自己寫個編譯器,然後若僅僅是個編譯器則所做之事未免和CUCU太雷同了,因此除了編譯器之外還打算寫一個簡單的運行時讓編譯器編譯出的程序跑在這個運行時裏,就像JAVA那般。
手上的參考資料有:龍書三(紫龍書)、深入理解JAVA虛擬機、自己翻譯的3篇博客,儘量不去翻閱其它資料。
所有的代碼均自己寫,完全不使用任何開源代碼及相關工具如LEX和YACC之類的
我甚至都不知道靠自己的能力能不能做出來,也不知道自己寫的日誌有沒有問題,只能走一步看一步,也許之後發現前面寫的完全不靠譜,把這個系列全部刪掉也有可能。
不過這很coooooooooooooooool,不是麼。。。。
一、語言的通俗描述
既然打算做一個帶運行時的語言,我們可以去實現一個簡單的精簡過JAVA語言,就叫RAVA好了。
這個RAVA僅有以下規則,大部分都是JAVA的規則,或者精簡過後的JAVA規則。
1、一個文件裏只能定義一個類。
2、類名不能相同。
3、包含一個static int main()作爲程序入口
4、一個類必須有一個構造函數
5、一個類中可以定義若干私有或共有變量,但變量必須要在構造函數中進行初始化,可以定義靜態變量。
6、3種基本類型 char,int,double分別佔1 、4、4字節。
7、支持數組,數組聲明方式和java一樣
8、使用new關鍵字新建對象或者數組。
9、可以聲明調用函數,函數聲明時必須說明訪問權限(private public),可以定義靜態函數。
10、函數必須有返回值,函數結束處必須有return。
11、控制語句只有if 、if else、while循環(不支持for循環)
12、其它一些java基本的規則(比如語句之後用分好分割,不能使用if for等作爲標識符)
二、文法和範式
文法即語法,接下來要把上面通俗的規則變成所謂的語法,那麼不可避免的問題就是:語法是什麼。
通俗的講,語法就是一門語言的規則,通過語法才能知道一個句子在這個語言中是不是合理的。那麼就會引出第二個問題:如何描述語法。
關於文法的內容可參考我翻譯的cucu編譯器的文章http://blog.csdn.net/roger__wong/article/details/8498591 以及編譯原理等相關資料。
文法由三部分組成:終結符號集合、非終結符號集合、一組產生式和開始符號
1、終結符號
終結符號又被稱作詞法單元,是詞法分析器的輸出內容,是代碼中不可分割的基本元素,根據需要,我們定義如下符號爲終結符號(每個符號之間用空格隔開):
if else while ( ) { } cpreop bitop logiop armtcop number literal id NUL new [ ] basetype class private public static return break continue . this ; = ,
其中cprop包括 > < >= <= == != 即比較運算符
bitop 爲位運算符,包括<< >> & | ^
logiop 邏輯運算符 包括 && ||
armtcop 算數運算符 包括 + - * /
number 數字常量 例如12345整形火 1.2345小數
id 標識符 按java規則
literal 字符串常量 如"ROgerwong"
NUL 空串
basetype 基本類型 包括 int char double 三種
2、非終結符號
在產生式中出現的除終結符號外都是非終結符號。
3、開始符號
語法樹的根,根據java語言特性定義class-def符號爲開始符號
4、推導式
class-name --> id
type --> basetype|class name
member-var-declare --> private|public
NUL|static
type id ;
def-args --> type id |type id , def-args
func-name-->ids
args --> ids | ids, args
func-call --> ids . func-name(NUL|args)
ops --> bitop | logiop | artmop | cprop
ids-> id|
id.ids|
ids[expr] |
this
expr --> (expr)
ids|
number|
literal|
func-call|
expr ops expr|
var-declare --> type args|type[] args
class-init --> ids = new
type ( args )| type[expr]| typex[expr](args)
setvalue--> ids = expr
stmt --> continue;|
break;|
var-declare;|
class-init;|
setvalue;|
expr;|
stmts --> NUL|
stmt stmts|
if(expr) { stmts}|
if(expr) {stmts} else {stmts}
while(expr) { stmts}
func-body --> stmts return expr;
member-func-declare --> private|public
NUL|static
type func-name( NUL|def-args ) { func-body }
constructor --> public|private
class-name(NUL|def-args) {stmts}
class-members--> NUL|
member-func-declare class-members|
member-var-declare class-members|
constructor class-members
class-body-->class-members
class-def --> class class-name { class-body }