c語言編譯器前端的設(shè)計與實現(xiàn)課程設(shè)計_第1頁
已閱讀1頁,還剩24頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、<p>  軟硬件專業(yè)綜合課程設(shè)計總結(jié)報告</p><p>  題目: C語言編譯器前端的設(shè)計與實現(xiàn) </p><p>  姓 名: </p><p>  學(xué) 號: </p><p>  專 業(yè): 計算機科學(xué)與技術(shù) </p><p>  指導(dǎo)

2、教師: </p><p>  起止日期: 12.11.26—13.01.20 </p><p>  計 算 機 與 信 息 工 程 學(xué) 院</p><p>  軟硬件專業(yè)綜合課程設(shè)計任務(wù)書</p><p>  C語言編譯器前端的設(shè)計與實現(xiàn)</p><p>  摘 要:編譯器是程序員使用的關(guān)鍵

3、工具,程序員每天都在使用編譯器,并且非常依賴于其正確性和可靠性。編譯器作為廣大IT從業(yè)者必須接觸的系統(tǒng)軟件,它的設(shè)計本身又是一個極其龐大的工程。編譯器相關(guān)的各項技術(shù)經(jīng)過近幾十年的發(fā)展,已經(jīng)日臻成熟,然而編譯器構(gòu)造原理和技術(shù)依然是計算機科學(xué)中理論與實踐相結(jié)合的最好典范。</p><p>  本文首先介紹了C語言及C語言編譯器的發(fā)展歷程,其次對本次開發(fā)所用到的工具Visual Studio C++2005以及面向?qū)ο?/p>

4、的程序設(shè)計方法做一下簡單介紹。最后重點介紹了編譯器前端的詳細開發(fā)過程,分為三個部分分別闡述:詞法分析器的設(shè)計,語法分析器的設(shè)計,語義分析部分。每個部分又分別從總體框架,詳細流程,重點數(shù)據(jù)結(jié)構(gòu)和函數(shù),以及與其他部分的接口等方面予以闡述。由于C語言本身的復(fù)雜性,很難面面俱到實現(xiàn)所有標準定義,所以本次設(shè)計只象征性的選擇部分具有代表性的功能。在本文的第四章詳細給出了此次設(shè)計所實現(xiàn)的功能和語法規(guī)范,同時也給出了編譯器的運行方式。</p>

5、;<p>  關(guān)鍵詞:編譯器前端、C源程序、面向?qū)ο蟪绦蛟O(shè)計方法、VC++</p><p><b>  目 錄</b></p><p><b>  摘要I</b></p><p><b>  第1章 緒論1</b></p><p>  1.1 C語言及編譯器概

6、述1</p><p>  1.2 C編譯器設(shè)計思想1</p><p>  1.3 開發(fā)工具的選用及介紹2</p><p>  1.4 論文組織結(jié)構(gòu)3</p><p>  第2章 C語言詞法分析器總體分析與設(shè)計4</p><p>  2.1 系統(tǒng)設(shè)計目標與功能分析4</p><p> 

7、 2.2 詞法分析4</p><p>  2.3 語法分析4</p><p>  2.3.1自頂向下的語法分析5</p><p>  2.3.2自底向上的語法分析5</p><p>  2.4 語義分析6</p><p><b>  2.5 符號表6</b></p>&l

8、t;p>  2.6 類型檢查7</p><p>  第3章 系統(tǒng)詳細設(shè)計8</p><p>  3.1 系統(tǒng)設(shè)計基本思路8</p><p>  3.2 詞法分析模塊設(shè)計8</p><p>  3.3 語法分析模塊設(shè)計11</p><p>  3.4 語義分析模塊設(shè)計14</p><

9、p>  第4章 結(jié)束語16</p><p><b>  參考文獻16</b></p><p><b>  附錄:</b></p><p>  附錄1:詞法分析核心代碼..........................................................................

10、..................17</p><p>  附錄2:語法分析核心代碼............................................................................................18</p><p><b>  第1章 緒論</b></p><p>  

11、1.1 C語言及編譯器概述</p><p>  C語言是在70年代初問世的。一九七八年由美國電話電報公司(AT&T)貝爾實驗室正式發(fā)表了C語言。同時由B.W.Kernighan和D.M.Ritchit合著了著名的“THE C PROGRAMMING LANGUAGE”一書。通常簡稱為《K&R》,也有人稱之為《K&R》標準。但是,在《K&R》中并沒有定義一個完整的標準C語言,后來由美

12、國國家標準學(xué)會在此基礎(chǔ)上制定了一個C 語言標準,于一九八三年發(fā)表。通常稱之為ANSI C。C語言是一種結(jié)構(gòu)化語言。它層次清晰,便于按模塊化方式組織程序,易于調(diào)試和維護。C語言的表現(xiàn)能力和處理能力極強。它不僅具有豐富的運算符和數(shù)據(jù)類型,便于實現(xiàn)各類復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。它還可以直接訪問內(nèi)存的物理地址,進行位(bit)一級的操作。由于C語言實現(xiàn)了對硬件的編程操作,因此C語言集高級語言和低級語言的功能于一體。既可用于系統(tǒng)軟件的開發(fā),也適合于應(yīng)用軟件

13、的開發(fā)。此外,C語言還具有效率高,可移植性強等特點。因此廣泛地移植到了各類各型計算機上,從而形成了多種版本的C語言。</p><p>  編譯是從源代碼(通常為高階語言)到能直接被計算機或虛擬機執(zhí)行的目標代碼(通常為低階語言或機器語言)的翻譯過程。然而,也存在從低階語言到高階語言的編譯器,這類編譯器中用來從由高階語言生成的低階語言代碼重新生成高階語言代碼的又被叫做反編譯器。也有從一種高階語言生成另一種高階語言的編

14、譯器,或者生成一種需要進一步處理的的中間代碼的編譯器(又叫級聯(lián))。</p><p>  典型的編譯器輸出是由包含入口點的名字和地址, 以及外部調(diào)用(到不在這個目標文件中的函數(shù)調(diào)用)的機器代碼所組成的目標文件。一組目標文件,不必是同一編譯器產(chǎn)生,但使用的編譯器必需采用同樣的輸出格式,可以鏈接在一起并生成可以由用戶直接執(zhí)行的可執(zhí)行程序。</p><p>  1.2 C編譯器前端設(shè)計思想<

15、/p><p>  一個編譯器的前端設(shè)計主要工作過程可以概括為以下幾個步驟:</p><p><b>  (1)詞法分析</b></p><p>  詞法分析器根據(jù)詞法規(guī)則識別出源程序中的各個記號(token),每個記號代表一類單詞(lexeme)。源程序中常見的記號可以歸為幾大類:關(guān)鍵字、標識符、字面量和特殊符號。詞法分析器的輸入是源程序,輸出是識

16、別的記號流。詞法分析器的任務(wù)是把源文件的字符流轉(zhuǎn)換成記號流。本質(zhì)上它查看連續(xù)的字符然后把它們識別為“單詞”。</p><p><b>  (2)語法分析</b></p><p>  語法分析器根據(jù)語法規(guī)則識別出記號流中的結(jié)構(gòu)(短語、句子),并構(gòu)造一棵能夠正確反映該結(jié)構(gòu)的語法樹。</p><p><b>  (3)語義分析</b&

17、gt;</p><p>  語義分析器根據(jù)語義規(guī)則對語法樹中的語法單元進行靜態(tài)語義檢查,如果類型檢查和轉(zhuǎn)換等,其目的在于保證語法正確的結(jié)構(gòu)在語義上也是合法的。</p><p>  本系統(tǒng)的設(shè)計主要是實現(xiàn)了其中的詞法分析、語法分析和語義分析三個部分。</p><p>  1.3 開發(fā)工具的選用及介紹</p><p>  軟件環(huán)境使用Window

18、s2000/XP操作系統(tǒng),用Visual C++ .NET為開發(fā)平臺,在開發(fā)此軟件時用的是VC++中的MFC框架。</p><p>  Visual C++.NET2005是微軟公司推出的開發(fā)Win32應(yīng)用程序(Windows 95/98/2000/XP/NT)的面向?qū)ο蟮目梢暬晒ぞ?。從原來的Visual C++6.0/ Visual C++.Net 2005升級而來,它的最大優(yōu)點就是提供了功能強大的MFC類

19、庫,MFC是一個很大的C++類層次結(jié)構(gòu),其中封裝了大量的類及其函數(shù),很多Windows程序所共有的標準內(nèi)容可以由MFC的類來提供,MFC類為這些內(nèi)容提供了用戶接口的標準實現(xiàn)方法,程序員所要做的就是通過預(yù)定義的接口把具體應(yīng)用程序特有的東西填入這個輪廓,這將簡化編程工作,大大的減少程序員編寫的代碼數(shù)量,使編程工作變得更加輕松容易。當然還有Visual 2008和最新的Visual 2010beta版也已經(jīng)發(fā)布。</p><

20、;p>  Visual Studio 2005的成功已被證實,即開發(fā)人員偏愛一個具備對他們需要的工具提供接口的集成開發(fā)環(huán)境。下面主要介紹它的有點。通過將開發(fā)人員在開發(fā)環(huán)境中需要的測試和性能工具(例如,單元測試、代碼分析和性能分析)合并在一起,Visual Studio 2005 Team System 也期待著這種成功。這使開發(fā)人員能夠在生命周期的較早階段就改善其代碼的質(zhì)量,而無需中斷他們的工作。通過盡早地為開發(fā)人員提供他們需要用

21、于識別和解決質(zhì)量問題的工具,更多的產(chǎn)品缺陷就能夠在它們還未構(gòu)成危害之前即被發(fā)現(xiàn)并解決。 Visual Studio 2005 Team System,那么過程就不僅僅是文檔了。它還能將自己體現(xiàn)為實際的工具行為更改。當您在項目初期選擇過程時,還需要選擇工作流和工作產(chǎn)品,它們會驅(qū)動系統(tǒng)的行為方式。對 SDLC 過程的支持是內(nèi)置的,這使得對工作流的支持是無縫的。通過將過程集成到團隊成員日常使用的基本工具中,Visual Studio 2005

22、 Team System 大大消除了過程采納的障礙,并使自動收集跨職能的項目標準成為可能,而無需實施人工報告的相關(guān)開銷。通過使用一個公共</p><p>  1.4 論文組織結(jié)構(gòu)</p><p><b>  第1章 緒論</b></p><p>  簡述了C語言的發(fā)展以及一般編譯器的工作原理,并介紹了本系統(tǒng)開發(fā)的主要平臺和工具及其特點。<

23、/p><p>  第2章 C語言詞法分析器的總體分析與設(shè)計</p><p>  簡單的介紹了系統(tǒng)的設(shè)計目標及系統(tǒng)要實現(xiàn)的功能。簡單的介紹了幾個要實現(xiàn)的編譯步驟的概念和要完成的任務(wù)。</p><p>  第3章 系統(tǒng)的詳細設(shè)計</p><p>  介紹了系統(tǒng)的基本流程,各個模塊的設(shè)計思想和核心代碼部分。</p><p> 

24、 第2章 C語言詞法分析器的總體分析與設(shè)計</p><p>  2.1 系統(tǒng)設(shè)計目標與功能分析</p><p>  本系統(tǒng)的設(shè)計目標是完成一個小型的C語言編譯器的前端設(shè)計,由于要完成一個完美的C語言編譯器前端是一件非常復(fù)雜的事情,不僅要考慮到C語言代碼的各種靈活用法,還需要能靈活運用C語言語法,甚至是了解語法的構(gòu)成原理。本系統(tǒng)只完成整個編譯過程中的詞法分析、語法分析、語義分析以及其中的建立

25、符號表和類型檢查幾個步驟。</p><p>  下面分別概括介紹編譯過程中的這幾個階段。</p><p><b>  2.2 詞法分析</b></p><p>  詞法分析程序又稱掃描器,它是編譯過程的第一個階段。其主要任務(wù)是從左到右依次描描字符串形式的源程序的各個字符,逐個識別出其中的單詞,并將其轉(zhuǎn)換成為內(nèi)部編碼形式的單詞符號串輸出,用于進行

26、語法分析。通??刹捎枚剑–LASS,VALUE)來表示一個單詞符號的內(nèi)部編碼,其中CLASS為一整數(shù)碼,用于表示該單詞的類別;VALUE則是單詞之值(如變量名在符號表中的序號,常數(shù)的二進制表示,以及運算符和分隔符的編碼,等等)。</p><p>  概括的說,掃描器在其工作過程中,一般應(yīng)完成下列的任務(wù):</p><p> ?。?)識別出源程序中的各個單詞符號,并將其轉(zhuǎn)換成內(nèi)部編碼形式;

27、</p><p> ?。?)刪除無用的空白字符、回車字符以及其他非實質(zhì)性字符;</p><p><b> ?。?)刪除注釋;</b></p><p> ?。?)進行詞法檢查,報告所發(fā)現(xiàn)的錯誤。</p><p>  此外,視編譯工作流程的組織,一些編譯程序在進行詞法分析時,還要完成將所識別出的標志符登錄到符號表的工作。&l

28、t;/p><p>  從功能上看,詞法分析上把字符串形式的源程序轉(zhuǎn)換為單詞串形式,然后進行語法分析。從工作方式上看,他與語法分析之間存在兩種接口方式。一種方式是將詞法分析的輸出結(jié)果存放在一個中間文件上,后面的語法分析程序?qū)⑺鳛檩斎脒M行語法分析 。另一種方式是將詞法分析編成一個子程序,該子程序由語法分析程序調(diào)用,當語法分析程序需要一個新的單詞時,就調(diào)用該子程序,每調(diào)用一次,則從源程序字符串中讀出一個具有獨立意義的單詞

29、。本設(shè)計采用前一種方式。</p><p><b>  2.3 語法分析</b></p><p>  語法分析程序又稱分析器,它以單詞串形式的源程序作為輸入或分析的對象,其基本任務(wù)是:根據(jù)程序設(shè)計語言的語法規(guī)則(即定義該語言的前后無關(guān)文法),分析源程序的語法結(jié)構(gòu),即分析如何由這些單詞組成該源程序的各種語法成分(如下標變量、函數(shù)、各種表達式、各種程序語句等),并在分析過程

30、中進行語法正確性檢查,產(chǎn)生內(nèi)部形式的中間代碼,供編譯程序后續(xù)階段處理。</p><p>  目前,已存在多種語法分析方面的方法,但就產(chǎn)生語法樹的方向而言,可大致把它們分為自頂向下分析和自底向上分析兩大類。</p><p>  2.3.1自頂向下的語法分析</p><p>  所謂自頂向下的語法分析,只指對于給定輸入串w,試圖為其構(gòu)造一個從文法開始符號S到w的最左推導(dǎo)

31、S=>w,或為w自上而下地構(gòu)造一棵S為根結(jié)點的語法樹。如果這一嘗試得到成功,則證明w是相應(yīng)文法的一個句子;反之,則不是。</p><p>  在進行自頂向下的語法分析時,通常有兩個障礙須加以解決:</p><p>  (1) 由于采取了最左推導(dǎo),故當相應(yīng)文法G中含有左遞歸的非終結(jié)符號時,便會使語法分析過程陷入循環(huán)不已的狀況。</p><p>  (2) 采用最

32、左推導(dǎo)以實現(xiàn)對符號串w的匹配,實際上是一個用文法產(chǎn)生式的諸候選式反復(fù)進行試探的過程,這勢必會出現(xiàn)大量的回溯,從而導(dǎo)致語法分析效率的大幅度下降。</p><p>  因此,欲實現(xiàn)自頂向下的語法分析,其首要任務(wù)是改造程序設(shè)計語言的文法,使得文法無左遞歸且無左公因子,以消除其中的左遞歸和避免回溯的出現(xiàn)。</p><p>  2.3.2自底向上的語法分析</p><p> 

33、 所謂自底向上的語法分析,是指從給定的輸入串w=a1a2…an出發(fā),試圖利用相應(yīng)文法中的產(chǎn)生式,逐步將其歸約為文法的開始符號S,即從葉結(jié)點a1,a2,…,an出發(fā),試圖逐步向上構(gòu)造一個語法樹,而其根結(jié)點恰好為S0由于上述分析過程通常采用的是最左歸約,所以實現(xiàn)此種語法分析的關(guān)鍵,是在分析的每一步,如何尋找或確定當前句型的句柄,以及確定將其歸約為什么非終結(jié)符號。</p><p>  和自頂向下的分析過程一樣,實現(xiàn)自底

34、向上的分析,通常也須使用一個分析棧來存放分析過程中所得的文法符號。分析開始時,在棧底放置一個界符#,然后將輸入符號逐個推入棧內(nèi),一旦在分析棧的棧頂出現(xiàn)句柄,就用相應(yīng)的產(chǎn)生式的左部去替換這個句柄,即進行一次歸約。由于歸約,便得到了新的棧頂,此時再查看棧的頂部是否形成新的句柄:若是,再進行歸約;反之,則繼續(xù)將后續(xù)的輸入符號移入棧內(nèi),并重復(fù)上述過程。若最終能將全部輸入符號(不包括右界符#)移掉,且分析棧中只留下棧底符號#及最后一步歸約所得的文

35、法開始符號,則表明對輸入串的分析已經(jīng)成功。但若全部輸入符號已被移掉,而分析棧卻不能出現(xiàn)上述格局,則表明輸入符號串不是文法的一個句子,其中必定存在語法錯誤。通常將上述過程稱為“移進-歸約”分析,它是最基本的自底向上分析過程。在此基礎(chǔ)上,根據(jù)尋找句柄策略的不同,便形成了不同的自底向上的語法分析方法。</p><p><b>  2.4 語義分析</b></p><p> 

36、 在完成了上述過程后編譯程序?qū)⒃闯绦蜃兂梢环N內(nèi)部表示形式,這種內(nèi)部表示形式就叫做中間代碼或中間語言,它是一種結(jié)構(gòu)簡單、含義明確的記號系統(tǒng)。有些快速編譯程序幾乎沒有中間代碼,但是為了使目標代碼的優(yōu)化比較容易實現(xiàn),獨立于機器進行,許多編譯程序都采用了某種復(fù)雜性程度介于源程序語言和機器語言之間的中間語言。但是,想對于詞法分析和語法分析都已有相當成熟的理論和算法,中間代碼目前還沒有一種公認的形式系統(tǒng),比較接近形式化的方法是語法制導(dǎo)翻譯。<

37、/p><p><b>  2.5 符號表</b></p><p>  符號表的信息欄中登記了每個名字的有關(guān)性質(zhì),如類型(整、實或布爾等)、種屬(簡單變量、數(shù)組、過程等)、大?。ㄩL度,即所需的存儲單元字數(shù))以及相對數(shù)(指分配給該名宇的存儲單元的相對地址)。不同的程序語言對于名字性質(zhì)的定義各有不同。現(xiàn)今多數(shù)程序語言中的名字或者是用說明語句規(guī)定其性質(zhì),或者采用某種隱含約定(如F

38、ORTRAN中凡以字符I,J,…N開頭的標識符代表整型變量名)。有些程序語言,如ADL沒有說明語句也沒有隱含約定,因此,符號表的性質(zhì)須到目標程序運行時才能確定下來。但編譯時登記在符號表中的各名字的性質(zhì)只能來自說明語句(包括隱含約定和標號定義)或其它引用情形。</p><p>  對于變量名、數(shù)組名和過程名而言,它們的信息欄中一般要求有下列信息:</p><p>  變量 類型(整、實、雙

39、實、布爾、字符、復(fù)、標號或指針等);</p><p>  種屬(簡單變量、數(shù)組或記錄結(jié)構(gòu)等);</p><p>  長度(所需的存儲單元數(shù));</p><p>  相對數(shù)(存儲單元相對地址);</p><p>  若為數(shù)組,則記錄其內(nèi)情向量;</p><p>  若為記錄結(jié)構(gòu),則把它與其分量按某種形式聯(lián)系起來;<

40、/p><p><b>  形式參數(shù)標志;</b></p><p>  若在 COMMON或 EQUVALENCE語句中(FORTRAN語言),把它和有關(guān)名字連接在一起;它的說明是否已處理過(即標志位“定義否”);</p><p>  是否對這個變量進行過賦值(包括出現(xiàn)在輸人名表中)的標志位。</p><p>  過程 是否

41、為程序的外部過程?</p><p>  若為函數(shù),類型是什么?</p><p><b>  其說明是否處理過?</b></p><p><b>  是否遞歸?</b></p><p>  形式參數(shù)是些什么?為了與實參進行比較,必須把它們的種屬、類型信息同過程名聯(lián)系在一起。</p>&l

42、t;p>  對于那些只使用單一符號表的簡單語言,對符號表填入新項的工作可由詞法分析程序來完成。也就是,當掃描器碰到一個標識符時就對它查填符號表,然后回送它在符號表中的位置作為單詞值。但在某些語言中,甚至在同一過程段里允許用同一標識符標識各種不同對象。例如,XYZ可能既是一個實變量名又是一個標號名,或者又是某個結(jié)構(gòu)型數(shù)據(jù)的一個分量名。在這種情況下,使用單一符號表或由詞法分析程序負責查填符號表都是非常不方便的。因此,采用多種符號表并讓

43、語法——語義分析程序負責查填工作是比較妥當?shù)摹τ谠~法分析程序來說,只要求它凡碰到標識符就直接送出此標識符自身即可。</p><p>  符號表中信息欄的具體組織和安排取決于所翻譯的具體語言與目標機器(的字長和指令系統(tǒng))。</p><p><b>  2.6 類型檢查</b></p><p>  為了進行類型檢查,編譯器需要給源程序的每一個組成

44、成分賦予一個類型表達式。然后,編譯器需要確定這些類型表達式是否滿足一組邏輯規(guī)則。這些規(guī)則被稱為源語言的類型系統(tǒng)。</p><p>  類型檢查具有發(fā)現(xiàn)程序中的錯誤的功能。原則上,如果目標代碼在保存元素值的同時保存了元素類型的信息,任何檢查都可以動態(tài)地進行。一個健全的類型系統(tǒng)可以消除對動態(tài)類型檢查的需要,因為它可以幫助我們靜態(tài)地確定這些錯誤不會在程序運行的時候發(fā)生。如果編譯器可以保證它接受的程序在運行時刻不會發(fā)生類

45、型錯誤,那么該語言的這個實現(xiàn)就被稱為強類型的。</p><p>  第3章 系統(tǒng)詳細設(shè)計</p><p>  3.1 系統(tǒng)設(shè)計基本思路</p><p>  基于C語言源程序分析器的開發(fā)在可行性分析的基礎(chǔ)上進一步全面、深入的分析,弄清C語言的編譯原理及運行狀況,在編譯程序工作的五個階段中,每個階段都必須遵從功能等價的原則。詞法規(guī)則與語法分析階段依據(jù)的語法規(guī)則一同構(gòu)成了

46、一個語言的語法,而語法則是從"形"的角度衡量一個程序是否合法。所以在詞法分析階段,詞法規(guī)則成為重要的研究對象。詞法分析器所處理的對象即詞法分析程序的輸入數(shù)據(jù),實際上是源程序經(jīng)過編譯預(yù)處理,去掉多余的符號后而形成的代碼,這樣給詞法分析帶來方便。詞法分析的過程是線性的從頭至尾掃描一遍,復(fù)雜度較低,易實現(xiàn)。最后概括出要實現(xiàn)的幾個功能流程圖如下:</p><p>  3.2 詞法分析模塊設(shè)計 <

47、/p><p>  詞法分析程序需要完成的任務(wù)如下:</p><p>  1) 識別出源程序的各個語法單位;</p><p>  2) 剔除無用的空白字符、制表符、回車字符以及其他與輸入介質(zhì)相關(guān)的非實質(zhì)性字符 ;</p><p>  3) 過濾掉源程序中的注釋;</p><p>  4) 進行詞法檢查,如果出現(xiàn)錯誤,記錄出

48、錯信息并報告。</p><p>  我們將編譯程序的重點放在中間代碼生成階段。詞法分析器的功能是輸入源程序,輸出單詞符號。這部分程序主要包括兩個類:</p><p><b>  包括兩個類:</b></p><p>  Class CTokenizer:</p><p>  從一個字符串中(這個把一個文件看作是一個字符串

49、,MFC中CFile->CString)分離出一個一個token,配上簡單的類型通過NextToken()返回:</p><p>  #define TT_EOL'\n'</p><p>  #define TT_EOF-1</p><p>  #define TT_INTEGER-2</p><p>  #d

50、efine TT_REAL-3</p><p>  #define TT_WORD-4</p><p>  #define TT_STRING'"'</p><p>  #define TT_CHAR'\''</p><p>  Class CScaner:</p>

51、<p>  得到具體的的token類型,定義TokenType如下:</p><p>  enum TokenType</p><p><b>  {</b></p><p>  // reserved Keyword</p><p>  _AUTO, _DOUBLE, _INT, _STRUCT,</

52、p><p>  _BREAK, _ELSE, _LONG, _SWITCH, </p><p>  _CASE, _ENUM, _REGISTER, _TYPEDEF,</p><p>  _CHAR, _EXTERN, _RETURN, _UNION,</p><p>  _CONST, _FLOAT, _SHORT, _UNSIGNED,&l

53、t;/p><p>  _CONTINUE, _FOR, _SIGNED, _VOID,</p><p>  _DEFAULT, _GOTO, _SIZEOF, _VOLATILE,</p><p>  _DO, _IF, _STATIC, _WHILE,</p><p>  _READ, _WRITE, _PRINTF,</p>&

54、lt;p>  // operations</p><p>  ASSIGN, PLUS, MINUS, TIMES, DIV, MOD,</p><p>  BITWISE_AND, BITWISE_OR, BITWISE_NOT, LOGICAL_NOT, LT, GT,</p><p>  // interpunctions</p><

55、p>  LPARAN, RPARAN, LBRACE, RBRACE, LSQUARE, RSQUARE, COMMA, DOT, SEMI, COLON,</p><p>  // complex operations</p><p>  EQ/* == */, NEQ/* != */, PLUS_PLUS/* ++ */, MINUS_MINUS/* -- */,</p&g

56、t;<p>  PLUS_ASSIGN/* += */, MINUS_ASSIGN/* -= */, TIMES_ASSIGN/* *= */, DIV_ASSIGN/* /= */,</p><p>  NGT/* <= */, NLT/* >= */, LOGICAL_AND/* && */, LOGICAL_OR/* || */,</p><p&

57、gt;<b>  // others</b></p><p>  _EOF, _ID, _NUM, _STRING, _CHARACTER, _LABEL, _ERROR, _NONE</p><p><b>  };</b></p><p>  CScaner通過一個CMap<CString, LPCSTR, en

58、um TokenType, enum TokenType> m_KeyIndex 把CString的關(guān)鍵字和TokenType對應(yīng),便于查找和反向查找。</p><p><b>  C關(guān)鍵字表:</b></p><p><b>  標識符詞法:</b></p><p>  identifier :</p>

59、<p>  nondigitidentifier nondigitidentifier digit</p><p>  nondigit : one of</p><p>  _ 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 zA B C D E F G H I J K L M N O P Q R S T U V W

60、 X Y Z</p><p>  digit : one of</p><p>  0 1 2 3 4 5 6 7 8 9</p><p><b>  escape:</b></p><p>  \n, \r, \b, \0-7</p><p>  3.3 語法分析模塊設(shè)計 </p>

61、<p>  在上一節(jié)中,實現(xiàn)了詞法分析程序的功能。一個字符串形式的源程序經(jīng)過詞法分析,即被轉(zhuǎn)換為一串單詞符號。編譯程序在完成了詞法分析之后,就進入語法分析階段。</p><p>  語法分析程序以單詞形式的源程序作為輸入或分析的對象。其基本任務(wù)是根據(jù)語言的語法規(guī)則(即描述該語言的上下文無關(guān)文法),分析源程序的語法結(jié)構(gòu)(即分析如何將這些單詞組成各種語法成分,如各種表達式、語句、函數(shù)或過程等),并在分析過

62、程中,對源程序進行語法正確性檢查。其分析結(jié)果是識別出無語法錯誤的語法成分。其輸出形式也有多種。</p><p>  語法分析模塊的核心部分設(shè)計如下:</p><p>  Class CParser:</p><p>  定義CTreeNode,和Tiny例程類似:</p><p>  #define MAX_CHILDREN 3</p&

63、gt;<p>  class CTreeNode</p><p><b>  {</b></p><p><b>  public:</b></p><p>  CTreeNode*child[ MAX_CHILDREN ];// point to child node</p><p

64、>  CTreeNode*father;// point to father node</p><p>  CTreeNode*sibling;// point to sibling node</p><p>  intlineno;</p><p>  NodeKindnodekind;</p><p&

65、gt;<b>  union {</b></p><p>  StmtKindstmt;</p><p>  ExpKindexp;</p><p><b>  } kind;</b></p><p>  enum TokenTypetype;</p><p>  C

66、StringszName;</p><p>  CStringszScope;// node function scope</p><p>  BOOLbArray;// is this an array declaration</p><p>  intiArraySize;// array size</p&

67、gt;<p><b>  };</b></p><p>  通過文法及相應(yīng)規(guī)則建立語法樹。</p><p><b>  Grammar:</b></p><p>  program->declaration_list</p><p>  declaration_list->

68、declaration_list declaration | declaration</p><p>  declaration->var_declaration | fun_declaration</p><p>  var_declaration->type_specifier ID(, ...)`;` | type_specifier ID `[` NUM `]`(, .

69、..)`;`</p><p>  type_specifier->`int` | `void` | `char`, actually this step is in declaration_list()</p><p>  fun_declaration->type_specifier ID `(` params `)` compound_stmt</p><

70、;p>  params->param_list | `void` | empty, `void` is thought as empty</p><p>  param_list->param_list `,` param | param</p><p>  param->type_specifier ID | type_specifier ID `[` `]`&l

71、t;/p><p>  compound_stmt->`{` loal_declarations statement_list `}` | expression_stmt</p><p>  local_declarations->local_declarations var_declaration | var_declaration</p><p>  `r

72、ead` `(` var `)` `;`</p><p>  `write` `(` expression `)` `;`</p><p>  `printf` `(` `"` STRING `"` `)` `;`</p><p>  expression_stmt->expression `;` | `;`</p><

73、p>  expression->var `=` expression | logic1_expression</p><p>  logic1_expression->logic1_expression `||` logic2_expression | logic2_expression</p><p>  logic2_expression-> logic2_ex

74、pression `&&` simple_expression | simple_expression</p><p>  simple_expression->additive_expression relop additive_expression | additive_expression</p><p>  relop-> `<=` | `<

75、` | `>` | `>=` | `==` | `!=`</p><p>  additive_expression -> additive_expression addop term | term</p><p>  addop-> `+` | `-`</p><p>  term->term mulop logic3_express

76、ion | logic3_expression</p><p>  mulop-> `*` | `/` | `%`</p><p>  logic3_expression-> `!` logic3_expression | factor</p><p>  factor->`(` expression `)` | var | call | NUM&

77、lt;/p><p>  var->ID | ID `[` expression `]`</p><p>  call->ID `(` args `)`</p><p>  args->args_list | empty</p><p>  args_list->args_list `,` expression | expr

78、ession</p><p>  sub_compoundstmt->ID `:` | call `;` | expression_stmt</p><p>  if_stmt->`if` `(` expression `)` compound_stmt</p><p>  | `if` `(` expression `)` compound_stmt

79、`else` compound_stmt</p><p>  while_stmt->`while` `(` expression `)` compound_stmt</p><p>  for_stmt->`for` `(` var `=` expression `;` expression `;` var `=` expression `)` compound_stmt&l

80、t;/p><p>  goto_stmt->`goto` ID `;`</p><p>  break_stmt->`break` `;`</p><p>  continue_stmt->`continue` `;`</p><p>  return_stmt->`return` `;` | `return` expre

81、ssion `;`</p><p><b>  基本樹形結(jié)構(gòu):</b></p><p><b>  if語句: </b></p><p><b>  while語句:</b></p><p><b>  for循環(huán)語句:</b></p>&l

82、t;p><b>  復(fù)合語句:</b></p><p><b>  支持的語句及運算:</b></p><p>  1) 數(shù)據(jù)類型:int,char void,PCode里支持float,在80x86 ASM里不支持</p><p>  2) 語句:賦值(=),if, while,for,return,break,c

83、ontinue</p><p>  3) 數(shù)學(xué)運算:+,-,*,/</p><p>  4) 關(guān)系運算:= =,>,<,>=,<=,!=</p><p>  5) 邏輯運算:&&,||,!</p><p>  6) 支持函數(shù)的定義、調(diào)用</p><p><b>  7)

84、 支持復(fù)合語句</b></p><p>  8) 注釋語句:C類型的 /* */ 和C++類型的 //</p><p>  3.4 語義分析模塊設(shè)計</p><p>  語義分析的任務(wù)是根據(jù)語義規(guī)則對識別出的各種語法成分分析其含義,進行初步翻譯。具體來說,其主要任務(wù)包括以下幾部分。</p><p>  1、確定類型。即確定標識符所

85、對應(yīng)數(shù)據(jù)對象的數(shù)據(jù)類型,這部分工作有時也由詞法分析來完成。</p><p>  2、語義檢查。動態(tài)語義檢查在運行時進行,需要生成相應(yīng)的目標代碼;而靜態(tài)語義檢查則在編譯時完成,它主要完成以下四個方面。</p><p>  3、識別含義。如果靜態(tài)語義正確,則進行正真的翻譯,即識別程序中各種語法成分的含義,并做相應(yīng)的語義處理,生成相應(yīng)的中間代碼或直接生成目標代碼。</p><

86、p>  語義分析程序是在詞法分析和語義分析之后,可以由語法分析程序直接調(diào)用相應(yīng)的語義子程序進行語義處理,也可以先生成語法樹的某種表示方法,再進行語義處理。</p><p>  編譯的各個階段都可能發(fā)現(xiàn)源程序中的錯誤。發(fā)現(xiàn)錯誤后如果立即停止編譯,往往會降低調(diào)式程序的效率,所以應(yīng)對出現(xiàn)的錯誤做適當?shù)奶幚恚瑥亩咕幾g能繼續(xù)進行。詞法分析可以檢測出源程序中的非法字符,就好比自然語言中出現(xiàn)的錯字和錯詞。語法分析能夠發(fā)

87、現(xiàn)程序語句中的各種語法錯誤,如括號不匹配等。語義分析能夠判斷運算對象的類型是否匹配,變量是否重復(fù)聲明或沒有聲明就使用等錯誤。任何時刻發(fā)現(xiàn)錯誤,都應(yīng)該報告錯誤信息,包括錯誤出現(xiàn)的位置和錯誤性質(zhì)等,為程序員調(diào)試程序提供方便。</p><p>  本程序在語義分析部分設(shè)計主要包括兩方面的內(nèi)容,即建立符號表和類型檢查。</p><p><b>  建立符號表:</b><

88、/p><p><b>  輔助類:</b></p><p>  Class LineListRec:</p><p>  主要成員是lineno,記錄某個Token(變量或函數(shù)名)聲明或使用時的行數(shù)。</p><p>  Class BucketListRec:</p><p><b>  

89、主要成員變量:</b></p><p>  CStringname;// variable name</p><p>  CStringscope;// function scope</p><p>  enum TokenTypetype;</p><p>  intmemloc;// memory

90、location for variable</p><p>  BOOLbArray; // for array checking</p><p>  LineListRec*lineno;</p><p>  BucketListRec*next;</p><p>  記錄每一個變量或函數(shù)名的具體情況。</p>

91、<p><b>  主要的類,</b></p><p><b>  建立符號表:</b></p><p>  Class CSymbolTable:</p><p>  主要成員變量:BucketListRec*hashTable[SIZE],把Class BucketListRec類的對象通過hash函數(shù)找

92、到位置后插入。</p><p>  函數(shù)PrintSynbalTable(LPCTSTR lpszPathName),輸入文件名,通過一個遞歸函數(shù)輸出符號表到文件lpszPathName。</p><p>  Class CFunArgsCheck:</p><p>  插入函數(shù)參數(shù)的類型,以備在下一個步驟中做匹配檢測。</p><p>&l

93、t;b>  類型檢測:</b></p><p>  Class CAnalyzer:</p><p><b>  包括兩個部分:</b></p><p><b>  類型匹配:</b></p><p>  函數(shù)或變量聲明時檢測是否已聲明,如已聲明則拋出錯誤;函數(shù)調(diào)用或變量使用時檢測

94、是否已聲明,如未聲明則拋出錯誤。</p><p><b>  函數(shù)調(diào)用參數(shù)檢測:</b></p><p>  檢測函數(shù)調(diào)用時傳入?yún)?shù)的類型與函數(shù)聲明時參數(shù)的類型是否匹配。</p><p><b>  第4章 結(jié)束語</b></p><p>  本次開發(fā)設(shè)計是對C語言課程、數(shù)據(jù)結(jié)構(gòu)、編譯原理等一系列的

95、課程的回顧學(xué)習(xí)。在開發(fā)基于C語言小型編譯器前端中,還是用系統(tǒng)分析、系統(tǒng)設(shè)計的思路。一個好的系統(tǒng)分析、設(shè)計工作,會使以后的系統(tǒng)實施順利高效的進行,從而達到事半功倍的效果,這也是我的一點心得體會吧。</p><p>  對于系統(tǒng)的可擴展性,在設(shè)計前也做了充分的考慮,在設(shè)計時預(yù)留了一些余地,以便本系統(tǒng)在C語言語法不變的情況下一直都能使用,而不需要再重新開發(fā)。同時在設(shè)計上使用的是模塊化的設(shè)計,更為系統(tǒng)以后的擴展提供了良好

96、的條件。</p><p>  同時系統(tǒng)也存在的問題與改進方向,由于本人第一次開發(fā)編程語言編譯程序,經(jīng)驗不足,所以存在著許多不足之處。由于時間緊,開發(fā)任務(wù)重,系統(tǒng)有些功能尚未健全。</p><p><b>  參考文獻</b></p><p>  [1] 錢煥延.編譯技術(shù)第2版[M].南京:東南大學(xué)出版社出版,2002。</p>&

97、lt;p>  [2] 康慕寧.編譯原理[M].西安:西北工業(yè)大學(xué)出版社出版,2003。</p><p>  [3] 賀世娟,陳冀川.Visual Basic 6.0 程序設(shè)計[M].北京:中國水利水電出版社出版,2002.8。</p><p>  [4] 楊克玉.VB6.0程序設(shè)計實訓(xùn)教程[M].北京:機械工業(yè)出版社出版,2005.2。</p><p>  [

98、5] 陳明.Visual Basic教程[M].北京:人民郵電出版社,2002.8。</p><p>  [6] 徐謖.Visual Basic應(yīng)用與開發(fā)案例教程[M].北京:清華大學(xué)出版社,2005.4。</p><p>  [7] 周峰.Visual Basic案例開發(fā)集錦[M].北京:電子工業(yè)出版社,2005。</p><p>  [8] 李冬梅,施海虎. 編

99、譯原理[M]. 人民郵電出版社,2006.8</p><p>  [9] 孫悅紅. 編譯原理及實現(xiàn)[M]. 清華大學(xué)出版社. 2005.4</p><p>  [10]木林森,高峰霞. Visual C++ 6.0 使用與開發(fā)[M]. 清華大學(xué)出版社,2003.1</p><p>  附錄一:詞法分析核心代碼</p><p>  int ge

100、tch()</p><p><b>  {</b></p><p>  if(cc == ll)</p><p><b>  {</b></p><p>  if(feof(fin))</p><p><b>  {</b></p><

101、;p>  printf("program incoplete");</p><p>  return -1;</p><p><b>  }</b></p><p><b>  ll = 0;</b></p><p><b>  cc = 0;</b>

102、</p><p>  printf("%d",cx);</p><p>  fprintf(fal,"%d",cx);</p><p><b>  ch = '';</b></p><p>  while(ch != 10)</p><p>

103、<b>  {</b></p><p>  if(EOF == fscanf(fin,"%c",&ch))</p><p><b>  {</b></p><p>  line[ll] = 0;</p><p><b>  break;</b><

104、;/p><p><b>  }</b></p><p>  printf("%c",ch);</p><p>  fprintf(fal,"%c",ch);</p><p>  line[ll]=ch;</p><p><b>  ll++;</

105、b></p><p><b>  }</b></p><p>  printf("\n");</p><p>  fprintf(fal,"\n");</p><p><b>  }</b></p><p>  ch = line

106、[cc];</p><p><b>  cc++;</b></p><p><b>  return 0;</b></p><p><b>  }</b></p><p>  附錄二:語法分析核心代碼</p><p>  int getsym()<

107、/p><p><b>  {</b></p><p>  int i,j,k;</p><p>  while(ch==''||ch==10||ch==9)</p><p><b>  getchdo;</b></p><p>  if(ch>='a

108、'&&ch<='z')</p><p><b>  {</b></p><p><b>  k=0;</b></p><p><b>  do </b></p><p><b>  {</b></p>

109、;<p><b>  if(k<al)</b></p><p><b>  {</b></p><p><b>  a[k]=ch;</b></p><p><b>  k++;</b></p><p><b>  }<

110、/b></p><p><b>  getchdo;</b></p><p>  } while (ch>='a'&&ch<='z'||ch>='0'&&ch<='9');</p><p><b>  a[k]

111、=0;</b></p><p>  strcpy(id,a);</p><p><b>  i=0;</b></p><p><b>  j=norw-1;</b></p><p><b>  do{</b></p><p>  k=(i+j

112、)/2;</p><p>  if(strcmp(id,work[k])<=0)</p><p><b>  j=k-1;</b></p><p>  if(strcmp(id,work[k])>=0)</p><p><b>  i=k+1;</b></p><p&

113、gt;  }while(i<=j);</p><p><b>  if(i-1>j)</b></p><p>  sym=wsym[k];</p><p><b>  else</b></p><p>  sym=ident;</p><p><b> 

114、 }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(ch>='0'&&ch<='9')</p><p><b>  {</b><

115、;/p><p><b>  k=0;</b></p><p><b>  num=0;</b></p><p>  sym=number;</p><p><b>  do{</b></p><p>  num=10*num+ch-'0';&

116、lt;/p><p><b>  k++;</b></p><p><b>  getchdo;</b></p><p>  }while(ch>='0'&&ch<='9');</p><p><b>  k--;</b>&

117、lt;/p><p>  if(k>nmax)</p><p><b>  {</b></p><p>  ERROR(30);</p><p><b>  }</b></p><p><b>  }</b></p><p>&l

118、t;b>  else</b></p><p><b>  {</b></p><p>  if(ch==':')</p><p><b>  {</b></p><p><b>  getchdo;</b></p><p&g

119、t;  if(ch=='=')</p><p><b>  {</b></p><p>  sym=becomes;</p><p><b>  getchdo;</b></p><p><b>  }</b></p><p><b

120、>  else</b></p><p><b>  sym=nul;</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p&

121、gt;  if(ch=='<')</p><p><b>  {</b></p><p><b>  getchdo;</b></p><p>  if(ch=='=')</p><p><b>  {</b></p><

122、;p><b>  sym=leq;</b></p><p><b>  getchdo;</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  sym=lss;</b

123、></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(ch=='>')</p><p><b>  {</b

124、></p><p><b>  getchdo;</b></p><p>  if(ch=='=')</p><p><b>  {</b></p><p><b>  sys=geq;</b></p><p><b> 

125、 getchdo;</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p><b>  sym=gtr;</b></p><p&g

126、t;<b>  }</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  sym=ssym[ch];</p><p>  if(sy

127、m!=period)</p><p><b>  getchdo;</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b> 

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論