版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、<p><b> C語言編譯器</b></p><p> 摘 要 編譯原理是計算機科學與技術專業(yè)最重要的一門專業(yè)基礎課程,內(nèi)容龐大,涉及面廣,知識點多。由于該課程教、學難度都非常大,往往費了大量時間而達不到預期教學效果俗語說:學習的最好方法是實踐。本次課程設計的目的正是基于此,力求為學生提供一個理論聯(lián)系實際的機會,通過布置一定難度的課題,要求學生獨立完成。我們這次課程設計的
2、主要任務是編程實現(xiàn)對輸入合法的算符優(yōu)先文法的相應的字符串進行算符優(yōu)先分析,并輸出算符優(yōu)先分析的過程。算符優(yōu)先分析法特別有利于表達式的處理,宜于手工實現(xiàn)。算符優(yōu)先分析過程是自下而上的歸約過程,但這種歸約未必是嚴格的規(guī)范歸約。而在整個歸約過程中,起決定作用的是相繼連個終結符之間的優(yōu)先關系。因此,所謂算符優(yōu)先分析法就是定義算符之間的某種優(yōu)先關系,并借助這種關系尋找句型的最左素短語進行歸約。通過實踐,建立系統(tǒng)設計的整體思想,鍛煉編寫程序、調(diào)試程
3、序的能力,學習文檔編寫規(guī)范,培養(yǎng)獨立學習、吸取他人經(jīng)驗、探索前言知識的習慣,樹立團隊協(xié)作精神。同時,課程設計可以充分彌補課堂教學及普通實驗中知識深度與廣度有限的缺陷,更好地幫助學生從全局角度把握課程體系。</p><p> 關鍵詞 程序設計;數(shù)據(jù)庫;SQL;C++; </p><p><b> 1 任務申請</b></p><p><
4、;b> 引言</b></p><p> 編譯器的設計涉及到編譯程序構造的一般原理、基本設計方法、主要實現(xiàn)技術和一些自動構造工具。盡管“編譯程序”是特指將高級程序設計語言翻譯成低級語言的軟件,但編譯程序構造的基本原理和技術也廣泛應用于一般的設計和實現(xiàn),因此,是一門對實踐性要求較高的課程。</p><p> 目前,世界上存在著數(shù)千種源語言,既有Fortran和Pasca
5、l這樣的傳統(tǒng)程序設計語言,也有各計算機應用領域中出現(xiàn)的專用語言。目標語言也同樣廣泛,目標語言可以是另一種程序設計語言或者是從微處理機到計算機的任何計算機的機器語言。不同語言需要不同的編譯器。根據(jù)編譯器的構造方法或者它們要實現(xiàn)的功能,編譯器被分為一遍編譯器、多遍編譯器、裝入并執(zhí)行編譯器、調(diào)試編譯器、優(yōu)化編譯器等多種類別。從表面上看,編譯器的種類似乎千變?nèi)f化,多種多樣,實質上任何編譯器所要完成的基本任務都是相同的。通過理解這些任務,我們可以
6、利用同樣的基本技術為各種各樣的源語言和目標機器構建編譯器。</p><p><b> 背景</b></p><p> 編譯程序是現(xiàn)代計算機系統(tǒng)的基本組成部分之一,而且多數(shù)計算機系統(tǒng)都含有不止一個高級語言的編譯程序,對有些高級語言甚至配置了幾個不同性能的編譯程序。從功能上看,一個編譯程序就是一個語言翻譯程序。它把一種語(稱作源語言)書寫的程序翻譯成另一種語言(稱作目
7、標語言)的等價的程序。比如匯編程序是一個翻譯程序,它把匯編語言程序翻譯成機器語言程序。如果源語言是像FORTRAN,PASCAL,或C那樣的高級語言,目標語言是像匯編語言或機器語言那樣的低級語言,則這種翻譯程序稱作編譯程序。</p><p><b> 目標</b></p><p><b> (1)設計符號表</b></p>&l
8、t;p> 確定符號表的組織方式,一般應包括名字欄和信息欄,其中名字欄作為關鍵字。要考慮能夠存儲有關名字的信息,并可以高效地完成如下操作:</p><p> a.查找:根據(jù)給定的名字,在符號表中查找其信息。如果該名字在符號表中不存在,則將其加入到符號表中,否則返回指向該名字的指針;</p><p> b.刪除:從符號表中刪除給定名字的表項。</p><p>
9、; (2)設計詞法分析器</p><p> 設計各單詞的狀態(tài)轉換圖,并為不同的單詞設計種別碼。將詞法分析器設計成供語法分析器調(diào)用的子程序。功能包括:</p><p> 具備預處理功能。將不翻譯的注釋等符號先濾掉,只保留要翻譯的符號串,即要求設計一個供詞法分析調(diào)用的預處理子程序;</p><p> 能夠拼出語言中的各個單詞;</p><p&
10、gt; 將拼出的標識符填入符號表;</p><p> 返回(種別碼, 屬性值)。</p><p><b> (3)語法分析器</b></p><p> 要求用預測分析法、遞歸下降分析法、算符優(yōu)先分析法、SLR分析法(幾種方法任選),實現(xiàn)對表達式、各種說明語句、控制語句進行語法分析。</p><p> (4)目標
11、代碼生成器</p><p> 能完成指定寄存器個數(shù)的情況下將一中間代碼程序段翻譯成匯編語言目標代碼(匯編指令應包括加、減、乘、除),要求指令條數(shù)最少的情況下,盡量使用寄存器,盡量少訪問內(nèi)存,這樣才能做到運行效率高</p><p><b> 可行性研究報告</b></p><p><b> 2.1、引言</b><
12、;/p><p> 編寫編譯器的原理和技術具有十分普遍的意義,以致于在每一個計算機科學家的研究生涯中,許多原理和技術都會反復用到。編譯器的編寫涉及到程序設計語言、計算機體系結構、語言理論、算法和軟件工程等學科。簡單的說,編譯器是一個程序,它讀入用某種語言(源語言)編寫的程序并將其翻譯成一個與之等價的以另一種語言(目標語言)編寫的程序。作為這個翻譯過程匠一個重要組成部分,編譯器能夠向用戶報告被編譯的源程序中</p
13、><p><b> 功能需求分析</b></p><p><b> 3.1、引言</b></p><p> 3.1.1詞法語法分析簡介</p><p> 詞法分析的任務是從左到右一個字符一個字符地讀入源程序,對構成源程序的字符流進行掃描和分解,從而識別出一個個的單詞(也稱單詞符號或符號)。這里所
14、謂的單詞是指邏輯上緊密相連的一組字符,這些字符具有集體含義。</p><p> 語法分析的任務是在詞法分析的基礎上將單詞序列分解成各類語法短語,如“程序”,“語句”,“表達式”等等,即判斷單詞序列是否符合組成各類語法短語的組成規(guī)則,一般這種語法短語,也稱為語法單位,可表示成語法樹。</p><p><b> 。</b></p><p>
15、3.1.2詞法需求分析簡</p><p> 介詞法分析階級是編譯過程的第一個階級。這個階級的任務是從左到右一個字符一個字符地讀入源程序,對構成源程序的字符流進行掃描和分解,從而識別一個個單詞(也稱為單詞符號或符號)。這里所謂的單詞是指邏輯上緊密相連的一組字符,這些字符具有集體含義。比如標識是由字母開頭,后跟字母、數(shù)字字符序列組成的一種單詞,。保留字是一種單詞,此外還有算符,界符等等。</p>&l
16、t;p><b> 3.2、任務概述</b></p><p><b> 3.2.1目標</b></p><p> 1、了解編譯器的基本結構,分析編譯器的設計原理。</p><p> 2、加深對詞法分析器的工作過程的理解;加強對詞法分析方法的掌握;能夠采用一種編程語言實現(xiàn)簡單的詞法分析程序;能夠使用自己編寫的分析
17、程序對簡單的程序段進行詞法分析。</p><p> 3、加深對語法分析器工作過程的理解;加強對遞歸下降法實現(xiàn)語法分析程序的掌握;能夠采用一種編程語言實現(xiàn)簡單的語法分析程序;能夠使用自己編寫的分析程序對簡單的程序段進行語法翻譯。</p><p> 4、加深對中間代碼生成的工作過程的理解。</p><p> 5、加深對代碼優(yōu)化的工作過程的理解。</p>
18、<p> 6、加深對目標代碼生成的工作過程的理解</p><p> 3.3、語法需求分析簡介</p><p> 語法分析是編譯過程的第二個階級。語法分析的任務是在詞法分析的基礎上將單詞序列分解成各類語法短語,如“程序”,“語句”,“表達式”等等。一般這種語法短語,也稱為語法單位,可表示成語法樹。語法分析所依據(jù)的是語言的語法規(guī)則,即描述程序結構的規(guī)則。通過語法分析確定整個
19、輸入串是否構成一個語法上正確的程序。詞法分析和語法分析本質上都是對源程序的結構進行分析。但詞法分析的任務僅對源程序進行線性掃描即可完成,比如識別標識符,因為標識符的結構是字母打頭的字母和數(shù)字序列,這只要順序掃描輸入流,遇到既不是字母又不是數(shù)字字符時,將前面所發(fā)現(xiàn)的所有字母和數(shù)字組合在一起而構成單詞標識符。但這種線性掃描則不能用于識別遞歸定義的語法成分,比如就不能用此辦法去匹配表達式中的括號。</p><p>
20、語法分析的任務是語法分析器接收詞法分析研究器提供的記號串,檢查它們是否能由源程序的文法產(chǎn)生,語法分析器在編譯器中的位置如圖所示:</p><p> 源程序記號 中間表示</p><p><b> 語法樹</b></p><p><b> 取下一</b>
21、</p><p><b> 個記號</b></p><p> 典型的文法的語法分析器有三類:一類是通用的語法分析方法,如Cocke-Younger-Kasami算法和Early算法,這些方法在生成編譯器時效率太低。編譯器常用的是自頂向下和自底向上的方法。</p><p> 采用自頂向下的遞歸子程序法,就是對應每個非終結符語法單元,編一個獨
22、立的處理子程序。語法分析從讀入第一個單詞開始,由非終結符即開始符出發(fā),沿語法描述圖箭頭指出的方向進行分析。當遇到非終結符時,則調(diào)用相應的處理子程序,從語法描述圖看也就進入了一個語法單元,再沿當前所進入的語法描述圖的箭頭方向進行分析,當遇到終結符時,則判斷當前讀入的單詞是否與圖中的終結符相匹配,若匹配,則執(zhí)行相應的語義程序。再讀取下一個單詞繼續(xù)分析。遇到分支點時將當前的單詞與分支點上的多個終結符逐個相比較,若都不匹配時可能是進入下一非終結
23、符語法單位或是出錯。</p><p><b> 關鍵技術實現(xiàn)介紹</b></p><p><b> 4.1、引言</b></p><p> 本次課程設計中的關鍵是:掃描和語法分析函數(shù),它使用一個用于存放文法符號的先進后出棧,并利用有限關系可以確定最左素短語是否已形成來決定分析器的動作。如果當前棧頂?shù)慕K結符號和帶輸入符
24、號之間優(yōu)先關系是<或=則表示棧頂符號串未形成最左素短語,此時分析器將移進輸入符號。如果當前棧頂?shù)慕K結符號和待輸入符號之間的優(yōu)先關系是>,則表示已找到最左素短語的尾,在從棧頂開始,按優(yōu)先關系在棧內(nèi)向左尋找最左素短語的頭,然后分析器將歸約最左素短語。如果出現(xiàn)兩個終結符號之間不存在優(yōu)先關系,則表示存在語法錯誤。以及如何編寫、調(diào)試、修改代碼。還要了解一個題目有許多種解決方法。鍛煉我們的思維能力。 </p><p&
25、gt;<b> 4.2、用途</b></p><p><b> 4.2.1功能</b></p><p> 員工培訓管理信息系統(tǒng)以計算機為工具,通過對培訓部門所需的信息管理,把管理人員從繁瑣的數(shù)據(jù)計算處理中解脫出來,使其有更多的精力從事公司的其他業(yè)務需求。</p><p><b> 4.2.2性能</
26、b></p><p> 1 數(shù)據(jù)精確度 由于采用數(shù)據(jù)庫技術并且用戶的應用領域對數(shù)據(jù)精確度的要求不是太高,所以這點在系統(tǒng)中表現(xiàn)得比較少,但是用戶數(shù)據(jù)的安全性與正確性是完全保證的,所以對用戶的使用沒有多大的障礙。 2 時間特性 本系統(tǒng)的數(shù)據(jù)庫較小,所以程序在響應時間,數(shù)據(jù)更新處理時間上性能是比較突出的。而且也正由于數(shù)據(jù)量相對較少,故在數(shù)據(jù)傳輸時間和系統(tǒng)運行時間上表現(xiàn)的較讓人滿意。 3
27、適應性 該系統(tǒng)軟件是使用Visual C++ 6.0在windows xp系統(tǒng)下完成的所以只要是兼容windows的軟件或是操作系統(tǒng),該軟件都可以正確地運行,有較好的適應能力與兼容性。而且應用戶的特殊需求軟件在完成后的維護階段可以保持一個與其他類軟件接口,隨時滿足用戶的使用要求。 </p><p><b> 4.3、運行環(huán)境</b></p><p><
28、;b> 4.3.1硬設備</b></p><p> 選用PC級服務器。具體配置如下:</p><p> Intel 486 CPU 或以上</p><p><b> 256M內(nèi)存</b></p><p> 1個4.3G硬盤,1個激光打印機</p><p><b&g
29、t; 4.3.2支持軟件</b></p><p> Microsoft access</p><p><b> 4.3.3數(shù)據(jù)結構</b></p><p> char ch='\0'; /*從字符緩沖區(qū)中讀取當前字符*/</p><p> int count=0; /*
30、詞法分析結果緩沖區(qū)計數(shù)器*/</p><p> static char spelling[10]={" "}; /*存放識別的字*/</p><p> static char line[81]={" "}; /*一行字符緩沖區(qū)( 最多 80 個字符)*/</p><p> char *pline; /*字符緩沖
31、區(qū)指針*/</p><p> static char ntab1[100][10]; /*變量名表:共100項,每項長度為10*/</p><p><b> 5 系統(tǒng)分析</b></p><p><b> 5.1、基礎知識</b></p><p> 5.1.1 算符優(yōu)先分析法的基本思想&l
32、t;/p><p> 仿照算術表達式的四則運算過程</p><p> 算符優(yōu)先分析的基本思想是只規(guī)定算符(廣義為終結符)之間的優(yōu)先關系,也就是只考慮終結符之間的優(yōu)先關系,不考慮非終結符之間的優(yōu)先關系。在歸約過程中只要找到可歸約串就歸約,并不考慮歸約到那個非終結符名,算符優(yōu)先分析的可歸約串不一定是規(guī)范句型的句柄,所以算符優(yōu)先歸約不是規(guī)范歸約。算符優(yōu)先分析的可歸約串是當前符號棧中的符號和剩余的輸
33、入符號構成句型的最左素短語。</p><p> 5.1.2算符優(yōu)先關系的定義</p><p> 設G是一個不含ε產(chǎn)生式的算符文法,a和b是任意兩個終結符,A、B、C是非終結符,算符優(yōu)先關系、、定義如下 : ?、?ab 當且僅當G中含有形如A→…ab…或A→…aBb…的產(chǎn)生式 ② ab 當且僅當G中含有形如A→…aB …的產(chǎn)生式,且Bb… 或BCb… ③ ab當且僅當G中含有形
34、如A→…Bb …的產(chǎn)生式,且B…a 或B…aC</p><p> 以上三種關系也可由下列語法樹來說明: ?、?a b 則存在語法子樹如圖2.1(a) 其中δ為ε或為B,這樣a, b在同一句柄中同時歸約所以優(yōu)先級相同?! 、?a b 則存在語法子樹如圖2.1(b) 其中δ為ε或為C。a,b不在同一句柄中,b先歸約,所以a的優(yōu)先級低于b?! 、?a b 則存在語法子樹如圖2.1(c) 。</p
35、><p> 圖2.1 由語法樹結構決定優(yōu)先性</p><p> 5.1.3算符優(yōu)先文法的定義</p><p> 設有一文法G,如果G中沒有形如A→…BC…的 產(chǎn)生式,其中B和C為非終結符,則稱G為算符文法(Operater Grammar)也稱OG文法。 例如:表達式文法E→E+E|E*E|(E)|i 其中任何一個產(chǎn)生式中都不包含兩個非終結符相鄰的情況,因
36、此該文法是算符文法。</p><p> 設有一不含ε產(chǎn)生式的算符文法G,如果對任意兩個終結符對a,b之間至多只有 、 和 三種關系中的一種成立,則稱G是一個算符優(yōu)先文法。(Operator Precedence Grammar)即OPG文法。</p><p> 由以上內(nèi)容我們可計算出給定的算符文法中任何兩個終結符對(a,b)之間的優(yōu)先關系,其算法如下:</p><p
37、> 首先定義如下兩個集合:</p><p> FIRSTVT(B)={b|B b… 或 B Cb…}</p><p> LASTVT(B)={a|B…a 或 B …aC}</p><p> 三種優(yōu)先關系的計算為</p><p><b> a) 關系: </b></p><p>
38、可直接查看產(chǎn)生式的右部,對如下形式的產(chǎn)生式</p><p> A→…ab… , A→…aBb…</p><p><b> 有a b 成 立。</b></p><p><b> b) 關系:</b></p><p> 求出每個非終結符B的FIRSTVT(B),在如下形式的產(chǎn)生式</p&g
39、t;<p> A→…aB… 中,對每一 b∈FIRSTVT(B),有ab成立。</p><p><b> c) 關系:</b></p><p> 計算每個非終結符B的LASTVT(B),在如下形式的產(chǎn)生式</p><p> A→…Bb… 中,對每一a∈LASTVT(B),有ab成立。</p><p>
40、; 5.1.4 最左素短語的定義</p><p> 設有文法G[S],其句型的素短語是一個短語,它至少包含一個終結符,并除自身外不包含其它素短語,最左邊的素短語稱最左素短語。</p><p> 例如,若表達式文法G[E]為:</p><p><b> E→E+T|T</b></p><p><b>
41、T→T*F|F</b></p><p><b> F→P↑F|P</b></p><p><b> P→(E)|i</b></p><p> 若有句型#T+T*F+i#,其短語有:</p><p> T+T*F+i 相對于非終結符E的短語</p><p>
42、 T+T*F 相對于非終結符E的短語</p><p> T 相對于非終結符E的短語</p><p> T*F 相對于非終結符T的短語</p><p> i 相對于非終結符P,F,T的短語</p><p> 由以上內(nèi)容知i和T*F為素短語,T*F為最左素短語。也為算符優(yōu)先分析的可歸約串。由算符優(yōu)先分析算法可知一個算符優(yōu)先文法的最左素短
43、語滿足如下條件:</p><p> ai-1 ai ai+1 ... aj aj+1</p><p> 上述句型#T+T*F+i#寫成算符分析過程的形式為:</p><p> #N1a1N2a2N3a3a4#其中a1 = +, a2 = *, a3 = +, a4 = i</p><p> a1 a2 (因+ *)</p>
44、<p> a2 a3 (因* +)</p><p> 由此 N2a2N3 即T*F為可歸約串,也就是前面分析的最左素短語。</p><p> 5.2、解決問題的基本思路</p><p> 根據(jù)課程設計的要求,程序應具有如下功能:對輸入的文法進行分析并判斷是否為算符優(yōu)先文法。如果是算符優(yōu)先分析文法則再進一步輸入符合該算符優(yōu)先文法的字符串,并對該字
45、符串進行算符優(yōu)先分析,同時輸出算符優(yōu)先分析的過程。</p><p><b> 5.3、總體方案</b></p><p> 5.3.1設計詞法分析器</p><p><b> 設計思想:</b></p><p> 要求:1. 對單詞的構詞規(guī)則有明確的定義;</p><p&g
46、t; 2. 編寫的分析程序能夠正確識別源程序中的單詞符號;</p><p> 3. 識別出的單詞以<種別碼,值>的形式保存在符號表中;</p><p> 4. 詞法分析中源程序的輸入以.c格式,分析后的符號表保存在.txt文件中。</p><p> 5. 對于源程序中的詞法錯誤,能夠做出簡單的錯誤處理,給出簡單的錯誤提示,保證順利完成整個源程序的
47、詞法分析;</p><p> 6. 輸入:由符合規(guī)定單詞類別結構的各類單詞組成的源程序。</p><p><b> 實現(xiàn)方法:</b></p><p> 根據(jù)加入語義過程的狀態(tài)轉換圖直接編寫詞法分析程序。根據(jù)每一組狀態(tài)轉換關系(標識符)組織程序結構,并將所有公共處理過程分別實現(xiàn)即可。在掃描源程序字符串時,一旦識別出關鍵字、運算符、標識符、
48、無符號常數(shù)中之一,即以二元式形式(類別編碼,值)輸出單詞。每次調(diào)用詞法分析程序,它均能自動繼續(xù)掃描下去,形成下一個單詞。</p><p> 5.3.2設計語法、語義分析器</p><p><b> 設計思想:</b></p><p> 要求:1. 對語法規(guī)則有明確的定義;</p><p> 2. 編寫的分析程序能
49、夠對實驗一的結果進行正確的語法分析;</p><p> 3.編寫的分析程序能夠對實驗二的結果進行正確的語義分析;</p><p> 4.對于遇到的語法、語義錯誤,能夠做出簡單的錯誤處理,給出簡單的錯誤提示,保證語義分析過程;</p><p><b> 實現(xiàn)方法: </b></p><p> 在詞法分析識別出單詞符
50、號的基礎上分析并規(guī)定程序的語法結構是否符合語法規(guī)則。其工作本質就是按文法的產(chǎn)生式,識別輸入符號串是否為一個句子。首先定義語法規(guī)則,然后按照規(guī)則實現(xiàn)語法分析。</p><p> 5.3.3單詞符號及種別表</p><p> 5.3.4系統(tǒng)功能結構</p><p> 啟動VC++,新建源程序并進行編程,程序的功能模塊圖如圖2-1所示</p><
51、p> 圖2-1系統(tǒng)功能結構圖</p><p><b> 函數(shù)功能:</b></p><p> Main()函數(shù):調(diào)用主函數(shù),運行程序;</p><p> FIRSTVT()函數(shù):構造FIRSTVT表;</p><p> LASTVT()函數(shù):構造LASTVT表;</p><p>
52、 OpPrioTable()函數(shù):構造算符優(yōu)先關系表;</p><p> InputAnalyse()函數(shù):分析輸入串是否為文法中的句子,并給出規(guī)約過程。</p><p><b> 6 系統(tǒng)設計</b></p><p><b> 6.1、算法實現(xiàn)</b></p><p> 算符優(yōu)先分析法的具
53、體過程如下:</p><p> 1、首先先輸入文件的路徑,在readfile(char sen[][col])函數(shù)中,將需要分析的文法通過輸入流文件打開函數(shù)open()復制到sen[row][col]中。</p><p> 2、然后利用FIRSTVT( )構造產(chǎn)生式sen[row][col]的FIRSTVT表。先找出形如A->…a…(a為第一個終結符)的產(chǎn)生式,把(A,a)壓入O
54、perator棧中。從Operator棧頂拋出項(A,a),填入first表相應位置。在找出形如B->A…的產(chǎn)生式,把(B,a)壓入Operator棧中。循環(huán)直到Operator棧為空,此時FIRSTVT表構造完畢。</p><p> 3、然后把產(chǎn)生式右部翻轉,調(diào)用FIRSTVT函數(shù)求出LASTVT表。</p><p> 4、接著調(diào)用OpPriotable()構造算符優(yōu)先關系表o
55、pTable。先把產(chǎn)生式中所有終結符填入opTable表第一行和第一列,然后利用產(chǎn)生式和FIRSTVT表LASTVT表分別找出滿足=關系、<關系、>關系的算符填表。若相應位已有關系,說明兩個終結符之間至少有兩種優(yōu)先關系,該文法不是算符優(yōu)先文法。</p><p> 5、最后調(diào)用InputAnalyse()對輸入串進行分析。初始化分析棧S,依次判斷當前輸入符a和分析棧中離棧頂最近的終結符S[ j ]的關
56、系,若S[ j ]< a ,則a移近,若S[ j ]< a ,則往前找到第一個S[ j ]>a,將S[ j -1]到棧頂S[ k ]規(guī)約,若S[ j ]= a ,如果S[ j ]=#,則接受,如果S[ j ]!=#,則移進。直到接受或者出錯,算符優(yōu)先分析結束。</p><p><b> 6.2編譯過程概述</b></p><p> 編譯程序是現(xiàn)代
57、計算機系統(tǒng)的基本組成部分之一,而且多數(shù)計算機系統(tǒng)都含有不止一個高級語言的編譯程序,對有些高級語言甚至配置了幾個不同性能的編譯程序。從功能上看,一個編譯程序就是一個語言翻譯程序。它把一種語(稱作源語言)書寫的程序翻譯成另一種語言(稱作目標語言)的等價的程序。如果源語言是像FORTRAN,PASCAL,或C那樣的高級語言,目標語言是像匯編語言或機器語言那樣的低級玉器言,則這種翻譯程序稱作編譯程序。</p><p>
58、 高級語言程序的處理過程如圖:</p><p><b> 需處理的源程序</b></p><p><b> 源程序</b></p><p><b> 目標匯編程序 </b></p><p><b> 可再裝配的機器代碼</b></p>
59、<p><b> 可在裝配的目標文件</b></p><p> 絕對機器代碼 </p><p> 一個源程序有時可能分成幾個模塊存放在不同的文件里,將這些源程序匯集在一起的任務,由一個叫做預處理程序的程序完成,有些預處理程序也負責宏展開,像C語言和預處理程序要完成文件合并、宏展開等任務。也就是
60、說,一個編譯程序的輸入可能要一個或多個預處理程序來產(chǎn)生,另外,為得到能運行的機器代碼,編譯程序的輸出可能仍需要進一步地處理。</p><p><b> 源程序</b></p><p><b> 圖1</b></p><p> 圖1將編譯過程劃分了詞法分析、語法分析、語義分析、中間代碼生成、代碼優(yōu)化、目標代碼生成、六個
61、階級。另外兩個重要的工作:表格處理和出錯處理與上述六個階級都有聯(lián)系。編譯過程是源程序和各種信息被子保留在種種不同的表格里,編譯各階級的工作都涉及到構造、查找或更新有關的表格,因此需要有表格處理的工作;如果編譯過程中發(fā)現(xiàn)源程序有錯誤,編譯程序應報告錯誤的性質和錯誤發(fā)生的地點,并且將錯誤所造成的影響限制在盡可能小的范圍內(nèi),使得源程序的其余部分能繼續(xù)被編譯下去,有些編譯程序還能自動校正錯誤,這些工作稱之為出錯處理。</p>&l
62、t;p> 詞法分析階級是編譯過程的第一個階級。這個階級的任務是從左到右一個字符一個字符地讀入源程序,對構成源程序的字符流進行掃描和分解,從而識別一個個單詞(也稱為單詞符號或符號)。這里所謂的單詞是指邏輯上緊密相連的一組字符,這些字符具有集體含義。比如標識是由字母開頭,后跟字母、數(shù)字字符序列組成的一種單詞,。保留字是一種單詞,此外還有算符,界符等等。</p><p> 語法分析是編譯過程的第二個階級。語法
63、分析的任務是在詞法分析的基礎上將單詞序列分解成各類語法短語,如“程序”,“語句”,“表達式”等等。一般這種語法短語,也稱為語法單位,可表示成語法樹。語法分析所依據(jù)的是語言的語法規(guī)則,即描述程序結構的規(guī)則。通過語法分析確定整個輸入串是否構成一個語法上正確的程序。詞法分析和語法分析本質上都是對源程序的結構進行分析。但詞法分析的任務僅對源程序進行線性掃描即可完成,比如識別標識符,因為標識符的結構是字母打頭的字母和數(shù)字序列,這只要順序掃描輸入流
64、,遇到既不是字母又不是數(shù)字字符時,將前面所發(fā)現(xiàn)的所有字母和數(shù)字組合在一起而構成單詞標識符。但這種線性掃描則不能用于識別遞歸定義的語法成分,比如就不能用此辦法去匹配表達式中的括號。</p><p> 語義分析階級是審查源程序有無語義錯誤,為代碼生成階級收集類型信息。比如語分析的一個工作是進行類型審查,審查每個算符是否具有語言規(guī)范允許的運算對象,當不符合語言規(guī)范時,編譯程序應報告錯誤。如有的編譯程序要對實數(shù)用個數(shù)組
65、下標的情況報告錯誤。又如某些語言規(guī)定運算對象可被強制,那么當二目運算一整數(shù)和一實型時,編譯程序應將整型轉換成實型而不能認為是源程序的錯誤。</p><p> 代碼優(yōu)化在此階級的任務是對前階級產(chǎn)生的是間代碼進行變換或進行改造,目的是使生成的目標代碼更為高效,即省時間和省空間。</p><p><b> 6.3、流程圖</b></p><p>
66、 圖3-1 程序流程圖</p><p><b> 7 代碼編寫</b></p><p> #include<iostream.h></p><p> #include<fstream.h></p><p> #include<string.h></p><
67、p> #include<iomanip.h></p><p> #include<malloc.h></p><p> enum keyword{ $right_paren,$left_paren,$mul,$div,$add,$sub,$fenhao,</p><p> $equal,$IF,$THEN,$ELSE,$grea
68、ter,$less,$id,$num,$end};//關鍵字的枚舉</p><p> typedef struct Token</p><p><b> {</b></p><p> keyword type;</p><p><b> char ch;</b></p><
69、;p> }Token;//定義的token結構</p><p> typedef enum{JUMP,JG,JL,equal,END,add,mul,sub,div}OpKind;//操作符定義為opkind</p><p> typedef struct</p><p><b> {</b></p><p&g
70、t; int label;//標號</p><p> OpKind op;//操作符</p><p> char par1,par2;//操作數(shù)</p><p><b> union</b></p><p><b> {</b></p><p> char res
71、ult;//結果</p><p> int address;//地址</p><p><b> };</b></p><p> }Quad; //四元式入口</p><p> #define MAX_TOKEN 256//Token表大小</p><p> #define MAX_QUA
72、D 256//四元式數(shù)組大小</p><p> Token tokentable[MAX_TOKEN];</p><p> Quad quad[MAX_QUAD];</p><p> int token_index;//token表索引</p><p> int total_len;//token表有效長度</p>&l
73、t;p> int quad_len;//四元式表有效長度</p><p> int quad_index;//四元式索引</p><p> Token cur;</p><p> Token queue[10];</p><p> int label,k,one; //標記接口</p><p> ch
74、ar curchar;//存儲當前待比較字符</p><p> char curtocmp;//存儲當前棧頂字符</p><p> ifstream ins;</p><p> int trueadd,falseadd,end; </p><p> int table[5][8]={{1,0,0,0,0,1,0,0},<
75、/p><p> {0,1,1,0,0,0,1,1},</p><p> {1,0,0,0,0,1,0,0},</p><p> {0,1,1,1,1,0,1,1},</p><p> {1,0,0,0,0,1,0,0}}; //存儲預測分析表,1為有產(chǎn)生式,0為沒有</p><p><b> int i
76、,j;</b></p><p><b> int flag;</b></p><p> struct Lchar</p><p><b> {</b></p><p> char char_ch;</p><p> struct Lchar *next;
77、</p><p> }Lchar,*temp,*top,*base;</p><p> int right;//定義開關項</p><p> bool initialize(char filename[255]);//文件打開初始化</p><p> bool accidence();//詞法分析</p><p&g
78、t; void print();//輸出單詞表</p><p> void backpath(int,int);//回填出口</p><p> void ERROR();</p><p> void sentence();//分析語句</p><p> void boolean();// 分析E->id < id | i
79、d > id語句</p><p> bool nexttoken();//讀下一單詞</p><p> char newchar();</p><p> void push();//進隊列</p><p> char dosome(void);//算法函數(shù)</p><p> void pushs(cha
80、r pchar);//入棧函數(shù)</p><p> void pop(void);//出棧函數(shù)</p><p> void doforpush(int t);//根據(jù)數(shù)組下標計算的值產(chǎn)生式入棧</p><p> void changchartoint();//根據(jù)curchar,curtocmp轉為數(shù)字以判斷是否有產(chǎn)生式</p><p>
81、 void semantic();//語法語義分析</p><p> char LL1();//LL(1)文法分析</p><p> void printQuad();//輸出四元式</p><p> void ERROR(char str[20]);</p><p> void AD_ADDRESS(int nlabel,OpKi
82、nd nop,char npar1,char npar2,int naddress);</p><p> void AD_RESULT(int nlabel,OpKind nop,char npar1,char npar2, char nresult);</p><p> void main()</p><p><b> { </b>
83、</p><p> cout<<" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "<<endl</p><p> <<" @基于LL(1)法的條件語句語法語義分析程序 @ "<<endl&l
84、t;/p><p> <<" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "<<endl;</p><p> cout<<"輸入您要編譯編譯文件的文件名(文件名.txt):";</p><p> char fname[
85、100];</p><p> cin>>fname;</p><p> if(!initialize(fname))//初始化文件</p><p><b> return;</b></p><p> if(!accidence())//詞法分析</p><p><b>
86、; return;</b></p><p><b> char ch;</b></p><p><b> while(1)</b></p><p><b> {</b></p><p> if(ins.eof())//ifstream ins;文件輸入串,
87、若文件已完。則break</p><p><b> break;</b></p><p> ins>>ch;//繼續(xù)讀入文件內(nèi)容}</p><p> cout<<endl<<"詞法分析結果如下:";</p><p> print();//打印詞法分析的結果&
88、lt;/p><p> cout<<endl;</p><p> cout<<"詞法分析結束。"<<endl<<endl;</p><p> semantic(); //語法語義分析</p><p> cout<<endl<<&qu
89、ot;輸出四元式:"<<endl;</p><p> printQuad();//輸出四元式</p><p> if(right==1)</p><p> cout<<"分析成功"<<endl;</p><p><b> else</b></
90、p><p> cout<<"分析失敗"<<endl;</p><p> cout<<"語法語義分析結束"<<endl;</p><p><b> }</b></p><p> char newchar()</p>&
91、lt;p> { char p;</p><p> p=char(k); //int label,k,one; //標記接口</p><p><b> k++;</b></p><p> return p; }</p><p><b> //文件打開初始化</b></p&g
92、t;<p> bool initialize(char filename[100])</p><p><b> { </b></p><p><b> one=0;</b></p><p> token_index=0;//token表索引</p><p> total_
93、len=0;//token表有效長度</p><p> quad_len=0;//四元表有效長度</p><p> quad_index=0;//四元表索引</p><p> label=0; //int label,k,one; //標記接口</p><p> end=0;// 前面定義的全局變量int trueadd,falsea
94、dd,end; </p><p><b> k=48;</b></p><p> ins.open(filename,ios::nocreate | ios::in);</p><p> if(ins.fail())</p><p><b> {</b></p><p&
95、gt; cout<<"文件打開出錯!"<<endl;</p><p> return false;}</p><p> return true;</p><p><b> }</b></p><p><b> //詞法分析</b></p&g
96、t;<p> bool accidence()</p><p><b> {</b></p><p><b> int k=0;</b></p><p> char buf[16];//暫存數(shù)組單元</p><p><b> char ch;</b>&l
97、t;/p><p><b> while(1)</b></p><p><b> {</b></p><p><b> ins>>ch;</b></p><p> if(ins.fail())</p><p><b> brea
98、k;</b></p><p> while(ch==' ')</p><p> {ins>>ch;}</p><p> if(ch=='I')</p><p><b> {</b></p><p><b> ins>
99、;>buf;</b></p><p><b> //對關鍵字分析</b></p><p> if(strcmp(buf,"F")==0)</p><p> tokentable[total_len++].type=$IF;</p><p><b> }</b&
100、gt;</p><p> else if(ch=='T')</p><p><b> {</b></p><p><b> ins>>buf;</b></p><p> if(strcmp(buf,"HEN")==0)</p>&
101、lt;p> tokentable[total_len++].type=$THEN;</p><p><b> }</b></p><p> else if(ch=='E')</p><p><b> {</b></p><p><b> ins>>
102、;buf;</b></p><p> if(strcmp(buf,"LSE")==0)</p><p> tokentable[total_len++].type=$ELSE;</p><p><b> }</b></p><p> //對關系運算符分析</p>&l
103、t;p> else if(ch=='>')</p><p><b> {</b></p><p> tokentable[total_len++].type=$greater;</p><p><b> }</b></p><p> else if(ch==
104、39;<')</p><p><b> {</b></p><p> tokentable[total_len++].type=$less;</p><p><b> }</b></p><p> else if(ch=='==')</p><
105、;p><b> {</b></p><p> tokentable[total_len++].type=$equal;</p><p><b> }</b></p><p><b> //對字母的分析</b></p><p> else if((ch>=&
106、#39;A'&& ch<='Z' )|| (ch>='a' && ch<='z'))</p><p><b> {</b></p><p> tokentable[total_len].type=$id;</p><p> token
107、table[total_len++].ch=ch;</p><p><b> }</b></p><p><b> //對數(shù)字的分析</b></p><p> else if(ch>='0' && ch<='9')</p><p>
108、 {tokentable[total_len].type=$num;</p><p> tokentable[total_len++].ch =ch;</p><p><b> }</b></p><p><b> Else</b></p><p> //采用switch語句對運算符,括號
109、分析</p><p> switch (ch)</p><p> {case '+' :</p><p> tokentable[total_len].type=$add;</p><p> tokentable[total_len++].ch =ch;</p><p><b> b
110、reak;</b></p><p> case '-' :</p><p> tokentable[total_len].type=$sub;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p&
111、gt;<p> case '/' : </p><p> tokentable[total_len].type=$div;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p><p> cas
112、e '*' :</p><p> tokentable[total_len].type=$mul;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p><p> case ';' :</p&
113、gt;<p> tokentable[total_len].type=$fenhao;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p><p> case '(' :</p><p> tok
114、entable[total_len].type=$left_paren;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p><p> case ')' :</p><p> tokentable[total_l
115、en].type=$right_paren;</p><p> tokentable[total_len++].ch =ch;</p><p><b> break;</b></p><p> default:cout<<"!"<<endl;}}</p><p> re
116、turn true;</p><p><b> }//詞法分析結束</b></p><p><b> //語法語義分析</b></p><p> void semantic()</p><p><b> { </b></p><p> if
117、(!nexttoken())</p><p> ERROR("s(0)");</p><p> cout<<"開始進行語法語義分析:"<<endl </p><p> <<"所使用的產(chǎn)生式:"<<endl</p><p> &l
118、t;<"<if語句> -> if E then S else S"<<endl</p><p> <<"S->if E then p1 else P2"<<endl</p><p> <<"E->a>b"<<endl</
119、p><p> <<"P1->x:=a*c"<<endl</p><p> <<"P2->x:=b*c"<<endl</p><p> <<"語法語義分析過程如下:"<<endl;</p><p>
120、 if(cur.type==$IF)</p><p><b> { </b></p><p> boolean();//分析布爾語句</p><p> if(!nexttoken())</p><p> ERROR("S(0)");</p><p> if(c
121、ur.type==$THEN)</p><p><b> { </b></p><p> backpath(trueadd,quad_len);//回填出口</p><p> sentence();//分析語句</p><p> end=quad_len;</p><p> AD
122、_ADDRESS(quad_len,JUMP,'-','-',end); //產(chǎn)生跳轉地址的四元式 </p><p> if(cur.type==$ELSE)</p><p><b> {</b></p><p> backpath(falseadd,quad_len);</p
123、><p> sentence();</p><p> backpath(end,quad_len); </p><p><b> }</b></p><p><b> else</b></p><p> ERROR("S(else)");}<
124、;/p><p><b> else</b></p><p><b> {</b></p><p> ERROR("S(then)");}} </p><p><b> else</b></p><p> ERROR("
125、;S(if)");</p><p> AD_RESULT(quad_len,END,0,0,'-'); //產(chǎn)生數(shù)值語句的四元式}</p><p><b> //讀下一單詞</b></p><p> bool nexttoken()</p><p><b> {</b&g
126、t;</p><p> if(token_index>=total_len)</p><p> return false;</p><p> if(tokentable[token_index].type==$fenhao)</p><p> token_index++;</p><p> cur.ty
127、pe=tokentable[token_index].type;</p><p> cur.ch=tokentable[token_index].ch;</p><p> token_index++;</p><p> return true;}</p><p><b> //進隊列</b></p>
128、<p> void push()</p><p><b> { one=0;</b></p><p> while(tokentable[token_index].type!=$fenhao)</p><p><b> {</b></p><p> queue[one].typ
129、e=tokentable[token_index].type;</p><p> queue[one].ch=tokentable[token_index].ch;</p><p> cout<<queue[one].ch;</p><p> token_index++;</p><p><b> one++;&
溫馨提示
- 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 編譯原理課程設計--c語言編譯器實現(xiàn)
- 編譯原理課程設計--c語言編譯器實現(xiàn)
- c語言編譯器實現(xiàn)-編譯原理課程設計
- 編譯原理課程設計____c語言編譯器的實現(xiàn)-
- 編譯原理課程設計---c語言編譯器的實現(xiàn)
- 編譯原理課程設計--編譯器
- 編譯原理課程設計___c語言編譯器的實現(xiàn)畢業(yè)論文
- 編譯原理課程設計報告_編譯器
- 編譯原理課程設計---編譯器的實現(xiàn)
- 小型c語言編譯器設計
- 編譯原理課程設計---s語言的編譯器的設計與實現(xiàn)
- 編譯原理課程設計報告--編譯器實現(xiàn)
- 編譯原理課程設計報告---編譯器功能的實現(xiàn)
- 編譯原理課程設計---簡單編譯器的設計與實現(xiàn)
- 編譯原理課程設計---小型程序設計語言編譯器的設計與實現(xiàn)
- c語言編譯器前端的設計與實現(xiàn)課程設計
- C語言安全編譯器研究.pdf
- 編譯原理課程設計-pl_0編譯器及其擴充
- 編譯原理課程設計報告(一個完整的編譯器)
- 編譯原理課程設計報告--pl0編譯器的擴充
評論
0/150
提交評論