




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、實(shí)驗(yàn)?zāi)康呐c要求目的:在分析理解一個(gè)教學(xué)型編譯程序(如 PL/O )的基礎(chǔ)上,對(duì)其詞法分析程序、 語法分析程序和語義處理程序進(jìn)行部分修改擴(kuò)充。 達(dá)到進(jìn)一步了解程序編譯過程的基本原理 和基本實(shí)現(xiàn)方法的目的。要求:對(duì) PL/0 作以下修改擴(kuò)充 基本內(nèi)容 : 增加單詞:保留字 ELSE , FOR, TO, DOWNTO , RETURN運(yùn)算符 +=, -=, + , - 修改單詞:不等號(hào) # 改為 <> 增加條件語句的 ELSE 子句二、 實(shí)驗(yàn)環(huán)境與工具( 1)計(jì)算機(jī)及操作系統(tǒng): PC 機(jī), WindowsXP( 2)程序設(shè)計(jì)語言: C+Builder6( 3)教學(xué)型編譯程序: PL/0
2、三、 設(shè)計(jì)方案(1)編譯過程的流程 :PL/0 編譯過程采用一趟掃描方式 ,以語法分析程序?yàn)楹诵?,詞法分析程序和 代碼生成程序都作為一個(gè)獨(dú)立的過程 ,當(dāng)語法分析需要讀單詞時(shí)就調(diào)用詞法 分析程序 ,而當(dāng)語法分析正確需生成相應(yīng)的目標(biāo)代碼時(shí) ,則調(diào)用代碼生成程序 此外 ,用表格管理程序建立變量 ,常量和過程標(biāo)識(shí)符的說明與引用之間的信息 聯(lián)系 .用出錯(cuò)處理程序?qū)υ~法和語法分析遇到的錯(cuò)誤給出在源程序中出錯(cuò)的 位置和錯(cuò)誤性質(zhì) .當(dāng)源程序編譯正確時(shí) ,PL/0 編譯程序自動(dòng)調(diào)用解釋執(zhí)行程序 對(duì)目標(biāo)代碼進(jìn)行解釋執(zhí)行 ,并按用戶程序要求輸入數(shù)據(jù)和輸出運(yùn)行結(jié)果 .功能模塊描述:(1) 符號(hào)表:符號(hào)表為一維數(shù)組
3、TABLE ,表項(xiàng)為一結(jié)構(gòu)體,包括標(biāo)識(shí)符的名稱,類型和表達(dá)標(biāo) 識(shí)符信息的聯(lián)合體。類型分三類:常量,變量,過程。當(dāng)類型為常量時(shí),只需把常 量的值填入表中,即賦值給聯(lián)合體。 當(dāng)類型為變量時(shí),需把該標(biāo)識(shí)符的層次,地址 信息填入表中,當(dāng)為過程時(shí),還需要整個(gè)過程的大小的信息。TX為TABLE表的指針,DX為局部變量在說明層中的相對(duì)位置,程序中每一層的DX從4開始,DX0-DX3分別分配給返回值單元,靜態(tài)鏈,動(dòng)態(tài)鏈和程序返回地址,此后每識(shí)別一個(gè)變量DX 加 1。struct ALFA NAME;OBJECTS KIND;union int VAL; /*CONSTANT*/struct int LEVEL
4、,ADR,SIZE; vp; /*VARIABLE,PROCEDUR:*/; TABLETXMAX;(2) 運(yùn)行時(shí)存儲(chǔ)組織和管理:解釋程序定義一個(gè)一維整型數(shù)組 S作為運(yùn)行棧,棧頂寄存器(指針) t,基址寄 存器(指針)b,程序地址寄存器P,指令寄存器i。在每個(gè)過程調(diào)用時(shí)在棧頂分配 4個(gè)聯(lián)系單元: 由于添加了返回值,所以當(dāng)前過程的活動(dòng)記錄的棧頂為存放返回值的單元。 SL: 靜態(tài)鏈,指向定義該過程的直接外過程(或主程序)運(yùn)行時(shí)最新數(shù)據(jù)段的基 地址。當(dāng)一個(gè)過程引用包圍它的過程(或主程序)所定義的標(biāo)識(shí)符時(shí),首先 沿靜態(tài)鏈跳過個(gè)數(shù)為層差的數(shù)據(jù)段,找到定義該標(biāo)識(shí)符過程的數(shù)據(jù)段地址, 再加上給此標(biāo)識(shí)符分配的
5、相對(duì)位置,就得出該標(biāo)識(shí)符在整個(gè)數(shù)據(jù)區(qū)棧中的絕 對(duì)位置。DL: 動(dòng)態(tài)鏈,指向調(diào)用該過程前正在運(yùn)行過程的數(shù)據(jù)段基地址。RA: 返回地址,記錄調(diào)用該過程時(shí)目標(biāo)程序的斷點(diǎn),即調(diào)用過程指令的下一條指 令的地址。動(dòng)態(tài)鏈和返回地址的作用是當(dāng)一個(gè)過程運(yùn)行結(jié)束后, 為了恢復(fù)調(diào)用該過程前的執(zhí)行 狀態(tài)而設(shè)置的。(3 )自頂向下的語法分析 : 遞歸子程序法:對(duì)應(yīng)每個(gè)非終結(jié)符語法單元編一個(gè)獨(dú)立的處理過程(或子程 序)。語法分析從讀入第一個(gè)單詞開始,由非終結(jié)符程序 (即開始符)出發(fā),沿語法描述圖箭頭所指出的方向進(jìn)行分析。 當(dāng)遇到非終結(jié)符時(shí), 則調(diào)用相應(yīng)的處理過 程,從語法描述圖看, 也就進(jìn)入了一個(gè)語法單元, 再沿當(dāng)前所進(jìn)
6、入的語法單元所指 箭頭方向繼續(xù)進(jìn)行分析。 當(dāng)遇到描述圖中是終結(jié)符時(shí), 則判斷當(dāng)前讀入的單詞是否 與圖中的終結(jié)符相匹配, 若匹配,再讀取下一個(gè)單詞繼續(xù)分析。遇到分支點(diǎn)時(shí),將 當(dāng)前的單詞與分支點(diǎn)上多個(gè)終結(jié)符逐個(gè)相比較, 若都不匹配時(shí)可能是進(jìn)入下一個(gè)非 終結(jié)符語法單位或是出錯(cuò)。(4 )中間代碼表示:由于添加了返回值,增加了一條指令 DEL用于返回。ret 0,0與OPR 0,0 的區(qū)別是 ret 0,0 先把返回值放到活動(dòng)記錄的返回值單元,并把棧頂指針 指向返回值單元, 當(dāng)被調(diào)用程序返回時(shí), 調(diào)用程序就可以在當(dāng)前運(yùn)行棧棧頂取得 被調(diào)用程序的返回值。四測(cè)試用例基本內(nèi)容1. 正確符號(hào)測(cè)試程序 :test
7、1COMPILE PL0TEST1-PL00 正確符號(hào)測(cè)試程序* A0* A應(yīng)是語句開始符A11 標(biāo)識(shí)符未說明k-k-kk-k-kA13 賦值語句左部標(biāo)識(shí)符后應(yīng)是賦值號(hào)A19 語句后的符號(hào)不正確2 Correct Symbols 2 Comment 2 abcdefghijklmnopqrstuvwxyz2 ABCDEFGHIJKLMNOPQRSTUVWXYZ2 1234567890 !"#$% & '()*+,-./:;<=>?_'0 JMP 0 11 INI 0 32 LIT 0 03 RET 00*A9 程序結(jié)尾丟了句號(hào) '.'
8、;ERROR IN PL/0 PROGRAM4. 增加條件語句的 ELSE 子句= COMPILE PL0 =0 PROGRAM EOX1;V AR A,B,C; BEGIN2 A:=20;4 B:=30;6 READ(C);8 WRITE(C);11IF C<50 THEN WRITE(A)17 ELSE WRITE(B);22END.0JMP011INI062LIT0203STO034LIT0305STO046OPR0167STO058LOD059OPR01410OPR01511LOD0512LIT05013OPR01014JPC01915LOD0316OPR01417OPR0151
9、8JMP02219LOD0420OPR01421OPR01522LIT0023RET00 RUN PL0 ? 565630 END PL0 五.設(shè)計(jì)心得:1. 通過這個(gè)課程設(shè)計(jì)的學(xué)習(xí)使 我更深地了解了編譯原理及其應(yīng)用。2. 團(tuán)體精神互相合作很重要。 在做設(shè)計(jì)的過程中遇到了不明白的問題時(shí)與同宿舍的 同學(xué)進(jìn)行了討論,可能在有些地方與之有類似之處,請(qǐng)老師理解!3. 提高了自學(xué)能力, buildr 以前是沒有怎么學(xué)過的,通過了這次的設(shè)計(jì),也使多進(jìn) 一步掌握了 buildrt 的應(yīng)用!雖然課程設(shè)計(jì)不能獨(dú)自一個(gè)人完成,但真的學(xué)到了許多!六源程序/* PL0 COMPILER WITH CODE GENER
10、A TION */ /#include <vcl.h>#pragma hdrstop#include "Unit1.h"/#pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1;/int COD=1;/0 為詞法分析int choice=1;/0 為 IF 未改const AL = 10; /* 標(biāo)示符的長度為 10*/const NORW = 20; /* 保留字的個(gè)數(shù)為 20*/ const TXMAX = 100; /* 標(biāo)示符表的最大長度為 100*/const
11、NMAX = 14;/*數(shù)字最大位數(shù)為14*/constAMAX =2047;/*最大尋址為 2047*/constLEVMAX= 3;/*嵌套最大層數(shù)為3*/constCXMAX = 200;/*代碼數(shù)組最大為200*/constNumOfSybol=43;/ 定義關(guān)鍵保留字 33 個(gè)typedef int *ERRORPOINT;typedef enum NUL, IDENT, NUMBER, PLUS, MINUS, TIMES,SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ,LPAREN, RPAREN,QUOT,/ 單引號(hào) COMMA, SEM
12、ICOLON, PERIOD,BECOMES,PLUSBECOMES,/+= MINUSBECOMES,/-=DOUBLEPLUS, /+DOUBLEMINUS, /- BEGINSYM, ENDSYM, IFSYM, THENSYM,WHILESYM, WRITESYM, READSYM, DOSYM, CALLSYM,CONSTSYM, V ARSYM, PROCSYM, PROGSYM,CHARSYM, ELSESYM,/ 在此加了 ELSE FORSYM, / 加了 FOR TOSYM, /加了 TO DOWNTOSYM, / 加了 DOWM RETURN / 加了 RETURN SY
13、MBOL; /* 詞匯表 ,其中控制程序結(jié)構(gòu)的保留字 14 個(gè) */ char *SYMOUT = "NUL", "IDENT", "NUMBER", "PLUS", "MINUS", "TIMES", "SLASH", "ODDSYM", "EQL", "NEQ", "LSS", "LEQ", "GTR", "GEQ"
14、;, "LPAREN", "RPAREN","QUOT",/ 單引號(hào)"COMMA", "SEMICOLON", "PERIOD","BECOMES","PLUSBECOMES", /+="MINUSBECOMES", /-="DOUBLEPLUS", /+"DOUBLEMINUS",/-"BEGINSYM", "ENDSYM", &quo
15、t;IFSYM", "THENSYM","WHILESYM", "WRITESYM", "READSYM", "DOSYM", "CALLSYM", "CONSTSYM", "V ARSYM", "PROCSYM", "PROGSYM", "CHARSYM", "ELSESYM", / 在此加了 ELSE"FORSYM",/ 加
16、了 FOR"TOSYM",/ 加了 TO"DOWNTOSYM"/ 加了 DOWM"RETURN" /加了 RETURN;typedef int *SYMSET; / 字符集 ;typedef char ALFA11;typedef enum CONSTANT, V ARIABLE, PROCEDUR,CHARACTOR OBJECTS ; typedef enum LIT, OPR, LOD, STO, CAL,RET, INI, JMP, JPC FCT;typedef struct FCT F;/* 函數(shù)命令 */int L;/*
17、0.LEVMAXLEVEL*/int A;/*0.AMAXDISPLACEMENT ADDR*/ INSTRUCTION;/LIT0A將常數(shù)值取到棧頂 ,A 為常數(shù)值LODLA將變量值取到棧頂 ,A 為偏移量 ,L 為層差STOLA將棧頂內(nèi)容送入某一變量單元中 ,A 為偏移量 ,L 為層差CALLA調(diào)用過程 ,A 為過程地址 ,L 為層差I(lǐng)NT0A在運(yùn)行棧中為被調(diào)用的過程開辟 A 個(gè)單元的數(shù)據(jù)區(qū)JMP0A無條件跳轉(zhuǎn)到 A 地址JPC0A條件跳轉(zhuǎn) ,當(dāng)棧頂布爾值非真則跳轉(zhuǎn)到 A 地址 ,否則順序執(zhí)行OPR00過程調(diào)用結(jié)束后 ,返回調(diào)用點(diǎn)并退棧OPR01棧頂元素取反OPR02次棧頂與棧頂相加 ,退
18、兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR03次棧頂減去棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR04次棧頂乘以棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR05次棧頂除以棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR06棧頂元素的奇偶判斷 ,結(jié)果值在棧頂OPR07OPR08次棧頂與棧頂是否相等 ,退兩上棧元素 ,結(jié)果值進(jìn)棧OPR09次棧頂與棧頂是否不等 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR010次棧頂是否小于棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR011次棧頂是否大于等于棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR012次棧頂是否大于棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧OPR013次棧頂是否小于等于棧頂 ,退兩個(gè)棧元素 ,結(jié)
19、果值進(jìn)棧OPR014棧頂值輸出到屏幕OPR015屏幕輸出換行OPR016從命令行讀入一個(gè)輸入置于棧頂*/ char CH; /* 最近讀進(jìn)的字符 */SYMBOL SYM; /* 存放每個(gè)單詞的類別 ,用內(nèi)部編碼形式表示 */ALFA ID; /* 存放用戶所定義的標(biāo)識(shí)符的值 ,即字符串的機(jī)內(nèi)表示 */ int NUM; /* 用戶所定義的數(shù) */intCC;/*CHARACTER COUNT*/intLL;/* 緩沖器的長度 */intCX;/*CODE 數(shù)組的下標(biāo)索引 */charLINE81;INSTRUCTION CODECXMAX;ALFAKWORDNORW+1;SYMBOLWSYM
20、NORW+1; /存放保留字SYMBOLSSYM'A'+1;/ 在''到'A'才是可用ALFAMNEMONIC9;SYMSETDECLBEGSYS, STATBEGSYS, FACBEGSYS;struct ALFA NAME; / 名稱OBJECTS KIND; / 類型union int VAL; /*常量 */struct int LEVEL,ADR,SIZE; vp; /* 變量或者過程 */; TABLETXMAX; / 即 TABLE100FILE *FIN,*FOUT; /輸入輸出文件的指針int ERR;/錯(cuò)誤個(gè)數(shù)統(tǒng)計(jì)String
21、 ERRORKIND34 = ""," 常數(shù)說明中的 '='寫成 ':='",/1" 常數(shù)說明中的 '='后應(yīng)是數(shù)字 ", /2" 常數(shù)說明中的標(biāo)識(shí)符后應(yīng)是 = 號(hào)",/3"CHAR,CONST,VAR,PROCEDURE 后應(yīng)為標(biāo)識(shí)符 ", /4 " 漏掉了 ','或''",/5" 過程說明后的符號(hào)不正確 ",/6" 應(yīng)是語句開始符 ",/7"
22、程序體內(nèi)語句部分的后跟符不正確",/8" 程序結(jié)尾丟了句號(hào) '.'",/9" 語句之間漏了 ''",/10" 標(biāo)識(shí)符未說明 ",/11" 賦值語句中 ,賦值號(hào)左部標(biāo)識(shí)符屬性應(yīng)是變量 ",/12" 賦值語句左部標(biāo)識(shí)符后應(yīng)是賦值號(hào)':='",/13"CALL 后應(yīng)為標(biāo)識(shí)符 ", /14"CALL 后標(biāo)識(shí)符屬性應(yīng)為過程 ", /15"條件語句中丟了 THEN'或'ELSE'
23、;",/16" 丟了 'END' 或 ''",/17"WHILE 型循環(huán)語句中丟了 'DO'",/18"語句后的符號(hào)不正確 ",/19" 應(yīng)為關(guān)系運(yùn)算符 ",/20" 表達(dá)式內(nèi)標(biāo)識(shí)符屬性不能是過程 ",/21" 表達(dá)式中漏掉右括號(hào) ')'", /22" 因子后的非法符號(hào) ",/23" 表達(dá)式的開始符不能是此符號(hào) ",/24"FOR 語句后應(yīng)有 TO 或
24、DOWN", /25" 字符類型不符 ",/26" 字符類型漏了 '''單引號(hào) ",/27"READ 函數(shù)內(nèi)的標(biāo)識(shí)符沒定義 ", /28 "NUL", /30" 數(shù)越界 ",/31"READ 語句括號(hào)中的標(biāo)識(shí)符不是變量 " /32 "NUL"/33"NUL"/34;void EXPRESSION(SYMSET FSYS, int LEV, int &TX); void TERM(SYMSET F
25、SYS, int LEV , int &TX);/int SymIn(SYMBOL SYM, SYMSET S1) return S1SYM;/SYMSET SymSetUnion(SYMSET S1, SYMSET S2) SYMSET S=(SYMSET)malloc(sizeof(int)*NumOfSybol); for (int i=0; i<NumOfSybol; i+) if (S1i | S2i) Si=1;else Si=0;return S;/SYMSET SymSetAdd(SYMBOL SY , SYMSET S) SYMSET S1; S1=(SYMSE
26、T)malloc(sizeof(int)*NumOfSybol); for (int i=0; i<NumOfSybol; i+) S1i=Si;S1SY=1;return S1;/SYMSET SymSetNew(SYMBOL a) SYMSET S; int i,k; S=(SYMSET)malloc(sizeof(int)*NumOfSybol); for (i=0; i<NumOfSybol; i+) Si=0;Sa=1;return S;/SYMSET SymSetNew(SYMBOL a, SYMBOL b) SYMSET S; int i,k;S=(SYMSET)ma
27、lloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0;Sa=1; Sb=1;return S;/SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c) SYMSET S; int i,k;S=(SYMSET)malloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0;Sa=1; Sb=1; Sc=1;return S;/SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c
28、, SYMBOL d) SYMSET S; int i,k;S=(SYMSET)malloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0;Sa=1; Sb=1; Sc=1; Sd=1;return S;/SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c, SYMBOL d,SYMBOL e) SYMSET S; int i,k;S=(SYMSET)malloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0
29、;Sa=1; Sb=1; Sc=1; Sd=1; Se=1;return S;/SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c, SYMBOL d,SYMBOL e, SYMBOL f) SYMSET S; int i,k;S=(SYMSET)malloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0;Sa=1; Sb=1; Sc=1; Sd=1; Se=1; Sf=1; return S;/SYMSET SymSetNULL() SYMSET S; int i,n,k;S=(
30、SYMSET)malloc(sizeof(int)*NumOfSybol);for (i=0; i<NumOfSybol; i+) Si=0;return S;/* 錯(cuò)誤處理 : 打印出錯(cuò)位置和錯(cuò)誤編碼*/void Error(int n) String s = "*"+AnsiString:StringOfChar(' ', CC-1)+""s=s+n+ERRORKINDn;Form1->printfs(s.c_str();/ Form1->printls(s.c_str(),n);/Form1->printls
31、(fprintf(FOUT,"%s%dn", s.c_str(), n);ERR+; /*Error*/void GetCh() /* 漏掉空格 ,讀取一個(gè)字符 */*CH: 存放當(dāng)前讀取的字符 ,初始值為空LINE: 為一維數(shù)組 ,其數(shù)組元素是字符 ,界對(duì)為 1:800.用于讀入一行的緩沖區(qū) LL: 計(jì)數(shù)器 ,初始值為 0.CC:計(jì)數(shù)器,初始值為0. */if (CC=LL) /緩沖區(qū)是否結(jié)束 ?/是則執(zhí)行下邊if (feof(FIN) / 判斷文件是否結(jié)束Form1->printfs("PROGRAM INCOMPLETE"); fprintf
32、(FOUT,"PROGRAM INCOMPLETEn");fclose(FOUT);exit(0); /goto 199;出口LL=0; CC=0;CH=' 'while (!feof(FIN) && CH!=10) /ASCII 碼 換行符 CH=fgetc(FIN); LINELL+=CH; / 逐個(gè)放到 LINE 緩沖區(qū)啊LINELL-1=' ' LINELL=0;String s=IntToStr(CX);while(s.Length()<3) s=" "+s;s=s+" "
33、;+LINE;Form1->printfs(s.c_str();fprintf(FOUT,"%sn",s);CH=LINECC+;/否 /*GetCh()*/void GetSym() /* 詞法分析 ,讀取一個(gè)單詞 */* 完成的任務(wù) :(1) 濾空格 :(2) 識(shí)別保留字 :設(shè)有一張保留字表 ,對(duì)每個(gè)字母打頭的字母 ,數(shù)字字符串要查此表 若查著則為保留字 ,將對(duì)應(yīng)的類別放在 SYM 中,若查不著 ,則認(rèn)為是用戶定義的標(biāo)識(shí)符(3)識(shí)別標(biāo)識(shí)符 :對(duì)用戶定義的標(biāo)識(shí)符將 IDENT 放在 SYM 中 ,標(biāo)識(shí)符本身的值放在 ID 中;NUM 中 .(4)拼數(shù) :當(dāng)所取的單詞
34、是數(shù)字時(shí) ,將數(shù)的類別 NUMBER 放在 SYM 中,數(shù)值本身的值存放的 (5)拼復(fù)用詞 :對(duì)兩處字符組成的算符識(shí)別后將類別送SYM 中 ;(6) 輸出源程序 :為邊讀入字符邊輸出 (可輸出在文件中 ).A: 維數(shù)組.數(shù)組元素為字符,界對(duì)1:10,存放讀進(jìn)的標(biāo)識(shí)符.ID: 同 A.WORD: 保留字表 ,一維數(shù)組 .數(shù)組元素是以字符為元素的一維數(shù)組.界對(duì)為 1:13.查表方式采用二分法 .*/int i,J,K; ALFA A; /存放讀進(jìn)的標(biāo)識(shí)符 .while (CH<=' ') GetCh();/濾空格并濾掉控制字符 ,因?yàn)?' '之前的都是控制字符
35、if (CH>='A' && CH<='Z') /* 如果是標(biāo)識(shí)符 */K=0;do if (K<AL) AK+=CH;GetCh();while(CH>='A' && CH<='Z')|(CH>='0' && CH<='9');AK='0'strcpy(ID,A); /將 A 的內(nèi)容 COPY 給 IDi=1; J=NORW;/NORW 是關(guān)鍵保留字的個(gè)數(shù)初始時(shí)為 14do / 以下為 查表方
36、式采用二分法方式查表方式 .K=(i+J) / 2;if (strcmp(ID,KWORDK)<=0) J=K-1;if (strcmp(ID,KWORDK)>=0) i=K+1; while(i<=J);if (i-1 > J) SYM=WSYMK; / 若查找到 ,則是關(guān)鍵保留字else SYM=IDENT;/否則為用戶定義的標(biāo)識(shí)符else if (CH>='0' && CH<='9') /* 數(shù)字處理 */K=0; NUM=0; / 值放在 NUM 中 SYM=NUMBER; / 類型為數(shù)字 do NUM
37、=10*NUM+(CH-'0');K+; GetCh();while(CH>='0' && CH<='9');if (K>NMAX) Error(30);/若 K 大于數(shù)值的最大位數(shù) NMAX14 位時(shí)則出錯(cuò) else if (CH=':') GetCh();if (CH='=') SYM=BECOMES; GetCh(); else SYM=NUL;else if (CH='<') /* 處理 <, <= */ GetCh();if (CH=
38、39;=') SYM=LEQ; GetCh(); else if(CH='>') SYM=NEQ; GetCh(); else SYM=LSS;else if (CH='>') /* 處理> ,>=的關(guān)系 */GetCh();if (CH='=') SYM=GEQ; GetCh(); else SYM=GTR;else if(CH='+')/ 處理以 '+'開頭的GetCh();if (CH='=') SYM=PLUSBECOMES; GetCh(); else if
39、(CH='+') SYM=DOUBLEPLUS; GetCh(); else SYM=PLUS; else if(CH='-')/ 處理以 '-'開頭的GetCh();if (CH='=') SYM=MINUSBECOMES; GetCh(); else if(CH='-') SYM=DOUBLEMINUS; GetCh(); else SYM=MINUS;else if(CH=''')SYM=QUOT;GetCh(); else SYM=SSYMCH; GetCh(); /*GetSym(
40、)*/void GEN(FCT X, int Y , int Z) /* 完成任務(wù) :生成目標(biāo)代碼 ,并送入目標(biāo)程序區(qū)FCT:功能代碼Y:層差Z: 位移量*/if (CX>CXMAX) Form1->printfs("PROGRAM TOO LONG"); fprintf(FOUT,"PROGRAM TOO LONGn");fclose(FOUT);exit(0);CODECX.F=X; CODECX.L=Y; CODECX.A=Z; CX+; /*GEN*/void TEST(SYMSET S1, SYMSET S2, int N) /*
41、測(cè)試當(dāng)前單詞符號(hào)是否合法 */ /*S1:當(dāng)語法分析進(jìn)入或退出時(shí)某一語法單元時(shí)當(dāng)前單詞符號(hào)應(yīng)屬于的集合S2:某一出錯(cuò)狀態(tài)時(shí),可恢復(fù)語法分析繼續(xù)正常工作的補(bǔ)充單詞符號(hào)集合N:錯(cuò)誤類型號(hào)*/if (!SymIn(SYM,S1) Error(N);while (!SymIn(SYM,SymSetUnion(S1,S2) GetSym(); /*TEST*/void ENTER(OBJECTS K, int LEV , int &TX, int &DX) /*登錄名字表 */TX+;/ 當(dāng)前的 TABLE 表的索引 strcpy(TABLETX.NAME,ID); TABLETX.KI
42、ND=K;switch (K) case CONSTANT:if (NUM>AMAX) Error(31); NUM=0; / 數(shù)越界 TABLETX.V AL=NUM;break;case VARIABLE:TABLETX.vp.LEVEL=LEV; TABLETX.vp.ADR=DX; DX+;break;case CHARACTOR:TABLETX.vp.LEVEL=LEV; TABLETX.vp.ADR=DX; DX+;break;case PROCEDUR: TABLETX.vp.LEVEL=LEV; break; /*ENTER*/int POSITION(ALFA ID,
43、int TX) /* 查找標(biāo)識(shí)符在名字表中的位置 */*看是否有過正確的定義*/int i=TX;strcpy(TABLE0.NAME,ID);while (strcmp(TABLEi.NAME,ID)!=0) i-; /采用靜態(tài)表搜索的方法 ,從后往前搜return i; /*POSITION*/void ConstDeclaration(int LEV ,int &TX,int &DX) /* 常量說明處理 */if (SYM=IDENT) GetSym();if (SYM=EQL|SYM=BECOMES) if (SYM=BECOMES) Error(1);/常數(shù)說明中的
44、 "="寫成 ":="GetSym();if (SYM=NUMBER) ENTER(CONSTANT,LEV ,TX,DX); GetSym();else Error(2);常數(shù)說明中的"="后邊應(yīng)是數(shù)字else Error(3);常數(shù)說明中的標(biāo)識(shí)符后應(yīng)該是"="else Error(4);/Const ,var,procedure 后邊應(yīng)為標(biāo)識(shí)符 /*ConstDeclaration()*/void VarDeclaration(int LEV ,int &TX,int &DX) /*變量說明處理
45、 */if (SYM=IDENT) ENTER(VARIABLE,LEV ,TX,DX); GetSym();else Error(4); /Const ,var,procedure 后邊應(yīng)為標(biāo)識(shí)符 /*VarDeclaration()*/void CharDeclaration(int LEV ,int &TX,int &DX) /*字符說明處理 */if (SYM=IDENT) ENTER(CHARACTOR,LEV ,TX,DX); GetSym();else Error(4); /Char,Const ,var,procedure 后邊應(yīng)為標(biāo)識(shí)符 /*CharDecla
46、ration()*/void ListCode(int CX0) /*L 列出目標(biāo)代碼清單 */if (Form1->ListSwitch->ItemIndex=0)for (int i=CX0; i<CX; i+) /*CX:CODE 數(shù)組的下標(biāo)索引 */ String s=IntToStr(i);while(s.Length()<3) s=" "+s;s=s+" "+MNEMONICCODEi.F+" "+IntToStr(CODEi.L)+" "+IntToStr(CODEi.A);
47、Form1->printfs(s.c_str();fprintf(FOUT,"%3d%5s%4d%4dn",i,MNEMONICCODEi.F,CODEi.L,CODEi.A); /*ListCode()*/;/void DOUBLEOP(int LEV ,int &TX) /+ 或 -int i;SYMBOL DOP;DOP=SYM;GetSym();if(SYM=IDENT)i=POSITION(ID,TX);if (i=0) Error(11); / 標(biāo)識(shí)符未說明elseif(TABLEi.KIND=VARIABLE) GEN(LOD,LEV-TABLE
48、i.vp.LEVEL,TABLEi.vp.ADR); else Error(25);GEN(LIT,0,1); if(DOP=DOUBLEPLUS) GEN(OPR,0,2);else GEN(OPR,0,3);GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetSym();else Error(25);void OPDOUBLE(int LEV ,int i)if(i=0) Error(11);else if(TABLEi.KIND=V ARIABLE) GEN(
49、LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); else Error(25);GEN(LIT,0,1);if(SYM=DOUBLEPLUS) GEN(OPR,0,2);else GEN(OPR,0,3);GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);GetSym();void FACTOR(SYMSET FSYS, int LEV , int &TX) /* 因子處理 */TX: 當(dāng)前的 TABLE 表的索引int i;bool ISV AR;TEST(FACBEGSYS,FSYS,24);while (SymIn
50、(SYM,FACBEGSYS) if (SYM=IDENT) ISVAR=false; i=POSITION(ID,TX); if (i=0) Error(11); / 標(biāo)識(shí)符未說明 elseswitch (TABLEi.KIND) case CONSTANT: GEN(LIT,0,TABLEi.V AL);break; /LIT 0 A 將常數(shù)值取到棧頂 ,A 為常數(shù)值case VARIABLE: GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);ISVAR=true;break; /LOD L A 將變量值取到棧頂 ,A 為偏移量 ,L 為層差 case
51、 CHARACTOR: GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);ISVAR=true;break; /LOD L A 將變量值取到棧頂 ,A 為偏移量 ,L 為層差 case PROCEDUR: Error(21);break; /表達(dá)式內(nèi)標(biāo)識(shí)符屬性不能是過程GetSym();if(ISV AR=true && (SYM=DOUBLEPLUS|SYM=DOUBLEMINUS) OPDOUBLE(LEV ,i);elseif (SYM=NUMBER) if (NUM>AMAX) Error(31); NUM=0; /數(shù)越界GEN
52、(LIT,0,NUM);/LIT 0 A 將常數(shù)值取到棧頂 ,A 為常數(shù)值 GetSym();elseif (SYM=LPAREN) GetSym();EXPRESSION(SymSetAdd(RPAREN,FSYS),LEV ,TX);/ 表達(dá)式處理if (SYM=RPAREN) GetSym();else Error(22);/ 表達(dá)式中漏掉了右括號(hào) ')' TEST(FSYS,FACBEGSYS,23);/*FACTOR*/void TERM(SYMSET FSYS, int LEV , int &TX) /* 項(xiàng)處理 */SYMBOL MULOP;FACTOR(
53、SymSetUnion(FSYS,SymSetNew(TIMES,SLASH), LEV ,TX);while (SYM=TIMES | SYM=SLASH) MULOP=SYM; GetSym(); FACTOR(SymSetUnion(FSYS,SymSetNew(TIMES,SLASH),LEV ,TX);/ 因子處理 if (MULOP=TIMES)GEN(OPR,0,4);/OPR 0 4 次棧頂乘以棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧 else GEN(OPR,0,5); /OPR 0 5 次棧頂除以棧頂 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧 /*TERM*/;/void EXPRESSIO
54、N(SYMSET FSYS, int LEV, int &TX) /*表達(dá)式處理 */SYMBOL ADDOP;if (SYM=PLUS | SYM=MINUS) ADDOP=SYM; GetSym();TERM(SymSetUnion(FSYS,SymSetNew(PLUS,MINUS),LEV ,TX); / 項(xiàng)處理if (ADDOP=MINUS)GEN(OPR,0,1); /OPR 0 1 棧頂元素取反/ 改造增量運(yùn)算開始 else if(SYM=DOUBLEPLUS|SYM=DOUBLEMINUS) / 添加增量計(jì)算 DOUBLEOP(LEV ,TX); /調(diào)用增量計(jì)算函數(shù) +
55、或 -/改造增量運(yùn)算結(jié)束 else TERM(SymSetUnion(FSYS,SymSetNew(PLUS,MINUS),LEV ,TX);while (SYM=PLUS | SYM=MINUS) ADDOP=SYM; GetSym();TERM(SymSetUnion(FSYS,SymSetNew(PLUS,MINUS),LEV ,TX);if (ADDOP=PLUS)GEN(OPR,0,2);/OPR 0 2 次棧頂與棧頂相加 ,退兩個(gè)棧元素 ,結(jié)果值進(jìn)棧 else GEN(OPR,0,3);/OPR 0 3 次棧頂減去棧頂 ,退兩個(gè)棧元素 , 結(jié)果值進(jìn)棧 /*EXPRESSION*/v
56、oid CONDITION(SYMSET FSYS,int LEV ,int &TX) /* 條件處理 */SYMBOL RELOP;if (SYM=ODDSYM) GetSym();EXPRESSION(FSYS,LEV ,TX);/ 表達(dá)式處理GEN(OPR,0,6); /OPR 0 6 棧頂元素的奇偶判斷 ,結(jié)果值在棧頂else EXPRESSION(SymSetUnion(SymSetNew(EQL,NEQ,LSS,LEQ,GTR,GEQ),FSYS),LEV ,TX); if (!SymIn(SYM,SymSetNew(EQL,NEQ,LSS,LEQ,GTR,GEQ) Err
57、or(20); / 應(yīng)為關(guān)系運(yùn)算 else RELOP=SYM; GetSym(); EXPRESSION(FSYS,LEV,TX);switch (RELOP) case EQL: GEN(OPR,0,8); break;/OPR8 次棧頂與棧頂是否相等 ,退兩上棧元素 , 結(jié)果值進(jìn)棧case NEQ: GEN(OPR,0,9); break;/OPR9 次棧頂與棧頂是否不等 , 退兩個(gè)棧元素 , 結(jié)果值進(jìn)棧case LSS: GEN(OPR,0,10); break;/OPRcase GEQ: GEN(OPR,0,11); break;/OPR10 次棧頂是否小于棧頂 ,退兩個(gè)棧元素 ,結(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025屆河南省周口市扶溝高級(jí)中學(xué)高三二輪檢測(cè)試題(二模)語文試題試卷含解析
- 2024-2025學(xué)年湖南省茶陵三中新高考物理試題適應(yīng)性訓(xùn)練(二)含解析
- 酒泉職業(yè)技術(shù)學(xué)院《數(shù)學(xué)解題方法》2023-2024學(xué)年第一學(xué)期期末試卷
- 鶴壁汽車工程職業(yè)學(xué)院《第二外語德語》2023-2024學(xué)年第二學(xué)期期末試卷
- 湖南工學(xué)院《程序設(shè)計(jì)基礎(chǔ)理論》2023-2024學(xué)年第二學(xué)期期末試卷
- 畢節(jié)工業(yè)職業(yè)技術(shù)學(xué)院《裝飾設(shè)計(jì)基礎(chǔ)》2023-2024學(xué)年第二學(xué)期期末試卷
- 揚(yáng)州大學(xué)《現(xiàn)代分析》2023-2024學(xué)年第二學(xué)期期末試卷
- 古人對(duì)時(shí)間的總結(jié)
- 公司投資的基本理念及方法論
- 公共交通車輛性能檢測(cè)制度
- 《客艙設(shè)備與服務(wù)》課件-1.客艙乘務(wù)員
- 100以內(nèi)進(jìn)退位加減法口算題每天60道
- 小兒推拿健康檔案表
- 2024年南京城市職業(yè)學(xué)院單招職業(yè)技能測(cè)試題庫及答案解析
- (正式版)HGT 20593-2024 鋼制化工設(shè)備焊接與檢驗(yàn)工程技術(shù)規(guī)范
- 部編版小學(xué)語文二年級(jí)下冊(cè)第三單元集體備課教材分析
- GIS在公共衛(wèi)生與疫情防控中的應(yīng)用
- 部編版小學(xué)道德與法治三年級(jí)下冊(cè)課堂同步試題全冊(cè)(含答案)
- 【電動(dòng)汽車充電樁控制系統(tǒng)設(shè)計(jì)10000字(論文)】
- 廣告牌制作安裝應(yīng)急預(yù)案
- T-CRHA 028-2023 成人住院患者靜脈血栓栓塞癥風(fēng)險(xiǎn)評(píng)估技術(shù)
評(píng)論
0/150
提交評(píng)論