plo簡介
此外,PL0還具有子程式概念,包括過程說明和過程調用語句。在
數據類型方面,PL0隻包含唯一的
整型,可以說明這種類型的
常量和
變數。運算符有+,-,*,/,=,<>,<,>,<=,>=,(,)。說明部分包括
常量說明、
變數說明和過程說明。
文法規則
<程式>::=<分程式>. <分程式>::=[<常量說明部分);][<變數說明部分>;]{<過程說明部分>;}<語句部分> <常量說明部分>::=const<常量定義>{,<常量定義>} <常量定義>::=<標識符>=<無符號整數> <無符號整數>::=<數字>{<數字>} <變數說明部分>::=var<標識符>{<標識符>} <標識符>::=<字母>{<字母>|<數字>} <過程說明部分>::=<過程首部><分程式>
<過程首部>::=procedure<標識符>
<語句部分>::=<語句>|<複合語句>
<複合語句>::=begin<語句>{;<語句>}end
<語句>::=<賦值語句>|<條件語句>|<當型循環語句>|<過程調用語句>|
<讀語句>|<寫語句>|<複合語句>|<空語句> <賦值語句>::=<標識符>:=<表達式> <條件>::=<表達式><關係運算符><表達式>|odd<表達式> <表達式>::=[+|-]<項>|<表達式><加法運算符><項>
<項>::=<因子>|<項><乘法運算符><因子>
<因子>::=<標識符>|<常量>|(<表達式>)
<常量>::=<無符號整數>
<加法運算符>::=+|-
<乘法運算符>::=*|/
<關係運算符>::=<|>|<>|>=|<=|=
<條條件語句>::=if<條件>then<語句>
<過程調用語句>::=call<標識符>
<當型循環語句>::=while<條件>do<語句>
<讀語句>::=read(<標識符>{,<標識符>})
<寫語句>::=write(<表達式>{,<表達式>})
<字母>::=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|z
設計思想
編譯程式的設計可以採用自頂向下和自底向上兩種不同的方法。由於許多高級語言(如PASCAL,C)中的語法成分都是
遞歸定義的,PL0也是如此,所以本實驗採用遞歸子程式法,這是一種自頂向下的的編譯方法,其基本思想是對
源程式的每個(或若干個)語法成分編制一個處理子程式,從處理<程式>這個語法成分的子程式開始,在分析過程中調用一系列過程或函式,對源程式進行語法和
語義分析,直到整個源程式處理完畢為止。
我們給出用PASCAL語言編寫的PL0的
編譯程式,要求學生先讀懂它,然後再用自己熟悉的高級語言改寫它,能力強的同學可以按照所學知識,自行設計實現方案。
編譯程式的功能
(1)
語法分析 對由PL/0語言編制的程式作語法分析,確定是否屬於PL/0語言,同時揭示出程式的內在結構。
(2)語法錯誤檢查 根據PL/0語言的文法規則設定檢測手段,通過查錯子程式和一些查錯語句,報告
源程式出錯位置、性質等,直至整個程式結束為止。 (3)生成
目標代碼 PL/0語言的目標代碼是建立在一個假想的
處理機上,此處理機稱為PL/0處理機。 (4)執行
目標代碼 PL/0
處理機是一種假想的處理機,其目標代碼不能在實際的機器上執行,故此
編譯程式設定了一個子程式,它對PL/0語言的目標代碼逐條
解釋執行,最後得出所需結果。
過程及函式
在PL/0語言的編譯文本中,除了
常量和
變數說明外,共有18個相互嵌套或並列的過程(或函式)。現對這些過程和函式作扼要說明。
(1)error(n):其功能是報告PL/0
源程式的出錯信息。n為錯誤類型號,共可查出36種錯誤。
(3)gen(x,y,z),
偽代碼生成
子程式。其功能是根據不同的x、y、z生成不同的
偽代碼。x表示指令碼,y表示層差,z表示位移量或數。
(4)test(sl,s2,n):查錯
子程式。其功能是檢測源程式中的語法錯誤。s1為可允許的下一個符號的集合。如當前符號不在此集合內,立即得到了一個錯誤。s2為另加的停止符號集,這些符號的出現雖然無疑是錯的,但是它們絕不應被忽略而跳過。n表示錯誤的類型號。
(5)block(1ev,tx,fsys):分程式處理模組。其功能為對分程式進行處理。lev
表示層差,tx表示標識符表的下標,fsys是符號集,表示可能出現的符號。
分程式處理模組是整個
編譯程式的核心,它包含以下的過程和函式。
①enter(k):其功能是造
符號表table。k表示符號的類型,其取值範圍是(constant, variable,proceable),即此
子程式對
常量、
變數和過程造
符號表table,以備檢查標識符是否說明過。
②position(id):其功能是查
符號表,它是一個函式。 id是所檢查的
標識符,若查到則給出標識符id在標識符表中的位置,否則給0。
③constdeclaration:常量造表子程式。其功能是為常量造一張常量表,內填常量名、常量值。它通過調用子程式enter(k)完成,此時k=constant。
④vardeclaration:
變數造表子程式。其功能是為
變數造一張變數表,內填變數名、所處層號。它也是通過調用子程式enter(k)來完成的,此時k=variable。
⑤listcode,列印(偽)代碼
子程式。其功能是輸出生成的
目標代碼。
⑥statement(fsys):語句處理
子程式。其功能是處理語句,它是
遞歸調用的核心部分。其
遞歸調用順序如下:
expression(fsys):處理
算術表達式子程式;
term(fsys):處理項子程式;
condition(fsys):處理因子子程式。
base(l):提供計算靜態鏈信息
子程式。它為過程調用提供調用所需的基地址。
整個PL/0
編譯程式通過主程式調用分程式處理模組block,再通過block
遞歸調用上述的子程式,達到對PL/0語言的程式進行編譯的目的。
編譯步驟
程式中用
數組word存貯PL/0語言的所有保留字。保留字有begin、call、const、do、end、if、odd、procedure、read、then、var、while、write;
用
數組swym存貯保留字所對應的
符號表symbol中的符號;
用
數組ssym存貯
關係運算符及特殊符號+、-、*、/、(、)、=、,、<、>及;所對應的
符號表symbol中的符號;
其具體步驟如下:
①在主程式中給出
編譯程式所需的初始值。置字元字數cc、行長ll、代碼分配下標cx、錯誤個數err等為0。調getsym讀單詞;
②調block模組,進入分程式處理;
③判斷所讀單詞是否為常量說明符號constsym,是則轉4),否則轉5)。
④讀單詞並作常量說明處理;查所讀單詞是否為“,”,是則重複本步;否則判斷此單詞是否為“;”,是則讀單詞,否則給出出錯信息。進行下一步;
⑤所讀單詞是否為
變數說明符號variable,是則讀單詞並作變數說明處理,再讀單詞並判斷是否為“,”,是則重複本步;否則判斷此單詞是否為“;”,是則讀單詞,否則給出出錯信息。進行下一步;
⑥cxl:=cx,並生成jmp 0,0指令,判斷所讀單詞是否為過程說明符號proceduresym,是則讀單詞轉7),否則轉11);
⑦判斷所讀單詞是否為標識符,是則轉8),否則給出出錯信息再進行下一步;
⑧標識符填表,再讀單詞。判斷所讀單詞是否為“;”,是則讀單詞,否則給出出錯信息。進行下一步;
⑩最近所讀單詞是否為“;”,是則繼續讀一單詞,否則給出出錯信息。轉6);
⑾code[cxl].a:=cx,生成分配
局部變數指令,語句處理,生成opr 0,0指令;
⑿返回主程式,err是否為0,是則調子程式interpret,轉13),否則給出出錯信息,結束編譯;
⒀解釋執行生成的目標代碼,列出結果
編程注意事項
PL/0語言可以看成PASCAL語言的子集,它的
編譯程式是一個編譯
解釋執行系統。PL/0的
目標程式為假想棧式計算機的彙編語言,與具體計算機無關。
PL/0的
編譯程式和
目標程式的
解釋執行程式都是用PASCAL語言書寫的,因此PL/0語言可在配備PASCAL語言的任何機器上實現 。其編譯過程採用一趟
掃描方式,以
語法分析程式為核心,
詞法分析和
代碼生成程式都作為一個獨立的過程,當語法分析需要讀單詞時就調用詞法分析程式,而當語法分析正確需要生成相應的
目標代碼時,則調用代碼生成程式。
用表格管理程式建立
變數、
常量和過程表示符的說明與引用之間的信息聯繫。