java编译器id_JAVA 词法编译器
(1)詞法分析概述(主要介紹詞法分析的主要功能)
1. 將正規(guī)式轉(zhuǎn)化為NFA
2. 將NFA轉(zhuǎn)化為DFA
3. 將DFA轉(zhuǎn)化為最小DFA
4. 模擬DFA
5. 識(shí)別源程序
6. 錯(cuò)誤信息判斷
(2)?采用的技術(shù)及平臺(tái)安裝(主要介紹采用了什么開(kāi)發(fā)語(yǔ)言,如何部署軟件運(yùn)行環(huán)境,簡(jiǎn)要說(shuō)明不超過(guò)300字)
本實(shí)驗(yàn)采用Java語(yǔ)言編寫,IDE為Eclipse Jee Oxygen,部署時(shí)直接下載安裝對(duì)應(yīng)軟件即可,Java語(yǔ)言的配置需要在安裝相應(yīng)文件后,設(shè)置環(huán)境變量和系統(tǒng)變量。
(3)?算法分析(主要介紹采用的算法及數(shù)據(jù)結(jié)構(gòu),以及如何用數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)算法,包含:數(shù)據(jù)結(jié)構(gòu)和算法分析兩部分內(nèi)容,在對(duì)應(yīng)算法分析部分,必須給出示例說(shuō)明算法)
1.?棧,優(yōu)先級(jí)識(shí)別正規(guī)式
數(shù)據(jù)結(jié)構(gòu):使用棧,分為運(yùn)算符棧和字符棧
算法:將‘#’符號(hào)壓入運(yùn)算符棧,當(dāng)輸入表達(dá)式的字符坐標(biāo)不等于表達(dá)式的長(zhǎng)度或者運(yùn)算符棧頂不等于‘#’時(shí),做循環(huán),在循環(huán)體中,判斷表達(dá)式的各個(gè)字符,若不是運(yùn)算符則壓入字符棧,若是運(yùn)算符,則與運(yùn)算符棧的棧頂元素進(jìn)行優(yōu)先級(jí)比較,若棧頂元素優(yōu)先級(jí)低,將運(yùn)算符壓棧,若相等,運(yùn)算符棧彈棧,若棧頂元素優(yōu)先級(jí)高,則彈出運(yùn)算符棧,以及連續(xù)彈出兩次字符棧,將上述彈出的兩個(gè)字符和一個(gè)運(yùn)算符作為一個(gè)運(yùn)算組。
2.?Thompson算法
數(shù)據(jù)結(jié)構(gòu):構(gòu)造節(jié)點(diǎn)和弧的結(jié)構(gòu)來(lái)表示NFA,構(gòu)造的結(jié)果類似圖。通過(guò)結(jié)點(diǎn)和弧可以遍歷整個(gè)圖;NFA棧,用來(lái)保存中間的NFA結(jié)果。
算法:在通過(guò)優(yōu)先級(jí)判斷后得到的表達(dá)式單元,比如AB|(A或B)這樣的正規(guī)式后,判斷運(yùn)算符是 | ,則調(diào)用事先編寫好的五個(gè)構(gòu)造函數(shù)(分別是或運(yùn)算,連接運(yùn)算,閉包運(yùn)算,單個(gè)字符,ε運(yùn)算)中的或運(yùn)算,構(gòu)造A|B的NFA,同時(shí)將構(gòu)造好的NFA壓進(jìn)NFA棧,這一過(guò)程實(shí)際就是將NFA構(gòu)造過(guò)程和表達(dá)式優(yōu)先級(jí)判斷過(guò)程同步。不斷重復(fù)過(guò)程,最終得到的NFA棧的棧頂元素就是完整的NFA。
3.?最小子集法
數(shù)據(jù)結(jié)構(gòu):定義了表示DFA的矩陣和 表示狀態(tài)集合的結(jié)構(gòu)。
算法:首先定義了ε閉包和smove函數(shù),設(shè)計(jì)遞歸的部分用棧來(lái)模擬遞歸。然后用表示狀態(tài)集合的數(shù)據(jù)結(jié)構(gòu)表示ε閉包+smove操作所得到的的狀態(tài)集合,在運(yùn)算過(guò)程中對(duì)于新的狀態(tài)標(biāo)號(hào),并在后續(xù)對(duì)新的狀態(tài)進(jìn)行對(duì)應(yīng)字符的smove+ε閉包運(yùn)算,直到不再產(chǎn)生新?tīng)顟B(tài)為止。完成上述運(yùn)算后,根據(jù)表示的新?tīng)顟B(tài)號(hào)和對(duì)應(yīng)的字符,構(gòu)造DFA矩陣。
4.?最小DFA算法
數(shù)據(jù)結(jié)構(gòu):定義了表示一個(gè)劃分的數(shù)據(jù)結(jié)構(gòu),以及記錄可以合并狀態(tài)(即同屬一個(gè)劃分的兩個(gè)狀態(tài))的集合。
算法:計(jì)算兩個(gè)狀態(tài)是否可以合并時(shí),采用的是n!的時(shí)間復(fù)雜度的算法,即第一步為第一個(gè)狀態(tài)和第2至n的狀態(tài)進(jìn)行是否可以合并為一組的判斷,將可以合并的兩個(gè)狀態(tài)進(jìn)行記錄,第二步為判斷第2個(gè)狀態(tài)和第3至n的狀態(tài)的判斷,同樣將可以合并的兩個(gè)狀態(tài)進(jìn)行記錄,循環(huán)上述步驟,直到n-1個(gè)狀態(tài)和第n各狀態(tài)進(jìn)行上述過(guò)程。在完成上述步驟后,對(duì)于得到的記錄可以合并為一組的狀態(tài)的集合,判斷二元組之間是否有公共狀態(tài),則表示這兩個(gè)二元組的三個(gè)狀態(tài)可以合并。比如,(1,2)和(2,3)表示1,2狀態(tài)可以合并,2,3狀態(tài)可以合并,通過(guò)判斷知道,1,2,和2,3有公共狀態(tài)2,則表示1,2,3這三個(gè)狀態(tài)可以合并為一個(gè)組,即(1,2,3),其他組的判斷也是這樣,在全部合并完之后,得到最終的劃分結(jié)果,再依照原先的DFA矩陣和劃分結(jié)果,構(gòu)造一個(gè)新的最小DFA矩陣。
5.?DFA模擬器算法
數(shù)據(jù)結(jié)構(gòu):無(wú)新定義數(shù)據(jù)結(jié)構(gòu)。
算法:主要是將源程序代碼段的各個(gè)字符依序進(jìn)行再矩陣?yán)锏臓顟B(tài)轉(zhuǎn)移,觀察最終結(jié)果是處于終態(tài),非終態(tài),還是出現(xiàn)錯(cuò)誤的字符。
6.?字符串最大匹配識(shí)別
數(shù)據(jù)結(jié)構(gòu):將構(gòu)造的最小DFA進(jìn)行集合化,即定義list這樣的集合
算法:主要是判斷在最大匹配的過(guò)程中,會(huì)產(chǎn)生什么樣的不同情況,比如當(dāng)前字符串無(wú)法被所有DFA識(shí)別,或者能識(shí)別但是不處于終態(tài),或者能識(shí)別且處于終態(tài),明確各種情況下的操作即可。在這里要注意將構(gòu)造的幾個(gè)最小DFA按照關(guān)鍵字,數(shù)字,特殊字符,。。。標(biāo)識(shí)符的順序進(jìn)行DFA模擬,確保沒(méi)有誤識(shí)別。
(4)?流程圖(繪制并說(shuō)明算法流程)
在這一過(guò)程中,文件流會(huì)不斷將生成的中間結(jié)果寫入txt文件中。
(5)?程序運(yùn)行截圖(根據(jù)實(shí)驗(yàn)指導(dǎo)書第3節(jié)提供的內(nèi)容及要求顯示輸出結(jié)果,并提供對(duì)應(yīng)交互信息)
1. 輸入正規(guī)式
課本例子:case:(a|b)* a b b
生成的dfa和最小dfa
結(jié)果
用例:case:(0|1|2|3|4|5|6|7|8|9)
2. 對(duì)于每一個(gè)正規(guī)式所生成的DFA和最小DFA,數(shù)字代表狀態(tài),null代表空
Void
id:(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z) (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9)*
digital:(0|1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)*
因?yàn)檎?guī)式比較多且比較復(fù)雜,所以只展示出其中兩個(gè),所有的結(jié)構(gòu)式保存在工程文件的resource.txt中。
3. 輸入源程序
4. 識(shí)別結(jié)果
控制臺(tái)
Resource.txt
5. 錯(cuò)誤信息
對(duì)于數(shù)字開(kāi)頭的標(biāo)識(shí)符,能將其非法性識(shí)別出來(lái),見(jiàn)下圖第四行的11a
(6)?測(cè)試用例
1.?正規(guī)式
KW:v o i d
KW:i n t
KW:f l o a t
KW:i f
KW:e l s e
id:(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z) (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9)*
ks:(|)|{|,|;|+|/|>|=|}
digital:(0|1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)*
(id這個(gè)用例在粘貼到界面內(nèi)時(shí)注意讓它的內(nèi)容顯示在同一行)
2.?源程序
void main(){
int x,a,b;
float y,c,d;
x=a+b;11a
??????y=c/d;
??????if(x>y)
??x=10;
??????else
???y=100;
}
?(7)?代碼結(jié)構(gòu)說(shuō)明
?
(8)程序分析(主要介紹編程中出現(xiàn)的錯(cuò)誤以及修改的說(shuō)明以及實(shí)驗(yàn)心得)
1. 正規(guī)式的優(yōu)先級(jí)是構(gòu)造NFA的關(guān)鍵,運(yùn)用數(shù)據(jù)結(jié)構(gòu)課中的算數(shù)表達(dá)式優(yōu)先級(jí)可以解決。
2. 構(gòu)造NFA的五個(gè)子結(jié)構(gòu),因?yàn)镹FA很像圖,所以定義了結(jié)點(diǎn)和弧這兩種結(jié)構(gòu),還定義了深度優(yōu)先遍歷NFA的函數(shù),更深體會(huì)到了大二學(xué)習(xí)的數(shù)據(jù)結(jié)構(gòu)知識(shí)對(duì)于編程的重要性。
3.在將NFA轉(zhuǎn)化為DFA的過(guò)程中,由于對(duì)于數(shù)字,或者標(biāo)識(shí)符這樣字符很多的正規(guī)式的NFA,會(huì)含有大量ε,所以一開(kāi)始用函數(shù)遞歸進(jìn)行空閉包操作時(shí),堆棧會(huì)溢出,后來(lái)將函數(shù)遞歸的形式用數(shù)據(jù)結(jié)構(gòu)棧來(lái)模擬后,成功解決,由此體會(huì)到函數(shù)調(diào)用時(shí)以堆棧形式調(diào)用這一方式,以及告誡自己在使用遞歸時(shí),雖然函數(shù)遞歸從代碼上看結(jié)構(gòu)更清楚,但是用棧來(lái)模擬遞歸的過(guò)程的性能會(huì)更好。
4. 接上一點(diǎn),在最初使用函數(shù)遞歸的形式模擬空閉包和Smove操作時(shí),由于中間變量的不斷更新,導(dǎo)致在遞歸函數(shù)逐層退出到最外面一層時(shí),中間變量的值已經(jīng)改變,所以為了能暫時(shí)保存最外層函數(shù)的中間變量的原值,學(xué)習(xí)了Java語(yǔ)言的深拷貝和淺拷貝,這一機(jī)制是為了在存儲(chǔ)內(nèi)部增加一塊存儲(chǔ)空間,而不是簡(jiǎn)單的引用變量。
5.在設(shè)計(jì)最大匹配掃描源程序的字符串的算法時(shí),因?yàn)樵趻呙柽^(guò)程中遇到的情況特別多,如果不將所有的過(guò)程用流程圖或偽代碼的形式預(yù)先定義好,編寫程序時(shí)代碼結(jié)構(gòu)會(huì)顯得臃腫。所以在編寫代碼時(shí),按照流程圖或偽代碼的參照來(lái)寫,代碼的結(jié)構(gòu)的簡(jiǎn)潔性以及程序的正確性會(huì)提高。
6. 在對(duì)字符串進(jìn)行較為復(fù)雜的操作,比如提取某個(gè)特定的中間字符串時(shí),使用java語(yǔ)言本身定義的正規(guī)式函數(shù),進(jìn)行split等操作時(shí),會(huì)方便很多,不過(guò)要明確正規(guī)式的規(guī)則。
7. 在源程序字符串匹配過(guò)程中,想象int這個(gè)關(guān)鍵詞,被用來(lái)識(shí)別字符串的DFA集合是有次序的,如果在識(shí)別int時(shí),標(biāo)識(shí)符DFA先于關(guān)鍵字intDFA,則int會(huì)被識(shí)別成一個(gè)標(biāo)識(shí)符,而不是關(guān)鍵字,所以要明確這些DFA的識(shí)別優(yōu)先級(jí)。
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的java编译器id_JAVA 词法编译器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java kafka 设置分区_Java
- 下一篇: python中easygui最新下载教程