編譯原理實(shí)驗(yàn)教案_第1頁(yè)
編譯原理實(shí)驗(yàn)教案_第2頁(yè)
編譯原理實(shí)驗(yàn)教案_第3頁(yè)
編譯原理實(shí)驗(yàn)教案_第4頁(yè)
編譯原理實(shí)驗(yàn)教案_第5頁(yè)
已閱讀5頁(yè),還剩67頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

編譯原理實(shí)驗(yàn)教案授課教師:程細(xì)才編譯原理實(shí)驗(yàn)教案授課教師:程細(xì)才適用專業(yè):計(jì)算機(jī)科學(xué)與技術(shù)使用班級(jí):04計(jì)算機(jī)科學(xué)與技術(shù)1\2班授課時(shí)間:2007年春季授課學(xué)時(shí):54/44/10學(xué)時(shí)使用教材:編譯原理華中科技大學(xué)出版社何炎祥主編實(shí)驗(yàn)指導(dǎo)書(shū):編譯原理實(shí)驗(yàn)指導(dǎo)書(shū),黃石理工學(xué)院計(jì)算機(jī)學(xué)院周次日期實(shí)驗(yàn)課題學(xué)時(shí)實(shí)驗(yàn)報(bào)告次數(shù)10實(shí)驗(yàn)一C語(yǔ)言子集編譯程序(1)2011實(shí)驗(yàn)一C語(yǔ)言子集編譯程序(2)2012實(shí)驗(yàn)一C語(yǔ)言子集編譯程序(3)2113實(shí)驗(yàn)二LEX詞法分析程序生成器2114實(shí)驗(yàn)三YACC21語(yǔ)法分析程序生成器實(shí)驗(yàn)一C語(yǔ)言子集編譯程序一、實(shí)驗(yàn)?zāi)康挠肅語(yǔ)言對(duì)一個(gè)C語(yǔ)言的子集編制一個(gè)一遍掃描的編譯程序,以加深對(duì)編譯原理的理解,掌握編譯程序的實(shí)現(xiàn)方法和技術(shù)。1.設(shè)計(jì)、編制并調(diào)試一個(gè)詞法分析程序,加深對(duì)詞法分析原理的理解。2.編制一個(gè)遞歸下降分析程序,并對(duì)C語(yǔ)言的簡(jiǎn)單子集進(jìn)行分析。3.通過(guò)上機(jī)實(shí)習(xí),加深對(duì)語(yǔ)法制導(dǎo)翻譯原理的理解,掌握將語(yǔ)法分析所識(shí)別的語(yǔ)法成分變換中間代碼的語(yǔ)義翻譯方法。二、實(shí)驗(yàn)要求、內(nèi)容及學(xué)時(shí)詞法分析部分:2學(xué)時(shí)(一)待分析的C語(yǔ)言子集的詞法:1.關(guān)鍵字 mainifelseintreturnvoidwhile所有關(guān)鍵字都是小寫(xiě)。2.專用符號(hào) =+-*/<<=>>===!=;:,{}[]()3.其他標(biāo)記ID和NUM通過(guò)以下正規(guī)式定義其他標(biāo)記: ID→letter(letter|digit)*NUM→digit(digit)*letter→a|…|z|A|…|Zdigit→0|…|94.空格由空白、制表符和換行符組成空格一般用來(lái)分隔ID、NUM、專用符號(hào)和關(guān)鍵字,詞法分析階段空格通常被忽略。各種單詞符號(hào)對(duì)應(yīng)的類別碼:(采用一符一類別碼,見(jiàn)下表)單詞符號(hào)類別碼單詞符號(hào)類別碼單詞符號(hào)類別碼main1-23;34int2*24>35char3/25<36if4(26>=37else5)27<=38for6[28==39while7]29!=40ID10{30‘\01000NUM20}31ERROR-1=21,32+22:33(二)詞法分析程序的功能:輸入:所給文法的源程序字符串。輸出:二元組(syn,token或sum)構(gòu)成的序列。其中,syn為單詞類別碼。token為存放的單詞自身字符串。sum為整型常量。具體實(shí)現(xiàn)時(shí),可以將單詞的二元組用結(jié)構(gòu)進(jìn)行處理。例如:對(duì)源程序 main() { inti=10; while(i)i=i-1;}的源文件,經(jīng)詞法分析后輸出如下序列:(1,main)(26,()(27,))(30,{)(2,int)(10,i)(21,=)(20,10)(34,;)(7,while)(26,()(10,i)(27,))(10,i)(21,=)(10,i)(23,-)(20,1)(34,;)(31,})(三)詞法分析程序主要算法思想: 算法的基本任務(wù)是從字符串表示的源程序中識(shí)別出具有獨(dú)立意義的單詞符號(hào),其基本思想是根據(jù)掃描到單詞符號(hào)的第一個(gè)字符的種類,拼出相應(yīng)的單詞符號(hào)。1.主程序示意結(jié)構(gòu)圖(如下):置初值調(diào)用掃描子程序輸出單詞二元組直至輸入串結(jié)束注:①關(guān)鍵字表初值 關(guān)鍵字作為特殊標(biāo)識(shí)符處理,把它們預(yù)先安排在一張表格中(稱為關(guān)鍵字),當(dāng)掃描程序識(shí)別出標(biāo)識(shí)符時(shí),查關(guān)鍵字表。如能查到匹配的單詞,則該單詞為關(guān)鍵字,否則為一般標(biāo)識(shí)符。關(guān)鍵字表可處理為一個(gè)字符串?dāng)?shù)組(實(shí)際為指向字符數(shù)組的指針數(shù)組),其描述如下:char*KEY_WORDS[8]={“main”,”int”,”char”,”if”,”else”,”for”,”while”};為分析方便,這里把main作關(guān)鍵字處理。②程序中需要用到的主要變量:syn,token和sum。2.掃描子程序(scaner)的算法思想 首先設(shè)置三個(gè)變量:token用來(lái)存放構(gòu)成單詞符號(hào)的字符串;sum用來(lái)存放整型單詞;syn用來(lái)存放單詞的類別碼。掃描子程序主要部分N—S圖如下:變量初始化忽略空格文件是否結(jié)束TF是否字母TF拼字符串是否數(shù)字是否關(guān)鍵字TFTF拼數(shù)是否運(yùn)算符、界符等符號(hào)syn為對(duì)應(yīng)關(guān)鍵字的類別碼syn=10syn=20TF給出相應(yīng)的syn值報(bào)錯(cuò)語(yǔ)法分析部分:2學(xué)時(shí)(一)待分析的C語(yǔ)言子集的語(yǔ)法用擴(kuò)充的BNF表示如下:1.<程序>→main()<語(yǔ)句塊>2.<語(yǔ)句塊>→’{‘<語(yǔ)句串>’}’3.<語(yǔ)句串>→<語(yǔ)句>{;<語(yǔ)句>};4.<語(yǔ)句>→<賦值語(yǔ)句>|<條件語(yǔ)句>|<循環(huán)語(yǔ)句>5.<賦值語(yǔ)句>→ID=<表達(dá)式>6.<條件語(yǔ)句>→if(<條件表達(dá)式>)<語(yǔ)句塊>7.<循環(huán)語(yǔ)句>→while(<條件表達(dá)式>)<語(yǔ)句塊>8.<條件表達(dá)式>→<表達(dá)式><關(guān)系運(yùn)算符><表達(dá)式>9.<表達(dá)式>→<項(xiàng)>{+<項(xiàng)>|-<項(xiàng)>}10.<項(xiàng)>→<項(xiàng)>{*<因子>|/<因子>}11.<因子>→ID|NUM|(<表達(dá)式>)12.<關(guān)系運(yùn)算符>→<|<=|>|>=|==|!=(二)語(yǔ)法分析程序的主要算法思想1.主程序結(jié)構(gòu)示意圖如下:置初值調(diào)用scaner讀下一個(gè)單詞符號(hào)調(diào)用lrparser結(jié)束2.遞歸下降分析程序結(jié)構(gòu)示意圖如下:注:上接lrparser是否單詞串main()TF調(diào)用scaner出錯(cuò)處理調(diào)用語(yǔ)句塊分析函數(shù)源程序是否結(jié)束TF輸出分析成功出錯(cuò)處理3.語(yǔ)句塊分析結(jié)構(gòu)示意圖。是否{TF調(diào)用scaner出錯(cuò)處理調(diào)用語(yǔ)句串分析函數(shù)(過(guò)程)是否}TF出錯(cuò)處理4.語(yǔ)句串分析結(jié)構(gòu)示意圖如下:調(diào)用statement函數(shù)當(dāng)為;時(shí)調(diào)用scaner調(diào)用statement函數(shù)出錯(cuò)處理5.statement函數(shù)N—S圖如下:是否標(biāo)識(shí)符TF調(diào)用scaner是否if是否=TFTF調(diào)用scaner是否while調(diào)用scaner出錯(cuò)處理調(diào)用conditionTF調(diào)用expression調(diào)用語(yǔ)句塊調(diào)用scaner出錯(cuò)處理調(diào)用condition調(diào)用語(yǔ)句塊6.expression函數(shù)結(jié)構(gòu)示意圖如下:調(diào)用term是否+、-TF調(diào)用scaner出錯(cuò)處理調(diào)用term7.term函數(shù)結(jié)構(gòu)示意圖如下:調(diào)用factor是否*、/TF調(diào)用scaner出錯(cuò)處理調(diào)用factor8.condition函數(shù)結(jié)構(gòu)示意圖如下:調(diào)用expression是否邏輯運(yùn)算符TF調(diào)用scaner出錯(cuò)處理調(diào)用expression9.factor函數(shù)結(jié)構(gòu)示意圖如下:是否標(biāo)識(shí)符TF調(diào)用scaner是否數(shù)字TF調(diào)用scaner是否(TF調(diào)用scaner出錯(cuò)處理調(diào)用expression是否)TF調(diào)用scaner出錯(cuò)處理語(yǔ)義分析部分:2學(xué)時(shí)(一)實(shí)驗(yàn)的輸入和輸出輸入是語(yǔ)法分析提供的正確的單詞串,輸出是四元式序列。例如,對(duì)于語(yǔ)句串i=2*3+4;if(i>10){j=3;}while(j>0)k=1;輸出的四元式序列如下:1:*, 2, 3, T12:+, T1, 4, T23:=, T2, , i4:j>, i, 10, 65:j, , , 76:=, 3, , j7:j>, j, 0, 98:j, , , 119:=, 1, , k10:j, , , 7(二)算法思想1.設(shè)置語(yǔ)義過(guò)程①intgen(op,arg1,arg2,result)該函數(shù)是將四元式(op,arg1,arg2,result)送到四元式表中。②char*newtemp()該函數(shù)回送一個(gè)新的臨時(shí)變量名,臨時(shí)變量名產(chǎn)生的順序?yàn)椋篢1,T2,……③intmerg(p1,p2)該函數(shù)將以p1和p2為頭指針的兩條鏈合并為一,合并后的鏈表首為返回值。④intbp(p,t)該函數(shù)的功能是把p所鏈接的每個(gè)四元式的第四區(qū)段都填為t。2.主程序示意圖如下:置初值調(diào)用scaner……調(diào)用lrparser打印四元式列表結(jié)束3.函數(shù)lrparse在原來(lái)語(yǔ)法分析的基礎(chǔ)上插入相應(yīng)的語(yǔ)義動(dòng)作。 將輸入串翻譯成四元式序列。在實(shí)驗(yàn)中我們只對(duì)表達(dá)式、if語(yǔ)句和while語(yǔ)句進(jìn)行翻譯,其具體翻譯程序見(jiàn)實(shí)例。算符優(yōu)先分析法部分:(選作)算符優(yōu)先分析法特別有利于表達(dá)式的處理,宜于手工實(shí)現(xiàn)。算符優(yōu)先分析過(guò)程是自下而上的歸約過(guò)程,但這種歸約未必是嚴(yán)格的規(guī)范歸約。因此,所謂算符優(yōu)先分析法就是定義算符之間的某種優(yōu)先關(guān)系,并借助這種關(guān)系尋找句型的最左素短語(yǔ)進(jìn)行歸約。算符優(yōu)先分析法通常有兩種:優(yōu)先矩陣法和優(yōu)先函數(shù)法。前者是提供一張算符優(yōu)先關(guān)系表,后者提供兩個(gè)優(yōu)先函數(shù)(入棧優(yōu)先函數(shù)f和比較優(yōu)先函數(shù)g),優(yōu)先函數(shù)法比優(yōu)先矩陣法節(jié)約存儲(chǔ)空間,所以較為普遍。下面介紹使用優(yōu)先函數(shù)法的分析過(guò)程。分析過(guò)程:先在算符棧置“$”,然后開(kāi)始順序掃描表達(dá)式。若讀來(lái)的單詞符號(hào)是操作數(shù),則直接進(jìn)操作數(shù)棧,然后繼續(xù)下一個(gè)單詞符號(hào)。分析過(guò)程從頭開(kāi)始,并重復(fù)進(jìn)行;若讀來(lái)的單詞符號(hào)是運(yùn)算符,則將當(dāng)前處于運(yùn)算符棧頂?shù)倪\(yùn)算符的入棧優(yōu)先函數(shù)f與的比較優(yōu)先函數(shù)g進(jìn)行比較。1.若,則進(jìn)算符棧,并繼續(xù)順序往下掃描,分析過(guò)程重復(fù)進(jìn)行。2.若,則產(chǎn)生對(duì)操作數(shù)棧頂?shù)娜舾身?xiàng)進(jìn)行運(yùn)算的中間代碼,并從運(yùn)算符棧頂移去,且從操作數(shù)棧頂移去相應(yīng)若干項(xiàng),然后把執(zhí)行運(yùn)算的結(jié)果壓入操作數(shù)棧。接著以運(yùn)算符棧新的項(xiàng)與進(jìn)行上述比較。3.重復(fù)步驟1,2,直到“$”和“$”配對(duì)為止。三、實(shí)驗(yàn)環(huán)境DOS或Windows操作系統(tǒng)TURBOC2.0或VisualC++四、實(shí)驗(yàn)參考(參考代碼)#ifndef_GLOBALS_H#define_GLOBALS_H#include<stdio.h>#include<stdlib.h>#include<string.h>#define_SYN_MAIN1#define_SYN_INT2#define_SYN_CHAR3#define_SYN_IF4#define_SYN_ELSE5#define_SYN_FOR6#define_SYN_WHILE7#define_SYN_ID10#define_SYN_NUM20#define_SYN_ASSIGN21#define_SYN_PLUS22#define_SYN_MINUS23#define_SYN_TIMES24#define_SYN_DIVIDE25#define_SYN_LPAREN26#define_SYN_RPAREN27#define_SYN_LEFTBRACKET128#define_SYN_RIGHTBRACKET129#define_SYN_LEFTBRACKET230#define_SYN_RIGHTBRACKET231#define_SYN_COMMA32#define_SYN_COLON33#define_SYN_SEMICOLON34#define_SYN_LG35#define_SYN_LT36#define_SYN_ME37#define_SYN_LE38#define_SYN_EQ39#define_SYN_NE40#define_SYN_END1000#define_SYN_ERROR-1#defineMAXLENGTH255#ifndef_SEMANTEM_H#define_SEMANTEM_H/*四元組的結(jié)構(gòu)*/typedefstructQUAD{charop[MAXLENGTH]; /*操作符*/charargv1[MAXLENGTH]; /*第一個(gè)操作數(shù)*/ charargv2[MAXLENGTH]; /*第二個(gè)操作數(shù)*/charresult[MAXLENGTH]; /*運(yùn)算結(jié)果*/}QUATERNION;voidlrparse(void); /*語(yǔ)法語(yǔ)義分析主函數(shù)*/#endifunionWORDCONTENT{ charT1[MAXLENGTH]; intT2; charT3;};typedefstructWORD{ intsyn; unionWORDCONTENTvalue;}WORD;#ifndef_SCAN_H#define_SCAN_H#define_TAB_LEGNTH4#define_KEY_WORD_END"waitingforyouexpanding"voidScaner(void);#endifQUATERNION*pQuad;intnSuffix,nNXQ,ntc,nfc;externWORDuWord;externintgnColumn,gnRow;FILE*fw;char*strFileName;char*strSource;char*Expression(void);char*Term(void);char*Factor(void);voidStatement_Block(int*nChain);/*FILE*Source;*/FILE*fw;char*strSource;voidDo_Tag(char*strSource);voidDo_Digit(char*strSource);voidDo_EndOfTag(char*strSource);voidDo_EndOfDigit(char*strSource);voidDo_EndOfEqual(char*strSource);voidDo_EndOfPlus(char*strSource);voidDo_EndOfSubtraction(char*strSource);voidDo_EndOfMultiply(char*strSource);voidDo_EndOfDivide(char*strSource);voidDo_EndOfLParen(char*strSource);voidDo_EndOfRParen(char*strSource);voidDo_EndOfLeftBracket1(char*strSource);voidDo_EndOfRightBracket1(char*strSource);voidDo_EndOfLeftBracket2(char*strSource);voidDo_EndOfRightBracket2(char*strSource);voidDo_EndOfColon(char*strSource);voidDo_EndOfComma(char*strSource);voidDo_EndOfSemicolon(char*strSource);voidDo_EndOfMore(char*strSource);voidDo_EndOfLess(char*strSource);voidDo_EndOfEnd(char*strSource);voidPrintWord(WORDuWord);voidApartWord(char*strSource);voidPrintError(intnColumn,intnRow,charchInput);voidScaner(void);intgnColumn,gnRow,gnLocate,gnLocateStart;WORDuWord;char*KEY_WORDS[20]={"main","int","char","if","else","for", "while","void",_KEY_WORD_END};intIsDigit(charchInput)//判斷掃描的字符是否數(shù)字{ if(chInput<='9'&&chInput>='0')return1; elsereturn0;}intIsChar(charchInput)//判斷掃描的字符是否字母{ if((chInput<='z'&&chInput>='a')||(chInput<='Z'&&chInput>='A')) return1; elsereturn0;}voidDo_Start(char*strSource)//開(kāi)始識(shí)別一個(gè)單詞{ gnLocateStart=gnLocate; switch(strSource[gnLocate]){ case'+':Do_EndOfPlus(strSource); break; case'-':Do_EndOfSubtraction(strSource); break; case'*':Do_EndOfMultiply(strSource); break; case'/':Do_EndOfDivide(strSource); break; case'(':Do_EndOfLParen(strSource); break; case')':Do_EndOfRParen(strSource); break; case'[':Do_EndOfLeftBracket1(strSource); break; case']':Do_EndOfRightBracket1(strSource); break; case'{':Do_EndOfLeftBracket2(strSource); break; case'}':Do_EndOfRightBracket2(strSource); break; case':':Do_EndOfColon(strSource); break; case',':Do_EndOfComma(strSource); break; case';':Do_EndOfSemicolon(strSource); break; case'>':Do_EndOfMore(strSource); break; case'<':Do_EndOfLess(strSource); break; case'=':Do_EndOfEqual(strSource); break; case'\0':Do_EndOfEnd(strSource); break; default: if(IsChar(strSource[gnLocate])) { Do_Tag(strSource); } else if(IsDigit(strSource[gnLocate])) { uWord.value.T2=strSource[gnLocate]-'0'; Do_Digit(strSource); } else { if(strSource[gnLocate]!='' &&strSource[gnLocate]!='\t' &&strSource[gnLocate]!='\n' &&strSource[gnLocate]!='\r') { PrintError(gnColumn,gnRow,strSource[gnLocate]); } if(strSource[gnLocate]=='\n' ||strSource[gnLocate]=='\r') { gnColumn++; gnRow=1; } else if(strSource[gnLocate]=='\t') { gnColumn+=_TAB_LEGNTH; } else gnRow++; gnLocate++;Do_Start(strSource); } break; } return;}voidDo_Tag(char*strSource)//識(shí)別標(biāo)識(shí)符的中間狀態(tài){ gnLocate++; gnRow++; if(IsChar(strSource[gnLocate])||IsDigit(strSource[gnLocate])) { Do_Tag(strSource); } else Do_EndOfTag(strSource); return;}voidDo_Digit(char*strSource)//識(shí)別整數(shù)的中間狀態(tài){ gnLocate++; gnRow++; if(IsDigit(strSource[gnLocate])) { uWord.value.T2=uWord.value.T2*10+strSource[gnLocate]-'0'; Do_Digit(strSource); } elseDo_EndOfDigit(strSource); return;}voidDo_EndOfTag(char*strSource)//識(shí)別標(biāo)識(shí)符的最后狀態(tài){ intnLoop; uWord.syn=_SYN_ID; strncpy(uWord.value.T1,strSource+gnLocateStart,gnLocate-gnLocateStart); uWord.value.T1[gnLocate-gnLocateStart]='\0'; nLoop=0; while(strcmp(KEY_WORDS[nLoop],_KEY_WORD_END)) { if(!strcmp(KEY_WORDS[nLoop],uWord.value.T1)) { uWord.syn=nLoop+1; } nLoop++; } return;}voidDo_EndOfDigit(char*strSource)//識(shí)別數(shù)的最后狀態(tài){ uWord.syn=_SYN_NUM; return;}voidDo_EndOfEqual(char*strSource)//識(shí)別==的最后狀態(tài),它的開(kāi)始狀態(tài)在Do_Start中已處理,//運(yùn)算符沒(méi)有中間狀態(tài),因?yàn)樽疃嘤蓛蓚€(gè)符號(hào)組成,//而數(shù)和標(biāo)識(shí)符可以由多個(gè)終結(jié)符組成。//以下類似的函數(shù)命名,其功能類似,不再加注。//以下如:+,-,*,/,(,0,[,],{,},:,逗號(hào),……{ if(strSource[gnLocate+1]!='=') { uWord.syn=_SYN_ASSIGN; uWord.value.T3=strSource[gnLocate]; } else { gnLocate++; gnRow++; uWord.syn=_SYN_EQ; strcpy(uWord.value.T1,"=="); } gnLocate++; gnRow++; return;}voidDo_EndOfPlus(char*strSource){ uWord.syn=_SYN_PLUS; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfSubtraction(char*strSource){ uWord.syn=_SYN_MINUS; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfMultiply(char*strSource){ uWord.syn=_SYN_TIMES; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfDivide(char*strSource){ uWord.syn=_SYN_DIVIDE; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfLParen(char*strSource){ uWord.syn=_SYN_LPAREN; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfRParen(char*strSource){ uWord.syn=_SYN_RPAREN; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfLeftBracket1(char*strSource){ uWord.syn=_SYN_LEFTBRACKET1; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfRightBracket1(char*strSource){ uWord.syn=_SYN_RIGHTBRACKET1; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfLeftBracket2(char*strSource){ uWord.syn=_SYN_LEFTBRACKET2; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfRightBracket2(char*strSource){ uWord.syn=_SYN_RIGHTBRACKET2; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfColon(char*strSource){ uWord.syn=_SYN_COLON; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfComma(char*strSource){ uWord.syn=_SYN_COMMA; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfSemicolon(char*strSource){ uWord.syn=_SYN_SEMICOLON; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidDo_EndOfMore(char*strSource){ if(strSource[gnLocate+1]!='=') { uWord.syn=_SYN_LG; uWord.value.T3=strSource[gnLocate]; } else { gnLocate++; gnRow++; uWord.syn=_SYN_ME; strcpy(uWord.value.T1,">="); } gnLocate++; gnRow++; return;}voidDo_EndOfLess(char*strSource){ if(strSource[gnLocate+1]!='=') { uWord.syn=_SYN_LT; uWord.value.T3=strSource[gnLocate]; } else { gnLocate++; gnRow++; uWord.syn=_SYN_LE; strcpy(uWord.value.T1,"<="); } gnLocate++; gnRow++; return;}voidDo_EndOfEnd(char*strSource){ uWord.syn=_SYN_END; uWord.value.T3=strSource[gnLocate]; gnLocate++; gnRow++; return;}voidPrintWord(WORDuWord)//輸出單詞二元組(種別碼,單詞){ if(uWord.syn<=_SYN_ID ||uWord.syn==_SYN_ME ||uWord.syn==_SYN_LE ||uWord.syn==_SYN_EQ) { fprintf(fw,"\n(%d,\t%s)",uWord.syn,uWord.value.T1); } elseif(uWord.syn==_SYN_NUM) { fprintf(fw,"\n(%d,\t%d)",uWord.syn,uWord.value.T2); } else { fprintf(fw,"\n(%d,\t%c)",uWord.syn,uWord.value.T3); } return;}voidApartWord(char*strSource)//識(shí)別出當(dāng)前合法文件中所有單詞,所以是一個(gè)調(diào)用scaner()函數(shù)的循環(huán)。{ gnColumn=gnRow=1; gnLocate=gnLocateStart=0; while(strSource[gnLocate]) { Scaner(); } return;}voidPrintError(intnColumn,intnRow,charchInput){ fprintf(fw,"\n無(wú)法識(shí)別的單詞-->Col:%d\tRow:%d\tChar:%c", nColumn,nRow,chInput); return;}voidScaner(void)//詞法分析框架函數(shù){ Do_Start(strSource); PrintWord(uWord); return;}//以下注釋中為詞法分析部分的測(cè)試主函數(shù)/*voidmain(){ strSource="main(){inti=10;while(i)i=i-1;}"; fw=stdout; ApartWord(strSource);}*///只要做詞法分析,則下面代碼不要.voidLocateError(intnColumn,intnRow)//輸出錯(cuò)誤所在的行、列提示信息{ fprintf(fw,"\nCol:%d\tRow:%d--->",nColumn+1,nRow);}voiderror(char*strError)//輸出具體錯(cuò)誤信息(傳給fw指向的文件,即輸出文件),//本程序錯(cuò)誤信息種類設(shè)置較簡(jiǎn)單,可以自己補(bǔ)充。{ LocateError(gnColumn,gnRow); fprintf(fw,"%s",strError); return;}voidMatch(intsyn,char*strError)//判斷當(dāng)前識(shí)別出的單詞是否與語(yǔ)法中約定的相符,//若相符,調(diào)用scaner()識(shí)別下一個(gè)單詞備用;否則報(bào)語(yǔ)法分析錯(cuò){ if(syn==uWord.syn)Scaner(); elseerror(strError); return;}voidgen(char*op,char*argv1,char*argv2,char*result)//隨著進(jìn)程生成四元組,將其保存在pQuad結(jié)構(gòu)體數(shù)組中,為輸出作準(zhǔn)備{ sprintf(pQuad[nNXQ].op,op); sprintf(pQuad[nNXQ].argv1,argv1); sprintf(pQuad[nNXQ].argv2,argv2); sprintf(pQuad[nNXQ].result,result); nNXQ++; return;}voidPrintQuaternion(void)//輸出四元組{ intnLoop; for(nLoop=1;nLoop<nNXQ;nLoop++) { fprintf(fw,"\n%d:%s,\t%s,\t%s,\t%s", nLoop,pQuad[nLoop].op,pQuad[nLoop].argv1, pQuad[nLoop].argv2,pQuad[nLoop].result); }}char*Newtemp(void)//自動(dòng)產(chǎn)生中間結(jié)果標(biāo)識(shí)“T1”,“T2{ char*strTempID=(char*)malloc(MAXLENGTH); sprintf(strTempID,"T%d",++nSuffix); returnstrTempID;}intmerg(intp1,intp2)//合并p1和p2{ intp,nResult; if(p2==0)nResult=p1; else { nResult=p=p2; while(atoi(pQuad[p].result)) { p=atoi(pQuad[p].result); sprintf(pQuad[p].result,"%s",p1); } } returnnResult;}voidbp(intp,intt)//將中間結(jié)果(如:t1,t2等)填到四元組中{ intw,q=p; while(q) { w=atoi(pQuad[q].result); sprintf(pQuad[q].result,"%d",t); q=w; } return;}char*Expression(void)//處理表達(dá)式{ charopp[MAXLENGTH],*eplace, eplace1[MAXLENGTH],eplace2[MAXLENGTH]; eplace=(char*)malloc(MAXLENGTH); strcpy(eplace1,Term()); strcpy(eplace,eplace1); while(uWord.syn==_SYN_PLUS||uWord.syn==_SYN_MINUS) { sprintf(opp,"%c",uWord.value.T3); Scaner(); strcpy(eplace2,Term()); strcpy(eplace,Newtemp()); gen(opp,eplace1,eplace2,eplace); strcpy(eplace1,eplace); } returneplace;}char*Term(void)//處理相乘或相除(可以連乘連除,所以下面的分析是一個(gè)循環(huán))的項(xiàng){ charopp[2],*eplace,*eplace1,*eplace2; eplace=(char*)malloc(MAXLENGTH); eplace=eplace1=Factor(); strcpy(eplace,eplace1); while(uWord.syn==_SYN_TIMES||uWord.syn==_SYN_DIVIDE) { sprintf(opp,"%c",uWord.value.T3); Scaner(); eplace2=Factor(); eplace=Newtemp(); gen(opp,eplace1,eplace2,eplace); eplace1=eplace; } returneplace;}char*Factor(void)//處理表達(dá)式中的因子,如a1*12中的a1和12,即可以為數(shù)或標(biāo)識(shí)符.{ char*eplace=(char*)malloc(MAXLENGTH); if(uWord.syn==_SYN_ID||uWord.syn==_SYN_NUM) { if(uWord.syn==_SYN_ID) { sprintf(eplace,"%s",uWord.value.T1); } elsesprintf(eplace,"%d",uWord.value.T2); Scaner(); } else { Match(_SYN_LPAREN,"("); eplace=Expression(); Match(_SYN_RPAREN,")"); } returneplace;}voidCondition(int*etc,int*efc)//處理?xiàng)l件表達(dá)式{ charopp[3],*eplace1,*eplace2; charstrTemp[4]; eplace1=Expression(); if(uWord.syn<=_SYN_NE||uWord.syn>=_SYN_LG) { switch(uWord.syn) { case_SYN_LT: case_SYN_LG: sprintf(opp,"%c",uWord.value.T3); break; default: sprintf(opp,"%s",uWord.value.T1); break; } Scaner(); eplace2=Expression(); *etc=nNXQ; *efc=nNXQ+1; sprintf(strTemp,"j%s",opp); gen(strTemp,eplace1,eplace2,"0"); gen("j","","","0");//條件表達(dá)式對(duì)應(yīng)的四元組第一項(xiàng)加標(biāo)志j } elseerror("關(guān)系運(yùn)算符");}voidStatement(int*nChain)//分析賦值、if、while語(yǔ)句{ charstrTemp[MAXLENGTH],eplace[MAXLENGTH]; intnChainTemp,nWQUAD; switch(uWord.syn) { //處理賦值語(yǔ)句 case_SYN_ID: strcpy(strTemp,uWord.value.T1); Scaner(); Match(_SYN_ASSIGN,"="); strcpy(eplace,Expression()); Match(_SYN_SEMICOLON,";"); gen("=",eplace,"",strTemp); *nChain=0; break; //處理if語(yǔ)句 case_SYN_IF: Match(_SYN_IF,"if"); Match(_SYN_LPAREN,"("); Condition(&ntc,&nfc); bp(ntc,nNXQ); Match(_SYN_RPAREN,")"); Statement_Block(&nChainTemp); *nChain=merg(nChainTemp,nfc); break; //處理while語(yǔ)句 case_SYN_WHILE: Match(_SYN_WHILE,"while"); nW

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論