版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、實驗?zāi)康呐c要求目的:在分析理解一個教學(xué)型編譯程序(如 PL/O )的基礎(chǔ)上,對其詞法分析程序、 語法分析程序和語義處理程序進行部分修改擴充。 達到進一步了解程序編譯過程的基本原理 和基本實現(xiàn)方法的目的。要求:對 PL/0 作以下修改擴充 基本內(nèi)容 : 增加單詞:保留字 ELSE , FOR, TO, DOWNTO , RETURN運算符 +=, -=, + , - 修改單詞:不等號 # 改為 <> 增加條件語句的 ELSE 子句二、 實驗環(huán)境與工具( 1)計算機及操作系統(tǒng): PC 機, WindowsXP( 2)程序設(shè)計語言: C+Builder6( 3)教學(xué)型編譯程序: PL/0
2、三、 設(shè)計方案(1)編譯過程的流程 :PL/0 編譯過程采用一趟掃描方式 ,以語法分析程序為核心 ,詞法分析程序和 代碼生成程序都作為一個獨立的過程 ,當語法分析需要讀單詞時就調(diào)用詞法 分析程序 ,而當語法分析正確需生成相應(yīng)的目標代碼時 ,則調(diào)用代碼生成程序 此外 ,用表格管理程序建立變量 ,常量和過程標識符的說明與引用之間的信息 聯(lián)系 .用出錯處理程序?qū)υ~法和語法分析遇到的錯誤給出在源程序中出錯的 位置和錯誤性質(zhì) .當源程序編譯正確時 ,PL/0 編譯程序自動調(diào)用解釋執(zhí)行程序 對目標代碼進行解釋執(zhí)行 ,并按用戶程序要求輸入數(shù)據(jù)和輸出運行結(jié)果 .功能模塊描述:(1) 符號表:符號表為一維數(shù)組
3、TABLE ,表項為一結(jié)構(gòu)體,包括標識符的名稱,類型和表達標 識符信息的聯(lián)合體。類型分三類:常量,變量,過程。當類型為常量時,只需把常 量的值填入表中,即賦值給聯(lián)合體。 當類型為變量時,需把該標識符的層次,地址 信息填入表中,當為過程時,還需要整個過程的大小的信息。TX為TABLE表的指針,DX為局部變量在說明層中的相對位置,程序中每一層的DX從4開始,DX0-DX3分別分配給返回值單元,靜態(tài)鏈,動態(tài)鏈和程序返回地址,此后每識別一個變量DX 加 1。struct ALFA NAME;OBJECTS KIND;union int VAL; /*CONSTANT*/struct int LEVEL
4、,ADR,SIZE; vp; /*VARIABLE,PROCEDUR:*/; TABLETXMAX;(2) 運行時存儲組織和管理:解釋程序定義一個一維整型數(shù)組 S作為運行棧,棧頂寄存器(指針) t,基址寄 存器(指針)b,程序地址寄存器P,指令寄存器i。在每個過程調(diào)用時在棧頂分配 4個聯(lián)系單元: 由于添加了返回值,所以當前過程的活動記錄的棧頂為存放返回值的單元。 SL: 靜態(tài)鏈,指向定義該過程的直接外過程(或主程序)運行時最新數(shù)據(jù)段的基 地址。當一個過程引用包圍它的過程(或主程序)所定義的標識符時,首先 沿靜態(tài)鏈跳過個數(shù)為層差的數(shù)據(jù)段,找到定義該標識符過程的數(shù)據(jù)段地址, 再加上給此標識符分配的
5、相對位置,就得出該標識符在整個數(shù)據(jù)區(qū)棧中的絕 對位置。DL: 動態(tài)鏈,指向調(diào)用該過程前正在運行過程的數(shù)據(jù)段基地址。RA: 返回地址,記錄調(diào)用該過程時目標程序的斷點,即調(diào)用過程指令的下一條指 令的地址。動態(tài)鏈和返回地址的作用是當一個過程運行結(jié)束后, 為了恢復(fù)調(diào)用該過程前的執(zhí)行 狀態(tài)而設(shè)置的。(3 )自頂向下的語法分析 : 遞歸子程序法:對應(yīng)每個非終結(jié)符語法單元編一個獨立的處理過程(或子程 序)。語法分析從讀入第一個單詞開始,由非終結(jié)符程序 (即開始符)出發(fā),沿語法描述圖箭頭所指出的方向進行分析。 當遇到非終結(jié)符時, 則調(diào)用相應(yīng)的處理過 程,從語法描述圖看, 也就進入了一個語法單元, 再沿當前所進
6、入的語法單元所指 箭頭方向繼續(xù)進行分析。 當遇到描述圖中是終結(jié)符時, 則判斷當前讀入的單詞是否 與圖中的終結(jié)符相匹配, 若匹配,再讀取下一個單詞繼續(xù)分析。遇到分支點時,將 當前的單詞與分支點上多個終結(jié)符逐個相比較, 若都不匹配時可能是進入下一個非 終結(jié)符語法單位或是出錯。(4 )中間代碼表示:由于添加了返回值,增加了一條指令 DEL用于返回。ret 0,0與OPR 0,0 的區(qū)別是 ret 0,0 先把返回值放到活動記錄的返回值單元,并把棧頂指針 指向返回值單元, 當被調(diào)用程序返回時, 調(diào)用程序就可以在當前運行棧棧頂取得 被調(diào)用程序的返回值。四測試用例基本內(nèi)容1. 正確符號測試程序 :test
7、1COMPILE PL0TEST1-PL00 正確符號測試程序* A0* A應(yīng)是語句開始符A11 標識符未說明k-k-kk-k-kA13 賦值語句左部標識符后應(yīng)是賦值號A19 語句后的符號不正確2 Correct Symbols 2 Comment 2 abcdefghijklmnopqrstuvwxyz2 ABCDEFGHIJKLMNOPQRSTUVWXYZ2 1234567890 !"#$% & '()*+,-./:;<=>?_'0 JMP 0 11 INI 0 32 LIT 0 03 RET 00*A9 程序結(jié)尾丟了句號 '.'
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è)計心得:1. 通過這個課程設(shè)計的學(xué)習(xí)使 我更深地了解了編譯原理及其應(yīng)用。2. 團體精神互相合作很重要。 在做設(shè)計的過程中遇到了不明白的問題時與同宿舍的 同學(xué)進行了討論,可能在有些地方與之有類似之處,請老師理解!3. 提高了自學(xué)能力, buildr 以前是沒有怎么學(xué)過的,通過了這次的設(shè)計,也使多進 一步掌握了 buildrt 的應(yīng)用!雖然課程設(shè)計不能獨自一個人完成,但真的學(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; /* 標示符的長度為 10*/const NORW = 20; /* 保留字的個數(shù)為 20*/ const TXMAX = 100; /* 標示符表的最大長度為 100*/const
11、NMAX = 14;/*數(shù)字最大位數(shù)為14*/constAMAX =2047;/*最大尋址為 2047*/constLEVMAX= 3;/*嵌套最大層數(shù)為3*/constCXMAX = 200;/*代碼數(shù)組最大為200*/constNumOfSybol=43;/ 定義關(guān)鍵保留字 33 個typedef int *ERRORPOINT;typedef enum NUL, IDENT, NUMBER, PLUS, MINUS, TIMES,SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ,LPAREN, RPAREN,QUOT,/ 單引號 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 個 */ char *SYMOUT = "NUL", "IDENT", "NUMBER", "PLUS", "MINUS", "TIMES", "SLASH", "ODDSYM", "EQL", "NEQ", "LSS", "LEQ", "GTR", "GEQ"
14、;, "LPAREN", "RPAREN","QUOT",/ 單引號"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在運行棧中為被調(diào)用的過程開辟 A 個單元的數(shù)據(jù)區(qū)JMP0A無條件跳轉(zhuǎn)到 A 地址JPC0A條件跳轉(zhuǎn) ,當棧頂布爾值非真則跳轉(zhuǎn)到 A 地址 ,否則順序執(zhí)行OPR00過程調(diào)用結(jié)束后 ,返回調(diào)用點并退棧OPR01棧頂元素取反OPR02次棧頂與棧頂相加 ,退
18、兩個棧元素 ,結(jié)果值進棧OPR03次棧頂減去棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR04次棧頂乘以棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR05次棧頂除以棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR06棧頂元素的奇偶判斷 ,結(jié)果值在棧頂OPR07OPR08次棧頂與棧頂是否相等 ,退兩上棧元素 ,結(jié)果值進棧OPR09次棧頂與棧頂是否不等 ,退兩個棧元素 ,結(jié)果值進棧OPR010次棧頂是否小于棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR011次棧頂是否大于等于棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR012次棧頂是否大于棧頂 ,退兩個棧元素 ,結(jié)果值進棧OPR013次棧頂是否小于等于棧頂 ,退兩個棧元素 ,結(jié)
19、果值進棧OPR014棧頂值輸出到屏幕OPR015屏幕輸出換行OPR016從命令行讀入一個輸入置于棧頂*/ char CH; /* 最近讀進的字符 */SYMBOL SYM; /* 存放每個單詞的類別 ,用內(nèi)部編碼形式表示 */ALFA ID; /* 存放用戶所定義的標識符的值 ,即字符串的機內(nèi)表示 */ int NUM; /* 用戶所定義的數(shù) */intCC;/*CHARACTER COUNT*/intLL;/* 緩沖器的長度 */intCX;/*CODE 數(shù)組的下標索引 */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;/錯誤個數(shù)統(tǒng)計String
21、 ERRORKIND34 = ""," 常數(shù)說明中的 '='寫成 ':='",/1" 常數(shù)說明中的 '='后應(yīng)是數(shù)字 ", /2" 常數(shù)說明中的標識符后應(yīng)是 = 號",/3"CHAR,CONST,VAR,PROCEDURE 后應(yīng)為標識符 ", /4 " 漏掉了 ','或''",/5" 過程說明后的符號不正確 ",/6" 應(yīng)是語句開始符 ",/7"
22、程序體內(nèi)語句部分的后跟符不正確",/8" 程序結(jié)尾丟了句號 '.'",/9" 語句之間漏了 ''",/10" 標識符未說明 ",/11" 賦值語句中 ,賦值號左部標識符屬性應(yīng)是變量 ",/12" 賦值語句左部標識符后應(yīng)是賦值號':='",/13"CALL 后應(yīng)為標識符 ", /14"CALL 后標識符屬性應(yīng)為過程 ", /15"條件語句中丟了 THEN'或'ELSE'
23、;",/16" 丟了 'END' 或 ''",/17"WHILE 型循環(huán)語句中丟了 'DO'",/18"語句后的符號不正確 ",/19" 應(yīng)為關(guān)系運算符 ",/20" 表達式內(nèi)標識符屬性不能是過程 ",/21" 表達式中漏掉右括號 ')'", /22" 因子后的非法符號 ",/23" 表達式的開始符不能是此符號 ",/24"FOR 語句后應(yīng)有 TO 或
24、DOWN", /25" 字符類型不符 ",/26" 字符類型漏了 '''單引號 ",/27"READ 函數(shù)內(nèi)的標識符沒定義 ", /28 "NUL", /30" 數(shù)越界 ",/31"READ 語句括號中的標識符不是變量 " /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;/* 錯誤處理 : 打印出錯位置和錯誤編碼*/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() /* 漏掉空格 ,讀取一個字符 */*CH: 存放當前讀取的字符 ,初始值為空LINE: 為一維數(shù)組 ,其數(shù)組元素是字符 ,界對為 1:800.用于讀入一行的緩沖區(qū) LL: 計數(shù)器 ,初始值為 0.CC:計數(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; / 逐個放到 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() /* 詞法分析 ,讀取一個單詞 */* 完成的任務(wù) :(1) 濾空格 :(2) 識別保留字 :設(shè)有一張保留字表 ,對每個字母打頭的字母 ,數(shù)字字符串要查此表 若查著則為保留字 ,將對應(yīng)的類別放在 SYM 中,若查不著 ,則認為是用戶定義的標識符(3)識別標識符 :對用戶定義的標識符將 IDENT 放在 SYM 中 ,標識符本身的值放在 ID 中;NUM 中 .(4)拼數(shù) :當所取的單詞
34、是數(shù)字時 ,將數(shù)的類別 NUMBER 放在 SYM 中,數(shù)值本身的值存放的 (5)拼復(fù)用詞 :對兩處字符組成的算符識別后將類別送SYM 中 ;(6) 輸出源程序 :為邊讀入字符邊輸出 (可輸出在文件中 ).A: 維數(shù)組.數(shù)組元素為字符,界對1:10,存放讀進的標識符.ID: 同 A.WORD: 保留字表 ,一維數(shù)組 .數(shù)組元素是以字符為元素的一維數(shù)組.界對為 1:13.查表方式采用二分法 .*/int i,J,K; ALFA A; /存放讀進的標識符 .while (CH<=' ') GetCh();/濾空格并濾掉控制字符 ,因為 ' '之前的都是控制字符
35、if (CH>='A' && CH<='Z') /* 如果是標識符 */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)鍵保留字的個數(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;/否則為用戶定義的標識符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 位時則出錯 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ù) :生成目標代碼 ,并送入目標程序區(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、測試當前單詞符號是否合法 */ /*S1:當語法分析進入或退出時某一語法單元時當前單詞符號應(yīng)屬于的集合S2:某一出錯狀態(tài)時,可恢復(fù)語法分析繼續(xù)正常工作的補充單詞符號集合N:錯誤類型號*/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+;/ 當前的 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) /* 查找標識符在名字表中的位置 */*看是否有過正確的定義*/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ù)說明中的標識符后應(yīng)該是"="else Error(4);/Const ,var,procedure 后邊應(yīng)為標識符 /*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)為標識符 /*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)為標識符 /*CharDecla
46、ration()*/void ListCode(int CX0) /*L 列出目標代碼清單 */if (Form1->ListSwitch->ItemIndex=0)for (int i=CX0; i<CX; i+) /*CX:CODE 數(shù)組的下標索引 */ 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); / 標識符未說明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: 當前的 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); / 標識符未說明 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; /表達式內(nèi)標識符屬性不能是過程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);/ 表達式處理if (SYM=RPAREN) GetSym();else Error(22);/ 表達式中漏掉了右括號 ')' TEST(FSYS,FACBEGSYS,23);/*FACTOR*/void TERM(SYMSET FSYS, int LEV , int &TX) /* 項處理 */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 次棧頂乘以棧頂 ,退兩個棧元素 ,結(jié)果值進棧 else GEN(OPR,0,5); /OPR 0 5 次棧頂除以棧頂 ,退兩個棧元素 ,結(jié)果值進棧 /*TERM*/;/void EXPRESSIO
54、N(SYMSET FSYS, int LEV, int &TX) /*表達式處理 */SYMBOL ADDOP;if (SYM=PLUS | SYM=MINUS) ADDOP=SYM; GetSym();TERM(SymSetUnion(FSYS,SymSetNew(PLUS,MINUS),LEV ,TX); / 項處理if (ADDOP=MINUS)GEN(OPR,0,1); /OPR 0 1 棧頂元素取反/ 改造增量運算開始 else if(SYM=DOUBLEPLUS|SYM=DOUBLEMINUS) / 添加增量計算 DOUBLEOP(LEV ,TX); /調(diào)用增量計算函數(shù) +
55、或 -/改造增量運算結(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 次棧頂與棧頂相加 ,退兩個棧元素 ,結(jié)果值進棧 else GEN(OPR,0,3);/OPR 0 3 次棧頂減去棧頂 ,退兩個棧元素 , 結(jié)果值進棧 /*EXPRESSION*/v
56、oid CONDITION(SYMSET FSYS,int LEV ,int &TX) /* 條件處理 */SYMBOL RELOP;if (SYM=ODDSYM) GetSym();EXPRESSION(FSYS,LEV ,TX);/ 表達式處理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)系運算 else RELOP=SYM; GetSym(); EXPRESSION(FSYS,LEV,TX);switch (RELOP) case EQL: GEN(OPR,0,8); break;/OPR8 次棧頂與棧頂是否相等 ,退兩上棧元素 , 結(jié)果值進棧case NEQ: GEN(OPR,0,9); break;/OPR9 次棧頂與棧頂是否不等 , 退兩個棧元素 , 結(jié)果值進棧case LSS: GEN(OPR,0,10); break;/OPRcase GEQ: GEN(OPR,0,11); break;/OPR10 次棧頂是否小于棧頂 ,退兩個棧元素 ,結(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度藥店員工績效考核合同3篇
- 2024年度環(huán)保公益活動贊助協(xié)議3篇
- 2024版光伏發(fā)電項目建筑材料承包合同3篇
- 2024版吊裝運輸勞務(wù)派遣服務(wù)合同3篇
- 2024年度企業(yè)社會責任報告編制與咨詢合同3篇
- 2024廚師聘用協(xié)議書9篇
- 污水管網(wǎng)改造提升項目計劃書
- 圖書館數(shù)字化管理的實施路徑與方案設(shè)計
- 美麗鄉(xiāng)村配套污水處理設(shè)施工程項目招商引資報告
- 2024年度退婚協(xié)議書撰寫與法律風險提示服務(wù)3篇
- 《壓力平衡式旋塞閥》課件
- 物聯(lián)網(wǎng)與人工智能技術(shù)融合發(fā)展年度報告
- 婦產(chǎn)科醫(yī)生醫(yī)患溝通技巧
- 內(nèi)科學(xué)糖尿病教案
- 《高尿酸血癥》課件
- 微量泵的操作及報警處置課件查房
- 云南省昆明市西山區(qū)2023-2024學(xué)年七年級上學(xué)期期末語文試卷
- 人教版小學(xué)數(shù)學(xué)四年級上冊5 1《平行與垂直》練習(xí)
- 市政設(shè)施養(yǎng)護面年度計劃表
- 公差配合與技術(shù)測量技術(shù)教案
- 堅持教育、科技、人才“三位一體”為高質(zhì)量發(fā)展貢獻高校力量
評論
0/150
提交評論