2023年PL語言編譯器分析實驗報告_第1頁
2023年PL語言編譯器分析實驗報告_第2頁
2023年PL語言編譯器分析實驗報告_第3頁
2023年PL語言編譯器分析實驗報告_第4頁
2023年PL語言編譯器分析實驗報告_第5頁
已閱讀5頁,還剩3頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

PL/0語言編譯器分析實驗一、實驗目的通過閱讀與解析一個實際編譯器(PL/0語言編譯器)的源代碼,加深對編譯階段(涉及詞法分析、語法分析、語義分析、中間代碼生成等)和編譯系統軟件結構的理解,并達成提高學生學習愛好的目的。二、實驗規定(1)規定掌握基本的程序設計技巧(C語言)和閱讀較大規模程序源代碼的能力;(2)理解并掌握編譯過程的邏輯階段及各邏輯階段的功能;(3)規定能把握整個系統(PL/0語言編譯器)的體系結構,各功能模塊的功能,各模塊之間的接口;(4)規定能總結出實現編譯過程各邏輯階段功能采用的具體算法與技三、實驗報告pl/0語言是pascal語言的一個子集,我們這里分析的pl/0的編譯程序涉及了對pl/0語言源程序進行分析解決、編譯生成類pcode代碼,并在虛擬機上解釋運營生成的類pcode代碼的功能。pl/0語言編譯程序采用以語法分析為核心、一遍掃描的編譯方法。詞法分析和代碼生成作為獨立的子程序供語法分析程序調用。語法分析的同時,提供了犯錯報告和犯錯恢復的功能。在源程序沒有錯誤編譯通過的情況下,調用類pcode解釋程序解釋執行生成的類pcode代碼。詞法分析子程序分析:詞法分析子程序名為getsym,功能是從源程序中讀出一個單詞符號(token),把它的信息放入全局變量sym、id和num中,語法分析器需要單詞時,直接從這三個變量中獲得。(注意!語法分析器每次用完這三個變量的值就立即調用getsym子程序獲取新的單詞供下一次使用。而不是在需要新單詞時才調用getsym過程。)getsym過程通過反復調用getch子過程從源程序過獲取字符,并把它們拼成單詞。getch過程中使用了行緩沖區技術以提高程序運營效率。詞法分析器的分析過程:調用getsym時,它通過getch過程從源程序中獲得一個字符。假如這個字符是字母,則繼續獲取字符或數字,最終可以拼成一個單詞,查保存字表,假如查到為保存字,則把sym變量賦成相應的保存字類型值;假如沒有查到,則這個單詞應是一個用戶自定義的標記符(也許是變量名、常量名或是過程的名字),把sym置為ident,把這個單詞存入id變量。查保存字表時使用了二分法查找以提高效率。假如getch獲得的字符是數字,則繼續用getch獲取數字,并把它們拼成一個整數,然后把sym置為number,并把拼成的數值放入num變量。假如辨認出其它合法的符號(比如:賦值號、大于號、小于等于號等),則把sym則成相應的類型。假如碰到不合法的字符,把sym置成nul。語法分析子程序分析:語法分析子程序采用了自頂向下的遞歸子程序法,語法分析同時也根據程序的語意生成相應的代碼,并提供了犯錯解決的機制。語法分析重要由分程序分析過程(block)、常量定義分析過程(constdeclaration)、變量定義分析過程(vardeclaration)、語句分析過程(statement)、表達式解決過程(expression)、項解決過程(term)、因子解決過程(factor)和條件解決過程(condition)構成。這些過程在結構上構成一個嵌套的層次結構。除此之外,尚有犯錯報告過程(error)、代碼生成過程(gen)、測試單詞合法性及犯錯恢復過程(test)、登錄名字表過程(enter)、查詢名字表函數(position)以及列出類pcode代碼過程(listcode)作過語法分析的輔助過程。由pl/0的語法圖可知:一個完整的pl/0程序是由分程序和句號構成的。因此,本編譯程序在運營的時候,通過主程序中調用分程序解決過程block來分析分程序部分(分程序分析過程中還也許會遞歸調用block過程),然后,判斷最后讀入的符號是否為句號。假如是句號且分程序分析中未犯錯,則是一個合法的pl/0程序,可以運營生成的代碼,否則就說明源pl/0程序是不合法的,輸出犯錯提醒即可。語法單元分析:1、分程序解決過程:語法分析開始后,一方面調用分程序解決過程(block)解決分程序。過程入口參數置為:0層、符號表位置0、犯錯恢復單詞集合為句號、聲明符或語句開始符。進入block過程后,一方面把局部數據段分派指針設為3,準備分派3個單元供運營期存放靜態鏈sl、動態鏈dl和返回地址ra。然后用tx0記錄下當前符號表位置并產生一條jmp指令,準備跳轉到主程序的開始位置,由于當前還沒有知到主程序究竟在何處開始,所以jmp的目的暫時填為0,稍后再改。同時在符號表的當前位置記錄下這個jmp指令在代碼段中的位置。在判斷了嵌套層數沒有超過規定的層數后,開始分析源程序。一方面判斷是否碰到了常量聲明,假如碰到則開始常量定義,把常量存入符號表。接下去用同樣的方法分析變量聲明,變量定義過程中會用dx變量記錄下局部數據段分派的空間個數。然后假如碰到procedure保存字則進行過程聲明和定義,聲明的方法是把過程的名字和所在的層次記入符號表,過程定義的方法就是通過遞歸調用block過程,由于每個過程都是一個分程序。由于這是分程序中的分程序,因此調用block時需把當前的層次號lev加一傳遞給block過程。分程序聲明部分完畢后,即將進入語句的解決,這時的代碼分派指針cx的值正好指向語句的開始位置,這個位置正是前面的jmp指令需要跳轉到的位置。于是通過前面記錄下來的地址值,把這個jmp指令的跳轉位置改成當前cx的位置。并在符號表中記錄下當前的代碼段分派地址和局部數據段要分派的大小(dx的值)。生成一條int指令,分派dx個空間,作為這個分程序段的第一條指令。下面就調用語句解決過程statement分析語句。分析完畢后,生成操作數為0的opr指令,用于從分程序返回(對于0層的主程序來說,就是程序運營完畢,退出)。2、常量定義過程:通過循環,反復獲得標記符和相應的值,存入符號表。符號表中記錄下標記符的名字和它相應的值。3、變量定義過程:與常量定義類似,通過循環,反復獲得標記符,存入符號表。符號表中記錄下標記符的名字、它所在的層及它在所在層中的偏移地址。4、語句解決過程:語句解決過程是一個嵌套子程序,通過調用表達式解決、項解決、因子解決等過程及遞歸調用自己來實現對語句的分析。語句解決過程可以辨認的語句涉及賦值語句、read語句、write語句、call語句、if語句、while語句。當碰到begin/end語句時,就遞歸調用自己來分析。分析的同時生成相應的類pcode指令。5、賦值語句的解決:一方面獲取賦值號左邊的標記符,從符號表中找到它的信息,并確認這個標記符確為變量名。然后通過調用表達式解決過程算得賦值號右部的表達式的值并生成相應的指令保證這個值放在運營期的數據棧頂。最后通過前面查到的左部變量的位置信息,生成相應的sto指令,把棧頂值存入指定的變量的空間,實現了賦值操作。6、read語句的解決:擬定read語句語法合理的前提下(否則報錯),生成相應的指令:第一條是16號操作的opr指令,實現從標準輸入設備上讀一個整數值,放在數據棧頂。第二條是sto指令,把棧頂的值存入read語句括號中的變量所在的單元。7、write語句的解決:與read語句相似。在語法對的的前提下,生成指令:通過循環調用表達式解決過程分析write語句括號中的每一個表達式,生成相應指令保證把表達式的值算出并放到數據棧頂并生成14號操作的opr指令,輸出表達式的值。最后生成15號操作的opr指令輸出一個換行。8、call語句的解決:從符號表中找到call語句右部的標記符,獲得其所在層次和偏移地址。然后生成相應的cal指令。至于調用子過程所需的保護現場等工作是由類pcode解釋程序在解釋執行cal指令時自動完畢的。9、if語句的解決:按if語句的語法,一方面調用邏輯表達式解決過程解決if語句的條件,把相應的真假值放到數據棧頂。接下去記錄下代碼段分派位置(即下面生成的jpc指令的位置),然后生成條件轉移jpc指令(遇0或遇假轉移),轉移地址未知暫時填0。然后調用語句解決過程解決then語句后面的語句或語句塊。then后的語句解決完后,當前代碼段分派指針的位置就應當是上面的jpc指令的轉移位置。通過前面記錄下的jpc指令的位置,把它的跳轉位置改成當前的代碼段指針位置。10、begin/end語句的解決:通過循環遍歷begin/end語句塊中的每一個語句,通過遞歸調用語句分析過程分析并生成相應代碼。11、while語句的解決:一方面用cx1變量記下當前代碼段分派位置,作為循環的開始位置。然后解決while語句中的條件表達式生成相應代碼把結果放在數據棧頂,再用cx2變量記下當前位置,生成條件轉移指令,轉移位置未知,填0。通過遞歸調用語句分析過程分析do語句后的語句或語句塊并生成相應代碼。最后生成一條無條件跳轉指令jmp,跳轉到cx1所指位置,并把cx2所指的條件跳轉指令的跳轉位置改成當前代碼段分派位置。12、表達式、項、因子解決:根據pl/0語法可知,表達式應當是由正負號或無符號開頭、由若干個項以加減號連接而成。而項是由若干個因子以乘除號連接而成,因子則也許是一個標記符或一個數字,或是一個以括號括起來的子表達式。根據這樣的結構,構造出相應的過程,遞歸調用就完畢了表達式的解決。把項和因子獨立開解決解決了加減號與乘除號的優先級問題。在這幾個過程的反復調用中,始終傳遞fsys變量的值,保證可以在犯錯的情況下跳過犯錯的符號,使分析過程得以進行下去。13、邏輯表達式的解決:一方面判斷是否為一元邏輯表達式:判奇偶。假如是,則通過調用表達式解決過程分析計算表達式的值,然后生成判奇指令。假如不是,則肯定是二元邏輯運算符,通過調用表達式解決過程依次分析運算符左右兩部分的值,放在棧頂的兩個空間中,然后依不同的邏輯運算符,生成相應的邏輯判斷指令,放入代碼段。14、判斷單詞合法性與犯錯恢復過程分析:本過程有三個參數,s1、s2為兩個符號集合,n為犯錯代碼。本過程的功能是:測試當前符號(即sym變量中的值)是否在s1集合中,假如不在,就通過調用犯錯報告過程輸出犯錯代碼n,并放棄當前符號,通過詞法分析過程獲取一下單詞,直到這個單詞出現在s1或s2集合中為止。這個過程在實際使用中很靈活,重要有兩個用法:在進入某個語法單位時,調用本過程,檢查當前符號是否屬于該語法單位的開始符號集合。若不屬于,則濾去開始符號和后繼符號集合外的所有符號。在語法單位分析結束時,調用本過程,檢查當前符號是否屬于調用該語法單位時應有的后繼符號集合。若不屬于,則濾去后繼符號和開始符號集合外的所有符號。通過這樣的機制,可以在源程序出現錯誤時,及時跳過犯錯的部分,保證語法分析可以繼續下去。15、類pcode代碼解釋執行過程分析:這個過程模擬了一臺可以運營類pcode指令的棧式計算機。它擁有一個棧式數據段用于存放運營期數據、擁有一個代碼段用于存放類pcode程序代碼。同時還擁用數據段分派指針、指令指針、指令寄存器、局部段基址指針等寄存器。16、解釋執行類pcode代碼時,數據段存儲分派方式:對于源程序的每一個過程(涉及主程序),在被調用時,一方面在數據段中開辟三個空間,存放靜態鏈sl、動態鏈dl和返回地址ra。靜態鏈記錄了定義該過程的直接外過程(或主程序)運營時最新數據段的基地址。動態鏈記錄調用該過程前正在運營的過程的數據段基址。返回地址記錄了調用該過程時程序運營的斷點位置。對于主程序來說,sl、dl和ra的值均置為0。靜態鏈的功能是在一個子過程要引用它的直接或間接父過程(這里的父過程是按定義過程時的嵌套情況來定的,而不是按執行時的調用順序定的)的變量時,可以通過靜態鏈,跳過個數為層差的數據段,找到包含要引用的變量所在的數據段基址,然后通過偏移地址訪問它。在過程返回時,解釋程序通過返回地址恢復指令指針的值到調用前的地址,通

溫馨提示

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

評論

0/150

提交評論