




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、 編譯原理實驗二 姓 名:朱彥榮學 號:20132184 專 業:軟件工程2 實驗題目:算符優先分析文法 完成語言:C/C+ 上級系統:VC+6.0 日 期:2015/11/24 算符優先分析文法設計一 任務:實驗目的:1.了解掌握算符優先分析的基本方法、內容;2.學會科學思考并解決問題,提高程序設計能力。實驗內容與要求: 用算符優先分析方法設計一個分析解釋程序,對輸入的賦值語句、輸出語句、清除語句進行詞法分析、語法分析、表達式求值并存儲于指定變量中;若存在錯誤,提示錯誤相關信息。文法表示:Sv=E|E?|clearEE+T|E-T|TTT*F|T/F|FF (E)|v|c 單詞種別碼設計:
2、= 1 ? 2 + 3 - 4 * 5 / 6 ( 7 ) 8 v 9 c 10 clear 11 # 12 N 13可歸約串語義解釋: 變量歸約;常量歸約;運算歸約;括號歸約; 賦值語句;輸出語句;清除語句。演示示例: a=5 b=a+10 b? b+a*a? a=a+b 二 分析: 首先,這是一個很好的題目,從知識的理解、將形式化的東西轉化成具體的過程、編程能力、編程技巧、調試改錯能力等多個方面考察了我們的學習情況。 算符優先文法是一種自下而上的文法分析方法,這種方法的用處十分廣泛,雖然有的文法不能用算符優先分析文法,如類似PQ.(P,Q為非終結符)這樣形式的產生式,但是對于大部分文法這種
3、分析方法還是十分有用的。 其次,對于本程序中的文法,實質上是算數表達式的計算。用這種文法就是再好不過了,作為從算符文法抽象出來的算符優先文法當然繼承了算符文法的特性。下面就切入正題了,我將詳細介紹一下我對于這個文法的思考出發點和分層分析的方法。 模塊一:構建firstVT()和lastVT()這兩個集合?;凇皟炏取边@兩個字,有效的回避了左遞歸(自上而下文法分析)和二義性的問題。關鍵是如何體現“優先”這兩個字。這就需要firstVT()和lastVT()集合了。firstVT(E)=a|Eàa.|EàQa.|firstVT(Q),從這個定義可以看到,firstVT()主要找
4、到是本產生式中的第一個非終結符和若第一個是非終結符則包含該非終結符的firstVT()集,因為firstVT有可能要求Q的firstVT()集,因此有可能要用遞歸才能求盡所有的firstVT()集。同理,lastVT(E)=a|Eà.a|Eà.aQ,可見這兩個關系好像反對稱的影像。說了這么多,還是沒有說到這兩個集合要干什么用。讓我們想象一個句型aQ.在這個句型中我們知道只有等Q的短語規約為Q了,才有可能將aQ.再次向上規約,因此a的優先級要小于Q產生式的firstVT(Q)集,因為我們可以斷定a必定是比Q中第一個出現的終結符優先級低的,也就是說優先級a<優先級firs
5、tVT(Q),至于第二個,第三個終結符。我們不敢判定。于是才要費盡心思地構造firstVT()這樣的一個集合。同理,對于lastVT(),讓我們想一下這種情況.Qa.,對于這個句型我們知道只有當Q的短語歸約成了Q,我們才敢將.Qa向上歸約。這樣的話就是說Q的產生式中最后出現的一個終結符的優先級必定是比a的優先級高的,也就是優先級lastVT(Q)>優先級a,同樣的對于倒數第二個,倒數第三個終結符。我們不敢判定。說了這么多我想應該能夠理解這兩個集合存在的必要性和決定性了。因為是程序,我就說一下程序如何實現這兩個集合的求解。 首先是一些數據結構和意義: char FIRSTVT2020; 存
6、儲firstVT()集,第二維代表第幾個產生式,第一維代表集合中的第幾個元素 char LASTVT2020; 存儲lastVT()集,第二維代表第幾個產生式,第一維代表集合中的第幾個元素 char INPUT2020; 按照一定的形式存儲文法中的所有產生式。然后是幾個函數:1. void setFIRSTVT(char X,int T);這個函數的目的是將求出的終結符X,存放到第T條產生式的左部對應的firstVT集合中。2. void getFIRSTVT(char X,int S)S標記產生式的位置,X為將要計算的產生式的左部。這個函數就比較復雜了,它將完成求出一個產生式左部的first
7、VT的終結符的重要任務,可以說是主控程序了。它的算法是逐個遍歷產生式,對每個產生式求出該產生式的直接a,并且若有EàQa還要遞歸的求出Q的firstVT()將其并入firstVT(E)的集合中。3. 同理void setLASTVT(char X,int T)4. void getLASTVT(char X,int S)和上面類似。5. void DisplayFirstVT_LasVT() 這個函數也是主程序開始時要進入的位置。它主要提示用戶輸入文法(產生式組),然后調用上面的函數計算并顯示兩種集合。下面是void getFIRSTVT(char X,int S)的函數。/找出FI
8、RSTVT集元素void getFIRSTVT(char X,int S) int i,j=0,k;/j當前數組指針 int T=0;/X position int L=0;/X offspring length char C20; for(i=0;i<20;i+) if(INPUTi0=X)/找到將要處理的產生式 T=i; /標記產生式的位置 break; /按照規則從產生式的右部第一個字符開始處理,直至遇上'/n'/每一次都判斷指針j指向的字符若滿足p->w中w的規定則放進C/若遇上|或'n'則求這段右部對應的firstVT() for(i=4;
9、i<20;i+) if(INPUTTi='|'|INPUTTi='n')/剛開始走不到這里 L=j;/j指針所指位置為C中字符串的長度 j=0;/交給L后就清零,以供下一次使用 for(k=0;k<L;k+) /要是數組C中的終結符,如小寫字母'a''z',加減乘除,乘方,#/則歸入fisrstVT集中 /若是Aab.則a成為F()一部分,b被忽略,A也不用求first集?需要求!除非A=X /若是QRa.,則不是算符優先文法,故不可能 /若是a.則只是填進a if(Ck>=97&&Ck<=
10、122)|Ck='+'|Ck='*'|Ck='-'|Ck='/'|Ck='!'|Ck='('|Ck=')'|Ck='#'|Ck='?'|Ck='=') /只能用一次,因是算符優先文法,故前兩個中必會至少存在一個終結符 setFIRSTVT(Ck,S);/存入FIRSTVT中,S標記產生式的位置 break;/跳出循環保證存入的是最左邊的終結符 if(C0>=65&&C0<=90&&C0!=X)
11、 /若C0中為AZ,并且C0不是X(否則將無限循環),則遞歸的進行填充 int flag=0,count; for(count=0;count<20;count+) if(INPUTcount0=C0)/找到將要處理的產生式 flag=1;/若存在,則填充 if(flag=1)/遞歸,所用極妙,畫龍點睛 getFIRSTVT(C0,S);/S為子集中的元素填入父集中指明了方向 else if(INPUTTi!='|'&&INPUTTi!='0')/該行沒結束,過濾'0' Cj=INPUTTi;/j從0開始 j+;/移進 if
12、(INPUTTi='n')/該行結束break; 比如說對于這個文法分析出的集合如下: 模塊二:構建優先符號表。為了體現“優先”的關系,只是構建出了上面的兩種集合是不夠的,由上面分析我們知道了這兩個集合的用處。說白了就是為了構造出算符優先分析表。因為關系無非四類1.等于,2.大于,3.小于,4沒有關系。注意這里的“沒有關系”也是一種關系。而由第一個階段產生的兩個集合就可以找到所有的大于和小于關系,那就只剩下了等于關系,如果等于關系找到了,剩余的沒有填寫的關系就是沒有關系。等于關系是這樣的:如果存在這樣的句型.ab.或.aQb.則關系(a=b)。這樣的結果也是顯而易見的,因為a和
13、b注定要共同歸約,沒有誰先誰后,因此是等于關系。好了現在所有關系都搞請了,就可以建表了。還是首先解釋一下新定義的一個數據結構:char PriorityTable2020;優先關系表,其中存放著終結符以及終結符對應的關系。然后是一些函數:1. int IsVT(char ch) 判斷ch是否為終結符,若是則返回1,否則返回0 2.int SearchTbl(char ch) 搜索終結符ch在符號表中的行列數,用來定位將要填寫的位置。 3.int FL_map(char ch) 這個映射既是查找產生式左部的位置,若存在則返回該產生式的條數,即是第幾個產生式,失敗則返回-1這個出錯標記。 4.vo
14、idcreatePriorityTable() 這個是建表的主控程序,用來填寫所有關系與表中。遍歷所有的產生式,填寫所有的關系。這里主要解釋一下程序是如何找到橫縱坐標并且將關系填寫進去的。對于簡單的情況只要拿一個終結符來使用SearchTbl(終結符)就可以找到橫(縱)坐標了,但是因為對于大小關系我們往往要填的是“終結符<firstVT()”或“lastVT()>終結符”這樣的情況,因此勢必要從集合中取出終結符,并用該終結符來映射坐標,即是用到了類似這樣的轉換:temp_column=FIRSTVTFL_map(C2)count_1; tbl_column=SearchTbl(te
15、mp_column);/將上述結果再次轉換或者temp_row=LASTVTFL_map(C1)reg;tbl_row=SearchTbl(temp_row);/map這樣的映射。知道了這些程序不難讀懂。5. void DisplayPriorityTable()這個函數就是顯示優先關系表的內容的。下面是 voidcreatePriorityTable() 函數的實現過程:voidcreatePriorityTable()/創建并填寫優先級表/對每個產生式遍歷,求出四種關系1.=,2.<,3.>,4.沒有關系 char temp13='+','-',
16、'*','/','(',')','v','c','=','?','#','0' int j,L,i; int tbl_row,tbl_column;/表的元素坐標 char C20; for(int r=1;r<12;r+) PriorityTable0r=tempr-1;/初始化行頭,第0行PriorityTabler0=tempr-1;/初始化第0列 /掃描產生式的右部,如果發現終結符且該終結符周圍有其他字符 /若該其他字符為
17、終結符,則這兩者關系為相等 /若該其他字符為非終結符,則根據非終結符的firstVT,LastVt填表 for(int p=0;p<4;p+) j=0; for(i=4;i<20;i+) /注意,此處因為時間有限考慮不是很全面,只是對老師給定的文法進行了周密的部署 /在別的文法上可能需要少許加工,不是問題 if(INPUTpi='|'|INPUTpi='n') /剛開始走不到這里 L=j;/j指針所指位置為C中字符串的長度 j=0;/交給L后就清零,以供下一次使用 if(L>1)/大于一則處理,否則不關心 /對于清零指令l自動忽略 if(IsV
18、T(C0)&&IsVT(C1)|(L=3)&&IsVT(C0)&&IsVT(C2)&&(FL_map(C1)!=-1) /若為終結符因至少有兩個,若出現兩個終結符則C0'='C1|C2,注意這是此文法的情況 /則需要填表,查表找到C0的行數,C1,C2的列數進行填表 tbl_row=SearchTbl(C0);/記錄行數 if(IsVT(C1) /列數,若是終結符 v= tbl_column=SearchTbl(C1); if(IsVT(C2)&&(L=3) /列數 (E) tbl_column=S
19、earchTbl(C2); PriorityTabletbl_rowtbl_column='='/填表 if(L=3)&&IsVT(C0)&&IsVT(C1)&&(FL_map(C2)!=-1) /v=E,這種情況 int count_1=0; char temp_column; tbl_row=SearchTbl(C1);/ =<firstVT(E) while(FIRSTVTFL_map(C2)count_1!='0') /填寫小于關系 temp_column=FIRSTVTFL_map(C2)count
20、_1;/映射,仔細體會 tbl_column=SearchTbl(temp_column);/將上述結果再次轉換 PriorityTabletbl_rowtbl_column='<'/填寫關系 count_1+;/準備填寫下一個 count_1=0;/清零 if(L=3)&&IsVT(C0)&&IsVT(C2)&&(FL_map(C1)!=-1) /彌補(E),針對本文法/首先填寫<關系 char temp_row,temp_column; int reg=0; tbl_row=SearchTbl(C0); while
21、(FIRSTVTFL_map(C1)reg!='0') /填寫小于關系 '('<firstVT(E) temp_column=FIRSTVTFL_map(C1)reg; tbl_column=SearchTbl(temp_column);/皆是映射 PriorityTabletbl_rowtbl_column='<' reg+; reg=0;/清零 tbl_column=SearchTbl(C2); while(LASTVTFL_map(C1)reg!='0') /填寫大于關系 lastVT(E)>')&
22、#39; temp_row=LASTVTFL_map(C1)reg; tbl_row=SearchTbl(temp_row);/map PriorityTabletbl_rowtbl_column='>' reg+; reg=0;/reset else if(FL_map(C0)!=-1)&&IsVT(C1) /C0肯定為非終結符lastVT(C0)>C1 /填寫大于關系 char temp_row,temp_column; int count=0; tbl_column=SearchTbl(C1); while(LASTVTFL_map(C0)co
23、unt!='0') /填寫大于關系 temp_row=LASTVTFL_map(C0)count; tbl_row=SearchTbl(temp_row);/同上 PriorityTabletbl_rowtbl_column='>' count+; count=0; if(L=3) /在這種情況下C2必為非終結符,求C2的firstVT(),填寫小于關系 /E+T,E-T,T*F,T/F等情況 tbl_row=SearchTbl(C1); while(FIRSTVTFL_map(C2)count!='0') /填寫小于關系 temp_col
24、umn=FIRSTVTFL_map(C2)count; tbl_column=SearchTbl(temp_column);/map PriorityTabletbl_rowtbl_column='<' count+; count=0; /end if else if(INPUTpi!='|'&&INPUTpi!='0')/該行沒結束,過濾'0' Cj=INPUTpi;/j從0開始 j+;/移進 if(INPUTpi='n') /該行結束break; /補上#的關系for(int m1=1;m
25、1<11;m1+)PriorityTableSearchTbl('#')m1='<'/這個容易理解,補行for(int m2=1;m2<11;m2+)PriorityTablem2SearchTbl('#')='>'/補列PriorityTableSearchTbl('#')SearchTbl('#')='='比如說對于這個文法分析出來的優先關系表如下: 模塊三:構建詞法分析的程序做好了上面兩步運算已經累得不行了,下面還要繼續進行分析,那就是詞法分析程序,多虧
26、這個程序在實驗一已經完成過,這里就拿出那里的代碼進行必要的改進和刪除,保留適合本文法要求的部分即可。其實想來無非是用到了識別標識符、識別常數、識別+、-、*、/、?、#、(、)、保留字clear等符號的算法罷了。還是比較好寫的。但考慮到后面的運算,也就是最精彩的部分a=3;b=a+3;這樣的句子,我們不得不在進行詞法分析的時候將這些標識符登記到標識符表中,將句子打碎成二元組存放到符號表中。注意這里的符號表沒有什么其他意義,就是存放將句子解釋成的有序序列罷了。綜上所述,詞法分析這一過程就是識別字符串,若正確則填表,若錯誤,則報錯。兩個任務:填表、報錯。由此也可以看到表格處理和錯誤處理在整個編譯過
27、程中無處不在。這里新增了一些數據結構和全局變量:typedef struct char IDentifier30;/標識符長度 int value;/定義標識符代表的數值IDentifierTable;typedef struct int syn;/種別碼 int value;/數值或者標識符入口指針SymbolTbl;IDentifierTable idTbl30;/定義全局標識符表SymbolTbl symbol100;/定義符號表,記錄輸入的程序片段下面是這一模塊的具體的函數:1. void InsertID(char name,int entry,int value)功能是將標識符的名
28、字和數值插入到以entry為標識符入口地址的標識符表中。2. int ScanEntry(char name) 查找標識符表中是否有空閑位置,若有則返回入口地址,若無則報錯。3.void Insert_Into_SymbolTbl(int syn,int value,int &pointer)將句子打散成的所有的二元組(名字和數值)插入到以pointer為符號表入口地址的符號表中。4. bool IsExist(char id) 查找表中是否已經存在該標識符5.int Search_Free_Entity( )這個函數即是在標識符表中申請一個可用的存儲空間,若有則返回入口地址,否則報錯
29、,申請失敗。6. bool IsLetter(char letter)判斷是否為字母7. bool IsDigit(char digit) 判斷是否為數字8.void Scanner(char sentence,char name,int &syn,int &scan_point,int &value)掃描子程序,識別正規式。對句子進行掃描,拋出一個個單詞。scan_point為掃描的總指針,name和value用來記錄返回值;sentence即是要分析的句子;syn為種別碼。這個程序是詞法分析的核心,在上一實驗中已詳細介紹過,再次不必贅述。9. bool Check_
30、Is_Right(char sentence)檢查句子是不是#。#的形式,因為程序的需要,輸入的句子規定必須是這樣的形式。10. void LexicalAnalysisCtl()詞法分析的主控程序,也就是老師上課一再講的那個主控程序。這個程序控制著Scanner(char sentence,char name,int &syn,int &scan_point,int &value)產生不同的正規式,并且負責著登記數據和錯誤處理。11. void Clear_Symbol_Tbl()這個函數負責著清除符號表中的句子,以便接下來的句子輸入。12. void Clear_I
31、Dentifier_Tbl() 這個函數的功能是清楚標識符表的所有內容。一般會在“清除語句”中使用。下面是Scanner的程序:void Scanner(char sentence,char name,int &syn,int &scan_point,int &value)char token30,ch;int p_token=0;/token的指針int digit_value=0;/記錄常數的大小for(int n=0;n<30;n+) tokenn='0'/對字符數組清零ch=sentencescan_point; /讀入一個字符if(ch=
32、'#'&&scan_point=0)/該字符的種別碼已經在主程序中登記了scan_point+;/剛開始的第一個字符一定為#ch=sentencescan_point;/指針下移,掃描下一字符 if(IsLetter(ch) /ch是否為字母while(IsLetter(ch)|IsDigit(ch) /ch是否為字母或數字 tokenp_token+=ch; scan_point+; ch=sentencescan_point; /讀入一個字符tokenp_token='0'syn=9;/代表找到了標識符if(strcmp(token,&quo
33、t;clear")=0)/代表找到了保留字“clear”syn=11;strcpy(name,token);/帶回標識符else if(IsDigit(ch) /ch是否為數字 digit_value=0; while(IsDigit(ch) /此處假設只是整數 digit_value=digit_value*10+ch-'0' scan_point+; ch=sentencescan_point; /讀入一個字符 value=digit_value;/帶回整數值 syn=10; else switch(ch) case'=':syn=1; break
34、;case'?':syn=2; break;case'+':syn=3; break;case'-':syn=4; break;case'*':syn=5; break;case'/':syn=6; break; case'(':syn=7; break;case')':syn=8; break;case'#':syn=12; break;default:printf("輸入句子有誤!n");exit(0);break; scan_point+;/
35、保持指針始終指向待判斷的字符ch=sentencescan_point; /讀入一個字符 下面是主控程序:void LexicalAnalysisCtl()/主控程序char sentence100="0"int syn=-1; char name30=""int value;int scan_point=0;/從開始處掃描int id_pointer;/定義標識符表入口指針int sym_pointer=0,entry;do printf("請輸入句子,以#開始并且以#結束n"); scanf("%s",sent
36、ence);while(!Check_Is_Right(sentence);Insert_Into_SymbolTbl(12,-1,sym_pointer);printf("(%d , )n",12); while(syn!=12)/直到掃描到第二個#為止 Scanner(sentence,name,syn,scan_point,value); switch(syn) /若是單詞 case 9:printf("(%d , %s)n",syn,name); /登記到表中 if(!IsExist(name) /不存在則插入 /查找可插入位置 id_point
37、er=Search_Free_Entity(); InsertID(name,id_pointer,-1);/-1代表還沒被賦值 /搜索該標識符的入口地址放入value中 entry=ScanEntry(name); Insert_Into_SymbolTbl(syn,entry,sym_pointer); break; case 10:/常數 Insert_Into_SymbolTbl(syn,value,sym_pointer); printf("(%d , %d)n",syn,value); break; default:printf("(%d , )n&q
38、uot;,syn); Insert_Into_SymbolTbl(syn,-1,sym_pointer);/-1代表該處不需要值 printf("-詞法分析正確!-n");/打印出符號表和標識符表 printf("標識符的入口地址 標識符 標識符的值(-1代表沒被賦值)n"); for(int m1=0;m1<30;m1+)/標識符表 if(!(strcmp(idTblm1.IDentifier,"")=0) printf("t%d %s %dn",m1,idTblm1.IDentifier,idTblm1.
39、value); printf("符號表的入口地址 種別碼 具體的值(或標識符入口)n"); for(int m2=0;m2<sym_pointer;m2+)/符號表printf("t%d %d %dn",m2,symbolm2.syn ,symbolm2.value);printf("-n");比如說對于#temp=2+(3*(2+4)#這個句子的詞法分析結果為: 模塊四:核心功能模塊-算符優先分析 前面做了那么多鋪墊就是為了算符優先分析做準備。到了這一步,真的很不容易,因此我們更要對今天的編譯器的處理能力感到驚嘆,的確不是一個
40、人可以完成的,就算一個人可以完成那所用的時間也真的不值。但是對于我們來說,學習一些編譯原理上的一些處理問題的辦法和角度,對我們未來的工作和生活絕對是大有裨益的。好了,就說一說這個費了我兩天才完成的核心程序吧。其實,核心程序并沒有那么難以理解!只要我們舉幾個簡單的例子,模擬一下計算機在處理這個句子的過程,便不難寫出程序。 首先分析我們現在有什么? 1.現在的情況是已經分析出了句子的單詞,并且變成了單詞塊,存放在SymbolTbl symbol100中,單詞的形式是(種別碼,常數值)(種別碼,標識符入口地址)、(種別碼,用-1表示無意義)這是三大類。 2.并且分析出了標識符存放在了IDentifi
41、erTable idTbl30中。標識符的形式是(標識符名字,標識符的值),用-1表示暫未被賦值(這里就湊合一點,時間比較緊,待改進)。 3.分析出了算符優先分析的優先關系表存放在char PriorityTable2020中。 4.已經編碼出了種別碼表,放在char SymbolTbl_Define15中,這個是老師要求的次序,便于一致。但又需要一次轉換,以后再說。 好了,我們已經有了這么多數據和方法(函數function),是不是馬上就可以進行下去了呢?!還不行,因為我們迫切需要一個后進先出的存儲結構來保存我們的數據,來完成我們的移進,歸約。那就是棧。我們需要構造一個這樣的棧:它的每個元素
42、的數據結構都是符號表中元素的數據結構,即為(種別碼,-),-處即為上面分析的三種情況。棧的能力主要有:template <typename T>1. T gettop() 獲得棧頂元素2.int getTopPointer() 得到棧頂指針的數值3.T traverseStack(int pointer) 定義遍歷整個棧的能力4. void push(T num) 將元素壓棧的能力5.T pop() 將元素彈出棧的能力6. Stack()top=-1; 初始化的能力7. void Clear_Stack() 清空堆棧的能力數據對象:Stack<SymbolTbl> Re
43、ource_Symbol;/定義堆棧還有幾個分析將使用的函數:char SearchSyn(int syn) 根據種別碼返回相應字符,因為我們是在對種別碼進行大小比較,需要先將該種別碼映射成具體的終結符。然后再將該終結符映射成優先關系表中的橫縱坐標。int Search_Priority_Setxy(char ch)搜索一個字符在優先符表中的位置,這就是我說的“將該終結符映射成優先關系表中的橫縱坐標?!钡挠成浞椒?。void Print_Context(int Stack_Top,int Sym_Pointer)打印出當前堆棧和符號表的上下文void MainProc_Analysis()主分析
44、函數,整個算法的核心。 好了,有了這些東西,我們的分析總算可以一馬平川了。 1.首先將符號表的第一個元素#,對應的(種別碼,-1)壓棧,即 SymbolTbl temp_sym; temp_sym.syn=12; temp_sym.value=-1;/-1代表這個地方不需要 Reource_Symbol.push(temp_sym);/將#壓棧 2.對于堆棧定義兩個指針,一個指針pStackTop始終指向棧頂,在棧被修改(push,pop)之后都要修改。另一個堆棧指針是pScanStack,負責對整個堆棧的掃描,不斷地查找可歸約串的結束位置。 對于符號表,定義Sym_scan_pointer指
45、針,從一開始,對符號表進行掃描。 3.因為現在不僅是語法分析,還包含了語義分析,我們要定義好語義子程序,比如說“清除語句”,#clear#,我們遇到這個東西時,就要1.清空符號表和標識符表;2.清除屏幕(我自己理解的,清除應該就是這些吧。) 因此,我們在進行其他分析之前,先把這個清除語句搞定。if(sym_length>=3&&(symbol1.syn=11) /清除語句,清除屏幕并且清空標號表中的值 Clear_IDentifier_Tbl(); Clear_Symbol_Tbl(); system("cls"); goto end; 4.掃除了這些
46、障礙,我們總算可以進行真正的分析了。 首先棧掃描指針和棧頂指針同時指向棧頂開始分析:下面進行永真循環:*查看棧掃描指針pScanStack所指的元素和符號表指針所指元素的關系。4.1若為小于: 則將符號表指針所指元素壓棧,修改棧的兩個指針都指向棧頂。符號表指針下移。4.2若為等于: 此時要分兩種情況:1.若是棧掃描指針pScanStack所指的元素和符號表指針所指元素都是#,則查看棧中是否只有兩個元素且棧頂元素是否為N,若為真,則說明歸約成功,輸出棧頂的值,然后結束分析。否則,則報錯。 2.若不是上面的情況,則按照小于關系處理。4.3若為大于: 這個時候,就是激動人心的時候了,因為要進行歸約了
47、。 首先對齊pStackTop,pScanStack這兩個指針,雖然這個時候肯定是對齊的(自己想),然后進入小循環 while(Prior_Relation='>'),小循環的內容是: *判斷現在棧掃描指針所指元素的種別碼,該種別碼所對應元素即是大于符號表中指針所指的元素。4.3.1若該元素為標識符:語義分析:判斷標識符是否已定義;彈出棧頂元素,將N(13,標識符的值)壓入棧中,這里取了一次巧,即是讓N來承載歸約的結果,更加方便。重新修改棧頂指針,棧掃描指針,將棧掃描指針指向從棧頂數第一個終結符的位置,即下移。pScanStack=Reource_Symbol.getTo
48、pPointer()-1;重新定位行列指針(列不變),修改關系。row_prior=Search_Priority_Setxy(SearchSyn(Reource_Symbol.traverseStack(pScanStack).syn); Prior_Relation=PriorityTablerow_priorcolumn_prior; 4.3.2若該元素為常量,則分析的過程和標識符極其相似,唯一不同的是,N(13,值)中的值,一個是從標識符表中查到的,另一個是直接就有的。4.3.3若該元素為=,這時根據文法的要求,出現等號就應該滿足“v=N”這種情況。首先判斷是否滿足,若不滿足則報錯,若
49、滿足,則將這三個元素歸約為一個元素N(13,舊N.value),并且要反填符號表,將該變量的值賦為舊N.value。這一步語義分析十分重要,直接關系著以后引用這個變量時是否能夠找到它的值。idTblReource_Symbol.traverseStack(pScanStack-1).value.value=Reource_Symbol.gettop().value;/此時棧頂必為E然后就是修改棧的兩個指針,重新定位行列(列不變),修改關系。4.3.4若該元素為+、-、*、/,則這四個的處理方式一樣。首先判斷棧頂是否滿足N op N,op=+|-|*|/,若滿足則歸約,否則認為是錯誤的,進行報錯處理。規約之后,同樣的將N op N歸約為N,并且將 “新N.value=(N1.value op N1.value)” -語義分析然后就是修改棧的兩個指針,重新定位行列(列不變),修改關系。4.3.5若該元素為),這個時候棧頂一定為(N),若不是,則句子出錯,進行錯誤處理,又因為(是大于任何終結符的,因此(N)就構成了“魚眼睛”,“< = >”,所以需
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 材料疲勞斷裂影響因素研究重點基礎知識點
- 食用油火災應急處置預案(3篇)
- 火災應急預案范文文庫(3篇)
- 動態編程與遞歸解法試題及答案
- 網絡管理員職業素養提升及試題答案
- 企業品牌建設與戰略目標試題及答案
- 編程語言趨勢及其對職業發展的影響試題及答案
- 2025年VB考試重要資料與試題及答案
- 網絡管理員職業要求與考試試題答案
- 2025年軟考增分技巧探討試題及答案
- 《陸上風電場工程概算定額》(NB-T 31010-2019)
- 小學科學冀人版六年級下冊全冊同步練習含答案
- 郵政儲蓄銀行-客戶經理(個人消費貸款)-試題+答案
- 教學能力比賽-教學實施報告(汽車運用與維修)1
- 青年筑夢之旅創業計劃書
- 髂動脈瘤破裂的護理課件
- 網絡設備的認證與授權管理最佳實踐手冊
- 山東省棗莊市山亭區2022年部編版小升初語文試卷
- 自然辯證法概論試題及答案
- 設備安全操作培訓
- 社會學知識競賽(58道含答案)
評論
0/150
提交評論