h5 網(wǎng)站建設(shè)網(wǎng)絡(luò)營(yíng)銷(xiāo)活動(dòng)方案
文章目錄
- 一、 設(shè)計(jì)目的及要求
- 1.1 設(shè)計(jì)目的
- 1.2 設(shè)計(jì)要求
- 1.2.1 要求一
- 1.2.2 要求二
- 1.2.3 要求三
- 二、程序設(shè)計(jì)
- 2.1 程序的組織結(jié)構(gòu)
- 2.1.1 PL/0編譯程序函數(shù)定義層次結(jié)構(gòu)
- 2.1.2 PL/0編譯程序函數(shù)過(guò)程或函數(shù)功能表
- 2.1.3 PL/0指令功能表
- 2.1.4 PL/0語(yǔ)言的出錯(cuò)信息表
- 2.2程序流程圖
- 2.2.1 PL/0編譯程序和解釋執(zhí)行過(guò)程
- 2.2.2 PL/0程序語(yǔ)法分析
- 2.2.3 else語(yǔ)句流程圖
- 2.2.4 do-while-until語(yǔ)句流程圖
- 2.2.5 for語(yǔ)句流程圖
- 2.3 目標(biāo)代碼生成模式
- 2.3.1 if-then-else
- 2.3.2 do while-until
- 2.3.3 for-to/downto-do
- 三、系統(tǒng)實(shí)現(xiàn)
- 3.1 else語(yǔ)句擴(kuò)充
- 3.2 do-while-until語(yǔ)句擴(kuò)充
- 3.3 for語(yǔ)句擴(kuò)充
- 3.3.1 downto-do-end
- 3.3.2 to-do-end
- 四、程序源代碼
- 4.1 else語(yǔ)句擴(kuò)充
- 4.2 do-while- until語(yǔ)句擴(kuò)充
- 4.3 for語(yǔ)句擴(kuò)充
- 4.3.1 “變量=初值”部分代碼
- 4.3.2 “downto-do-end”部分代碼
- 4.3.3 “to-do-end”部分代碼
- 五、系統(tǒng)測(cè)試
- 5.1 else語(yǔ)句擴(kuò)充
- 5.2 do-while-until語(yǔ)句擴(kuò)充
- 5.3 for語(yǔ)句擴(kuò)充
- 六、設(shè)計(jì)總結(jié)
- 七、致謝
- 源碼與測(cè)試用例下載
一、 設(shè)計(jì)目的及要求
1.1 設(shè)計(jì)目的
根據(jù)所學(xué)的編譯原理理論知識(shí),在符合 PL/0 語(yǔ)言基本詞法、語(yǔ)法規(guī)則的前提下,以原PL/0 編譯程序C語(yǔ)言版本代碼為基礎(chǔ),對(duì) PL/0 語(yǔ)言的功能進(jìn)行擴(kuò)充。使理論與實(shí)踐相結(jié)合,加深對(duì)編譯原理的理解。
1.2 設(shè)計(jì)要求
1.2.1 要求一
1)擴(kuò)充語(yǔ)言成份:“if 條件 then 語(yǔ)句系列1 else 語(yǔ)句系列2”。
2)寫(xiě)出相應(yīng)的編譯程序。
1.2.2 要求二
1)擴(kuò)充語(yǔ)言成份:“do while 語(yǔ)句系列 until 條件”,即循環(huán)執(zhí)行循環(huán)體內(nèi)的語(yǔ)句系列,直到條件為真為止。
2)寫(xiě)出相應(yīng)的編譯程序
1.2.3 要求三
1)擴(kuò)充語(yǔ)言成份:
①“for 變量= 初值 to 終值 do begin 語(yǔ)句系列 end”
②“for 變量= 初值 downto 終值 do begin 語(yǔ)句系列 end”
其中,語(yǔ)句①中循環(huán)變量的步長(zhǎng)為1,語(yǔ)句②中循環(huán)變量的步長(zhǎng)為-1。
2)寫(xiě)出相應(yīng)的編譯程序
二、程序設(shè)計(jì)
2.1 程序的組織結(jié)構(gòu)
2.1.1 PL/0編譯程序函數(shù)定義層次結(jié)構(gòu)
表1 層次結(jié)構(gòu)圖
2.1.2 PL/0編譯程序函數(shù)過(guò)程或函數(shù)功能表
表 2函數(shù)功能表
2.1.3 PL/0指令功能表
表 3指令功能表
2.1.4 PL/0語(yǔ)言的出錯(cuò)信息表
表 4 出錯(cuò)信息表
2.2程序流程圖
2.2.1 PL/0編譯程序和解釋執(zhí)行過(guò)程
圖 1 解釋執(zhí)行過(guò)程
2.2.2 PL/0程序語(yǔ)法分析
圖 2 語(yǔ)法分析流程圖
2.2.3 else語(yǔ)句流程圖
圖 3 else語(yǔ)句流程
表 5 else語(yǔ)句四元式序列
2.2.4 do-while-until語(yǔ)句流程圖
圖 4 do-while-until 語(yǔ)句流程
表 6 do-while-until 語(yǔ)句四元式序列
2.2.5 for語(yǔ)句流程圖
圖 5 for語(yǔ)句流程
表 7 for語(yǔ)句四元式序列
2.3 目標(biāo)代碼生成模式
2.3.1 if-then-else
2.3.2 do while-until
2.3.3 for-to/downto-do
三、系統(tǒng)實(shí)現(xiàn)
3.1 else語(yǔ)句擴(kuò)充
本部分程序首先判斷then語(yǔ)句塊的最后一個(gè)單詞是否為“;”。如果then最后一個(gè)字符是“;”,則需要跳過(guò)該符號(hào)之后再執(zhí)行else及之后的語(yǔ)句。接下來(lái)的符號(hào)是else時(shí),先記錄當(dāng)前jmp指令的位置,并為jpc指令賦值,使if為false時(shí)能直接跳轉(zhuǎn)到else語(yǔ)句之后進(jìn)行代碼執(zhí)行,然后調(diào)用函數(shù)處理else之后的語(yǔ)句,最后為jmp指令賦值,使if執(zhí)行結(jié)束時(shí)能直接跳轉(zhuǎn)到if-else結(jié)束位置。
圖 6 else語(yǔ)句執(zhí)行流程和代碼結(jié)構(gòu)
3.2 do-while-until語(yǔ)句擴(kuò)充
本部分程序首先判斷當(dāng)前符號(hào)是否為do,然后讀取下一個(gè)字符并判斷是否為while。接著記錄當(dāng)前位置,此時(shí)為while循環(huán)體開(kāi)始位置。接下來(lái),允許while后能接的字符為until,然后執(zhí)行while循環(huán)體內(nèi)的語(yǔ)句。接著判斷while的最后一個(gè)字符是否是“;”,是,則跳過(guò)該符號(hào)執(zhí)行until及之后的語(yǔ)句。當(dāng)下一個(gè)符號(hào)是until時(shí),執(zhí)行判斷語(yǔ)句。當(dāng)判斷條件為false時(shí),執(zhí)行條件跳轉(zhuǎn),跳轉(zhuǎn)到while循環(huán)體的開(kāi)始位置繼續(xù)運(yùn)行。
圖 7 do-while-until執(zhí)行流程和代碼結(jié)構(gòu)
3.3 for語(yǔ)句擴(kuò)充
首先識(shí)別當(dāng)前符號(hào)為for,然后執(zhí)行變量定位與賦值語(yǔ)句。
3.3.1 downto-do-end
識(shí)別當(dāng)前符號(hào)為downto,記錄當(dāng)前位置,即判斷當(dāng)前變量與終值大小關(guān)系的位置。將循環(huán)判斷變量取出并放到棧頂后,判斷循環(huán)變量條件并生成比較指令,判斷此戰(zhàn)頂是否大于等于棧頂,往后退兩個(gè)棧元素,結(jié)果值進(jìn)棧。再次記錄當(dāng)前位置,即do循環(huán)開(kāi)始的位置。識(shí)別當(dāng)前符號(hào)是否為do,并在成立的情況下運(yùn)行do內(nèi)循環(huán)體。然后將循環(huán)變量取出放到棧頂,再將步長(zhǎng)1取出放到棧頂,執(zhí)行指令,次棧頂減去棧頂,退兩個(gè)棧元素,結(jié)果值進(jìn)棧,最后將棧頂?shù)闹荡嫒胙h(huán)變量。這就完成了變量的自減。然后執(zhí)行無(wú)條件跳轉(zhuǎn)語(yǔ)句,跳轉(zhuǎn)到比較變量與終值大小關(guān)系的位置。最后地址回填,將jpc的目的地址賦值為do執(zhí)行完后的位置,即當(dāng)次棧頂小于棧頂時(shí),結(jié)束for循環(huán)語(yǔ)句。
圖 8 do-while-until語(yǔ)句執(zhí)行流程和代碼結(jié)構(gòu)
3.3.2 to-do-end
與上述downto-do-end基本邏輯一致,只是將判斷的大于等于改為了小于等于,將變量的自減改為了自增。
圖 9 for語(yǔ)句執(zhí)行流程和代碼流程
四、程序源代碼
4.1 else語(yǔ)句擴(kuò)充
解決對(duì)編譯程序if-else的擴(kuò)展,補(bǔ)充了代碼中缺失的else語(yǔ)句塊
//添加處理else語(yǔ)句
cx2=cx; /*記錄jmp指令的位置,執(zhí)行完then語(yǔ)句后需要無(wú)條件轉(zhuǎn)移,出發(fā)地址為cx2 */
gendo(jmp,0,0); /*執(zhí)行完if為真后,無(wú)條件轉(zhuǎn)移,將來(lái)會(huì)直接跳轉(zhuǎn)到else后 */
bool isSemi=false; //分號(hào);跳過(guò)
code[cx1]a = cx; /* 經(jīng)statement處理后,cx為else語(yǔ)句執(zhí)行開(kāi)始的位置,它正是前面未定的跳轉(zhuǎn)地址 (回填cx1的地址,即if執(zhí)行為假) 為jpc指令賦值 */
if(sym==semicolon) //如果then語(yǔ)句塊的最后一個(gè)單詞為“;”,則跳過(guò){getsymdo; //取下一個(gè)單詞 isSemi=true; //有";" }//接下來(lái)的符號(hào)是else
if(sym==elsesym) //若為else,執(zhí)行其中的語(yǔ)句{getsymdo;statementdo(fsys,ptx,lev); //處理else后的語(yǔ)句 code[cx2]a=cx; /*當(dāng)前是else后語(yǔ)句的結(jié)束位置,判斷正式結(jié)束,回填if執(zhí)行結(jié)束時(shí)的地址,為jmp指令賦值,if語(yǔ)句執(zhí)行后應(yīng)跳轉(zhuǎn)至此*/
}
//上述為添加的else語(yǔ)句處理過(guò)程
4.2 do-while- until語(yǔ)句擴(kuò)充
解決了do while until 語(yǔ)句的擴(kuò)充,在程序中添加了do while until語(yǔ)句塊。
//添加do while until 語(yǔ)句
if (sym == dosym) //此時(shí)識(shí)別的符號(hào)是do
{getsymdo;if (sym == whilesym) //do while 語(yǔ)句 {cx1 = cx; //記錄當(dāng)前的位置,即while循環(huán)體開(kāi)始位置 getsymdo;memcpy(nxtlev, fsys, sizeof(bool)* symnum);nxtlev[untilsym] = true; //后跟符號(hào)為until statementdo(fsys, ptx, lev); //執(zhí)行while循環(huán)體 if (sym == semicolon) //分號(hào),跳過(guò) {getsymdo;}if (sym == untilsym) //為until 執(zhí)行條件語(yǔ)句 {getsymdo;conditiondo(nxtlev, ptx, lev); //執(zhí)行條件判斷 gendo(jpc, 0, cx1); //條件跳轉(zhuǎn),為flase是跳轉(zhuǎn)到while循環(huán)體內(nèi) }}
//以上為添加的do while until 語(yǔ)句
4.3 for語(yǔ)句擴(kuò)充
解決對(duì)編譯程序for語(yǔ)句的擴(kuò)展,補(bǔ)充了for-to和for-downto語(yǔ)句塊
4.3.1 “變量=初值”部分代碼
找到變量位置并為變量賦初值
if(sym==forsym) //準(zhǔn)備按照f(shuō)or語(yǔ)句處理
{getsymdo;if(sym==ident) //準(zhǔn)備按照賦值語(yǔ)句處理 {i=position(id,*ptx);if(i==0){error(11); //變量未找到 }else{if(table[i]kind!=variable){error(12); //賦值語(yǔ)句格式錯(cuò)誤i=0; }else{getsymdo;if(sym==becomes) //變量賦初始值{getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[tosym]=true;nxtlev[downtosym]=true;nxtlev[dosym]=true;expressiondo(nxtlev,ptx,lev);}else{error(13); //沒(méi)有檢測(cè)到賦值符號(hào) }if(i!=0){gen(sto,lev-table[i]level,table[i]adr);}
4.3.2 “downto-do-end”部分代碼
if(sym==downtosym)
{cx1=cx; //記錄當(dāng)前位置,即downto后開(kāi)始判斷當(dāng)前變量與終值大小關(guān)系的位置 getsymdo; gendo(lod,lev-table[i]level,table[i]adr); //將循環(huán)判斷變量取出放到棧頂 nxtlev[beginsym]=true; //接下來(lái)識(shí)別的符號(hào)為begin expressiondo(nxtlev,ptx,lev); //判斷循環(huán)變量條件 gen(opr,0,11); //生成比較指令 次棧頂是否大于等于棧頂,退兩個(gè)棧元素,結(jié)果值進(jìn)棧 cx2=cx; //記錄循環(huán)開(kāi)始地址gen(jpc,0,0); //條件跳轉(zhuǎn),暫時(shí)未知目的地址 ,用0代替 if(sym==dosym){getsymdo ;statementdo ( fsys, ptx, lev) ; //運(yùn)行do內(nèi)代碼 gen (lod, lev - table [i] level, table[i]adr); //將循環(huán)變量取出放在棧頂 gen (lit, 0, 1); //常數(shù)1添加到棧頂 即將步長(zhǎng)取到棧頂 gen (opr, 0, 3); //循環(huán)變量減少1 次棧頂減去棧頂,退兩個(gè)棧元素,結(jié)果值進(jìn)棧gendo (sto, lev - table[i] level, table[i]adr); //將棧頂?shù)闹荡嫒胙h(huán)變量 gendo(jmp , 0, cx1); //無(wú)條件跳轉(zhuǎn),到判斷變量與終值大小關(guān)系的位置 code[cx2]a=cx; /*地址回填, jpc的目的地址時(shí)do執(zhí)行完后的位置
即當(dāng)次棧頂小于棧頂時(shí),結(jié)束for循環(huán)語(yǔ)句*/ } else{error(18);}
}
4.3.3 “to-do-end”部分代碼
if(sym==tosym)
{cx1=cx; //記錄比較地址getsymdo;gendo(lod,lev-table[i]level,table[i]adr); memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[beginsym]=true;expressiondo(nxtlev,ptx,lev); //處理循環(huán)邊界表達(dá)式gen(opr,0,13); //生成條件比較表達(dá)式cx2=cx; //記錄條件跳轉(zhuǎn)地址gen(jpc,0,0);if(sym==dosym){getsymdo;statementdo(nxtlev,ptx,lev);gen(lod,lev-table[i]level,table[i]adr); //變量提到棧頂gen(lit,0,1); //常數(shù)1加到棧頂gen(opr,0,2); //循環(huán)變量增加到1gendo(sto,lev-table[i]level,table[i]adr); //賦值gen(jmp,0,cx1); //回條件判斷code[cx2]a=cx; //跳出循環(huán) } else{error(18); /* 缺少do */}
}
五、系統(tǒng)測(cè)試
5.1 else語(yǔ)句擴(kuò)充
5.2 do-while-until語(yǔ)句擴(kuò)充
5.3 for語(yǔ)句擴(kuò)充
六、設(shè)計(jì)總結(jié)
經(jīng)歷了長(zhǎng)達(dá)一周的課程設(shè)計(jì)工作,我們小組終于完成了本次課程設(shè)計(jì)的代碼編寫(xiě)及論文編撰任務(wù)。我們?cè)诖_認(rèn)合作意向之后,很快就確定下來(lái)了各自的任務(wù)分工,在獨(dú)立完成各自任務(wù)的同時(shí),我們也常常合作工作,指出對(duì)方的不足并解決,對(duì)方的一些問(wèn)題很慶幸能與默契地搭檔一起進(jìn)行本次課程設(shè)計(jì)。
在課程設(shè)計(jì)的過(guò)程中,我們首先遇到的問(wèn)題是龐大源代碼的閱讀,我們需要先初步閱讀并理解老師給出的基礎(chǔ)代碼之后,再在此基礎(chǔ)上進(jìn)行代碼的擴(kuò)充,基礎(chǔ)代碼的行數(shù)已經(jīng)多達(dá)上千行,我們采取分工的方式,一人讀懂一部分函數(shù)的功能,然后再以口述的方式給對(duì)方講解,節(jié)省理解代碼的時(shí)間。
接下來(lái),我們先進(jìn)行的是if-else語(yǔ)句的擴(kuò)充這一部分的難點(diǎn)是理清jpc和jmp的跳轉(zhuǎn)以及地址的回填如何進(jìn)行。我們根據(jù)老師給出的指導(dǎo),仔細(xì)分析了代碼執(zhí)行流程和結(jié)構(gòu),確定了jpc和jmp的地址并根據(jù)網(wǎng)上查找到的資料,確定了地址回填的編寫(xiě)方式在編寫(xiě)過(guò)程中,我們起初將cx2=cx語(yǔ)句寫(xiě)在了if(sym=elsesym)語(yǔ)句內(nèi)部,后來(lái)檢查的時(shí)候,我們經(jīng)過(guò)討論,認(rèn)為應(yīng)該放到if前,因?yàn)閠hen的語(yǔ)句執(zhí)行完之后即可跳轉(zhuǎn)到else語(yǔ)句末尾,而不必先識(shí)別else再跳轉(zhuǎn)。最后,我們還是放在了外部,因?yàn)槿绻旁谕獠?#xff0c;在編譯時(shí)無(wú)需再編譯else語(yǔ)句,能節(jié)省時(shí)間
dowhile語(yǔ)句的擴(kuò)充因?yàn)橛衑lse的語(yǔ)句擴(kuò)充作為基礎(chǔ),寫(xiě)代碼并不困難,基本的邏輯思路是一致的,但是我們犯了一個(gè)邏輯上的錯(cuò)誤,我們把題目的do-while-until理解成了do-while的結(jié)構(gòu),導(dǎo)致地址的跳轉(zhuǎn)邏輯錯(cuò)誤。
for語(yǔ)句的難點(diǎn)是變量和終值大小的比較如何實(shí)現(xiàn),以及變量的自增與自減如何實(shí)現(xiàn)我們首先確定了for語(yǔ)句的代碼大致執(zhí)行順序與結(jié)構(gòu),但是接著的代碼編寫(xiě)部分有些無(wú)從下筆我們決定先整理出函數(shù)表以及指令功能表,以便接下來(lái)的編寫(xiě)能更清晰地調(diào)用相關(guān)函數(shù)實(shí)現(xiàn)目標(biāo)功能。for后的“變量=初值”部分的代碼直接使用的base代碼中已給出的賦值代碼,并未做修改。變量與終值的比較及變量的自增自減,我們?cè)诓檎伊讼嚓P(guān)的資料之后,才確定了gen的函數(shù)調(diào)用方式。
通過(guò)本次課設(shè),我們進(jìn)一步鞏固了編譯原理的理論知識(shí),在課設(shè)過(guò)程中以實(shí)踐的方式,進(jìn)一步加深了對(duì)相關(guān)知識(shí)的理解與應(yīng)用。
七、致謝
在本次課程設(shè)計(jì)中,首先我們由衷地感謝臺(tái)安老師對(duì)于編譯原理課程的教授與指導(dǎo)。從課程設(shè)計(jì)正式開(kāi)始到后期的完成,都離不開(kāi)臺(tái)老師的悉心指導(dǎo)。臺(tái)老師嚴(yán)謹(jǐn)求時(shí)的治學(xué)態(tài)度,踏實(shí)堅(jiān)韌的工作精神,平易近人的待人方式給我們?cè)S多啟發(fā)和幫助。也正是因?yàn)槔蠋煹恼J(rèn)真負(fù)責(zé),為我們編譯原理的課設(shè)奠定了堅(jiān)實(shí)的理論基礎(chǔ)。在此,我們?cè)俅蜗蚺_(tái)老師致以誠(chéng)摯的謝意和崇高的敬意。
其次,在本次課設(shè)中還要感謝我親愛(ài)的搭檔,我們兩個(gè)人分工明確,在確定了思路后就立刻開(kāi)始完成自己的部分,在不理解的地方一起進(jìn)行討論,最終在規(guī)定的時(shí)間內(nèi)完成。
最后再次感謝所有在本次課程設(shè)計(jì)中幫助過(guò)我們的老師和同學(xué)們!
源碼與測(cè)試用例下載
https://download.csdn.net/download/weixin_47500703/85901408