D 語言的子集的 Z 編譯器

  把 D 語言的語法規則改寫成 ANTLR 的語法腳本後,大概有30多K,編譯的時候,出了很多的錯誤,最後內存溢出了。想一想,也是,一來我對 ANTLR 還不熟,二來,Digit Mars 上的 D 語言語法介紹,很多左遞歸,有幾個沒有定義的過程,兩個拼寫錯誤,一個同名不同義的過程等等。在這種情況下,30多K的語法腳本想要很快的就編譯通過,是很困難的。

  所以,還是決定用 ANTLR 實現一下 Z 編譯器。這一次,把 Z 作爲 D 的一個子集,語法定義大部分直接從 D 的語法腳本中複製,一來可以熟悉 ANTLR,二來,完成的語法文件,對於 D 來說也是有用的。

  作爲 D 的子集,現在 Z 也支持一些 D 的風格的語法,比如三種註釋方式:
// 行註釋
/* 註釋 */
/+ 嵌套註釋 +/

  另外,也支持 D 中的帶有“_”的數字格式:
int a = 123_456_789;

  這個版本中增加支持了 bool 類型:
bool b = true;
b = 30 > 10;

  也支持 D 語言中的自動類型推導:
auto a = 1;
auto b = true;
if(b) write(a);

  其它的一般都是 C 和 D 公有的,比如十六進制數字、八進制數字:
int a = 0x83_af; // 十六進制數字
int b = 067; // 八進制數字

  連等賦值:
a = b = c = 2;

  ++、--、+=、-=、*=、/= (++、--只支持左操作符方式):
int n = 10;
int a *= ++n;

  也增加了 for、while、do-while 循環:
// 1 到 100 的和
// for 循環
int n = 0;
for(int i=1; i<=100; ++i)
n += i;
write(n);
// while 循環
i = 0; n = 0;
while( i < 100 )
n += ++i;
write(n);
// do-while 循環
i = 0; n = 0;
do
n += ++i;
while( i < 100 )
write(n);

  另外,因爲語法文件大部分從 D 複製,所以,運算符優先級也和 C/D 一樣了(就是上次說的“&&”的優先級高於“||”之類的問題)。負號現在也遵照這種方式放入表達式中,所以,不只沒有上一版中必須加空格的問題,而且支持對變量求負:
int a = 10;
int b=5-3; // 5 - 3
b=5--3; // 5 - (-3);
b=7*-a; // 7 * (-a);

  雖然可以在定義變量的時候使用逗號,但是普通表達式還不支持逗號方式。另外,Z 還是有一個和 D 比較大的不同,就是 bool 類型和 int 類型之間不允許互相轉換,否則會引發編譯時錯誤,而 if for while do-while 的條件表達式也必須最終爲 bool 類型纔可以:
int n = 1;
bool a = n == 0;
a = a && n > 10 || n != 3;
bool b = n; // error
if(b) write(1);
if(n) write(2); // error

  ANTLR 確實對於語法的細節控制能力更強,而且,生成 AST 的能力也很突出。ANTLRWorks 雖然有時候不工作,有時候和實際代碼效果有出入,總體來說還是幫助很大。從 AST 生成代碼也比上一版中更方便。不過,在我的實現代碼裏很多異常都是直接用斷言實現的,沒有打印行號。另外,因爲 ANTLR 有很強的錯誤恢復能力,目前還不知道怎麼判斷代碼分析中是否出現錯誤……

  下面是可執行程序和源代碼:
發佈了0 篇原創文章 · 獲贊 0 · 訪問量 1306
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章