前面兩篇(一、二)只是直觀地針對已明確給出的教學語言 Tiny 源程序進行直接的詞法分析(其實根本就稱不上),不具有一般性(下面這個針對C++源程序的詞法分析也相當單一,考慮面不足)。下面是我們的課程實驗,需要結合課堂上學到的利用有限自動機DFA的方法來設計並分析源程序,提取出符合要求的Token。
根據老師給出的課件以及教材上的內容,掃描程序(詞法分析)有下面3種實現方式,前面兩篇(一、二)就是屬於“直接編寫”這一類,而本文則是“DFA”這一類。
1、按實驗要求(如下),目前只拙劣地實現了第(1)和(5)點。
而且第(1)點中有兩個要求未能完成:
★ 浮點數,因爲包含單行、多行註釋的DFA已經很混亂了,這部分暫時先不實現,考慮將來用“表驅動法”(即狀態轉換表)來實現。
★ 註釋,與教材類似不打印單行和多行註釋,因此代碼實現中少了處理註釋的內容。
實驗中用到的C++源程序與要求如下圖:
2、對實驗要求中的“樣例程序”稍微修改了一下。
★ 頭文件 #include<iostream.h> 被改爲 #include "iostream.h",即 iostream.h 是由雙引號 "" 而不是尖括號 < > 包圍的,實際上回到了 C 的代碼規範。這樣修改是因爲原本確定 DFA 時考慮不全面,忽略了“小於等於 <=,大於等於 >=,判斷 ==,不等於 != ”這幾種特殊情況,因爲他們會跟 < > = ! 這幾個特殊字符造成二義性。
★ 同時,C++ 中的 IO 有“ >> 與 << ”也可能與上述特殊字符造成歧義,這個使得實現代碼中的 unGetNextChar(int step) 與教材中的有所不同,因爲該函數帶了一個“步長參數 step”,其實也是爲了遷就 #include<iostream.h> 中的 > 與代碼中的 >> 和 >= 。
其實,"iostream.h"也被作爲字符串識別了,目前尚改進不了。
★ 另外爲了測試算術運算符,對實驗要求中的樣例程序進行了修改,程序按照該樣例作爲輸入,如下圖加上了一個“i = i + 2;”語句:
3、程序中的打印輸出模仿了教材中的樣例輸出。
★ 對於以上樣例輸入,最終程序輸出結果如下:
4、針對該C++源程序設計的DFA 圖大致如下:
5、實現代碼(Java)
近來喜歡上了Vim的代碼高亮,看着清晰明朗,下面是整個實現代碼在Vim下的截圖,文本代碼在本文最後: