




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、高品質(zhì)文檔2022年詞法分析小結(jié) 詞法分析是編譯器工作的第一階段,它的工作就是從輸入(源代碼)中取得token,以作為parser(語法分析)的輸入,一般在詞法分析階段都會把一些無用的空白字符(white space,即空格、tab和換行)以及解釋剔除,以降低下一步分析的簡單度,詞法分析器一般會供應一個gettoken()這樣的方法,parser可以在做語法分析時調(diào)用詞法分析器的這個方法來得到下一個token,所以詞法分析器并不是一次性遍歷全部源代碼,而是實行這種on-demand的方式:只在parser需要時才工作,并且每次只取一個token。 token和lexeme 首先,token不等
2、于lexeme。token和lexeme的關系就類似于面對對象語言中“類”和“實例”(或“對象”)之間的關系,這個用中文不知該如何解釋才好,比如語言中的變量a和b,它們都屬于同一種token:identifier,而a的lexeme是”a”,b則是”b”,而每個關鍵字都是一種token。token可以附帶有一個值屬性,例如變量a,當調(diào)用詞法分析器的gettoken()時,會返回一個identifier類型的token,這個token帶有一個屬性“a”,屬性可以是多樣的,例如表示數(shù)字的token可以帶有一個表示數(shù)字值的屬性,它是整型的。 如下代碼: int age = 23; int count
3、 = 50; 可以依次提取出8個token:int(值為”int”),id(值為”age”),assign(值為”=”),number(值為整型數(shù)值23),int(值為”int”),id(值為”count”),assign(值為”=”),number(值為50) 正則表達式 正則表達式可以用來描述字符串模式,例如我們可以用digit+來表示number的token,其中digit表示單個數(shù)字(這里說正則表達式并不完全和實現(xiàn)的正則引擎所識別的正則表達式等價,這里只是為了描述問題而已)。 然而像c語言的的多行解釋,用正則表達式來描述就比較麻煩,此時更傾向于直接用有窮自動機(finite autom
4、aton)來描述,因為用它來描述特別直觀且很簡單。 有窮自動機(finite automata) 有窮自動機也稱為有限狀態(tài)機,狀態(tài)在輸入字符的作用下發(fā)生遷移,因此,它可以用來識別token,也因此,我們只要畫得出fa,之后再用代碼實現(xiàn)這個fa,那詞法分析器也就差不多弄好了。 有窮自動機分確定性(dfa)和非確定性(nfa)兩種,假如對于同一個輸入,只會有一個確定的狀態(tài)遷移路線,也就是只有一個確定的“下一狀態(tài)”,那就是dfa,否則就是nfa。 因為dfa對于同一個輸入只有一個確定的下一狀態(tài),所以詞法分析器當然優(yōu)先采納它,那nfa拿來干嘛用呢?nfa用來做描述用時更便利,我們可以特別快速地畫出一個
5、識別token的nfa圖,但要想直接畫出個dfa那要動不少腦筋。 依據(jù)正則表達式構建nfa 如上所述,nfa更簡單畫出,那我們就先討論nfa,在定義token時,我們可以用正則表達式來描述它,因為正則表達式干這行很合適,例如一個digit+就可以描述數(shù)字,多便利。因此,我們需要依據(jù)正則表達式畫出與之等價的nfa。而這個算法特別簡潔,就是tompsons construction,這個書上寫得很清晰了。 將nfa轉(zhuǎn)化成dfa(nfa的確定化) 對于計算機來說,面對同一個輸入,假如有多個下一狀態(tài),那計算機就不清晰要轉(zhuǎn)到哪個狀態(tài),所以我們期望能從正則表達式得到dfa,而不是nfa,因為這樣將來編程實
6、現(xiàn)時比較自然(同一輸入有確定的一個下一狀態(tài)),而幸運的是,每個nfa都可以轉(zhuǎn)化成dfa。為什么nfa可以轉(zhuǎn)化成dfa?因為fa(finite automata)中的狀態(tài)都是我們自己畫的,只要fa能正確的識別token,那就ok了,也就是,假如nfa和dfa都可以達到一樣的效果:識別token,那其它的我們就不管了。 而nfa確定化的本質(zhì),就是將原來多個狀態(tài)改用一個狀態(tài)來表示,新狀態(tài)其實是一個狀態(tài)集,比如nfa中狀態(tài)s1在輸入a下可以到達s2和s3,那么,在dfa中,就把s2和s3合起來認為是一個狀態(tài)。還有一個問題是nfa中的空轉(zhuǎn)換(?輸入),假如s1在?輸入下可以到達s2,就表示s1可以無條件
7、地轉(zhuǎn)移到s2,那s1和s2自然可以合并起來作為dfa中的一個狀態(tài),于是nfa轉(zhuǎn)dfa的算法也就好理解了。但首先得先定義下空閉包(?-closure): ?-closure: 狀態(tài)s的?-closure即s經(jīng)過?轉(zhuǎn)換可以到達的狀態(tài)集,s的?-closure永久都會包含s自身。一個狀態(tài)集的?-closure即該狀態(tài)集中各狀態(tài)的?-closure的集合。 nfa確定化算法(subset construction): 從開頭狀態(tài)開頭,計算它的?-closure,得到狀態(tài)集set1,然后考察set1在某個輸入a的作用下會遷移到哪些狀態(tài),把這些狀態(tài)集中到一起,再求這個集合的?-closure,得到set2
8、,這樣我們就可以畫兩個圈,一個標上set1,另一個標上set2,然后畫條從set1到set2的線把這兩圓連起來,在線上標上a,這樣dfa的一部分就畫好了,然后我們再考察set1在其它輸入下可以達到的狀態(tài)集的?-closure,同樣畫圈連線,以此類推,最終的時候,把包含了原nfa中終結(jié)狀態(tài)(final state或acceptin state)的dfa狀態(tài)(在轉(zhuǎn)換后的dfa中,每個狀態(tài)都是包含了一個或多個原nfa中的狀態(tài))標記為終結(jié)狀態(tài)。 最小化dfa狀態(tài)數(shù) 由一個正則表達式,可以構建出一個等價的nfa,然后nfa又可以確定化成dfa,好像到此事情搞完了,但事實證明(有時也可以明顯地發(fā)覺),最終
9、構成的這dfa好像有些簡單,有些狀態(tài)似乎很冗余,呃,是的,dfa是可以最小化的。 最小化dfa狀態(tài)數(shù)算法的思想是,在開頭時,假設是最完善的狀況,整個dfa只有兩個狀態(tài),一個終結(jié)狀態(tài),一個開頭(莫非不能有只有一種狀態(tài)的狀況么?假如原dfa中存在非終結(jié)狀態(tài),當然就不能,非終結(jié)態(tài)怎么可以和終結(jié)態(tài)合并?。?,當然,這是假設,不是真的,所以這個算法,就是在這個完善的假設下,對假設進一步考察,假如發(fā)覺有些狀態(tài)不能合并,那就分出來吧,這樣重復考察,直到發(fā)覺沒有狀態(tài)會不能合并時,就做完了,此時不也正是最優(yōu)解么。 嗯,就是這個,所以一開頭,我們把全部非終結(jié)狀態(tài)用一個袋子包起來,看成是一個狀態(tài),把全部終結(jié)狀態(tài)也用另
10、一袋子包起來,也看成是一個狀態(tài),留意,別把原dfa中各狀態(tài)間的連線給扯斷了。然后,我們抽出其中一個袋子,考察其中的各個狀態(tài),我們預備好全部的可能輸入,然后逐個拿出來測試,假如該袋子中的全部狀態(tài)在某個輸入a下達到的狀態(tài)正好都在這個袋子中,那就說明,這個袋子中的這些狀態(tài)“在目前看來”是可以合并的,也就是說,假如在全部的可能輸入的作用下,袋子中的狀態(tài)達到的新狀態(tài)正好也都是這個袋子中的狀態(tài),那它們就可以合并。而假如,在某個輸入a下,袋子中的一部分狀態(tài)會轉(zhuǎn)移到同一袋子中的其它狀態(tài),而有幾個叛徒,假設是s1和s2,竟然在輸入a下會遷移到其它袋子中的狀態(tài),那就說明s1和s2是不行以和其它轉(zhuǎn)移到同一袋子中的狀
11、態(tài)合并的,于是,我們就把s1和s2裝成一個新袋子,從原袋子中分出來,當然,現(xiàn)在還是假設s1和s2可以合并,所以才把它們裝一起,畢竟真的可不行以合并呆會還要再考察??疾焱贻斎隺,還要接著考察其它的可能輸入。假如在考察完一個袋子后,發(fā)覺全部狀態(tài)在a輸入下都可以轉(zhuǎn)移到本袋子中的狀態(tài),那么最終的dfa它們就被合并成一個狀態(tài),并且在a輸入下,它有一個到自身的狀態(tài)遷移。 實現(xiàn)詞法分析器 對于一個token,比如用來表示數(shù)字的token:num,我們可以用正則表達式描述它,然后畫出nfa,再將nfa轉(zhuǎn)化成dfa,再最小化dfa的狀態(tài),但是我們的詞法分析器是不是分析一個token,所以我們要把全部類型的tok
12、en的dfa合并成一個dfa,這樣,這個dfa也就可以識別語言的全部token了,假如在某一連串的輸入下,dfa達不到終結(jié)狀態(tài),那就說明源代碼有錯誤了。 我用c#實現(xiàn)了一個用于compiler construction: principles and practice中tiny語言的詞法分析器,tiny語言有關鍵字:if, then, else, end, repeat, until, read, write,有操作符+,-,*,/,=,(,),;,:=(全角逗號不算,是文章的分隔符)這10個,然后其余的token有number (一或多個數(shù)字)和identifier(一或多個字母),其dfa如下圖: 上面這張圖和編譯原理及實踐中的一樣,其中的帶中括號的輸入說明這個輸入是lookahead的,在匹配勝利后是要重新放回輸入流中的,比如識別num時,假如發(fā)覺個非digit的,那就說明識別到了一個number,但是最終識別的那個非digit字符是要放回輸入流的,因為它要留著下一次識別。 其中從start到done的那個other,指全部非white space,非,非letter,非
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 礦山員工勞動合同(含安全生產(chǎn)責任追究辦法及流程)
- 二零二五年度美容院員工兼職工作合同模板
- 二零二五年度床上用品售后服務保障合同
- 服裝店裝修免租期協(xié)議書
- 融資租賃解除居間合同
- 中介二手房合同范例
- 蘭花股合同范例
- 專利代理協(xié)議合同范例
- 代理采購付款合同范例
- 2025年表面涂鍍材料合作協(xié)議書
- 人教版八年級音樂下冊(簡譜)第1單元《原始狩獵圖》教學設計
- 行政或后勤崗位招聘筆試題及解答(某大型國企)2025年
- 2024年中考英語閱讀理解C篇真題匯編(附答案)1635
- 2024年度教師培訓計劃7篇
- DL-T+544-2012電力通信運行管理規(guī)程
- 零食門市轉(zhuǎn)讓協(xié)議書范本
- 家庭經(jīng)濟困難學生認定申請表
- 2024版工程合同變更流程
- 運用PDCA縮短ST段抬高型急性心肌梗死病人在急診停留時間
- 陜西省咸陽彩虹中學2025年高考數(shù)學試題模擬卷(1)含解析
- 2023年全省職業(yè)院校技能大賽高職教師組護理技能賽項競賽規(guī)程
評論
0/150
提交評論