编译概述与引论
本博文中,介紹編譯程序的基本概念,概述編譯過(guò)程和編譯程序結(jié)構(gòu),編譯程序和程序設(shè)計(jì)環(huán)境以及編譯程序的生成過(guò)程和構(gòu)造工具知識(shí)。
什么叫編譯程序
通常,我們所說(shuō)的翻譯程序是指這樣的一個(gè)程序,它能夠把某一種語(yǔ)言程序(稱為源語(yǔ)言程序)轉(zhuǎn)換成另一種語(yǔ)言程序(稱為目標(biāo)語(yǔ)言程序),而后者與前者在邏輯上是等價(jià)的。如果源語(yǔ)言是諸如FORTRAN、Pascal、C、Ada、Smalltalk或Java這樣的“高級(jí)語(yǔ)言”,而目標(biāo)語(yǔ)言是諸如匯編語(yǔ)言或機(jī)器語(yǔ)言之類的“低級(jí)語(yǔ)言”,這樣的一個(gè)翻譯程序就稱為編譯程序。
高級(jí)語(yǔ)言程序除了像上面所說(shuō)的先編譯后執(zhí)行外,有時(shí)也可“解釋”執(zhí)行。一個(gè)源語(yǔ)言的解釋程序是這樣的程序,它以該語(yǔ)言寫(xiě)的源程序作為輸入,但不產(chǎn)生目標(biāo)程序,而是邊解釋邊執(zhí)行源程序本身。實(shí)際上,許多編譯程序的構(gòu)造與實(shí)現(xiàn)技術(shù)同樣適用于解釋程序。
根據(jù)不同的用途和側(cè)重,編譯程序還可進(jìn)一步分類。專門(mén)用于幫助程序開(kāi)發(fā)和調(diào)試的編譯程序稱為診斷編譯程序(Diagnostic Compiler),著重于提高目標(biāo)代碼效率的編譯程序叫優(yōu)化編譯程序(Optimizing Compiler)。現(xiàn)在很多編譯程序同時(shí)提供了調(diào)試、優(yōu)化等多種功能,用戶可以通過(guò)“開(kāi)關(guān)”進(jìn)行選擇。運(yùn)行編譯程序的計(jì)算機(jī)稱宿主機(jī),運(yùn)行編譯程序所產(chǎn)生目標(biāo)代碼的計(jì)算機(jī)稱目標(biāo)機(jī)。如果一個(gè)編譯程序產(chǎn)生不同于其宿主機(jī)的機(jī)器代碼,則稱它為交叉編譯程序(Cross Compiler)。如果不需重寫(xiě)編譯程序中與機(jī)器無(wú)關(guān)的部分就能改變目標(biāo)機(jī),則稱該編譯程序?yàn)?font color="#DC143C">可變目標(biāo)編譯程序(Retargetable Compiler)。
世界上第一個(gè)編譯程序—FORTRAN編譯程序是20世紀(jì)50年代中期研制成功的。當(dāng)時(shí),人們普遍認(rèn)為設(shè)計(jì)和實(shí)現(xiàn)編譯程序是一件十分困難、令人生畏的事情。經(jīng)過(guò)40年的努力,編譯理論與技術(shù)得到迅速發(fā)展,到目前為止,現(xiàn)在已形成了一套比較成熟的、系統(tǒng)化的理論與方法,并且開(kāi)發(fā)出了一些好的編譯程序的實(shí)現(xiàn)語(yǔ)言、環(huán)境與工具。在此基礎(chǔ)上設(shè)計(jì)并實(shí)現(xiàn)一個(gè)編譯程序不再是高不可攀的事情。
編譯過(guò)程概述
編譯程序的工作,從輸入源程序開(kāi)始到輸出目標(biāo)程序?yàn)橹沟恼麄€(gè)過(guò)程,是非常復(fù)雜的。但就其過(guò)程而言,它與人們進(jìn)行自然語(yǔ)言之間的翻譯有許多相近之處。當(dāng)我們把一種文字翻譯為另一種文字,例如把一段英文翻譯為中文時(shí),通常需經(jīng)下列步驟:
類似地,編譯程序的工作過(guò)程一般也可以劃分為五個(gè)階段:詞法分析、語(yǔ)法分析、語(yǔ)義分析及中間代碼生成、優(yōu)化、目標(biāo)代碼生成。
第一階段,詞法分析。 詞法分析的任務(wù)是:輸入源程序,對(duì)構(gòu)成源程序的字符串進(jìn)行掃描和分解,識(shí)別出一個(gè)個(gè)的單詞(亦稱單詞符號(hào)或簡(jiǎn)稱符號(hào)),如基本字(begin、end、if、for、while等),標(biāo)識(shí)符、常數(shù)、算符和界符(標(biāo)點(diǎn)符號(hào)、左右括號(hào)等等)。單詞符號(hào)是語(yǔ)言的基本組成成分,是人們理解和編寫(xiě)程序的基本要素。識(shí)別和理解這些要素?zé)o疑也是翻譯的基礎(chǔ)。如同將英文翻譯成中文的情形一樣,如果你對(duì)英語(yǔ)單詞不理解,那就談不上進(jìn)行正確的翻譯。在詞法分析階段的工作中所依循的是語(yǔ)言的詞法規(guī)則(或稱構(gòu)詞規(guī)則)。描述詞法規(guī)則的有效工具是正規(guī)式和有限自動(dòng)機(jī)。
第二階段,語(yǔ)法分析。 語(yǔ)法分析的任務(wù)是:在詞法分析的基礎(chǔ)上,根據(jù)語(yǔ)言的語(yǔ)法規(guī)則,把單詞符號(hào)串分解成各類語(yǔ)法單位(語(yǔ)法范疇),如“短語(yǔ)”、“子句”、“句子”(“語(yǔ)句”)、“程序段”和“程序”等。通過(guò)語(yǔ)法分析,確定整個(gè)輸入串是否構(gòu)成語(yǔ)法上正確的“程序”。語(yǔ)法分析所依循的是語(yǔ)言的語(yǔ)法規(guī)則。語(yǔ)法規(guī)則通常用上下文無(wú)關(guān)文法描述。詞法分析是一種線性分析,而語(yǔ)法分析是一種層次結(jié)構(gòu)分析。
第三階段,語(yǔ)義分析與中間代碼產(chǎn)生。 這一階段的任務(wù)是:對(duì)語(yǔ)法分析所識(shí)別出的各類語(yǔ)法范疇,分析其含義,并進(jìn)行初步翻譯(產(chǎn)生中間代碼)。這一階段通常包括兩個(gè)方面的工作。首先,對(duì)每種語(yǔ)法范疇進(jìn)行靜態(tài)語(yǔ)義檢查,例如,變量是否定義、類型是否正確等等。如果語(yǔ)義正確,則進(jìn)行另一方面工作,即進(jìn)行中間代碼的翻譯。這一階段所依循的是語(yǔ)言的語(yǔ)義規(guī)則。通常使用屬性文法描述語(yǔ)義規(guī)則。
“翻譯”僅僅在這里才開(kāi)始涉及到。所謂“中間代碼”是一種含義明確、便于處理的記號(hào)系統(tǒng),它通常獨(dú)立于具體的硬件。這種記號(hào)系統(tǒng)或者與現(xiàn)代計(jì)算機(jī)的指令形式有某種程度的接近,或者能夠比較容易地把它變換成現(xiàn)代計(jì)算機(jī)的機(jī)器指令。一般而言,中間代碼是一種獨(dú)立于具體硬件的記號(hào)系統(tǒng)。常用的中間代碼,除了四元式之外,還有三元式、間接三元式、逆波蘭記號(hào)和樹(shù)形表示等等。
第四階段,優(yōu)化。 優(yōu)化的任務(wù)在于對(duì)前段產(chǎn)生的中間代碼進(jìn)行加工變換,以期在最后階段能產(chǎn)生出更為高效(省時(shí)間和空間)的目標(biāo)代碼。優(yōu)化的主要方面有:公共子表達(dá)式的提取、循環(huán)優(yōu)化、刪除無(wú)用代碼等等。有時(shí),為了便于“并行運(yùn)算”,還可以對(duì)代碼進(jìn)行并行化處理。優(yōu)化所依循的原則是程序的等價(jià)變換規(guī)則。
第五階段,目標(biāo)代碼生成。這一階段的的任務(wù)是:把中間代碼(或經(jīng)優(yōu)化處理之后)變換成特定機(jī)器上的低級(jí)語(yǔ)言代碼。這階段實(shí)現(xiàn)了最后的翻譯,它的工作有賴于硬件系統(tǒng)結(jié)構(gòu)和機(jī)器指令含義。這階段工作非常復(fù)雜,涉及到硬件系統(tǒng)功能部件的運(yùn)用,機(jī)器指令的選擇,各種數(shù)據(jù)類型變量的存儲(chǔ)空間分配,以及寄存器和后援寄存器的調(diào)度,等等。如何產(chǎn)生出足以充分發(fā)揮硬件效率的目標(biāo)代碼是一件非常不容易的事情。
目標(biāo)代碼的形式可以是絕對(duì)指令代碼或可重定位的指令代碼或匯編指令代碼。如目標(biāo)代碼是絕對(duì)指令代碼,則這種目標(biāo)代碼可立即執(zhí)行。如果目標(biāo)代碼是匯編指令代碼,則需匯編器匯編之后才能運(yùn)行。必須指出,現(xiàn)代多數(shù)實(shí)用編譯程序所產(chǎn)生的目標(biāo)代碼都是一種可重定位的指令代碼。這種目標(biāo)代碼在運(yùn)行前必須借助于一個(gè)連接裝配程序把各個(gè)目標(biāo)模塊(包括系統(tǒng)提供的庫(kù)模塊)連接在一起,確定程序變量(或常數(shù))在主存中的位置,裝入內(nèi)存中指定的起始地址,使之成為一個(gè)可以運(yùn)行的絕對(duì)指令代碼程序。
上述編譯過(guò)程的五個(gè)階段是一種典型的分法。事實(shí)上,并非所有編譯程序都分成這五階段。有些編譯程序?qū)?yōu)化沒(méi)有什么要求,優(yōu)化階段就可省去。在某些情況下,為了加快編譯速度,中間代碼生成階段也可以去掉。有些最簡(jiǎn)單的編譯程序是在語(yǔ)法分析的同時(shí)產(chǎn)生目標(biāo)代碼。但是,多數(shù)實(shí)用編譯程序的工作過(guò)程大致都像上面所說(shuō)的那五個(gè)階段。
編譯程序的結(jié)構(gòu)
編譯程序總框
上述編譯過(guò)程的五個(gè)階段是編譯程序工作時(shí)的動(dòng)態(tài)特征。編譯程序的結(jié)構(gòu)可以按照這五階段的任務(wù)分模塊進(jìn)行設(shè)計(jì)。
詞法分析器,又稱掃描器,輸入源程序,進(jìn)行詞法分析,輸出單詞符號(hào)。
語(yǔ)法分析器,簡(jiǎn)稱分析器,對(duì)單詞符號(hào)串進(jìn)行語(yǔ)法分析(根據(jù)語(yǔ)法規(guī)則進(jìn)行推導(dǎo)或歸約),識(shí)別出各類語(yǔ)法單位,最終判斷輸入串是否構(gòu)成語(yǔ)法上正確的“程序”。
語(yǔ)義分析及中間代碼產(chǎn)生器,按照語(yǔ)義規(guī)則對(duì)語(yǔ)法分析器歸約出(或推導(dǎo)出)的語(yǔ)法單位進(jìn)行語(yǔ)義分析并把它們翻譯成一定形式的中間代碼。有的編譯程序在識(shí)別出各類語(yǔ)法單位后,構(gòu)造并輸出一棵表示語(yǔ)法結(jié)構(gòu)的語(yǔ)法樹(shù),然后,根據(jù)語(yǔ)法樹(shù)進(jìn)行語(yǔ)義分析和中間代碼產(chǎn)生。還有許多編譯程序在識(shí)別出語(yǔ)法單位后并不真正構(gòu)造語(yǔ)法樹(shù),而是調(diào)用相應(yīng)的語(yǔ)義子程序。在這種編譯程序中,掃描器、分析器和中間代碼生成器三者并非是截然分開(kāi)的,而是相互穿插的。
優(yōu)化器,對(duì)中間代碼進(jìn)行優(yōu)化處理。
目標(biāo)代碼生成器,把中間代碼翻譯成目標(biāo)程序。
除了上述五個(gè)功能模塊外,一個(gè)完整的編譯程序還應(yīng)包括“表格管理”和“出錯(cuò)處理”兩部分。
表格與表格管理
編譯程序在工作過(guò)程中需要保持一系列的表格,以登記源程序的各類信息和編譯各階段的進(jìn)展?fàn)顩r。合理地設(shè)計(jì)和使用表格是編譯程序構(gòu)造的一個(gè)重要問(wèn)題。在編譯程序使用的表格中,最重要的是符號(hào)表。它用來(lái)登記源程序中出現(xiàn)的每個(gè)名字以及名字的各種屬性,例如,一個(gè)名字是常量名、變量名,還是過(guò)程名等等;如果是變量名,它的類型是什么、所占內(nèi)存是多大、地址是什么等等。通常,編譯程序在處理到名字的定義性出現(xiàn)時(shí),要把名字的各種屬性填入到符號(hào)表中;當(dāng)處理到名字的使用性出現(xiàn)時(shí),要對(duì)名字的屬性進(jìn)行查證。
當(dāng)掃描器識(shí)別出一個(gè)名字(標(biāo)識(shí)符)后,它把該名字填入到符號(hào)表中。但這時(shí)不能完全確定名字的屬性,它的各種屬性要在后續(xù)的各階段才能填入。例如,名字的類型等要在語(yǔ)義分析時(shí)才能確定,而名字的地址可能要到目標(biāo)代碼生成才能確定。
由此可見(jiàn),編譯各階段都涉及到構(gòu)造、查找、或更新有關(guān)的表格。
出錯(cuò)處理
一個(gè)編譯程序不僅應(yīng)能對(duì)書(shū)寫(xiě)正確的程序進(jìn)行翻譯,而且應(yīng)能對(duì)出現(xiàn)在源程序中的錯(cuò)誤進(jìn)行處理。如果源程序有錯(cuò)誤,編譯程序應(yīng)設(shè)法發(fā)現(xiàn)錯(cuò)誤,把有關(guān)錯(cuò)誤信息報(bào)告給用戶。這部分工作是由專門(mén)的一組程序(叫做出錯(cuò)處理程序)完成的。一個(gè)好的編譯程序應(yīng)能最大限度地發(fā)現(xiàn)源程序中的各種錯(cuò)誤,準(zhǔn)確地指出錯(cuò)誤的性質(zhì)和發(fā)生錯(cuò)誤的地點(diǎn),并且能將錯(cuò)誤所造成的影響限制在盡可能小的范圍內(nèi),使得源程序的其余部分能繼續(xù)被編譯下去,以便進(jìn)一步發(fā)現(xiàn)其他可能的錯(cuò)誤。如果不僅能夠發(fā)現(xiàn)錯(cuò)誤,而且還能自動(dòng)校正錯(cuò)誤,那當(dāng)然就更好了。但是,自動(dòng)校正錯(cuò)誤的代價(jià)是非常高的。
編譯過(guò)程的每一階段都可能檢測(cè)出錯(cuò)誤,其中,絕大多數(shù)錯(cuò)誤可以在編譯的前三階段檢測(cè)出來(lái)。源程序中的錯(cuò)誤通常分為語(yǔ)法錯(cuò)誤和語(yǔ)義錯(cuò)誤兩大類。語(yǔ)法錯(cuò)誤是指源程序中不符合語(yǔ)法(或詞法)規(guī)則的錯(cuò)誤,它們可在詞法分析或語(yǔ)法分析時(shí)檢測(cè)出來(lái)。例如,詞法分析階段能夠檢測(cè)出“非法字符”之類的錯(cuò)誤;語(yǔ)法分析階段能夠檢測(cè)出諸如“括號(hào)不匹配”、“缺少 ;”之類的錯(cuò)誤。語(yǔ)義錯(cuò)誤是指源程序中不符合語(yǔ)義規(guī)則的錯(cuò)誤,這些錯(cuò)誤一般在語(yǔ)義分析時(shí)檢測(cè)出來(lái),有的語(yǔ)義錯(cuò)誤要在運(yùn)行時(shí)才能檢測(cè)出來(lái)。語(yǔ)義錯(cuò)誤通常包括:說(shuō)明錯(cuò)誤、作用域錯(cuò)誤、類型不一致等等。
遍pass
在前面己經(jīng)介紹了編譯過(guò)程的五個(gè)階段僅僅是邏輯功能上的一種劃分。具體實(shí)現(xiàn)時(shí),受不同源語(yǔ)言、設(shè)計(jì)要求、使用對(duì)象和計(jì)算機(jī)條件(如主存容量)的限制,往往將編譯程序組織為若干遍(pass)。所謂“遍”就是對(duì)源程序或源程序的中間結(jié)果從頭到尾掃描一次,并作有關(guān)的加工處理,生成新的中間結(jié)果或目標(biāo)程序。通常,每遍的工作由從外存上獲得的前一遍的中間結(jié)果開(kāi)始(對(duì)于第一遍而言,從外存上獲得源程序),完成它所含的有關(guān)工作之后,再把結(jié)果記錄于外存。既可以將幾個(gè)不同階段合為一遍,也可以把一個(gè)階段的工作分為若干遍。例如,詞法分析這一階段可以單獨(dú)作為一遍,但更多的時(shí)候是把它與語(yǔ)法分析合并為一遍;為了便于處理,語(yǔ)法分析和語(yǔ)義分析及中間代碼生成又常常合為一遍。在優(yōu)化要求很高時(shí),往往還可把優(yōu)化階段分為若干遍來(lái)實(shí)現(xiàn)。
當(dāng)一遍中包含若干階段時(shí),各階段的工作是穿插進(jìn)行的。例如,我們可以把詞法分析、語(yǔ)法分析及語(yǔ)義分析與中間代碼生成這三階段安排成一遍。這時(shí),語(yǔ)法分析器處于核心位置,當(dāng)它在識(shí)別語(yǔ)法結(jié)構(gòu)而需要下一單詞符號(hào)時(shí),它就調(diào)用詞法分析器,一旦識(shí)別出一個(gè)語(yǔ)法單位時(shí),它就調(diào)用中間代碼生成器,完成相應(yīng)的語(yǔ)義分析并產(chǎn)生相應(yīng)的中間代碼。
一個(gè)編譯程序究竟應(yīng)分成幾遍,如何劃分,是與源語(yǔ)言、設(shè)計(jì)要求、硬件設(shè)備等諸因素有關(guān)的,因此難于統(tǒng)一劃定。遍數(shù)多一點(diǎn)有個(gè)好處,即整個(gè)編譯程序的邏輯結(jié)構(gòu)可能清晰一點(diǎn)。但遍數(shù)多勢(shì)必增加輸入/輸出所消耗的時(shí)間。因此,在主存可能的前提下,一般還是遍數(shù)盡可能少一點(diǎn)為好。應(yīng)當(dāng)注意的是,并不是每種語(yǔ)言都可以用單遍編譯程序?qū)崿F(xiàn)。
編譯前端與后端
概念上,我們有時(shí)把編譯程序劃分為編譯前端和編譯后端。前端主要由與源語(yǔ)言有關(guān)但與目標(biāo)機(jī)無(wú)關(guān)的那些部分組成。這些部分通常包括詞法分析、語(yǔ)法分析、語(yǔ)義分析及中間代碼生成,有的代碼優(yōu)化工作也可包括在前端。后端包括編譯程序中與目標(biāo)機(jī)有關(guān)的那些部分,如與目標(biāo)機(jī)有關(guān)的代碼優(yōu)化和目標(biāo)代碼生成等。通常,后端不依賴于源語(yǔ)言而僅僅依賴于中間語(yǔ)言。
可以取編譯程序的前端,改寫(xiě)其后端以生成不同目標(biāo)機(jī)上的相同語(yǔ)言的編譯程序。如果后端的設(shè)計(jì)是經(jīng)過(guò)精心考慮的,那么后端的改寫(xiě)將用不了太大工作量,這樣就可實(shí)現(xiàn)編譯程序的目標(biāo)機(jī)改變。也可以設(shè)想將幾種源語(yǔ)言編譯成相同的中間語(yǔ)言,然后為不同的前端配上相同的后端,這樣就可為同一臺(tái)機(jī)器生成不同語(yǔ)言的編譯程序。然而,由于不同語(yǔ)言存在某些微妙的區(qū)別,因此在這方面所取得的成果還非常有限。
為了實(shí)現(xiàn)編譯程序可改變目標(biāo)機(jī),通常需要有一種定義良好的中間語(yǔ)言支持。例如,在著名的Ada程序設(shè)計(jì)環(huán)境APSE中,使用的是一種稱為Diana的樹(shù)形結(jié)構(gòu)的中間語(yǔ)言。一個(gè)Ada源程序通過(guò)前端編譯轉(zhuǎn)換為Diana中間代碼,由編譯后端把Diana中間代碼轉(zhuǎn)換為目標(biāo)代碼。編譯前端與不同的編譯后端以Diana為界面,實(shí)現(xiàn)編譯程序的目標(biāo)機(jī)改變。
又如,在Java語(yǔ)言環(huán)境中,為了使編譯后的程序從一個(gè)平臺(tái)移到另一個(gè)平臺(tái)執(zhí)行,Java定義一種虛擬機(jī)代碼—Bytecode。只要實(shí)際使用的操作平臺(tái)上實(shí)現(xiàn)了執(zhí)行Bytecode的Java解釋器,這個(gè)操作平臺(tái)就可以執(zhí)行各種Java程序。這就是所謂Java語(yǔ)言的操作平臺(tái)無(wú)關(guān)性。
編譯程序與程序設(shè)計(jì)環(huán)境
編譯程序無(wú)疑是實(shí)現(xiàn)高級(jí)語(yǔ)言的一個(gè)最重要的工具。但支持程序設(shè)計(jì)人員進(jìn)行程序開(kāi)發(fā)通常還需要一些其他的工具;如編輯程序、連接程序,調(diào)試工具等等。編譯程序與這些程序設(shè)計(jì)工具一起構(gòu)成所謂的程序設(shè)計(jì)環(huán)境。
在高級(jí)語(yǔ)言發(fā)展的早期,這些程序設(shè)計(jì)工具往往是獨(dú)立的,缺乏整體性,而且也缺乏對(duì)軟件開(kāi)發(fā)全生命周期的支持 。隨著軟件技術(shù)的不斷發(fā)展,現(xiàn)在人們?cè)絹?lái)越傾向于構(gòu)造集成化的程序設(shè)計(jì)環(huán)境。一個(gè)集成化的程序設(shè)計(jì)環(huán)境的特點(diǎn)是,它將相互獨(dú)立的程序設(shè)計(jì)工具集成起來(lái),以便為程序員提供完整的、一體化的支持,從而進(jìn)一步提高程序開(kāi)發(fā)效率,改善程序質(zhì)量。
在一個(gè)好的集成化程序設(shè)計(jì)環(huán)境中,不僅包含豐富的程序設(shè)計(jì)工具,而且還支持程序設(shè)計(jì)方法學(xué),支持程序開(kāi)發(fā)的全生命周期。有代表性的集成化程序設(shè)計(jì)環(huán)境有Ada語(yǔ)言程序設(shè)計(jì)環(huán)境APSE、LISP語(yǔ)言程序設(shè)計(jì)環(huán)境INTERLISP等。廣大讀者所熟悉的Turbo Pascal、Turbo C、Visual C++等語(yǔ)言環(huán)境也都可認(rèn)為是集成化的程序設(shè)計(jì)環(huán)境。
在一個(gè)程序設(shè)計(jì)環(huán)境中,編譯程序起著中心的作用。連接程序、調(diào)試程序、程序分析等工具的工作直接依賴于編譯程序所產(chǎn)生的結(jié)果,而其他工具的構(gòu)造也常常要用到編譯的原理、方法和技術(shù)
編譯程序的生成
以前人們構(gòu)造編譯程序大多是用機(jī)器語(yǔ)言或匯編語(yǔ)言作工具的。為了充分發(fā)揮各種不同硬件系統(tǒng)的效率,為了滿足各種不同的具體要求,現(xiàn)在許多人仍然采用這種工具來(lái)構(gòu)造編譯程序(或編譯程序的“核心”部分)。但是,越來(lái)越多的人已經(jīng)使用高級(jí)語(yǔ)言作工具來(lái)編譯程序。因?yàn)?#xff0c;這樣可以大大節(jié)省程序設(shè)計(jì)時(shí)間,而且所構(gòu)造出來(lái)的編譯程序易于閱讀、維護(hù)和移植。
如果A機(jī)器上已有一個(gè)用A機(jī)器代碼實(shí)現(xiàn)的某高級(jí)語(yǔ)言L1的編譯程序,則我們可以用L1語(yǔ)言編寫(xiě)另一種高級(jí)L2的編譯程序,把寫(xiě)好的L2編譯程序經(jīng)過(guò)L1編譯程序編譯后就可得到A機(jī)器代碼實(shí)現(xiàn)的L2編譯程序。
采用一種所謂的“移植”方法,我們可以利用A機(jī)器上已有的高級(jí)語(yǔ)言L編寫(xiě)一個(gè)能夠在B機(jī)器上運(yùn)行的高級(jí)語(yǔ)言L的編譯程序。做法是,先用L語(yǔ)言編寫(xiě)出在A機(jī)器上運(yùn)行的產(chǎn)生B機(jī)器代碼的L編譯程序源程序,然后把該源程序經(jīng)過(guò)A機(jī)器上的L編譯程序編譯后得到能在A機(jī)器上運(yùn)行的產(chǎn)生B機(jī)器代碼的編譯程序,用這個(gè)編譯程序再一次編譯上述編譯程序源程序就得到了能在B機(jī)器上運(yùn)行的產(chǎn)生B機(jī)器代碼的編譯程序。
還可以采用“自編譯方式”產(chǎn)生編譯程序。方法是,先對(duì)語(yǔ)言的核心部分構(gòu)造一個(gè)小小的編譯程序(可用低級(jí)語(yǔ)言實(shí)現(xiàn)),再以它為工具構(gòu)造一個(gè)能夠編譯更多語(yǔ)言成分的較大編譯程序。如此擴(kuò)展下去,就像滾雪球一樣,越滾越大,最后形成人們所期望的整個(gè)編譯程序。這種通過(guò)一系列自展途徑而形成編譯程序的過(guò)程叫做自編譯過(guò)程。
現(xiàn)在人們已建立了多種編制部分編譯程序或整個(gè)編譯程序的有效工具。有些能用于自動(dòng)產(chǎn)生掃描器(如LEX),有些可用于自動(dòng)產(chǎn)生語(yǔ)法分析器(如YACC),有些甚至可用來(lái)自動(dòng)產(chǎn)生整個(gè)的編譯程序。這些構(gòu)造編譯程序的工具稱為編譯程序-編譯程序、編譯程序產(chǎn)生器或翻譯程序書(shū)寫(xiě)系統(tǒng),它們是按對(duì)源程序和目標(biāo)語(yǔ)言(或機(jī)器)的形式描述(作為輸入數(shù)據(jù))而自動(dòng)產(chǎn)生編譯程序的。
參考文獻(xiàn)及資源
總結(jié)