1、目的
設(shè)計(jì)并實(shí)現(xiàn)一個(gè)包含預(yù)處理功能的詞法分析程序,加深對編譯中詞法分析過程的理解。
2、實(shí)現(xiàn)功能:詞法分析
輸入:所給文法的源程序字符串。
輸出:二元組(syn,token或sum)構(gòu)成的序列。其中,
?syn為單詞種別碼。
?Token為存放的單詞自身字符串。
?Sum為整型常量。
具體實(shí)現(xiàn)時(shí),可以將單詞的二元組用結(jié)構(gòu)進(jìn)行處理。
3、待分析的C語言子集的詞法(可以自行擴(kuò)充,也可以按照C語言的詞法定義)
? 1)關(guān)鍵字
main??if??then ?while ?do ?static ?int ?double ?struct ?break ?else ?long ?switch ?case ?typedef ?char ?return ?const ?float ?short ?continue ?for ?void ?default ?sizeof ?do ????
所有的關(guān)鍵字都是小寫。
? ?2)運(yùn)算符和界符
?+ ?- ?* ?/ ?:?:= <??<> ?<=??>??>=??=??;?(??)??#
? 3)其他標(biāo)記ID和NUM
通過以下正規(guī)式定義其他標(biāo)記:
ID→letter(letter|digit)*
NUM→digit digit*
letter→a|…|z|A|…|Z
digit→0|…|9…
? ?4)空格由空白、制表符和換行符組成
空格一般用來分隔ID、NUM、專用符號和關(guān)鍵字,詞法分析階段通常被忽略。
4、各種單詞符號對應(yīng)的種別碼
表1???各種單詞符號的種別碼
單詞符號 ??種別碼 ??????單詞符號 ??種別碼 ??????
main ??????1? ? ? ? ? ? ? ? ? ;? ? ? ? ? ? ?41?????
if? ? ? ? ? ? ?2? ? ? ? ? ? ? ? ? (? ? ? ? ? ? ?42??????
then? ? ? ? 3? ? ? ? ? ? ? ? ? )? ? ? ? ? ? ?43 ?????
while? ? ? ?4? ? ? ? ? ? ? ?int? ? ? ? ? ? ? 7?
do? ? ? ? ? ?5? ? ? ? ? ? ? ?double? ? ? ?8???
static? ? ? ?6? ? ? ? ? ? ? ?struct? ? ? ? ?9???
ID? ? ? ? ? ?25? ? ? ? ? ? ? break? ? ? ? 10??
NUM??????26? ? ? ? ? ? ? else? ? ? ? ? ?11??
+? ? ? ? ? ? 27? ? ? ? ? ? ? ?long? ? ? ? ? 12??
-? ? ? ? ? ? ?28? ? ? ? ? ? ? switch? ? ? ? 13??
*? ? ? ? ? ? ?29? ? ? ? ? ? ?case? ? ? ? ? ?14?????
/? ? ? ? ? ? ?30? ? ? ? ? ? ? typedef? ? ? 15
:? ? ? ? ? ? ?31? ? ? ? ? ? ? char? ? ? ? ? ?16
:=? ? ? ? ? ?32? ? ? ? ? ? ? return? ? ? ? ?17
<? ? ? ? ? ? 33? ? ? ? ? ? ?const? ? ? ? ? ?18
<>? ? ? ? ? 34? ? ? ? ? ? ?float? ? ? ? ? ? ?19
<=? ? ? ? ? 35? ? ? ? ? ? ?short? ? ? ? ? ? 20
>? ? ? ? ? ? 36? ? ? ? ? ? ?continue? ? ? 21
>=? ? ? ? ? 37? ? ? ? ? ? ?for? ? ? ? ? ? ? ?22
=? ? ? ? ? ? 38? ? ? ? ? ? ?void? ? ? ? ? ? ?23
default ??39? ? ? ? ? ? ?sizeof? ? ? ? ? ?24
?# ???????????0???
5、此法分析程序主要思想:采用模塊設(shè)計(jì)
算法的基本任務(wù)是從字符串表示的源程序中識別出具有獨(dú)立意義的單詞符號,其基本思想是根據(jù)掃描到的單詞符號的第一個(gè)字符的種類,拼出相應(yīng)的單詞符號。算法執(zhí)行流程圖如下:
1、關(guān)鍵字表初值
關(guān)鍵字作為特殊標(biāo)識符處理,把它們預(yù)先安排在一張表格中(稱為關(guān)鍵字表),當(dāng)掃描程序識別出標(biāo)識符時(shí),查關(guān)鍵字表。如能查到匹配的單詞,則該單詞為關(guān)鍵字,否則為一般標(biāo)識符。關(guān)鍵字表為一個(gè)字符串?dāng)?shù)組,其描述如下:
char *rwtab[27]={“main”,”if”,”then”,”while”,”do”,”?static”,”int”,”?double”,”struct”,”break”,”else”,”long”,”switch”,”case”,”typedef”,”char”,”return”,”const”,”float”,”short”,”continue”,”for”,”void”,”default”,”sizeof”,”do”};
?(2) 程序中需要用到的主要變量:syn,token和sum。
2、?掃描子程序的算法思想
首先設(shè)置三個(gè)變量:token用來存放構(gòu)成單詞符號的字符串;sum用來存放整型單詞;syn用來存放單詞符號的種別編碼。掃描子程序主要部分流程如圖所示。
3、設(shè)計(jì)步驟
(1)首先把一個(gè)源程序代碼分為五類單詞符號:關(guān)鍵字、分隔符(界符)、標(biāo)識符、數(shù)字常量和漢字。
(2)設(shè)計(jì)程序,把關(guān)鍵字和界符存到一個(gè)二維數(shù)組里,每次取出一個(gè)單詞,然后判斷是哪一類符號,并寫入文件。在設(shè)計(jì)程序之前,我們得把待分析代碼寫入一個(gè)文本文件,然后在讀到內(nèi)存存到一個(gè)數(shù)組里。對該數(shù)組進(jìn)行分析
(3)對不符合標(biāo)識符定義的,也寫入文件。
流程圖如下:
存放關(guān)鍵字表:
存放運(yùn)算符表(在分析之前直接將其賦值):
主要函數(shù)模塊:具體函數(shù)代碼不再展示
其中主函數(shù)如下:
?完整源碼文件:訪問我的百度網(wǎng)盤
http://鏈接:https://pan.baidu.com/s/1aGcXKAcfI5uOqCWCdTBEFA?pwd=8080 提取碼:8080
測試代碼:
(1)、
(2)、
(3)、
(4)、
其中code1.txt測試沒有復(fù)雜的隔離符和漢字, ?主要測試預(yù)處理程序
code2.txt測試沒有復(fù)雜的隔離符但有漢字 ?測試對漢字的處理
code3.txt測試有復(fù)雜的隔離符且有漢字 ????測試復(fù)雜的隔離符
(前面三項(xiàng)都是測試整形的數(shù)據(jù))
code4.txt測試代碼中含有浮點(diǎn)型數(shù)據(jù)。
運(yùn)行結(jié)果:由于輸出項(xiàng)比較多,只截取部分圖
(1)、
(2)、
(3)、
(4)、
6、遇到的問題及解決過程
(1)字符分類問題:因?yàn)閷?shí)驗(yàn)要求給的界符并不多,我自己添加了更多的界符,界符存儲(chǔ)問題,開始是想用一個(gè)一維數(shù)組來存儲(chǔ),但是像“+=”這樣的界符是得用兩個(gè)字符來存儲(chǔ)的。故最后選用二維數(shù)組存儲(chǔ)界符。關(guān)鍵字也是選用二維數(shù)組來存儲(chǔ),在這里存儲(chǔ)界符和關(guān)鍵字的時(shí)候?yàn)榱撕退姆N別碼對應(yīng)起來,采用哈希存儲(chǔ)思想,就是它的下標(biāo)就是它的種別碼。最后將字符分為4類,另外由于實(shí)驗(yàn)要求沒有對庫函數(shù)的處理,我在此給它處理為標(biāo)識符。
(2)漢字問題:實(shí)驗(yàn)要求沒有說對漢字的處理,這里我作了處理,但是對連續(xù)的漢字進(jìn)行處理。開始由于編譯器采用UTF-8(BOM)編碼方式,這個(gè)是沒什么問題的,但是寫入文件卻是亂碼,我又把編譯器編碼方式改為GBK,但是還是亂碼,最后通過我一步一步試探,返現(xiàn)是待分析程序的文本文件的編碼方式不對,不能是UTF-8,然后我把該文本文件的編碼由UTF-8改為ANSI。這樣就解決了漢字問題。一開始我是沒有考慮漢字問題的,但是后面我一但考慮漢字以后,對我的字母和數(shù)字判斷產(chǎn)生了不小副作用,但是通過我一步步調(diào)試,這個(gè)過程非常麻煩而且浪費(fèi)時(shí)間,不過最終我還是解決了漢字問題。
(3)預(yù)處理問題:總的來說,這個(gè)過程問題不是很大,我所遇到的問題就是考慮不全,在去掉注釋的時(shí)候只考慮了“//”,而沒有考慮”/*……*/這種注釋,后面又做了修改。
(4)文件處理問題:這個(gè)就是C語言的一些處理文件函數(shù)忘記了,通過簡單的復(fù)習(xí),然后再經(jīng)過運(yùn)用,這個(gè)其實(shí)不算什么難問題。就是知識儲(chǔ)備問題。
(5)浮點(diǎn)數(shù)和正負(fù)數(shù)識別問題,一開始寫的時(shí)候只識別了整數(shù),而且不包括正負(fù)數(shù)。這個(gè)看似簡單的問題,在修改的時(shí)候卻是相當(dāng)?shù)穆闊?,比如那個(gè)“+”號,它可以處理為運(yùn)算符,但是又可以認(rèn)為是屬于正數(shù)的一部分。不過最后經(jīng)過反復(fù)調(diào)試和修改也總算解決了。
心得:文章來源:http://www.zghlxwxcb.cn/news/detail-717844.html
編譯原理這門課本來就是一門非常抽象的課程,而且比較難,第一部分是詞法分析。雖然用文字描述起來就幾句話的事,但是編程實(shí)現(xiàn)真的是一個(gè)復(fù)雜的事情。這也讓我深刻了解到高級語言到低級語言轉(zhuǎn)化的復(fù)雜性,光詞法分析這個(gè)階段就很復(fù)雜,那中間代碼產(chǎn)生那些,還與具體的計(jì)算機(jī)指令集,寄存器,內(nèi)存分配什么的都有關(guān)系,看來會(huì)寫編譯程序的程序員的水平是真的高。這次試驗(yàn)我花費(fèi)最多的時(shí)間就是調(diào)試部分了,因?yàn)槌绦蚪?jīng)不起測試,每當(dāng)換一個(gè)新的代碼測試,就會(huì)暴露出問題,而且改了以后可能又會(huì)對之前測試的代碼又有影響??偟恼f來就是程序總的設(shè)計(jì)階段沒做好,在做之前就得把大多數(shù)可能想好。不然中途心血來潮突然來一個(gè)別的問題沒考慮到,再修改就是一件非常麻煩的事情。在調(diào)試過程中,我對調(diào)試技巧有了一定的提升,并且對編譯原理這門課的重要性有了一個(gè)更深的認(rèn)識。再后面的兩次實(shí)驗(yàn)中,繼續(xù)實(shí)驗(yàn),爭取寫出一個(gè)健壯性好的程序。文章來源地址http://www.zghlxwxcb.cn/news/detail-717844.html
到了這里,關(guān)于編譯原理———詞法分析器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!