編譯原理:TINY語(yǔ)言編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)_第1頁(yè)
編譯原理:TINY語(yǔ)言編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)_第2頁(yè)
編譯原理:TINY語(yǔ)言編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)_第3頁(yè)
編譯原理:TINY語(yǔ)言編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)_第4頁(yè)
編譯原理:TINY語(yǔ)言編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)_第5頁(yè)
已閱讀5頁(yè),還剩3頁(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)介

編譯原理:TINY語(yǔ)?編譯器詞法分析源代碼剖析(main.c、scan.c詳細(xì)注釋)?錄?、任務(wù)介紹本?取?編譯原理課程第?次實(shí)驗(yàn),要求找出TINY語(yǔ)?的詞法分析器源代碼并進(jìn)?剖析。?、分析步驟1.解壓實(shí)驗(yàn)壓縮包。可以觀察到,TINY語(yǔ)?編譯器的源代碼的結(jié)構(gòu)為:?個(gè)main.c加若?.h頭?件加若?.c?件。因此從main.c??,開始分析。2.在main.c中,?先聲明了全局頭?件:#include“globals.h”3.注意到接下來(lái)的宏定義:NO_PARSE、NO_ANALYZE、NO_CODE,初始值為FALSE。將NO_PARSE設(shè)置為TRUE可以獲得?個(gè)僅掃描的編譯器,因此NO_PARSE代表是否進(jìn)?語(yǔ)法分析;將NO_ANALYZE設(shè)置為TRUE可以獲得?個(gè)僅解析的編譯器,因此NO_ANALYZE代表是否進(jìn)?語(yǔ)義分析;將NO_CODE設(shè)置為TRUE可以得到?個(gè)不?成代碼的編譯器,因此NO_CODE代表是否?成代碼。分析到這?,已經(jīng)可以確定該編譯器源代碼可以分為語(yǔ)法分析、語(yǔ)義分析、代碼?成三個(gè)部分。4.接下來(lái)的導(dǎo)?頭?件是由上?步的宏定義決定。通過(guò)if-else語(yǔ)句,實(shí)現(xiàn)對(duì)于不同的業(yè)務(wù)需求,導(dǎo)?不同的頭?件,執(zhí)?不同的函數(shù)調(diào)?。之前已經(jīng)得出NO_PARSE代表是否進(jìn)?語(yǔ)法分析,結(jié)合這?的if-else,可以確定語(yǔ)法分析與頭?件scan.h相關(guān)。5.接下來(lái)分析主函數(shù)。我注意到?些細(xì)節(jié):當(dāng)?戶沒(méi)有給出輸?參數(shù)時(shí),程序打印輸出,提??法,這就剛好對(duì)應(yīng)我在第11步時(shí)遇到的提?信息;如果輸?參數(shù)沒(méi)有后綴,程序?qū)?動(dòng)補(bǔ)全.tny,因此在調(diào)?TINY.exe時(shí)可以不指定輸?參數(shù)的?件后綴。提?信息;如果輸?參數(shù)沒(méi)有后綴,程序?qū)?動(dòng)補(bǔ)全.tny,因此在調(diào)?TINY.exe時(shí)可以不指定輸?參數(shù)的?件后綴。6.觀察到接下來(lái)與宏相關(guān)的if-else語(yǔ)句,根據(jù)#ifNO_PARSE時(shí)調(diào)?getToken(),?#else時(shí)調(diào)?parse(),推測(cè)getToken()就是詞法分析函數(shù),parse()中必然包括類似功能或者parse()中調(diào)?了getToken()函數(shù)。查找parse()函數(shù),發(fā)現(xiàn)它在parseu.c中。7.parse.c中應(yīng)有詞法分析與語(yǔ)法分析的相關(guān)實(shí)現(xiàn),在這?只關(guān)?詞法分析,注意到如下代碼:觀察到這?調(diào)?了getToken()函數(shù)!考慮到在進(jìn)?語(yǔ)法分析前必然要進(jìn)?詞法分析,因此可以確定stmt_sequence()函數(shù)進(jìn)?語(yǔ)法分析,?詞法分析函數(shù)就是getToken()!8.getToken()函數(shù)在scan.c中被定義,因此可以確定,scan.c就是詞法分析代碼所在的?件。根據(jù)課程知識(shí),詞法分析需要?前向后掃描,通過(guò)狀態(tài)轉(zhuǎn)換圖,依次得到每?個(gè)詞素的詞法單元。在scan.c中,?先定義了?個(gè)枚舉類型StateType,推測(cè)為DFA的狀態(tài)。9.繼續(xù)分析,chartokenString[MAXTOKENLEN+1]為標(biāo)識(shí)符或保留字,使?字符數(shù)組存儲(chǔ)。#defineBUFLEN256為源代碼?的輸?緩沖區(qū)的最?長(zhǎng)度。每??輸?放進(jìn)字符數(shù)組lineBuf[BUFLEN]中。10.getNextChar()函數(shù)從lineBuf獲取下?個(gè)?空字符,如果lineBuf已讀完,則讀取新?。11.ungetNextChar()函數(shù)?常簡(jiǎn)單,實(shí)現(xiàn)回退?格。推測(cè)該函數(shù)?于區(qū)分包含I/不包含E,相當(dāng)于JUMP。12.接下來(lái)定義了?個(gè)預(yù)留字的查找表,如if、then、else等,使?結(jié)構(gòu)體實(shí)現(xiàn)。reservedLookup()函數(shù)使?最為簡(jiǎn)單的線性查找算法,通過(guò)剛剛定義的查找表,查找某?個(gè)標(biāo)識(shí)符是否是保留字,從?可以區(qū)分保留字和?戶?定義的ID。13.getToken()函數(shù)基于狀態(tài)轉(zhuǎn)換實(shí)現(xiàn),返回下?個(gè)詞法單元。通過(guò)該函數(shù)中的狀態(tài)轉(zhuǎn)移,我們可以推測(cè)TINY函數(shù)的賦值符號(hào)為:=,{}內(nèi)為注釋,每?句以;結(jié)束,標(biāo)識(shí)符只能由字母組成,?持+、-、*、/、<等簡(jiǎn)單的運(yùn)算符。通過(guò)這?的狀態(tài)轉(zhuǎn)換,我們可以確定程序中定義的各DFA狀態(tài)的含義:START:起始狀態(tài)INASSIGN:輸?:之后,等待輸?=,從?賦值狀態(tài)INCOMMENT:輸?{之后,進(jìn)?注釋狀態(tài),編譯器忽略注釋內(nèi)容,直?遇到}結(jié)束INNUM:輸?數(shù)字之后,進(jìn)?數(shù)字的匹配狀態(tài),遇到?數(shù)字結(jié)束INID:輸?字母之后,進(jìn)?標(biāo)識(shí)符的匹配狀態(tài),可能為?戶?定義或預(yù)留符,遇到?字母結(jié)束DONE:成功匹配到?個(gè)詞法單元,完成匹配14.當(dāng)成功匹配?個(gè)詞素后結(jié)束狀態(tài)轉(zhuǎn)換循環(huán),若匹配到的詞法單元為ID,需要檢查該詞素是否為保留字。若全局變量TraceScan為TRUE,調(diào)?util.c中定義了printToken()函數(shù),將?個(gè)詞法單元及其詞匯表打印到listing?件中。getToken()函數(shù)最終返回下?個(gè)詞法單元,實(shí)現(xiàn)詞法分析。15.回到main.c,在結(jié)束語(yǔ)法分析,循環(huán)調(diào)?getToken()以得到所有的詞法單元之后,緊接著根據(jù)宏定義NO_PARSE、NO_PARSE與NO_CODE的值,決定是否進(jìn)?語(yǔ)法分析、語(yǔ)義分析與代碼?成(可以細(xì)分為若?步)。?此,TINY語(yǔ)?編譯器的源代碼分析完成。三、main.c注釋//全局頭?件#include"globals.h"#include<stdlib.h>//宏定義/*setNO_PARSEtoTRUEtogetascanner-onlycompiler*///NO_PARSE設(shè)置為TRUE以獲得?個(gè)僅掃描的編譯器:是否進(jìn)?語(yǔ)法分析將#defineNO_PARSEFALSE/*setNO_ANALYZEtoTRUEtogetaparser-onlycompiler*///NO_ANALYZE設(shè)置為TRUE以獲得?個(gè)僅解析的編譯器:是否進(jìn)?語(yǔ)義分析將#defineNO_ANALYZEFALSE/*setNO_CODEtoTRUEtogetacompilerthatdoesnot*generatecode*///NO_CODE設(shè)置為TRUE可以得到?個(gè)不?成代碼的編譯器將#defineNO_CODEFALSE#include"util.h"#ifNO_PARSE#include"scan.h"#else#include"parse.h"#if!NO_ANALYZE#include"analyze.h"#if!NO_CODE#include"cgen.h"#include"cgen.h"#endif#endif#endif/*allocateglobalvariables*/intlineno=0;FILE*source;FILE*listing;FILE*code;/*allocateandsettracingflags*/intEchoSource=FALSE;intTraceScan=FALSE;intTraceParse=FALSE;intTraceAnalyze=TRUE;intTraceCode=FALSE;intError=FALSE;main(intargc,char*argv[]){TreeNode*syntaxTree;charpgm[120];/*sourcecodefilename*/if(argc!=2){fprintf(stderr,"usage:%s<filename>\n",argv[0]);exit(1);}strcpy(pgm,argv[1]);//注意到,也正是因?yàn)樵撎幚恚x??件時(shí)可以不寫后綴名if(strchr(pgm,'.')==NULL)strcat(pgm,".tny");//read以?式打開?件source=fopen(pgm,"r");if(source==NULL){fprintf(stderr,"File%snotfound\n",pgm);exit(1);}listing=stdout;/*sendlistingtoscreen*/fprintf(listing,"\nTINYCOMPILATION:%s\n",pgm);#ifNO_PARSE//--->詞法分析本次關(guān)注的重點(diǎn)//getToken返回下?個(gè)詞法單元while(getToken()!=ENDFILE);#else//詞法分析+語(yǔ)法分析//parsegetToken?法本?調(diào)?syntaxTree=parse();if(TraceParse){fprintf(listing,"\nSyntaxtree:\n");printTree(syntaxTree);}#if!NO_PARSE//語(yǔ)義分析if(!Error){if(TraceAnalyze)fprintf(listing,"\nBuildingSymbolTable...\n");buildSymtab(syntaxTree);if(TraceAnalyze)fprintf(listing,"\nCheckingTypes...\n");typeCheck(syntaxTree);if(TraceAnalyze)fprintf(listing,"\nTypeCheckingFinished\n");}#if!NO_CODE//代碼?成if(!Error){char*codefile;intfnlen=strcspn(pgm,".");codefile=(char*)calloc(fnlen+4,sizeof(char));codefile=(char*)calloc(fnlen+4,sizeof(char));strncpy(codefile,pgm,fnlen);strcat(codefile,".tm");code=fopen(codefile,"w");if(code==NULL){printf("Unabletoopen%s\n",codefile);exit(1);}codeGen(syntaxTree,codefile);fclose(code);}#endif#endif#endiffclose(source);return0;}四、scan.c注釋#include"globals.h"#include"util.h"#include"scan.h"http://詞法分析,?前向后掃描/*statesinscannerDFA*///DFA狀態(tài)枚舉類型,typedefenum{START,INASSIGN,INCOMMENT,INNUM,INID,DONE}StateType;/*lexemeofidentifierorreservedword*///標(biāo)識(shí)符或保留字的詞匯,字符數(shù)組存儲(chǔ)chartokenString[MAXTOKENLEN+1];/*BUFLEN=lengthoftheinputbufferforsourcecodelines*///源代碼?的輸?緩沖區(qū)的長(zhǎng)度#defineBUFLEN256staticcharlineBuf[BUFLEN];/*holdsthecurrentline*/staticintlinepos=0;/*currentpositioninLineBuf*/staticintbufsize=0;/*currentsizeofbufferstring*/staticintEOF_flag=FALSE;/*correctsungetNextCharbehavioronEOF*//*getNextCharfetchesthenextnon-blankcharacterfromlineBuf,readinginanewlineiflineBufisexhausted*///getNextCharlineBuf獲取下?個(gè)?空字符,如果lineBuf從已耗盡,則讀取新?staticintgetNextChar(void){if(!(linepos<bufsize))//讀取新?{lineno++;if(fgets(lineBuf,BUFLEN-1,source)){if(EchoSource)fprintf(listing,"%4d:%s",lineno,lineBuf);bufsize=strlen(lineBuf);linepos=0;returnlineBuf[linepos++];}else{EOF_flag=TRUE;returnEOF;}}elsereturnlineBuf[linepos++];//返回下?個(gè)字符}}/*ungetNextCharbacktracksonecharacterinlineBuf*///回退staticvoidungetNextChar(void){if(!EOF_flag)linepos--;}/*lookuptableofreservedwords*///預(yù)留字查找表staticstruct{char*str;TokenTypetok;}reservedWords[MAXRESERVED]={{"if",IF},{"then",THEN},{"else",ELSE},{"end",END},{"repeat",REPEAT},{"until",UNTIL},{"read",READ},{"write",WRITE}};/*lookupanidentifiertoseeifitisareservedword*//*useslinearsearch*///查找標(biāo)識(shí)符以查看它是否是保留字!最為簡(jiǎn)單的線性查找staticTokenTypereservedLookup(char*s){inti;for(i=0;i<MAXRESERVED;i++)if(!strcmp(s,reservedWords[i].str))returnreservedWords[i].tok;returnID;}//scanner的主函數(shù)/****************************************//*theprimaryfunctionofthescanner*//****************************************//*functiongetTokenreturnsthe*nexttokeninsourcefile*///返回下?個(gè)詞法單元TokenTypegetToken(void){/*indexforstoringintotokenString*///索引inttokenStringIndex=0;/*holdscurrenttokentobereturned*///當(dāng)前詞法單元TokenTypecurrentToken;/*currentstate-alwaysbeginsatSTART*///當(dāng)前狀態(tài)—總是從頭開始StateTypestate=START;/*flagtoindicatesavetotokenString*///標(biāo)志,當(dāng)前字符是否有效intsave;while(state!=DONE)//匹配到?個(gè)詞素之后就結(jié)束{intc=getNextChar();save=TRUE;switch(state)//狀態(tài)轉(zhuǎn)移{caseSTART:if(isdigit(c))state=INNUM;//數(shù)字elseif(isalpha(c))state=INID;//idelseif(c==':')state=INASSIGN;//冒號(hào)elseif((c=='')||(c=='\t')||(c=='\n'))save=FALSE;elseif(c=='{'){save=FALSE;state=INCOMMENT;//注釋}}else{state=DONE;switch(c){caseEOF:save=FALSE;currentToken=ENDFILE;//結(jié)束break;//枚舉符號(hào)case'=':currentToken=EQ;break;case'<':currentToken=LT;break;case'+':currentToken=PLUS;break;case'-':currentToken=MINUS;break;case'*':currentToken=TIMES;break;case'/':currentToken=OVER;break;case'(':currentToken=LPAREN;break;case')':currentToken=RPAREN;break;case';':currentToken=SEMI;break;default:currentToken=ERROR;break;}}break;//注釋語(yǔ)句內(nèi)caseINCOMMENT:save=FALSE;if(c==EOF){state=DONE;currentToken=ENDFILE;}elseif(c=='}')state=START;//直到遇到}為?break;//冒號(hào)之后,TINY的語(yǔ)法,賦值語(yǔ)句caseINASSIGN:state=DONE;if(c=='=')currentToken=ASSIGN;//:=代表賦值else{/*backupintheinput*/ungetNextChar();save=FALSE;//不保存,回退,出錯(cuò)currentToken=ERROR;}break;//數(shù)字caseINNUM:if(!isdigit(c)){/*backupintheinput*/ungetNextChar();//回退,相當(dāng)于?師上課講的jumpsave=FALSE;//不保存現(xiàn)在的字符state=DONE;//完成?個(gè)詞素的

溫馨提示

  • 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)論