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

下載本文檔

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

文檔簡介

《編譯原理》試驗(yàn)匯報軟件131陳萬全132852需求分析 經(jīng)過對一個慣用高級程序設(shè)計語言簡單語言子集編譯系統(tǒng)中詞法分析、語法分析、語義處理模塊設(shè)計、開發(fā),掌握實(shí)際編譯系統(tǒng)關(guān)鍵結(jié)構(gòu)、工作流程及其實(shí)現(xiàn)技術(shù),取得分析、設(shè)計、實(shí)現(xiàn)編譯程序等方面實(shí)際操作能力,增強(qiáng)設(shè)計、編寫和調(diào)試程序能力。 經(jīng)過開源編譯器分析、編譯過程可視化等擴(kuò)展試驗(yàn),促進(jìn)學(xué)生增強(qiáng)復(fù)雜系統(tǒng)分析、設(shè)計和實(shí)現(xiàn)能力,激勵學(xué)生創(chuàng)新意識和能力。試驗(yàn)項目實(shí)驗(yàn)內(nèi)容1、詞法分析程序設(shè)計與實(shí)現(xiàn)結(jié)構(gòu)具關(guān)于鍵字、運(yùn)算符、標(biāo)識符、無符號常數(shù)等單詞詞法分析程序。輸入由符合及不符合要求單詞類別結(jié)構(gòu)各類單詞組成源程序。輸出單詞串二元式編碼(CLASS,VALUE)。2、語法分析程序設(shè)計與實(shí)現(xiàn)將詞法分析程序輸出單詞串作為輸入,針對常見表示式、賦值語句、條件語句、循環(huán)語句等語法成份,選擇有代表性語法分析方法,如遞歸下降法、算符優(yōu)先分析、LL(1)、LR等方法之一,設(shè)計實(shí)現(xiàn)對應(yīng)語法分析程序。3、語義分析程序設(shè)計與實(shí)現(xiàn)對各語法單位增加語義子程序,將表示式或可執(zhí)行語句翻譯為四元式序列輸出,并能進(jìn)行錯誤檢驗(yàn)與處理,將錯誤信息輸出。詞法分析程序設(shè)計與實(shí)現(xiàn)假定一個高級程序設(shè)計語言中單詞主要包含五個關(guān)鍵字begin、end、if、then、else;標(biāo)識符;無符號常數(shù);六種關(guān)系運(yùn)算符;一個賦值符和四個算術(shù)運(yùn)算符,試結(jié)構(gòu)能識別這些單詞詞法分析程序。輸入:由符合和不符合所要求單詞類別結(jié)構(gòu)各類單詞組成源程序文件。輸出:把所識別出每一單詞均按形如(CLASS,VALUE)二元式形式輸出,并將結(jié)果放到某個文件中。對于標(biāo)識符和無符號常數(shù),CLASS字段為對應(yīng)類別碼助記符;VALUE字段則是該標(biāo)識符、常數(shù)詳細(xì)值;對于關(guān)鍵字和運(yùn)算符,采取一詞一類編碼形式,僅需在二元式CLASS字段上放置對應(yīng)單詞類別碼助記符,VALUE字段則為“空”。語法分析程序設(shè)計與實(shí)現(xiàn)選擇對各種常見高級程序設(shè)計語言都較為通用語法結(jié)構(gòu)——算術(shù)表示式一個簡化子集——作為分析對象,依照以下描述其語法結(jié)構(gòu)BNF定義G2[<算術(shù)表示式>],任選一個學(xué)過語法分析方法,針對運(yùn)算對象為無符號常數(shù)和變量四則運(yùn)算,設(shè)計并實(shí)現(xiàn)一個語法分析程序。G2[<算術(shù)表示式>]:<算術(shù)表示式>→<項>|<算術(shù)表示式>+<項>|<算術(shù)表示式>-<項><項>→<因式>|<項>*<因式>|<項>/<因式><因式>→<運(yùn)算對象>|(<算術(shù)表示式>)若將語法范圍<算術(shù)表示式>、<項>、<因式>和<運(yùn)算對象>分別用E、T、F和i代表,則G2可寫成:G2[E]:E→T|E+T|E-TT→F|T*F|T/FF→i|(E)輸入:由試驗(yàn)一輸出單詞串,比如:UCON,PL,UCON,MU,ID······輸出:若輸入源程序中符號串是給定文法句子,則輸出“RIGHT”,而且給出每一步分析過程;若不是句子,即輸入串有錯誤,則輸出“ERROR”,而且顯示分析至此所得中間結(jié)果,如分析棧、符號棧中信息等,以及必要犯錯說明信息。3、語義分析程序設(shè)計與實(shí)現(xiàn)對文法G2[<算術(shù)表示式>]中產(chǎn)生式添加語義處理子程序,完成運(yùn)算對象是簡單變量(標(biāo)識符)和無符號數(shù)四則運(yùn)算計值處理,將輸入四則運(yùn)算轉(zhuǎn)換為四元式形式中間代碼。輸入:包含測試用例(由標(biāo)識符、無符號數(shù)和+、?、*、/、(、)組成算術(shù)表示式)源程序文件。輸出:將源程序轉(zhuǎn)換為中間代碼形式表示,并將中間代碼序列輸出到文件中。若源程序中有錯誤,應(yīng)指犯錯誤信息設(shè)計思緒詞法分析程序設(shè)計與實(shí)現(xiàn)1)單詞分類為了編程實(shí)現(xiàn)。我們假定要編譯語言中,全部關(guān)鍵字都是保留字,程序員不得將它們作為源程序中標(biāo)識符;作了這些限制以后,就能夠把關(guān)鍵字和標(biāo)識符識別統(tǒng)一進(jìn)行處理。即每當(dāng)開始識別一個單詞時,若掃視到第一個字符為字母,則把后續(xù)輸入字母或數(shù)字字符依次進(jìn)行拼接,直至掃視到非字母、數(shù)字字符為止,以期取得一個盡可能長字母數(shù)字字符串,然后以此字符串查所謂保留字表(此保留字表要事先造好),若查到此字符串,則取出對應(yīng)類別碼;反之,則表明該字符串應(yīng)為一標(biāo)識符。表1語言中各類單詞符號及其分類碼表單詞符號類別編碼類別碼助記符單詞值begin1BEGINend2ENDif3IFthen4THENelse5ELSE標(biāo)識符6ID字母打頭字母數(shù)字串無符號常數(shù)7UCON機(jī)內(nèi)二進(jìn)制表示<8LT<=9LE=10EQ<>11NE>12GT>=13GE:=14IS+15PL-16MI*17MU/18DI詞法分析器設(shè)計函數(shù)GETCHAR:每調(diào)用一次,就把掃描指示器當(dāng)前所指示源程序字符送入字符變量ch,然后把掃描指示器前推一個字符位置。字符數(shù)組TOKEN:用來依次存放一個單詞詞文中各個字符。函數(shù)CAT:每調(diào)用一次,就把當(dāng)前ch中字符拼接于TOKEN中所存字符串右邊。函數(shù)LOOKUP:每調(diào)用一次,就以TOKEN中字符串查保留字表,若查到,就將對應(yīng)關(guān)鍵字類別碼賦給整型變量c;不然將c置為零。函數(shù)RETRACT:每調(diào)用一次,就把掃描指示器回退一個字符位置(即退回多讀那個字符)。函數(shù)OUT:通常僅在進(jìn)入終態(tài)時調(diào)用此函數(shù),調(diào)用形式為OUT(c,VAL)。圖1識別表I所列語言中部分單詞DFA及相關(guān)語義過程3)詞法分析程序?qū)崿F(xiàn)編寫掃描器:charTOKEN[20],TOKEND[20],TOKENDO[20];intlookup(char*);voidout(int,char*);voidreport_error(void);//externvoidLEX(void);intsiagn=0;//標(biāo)志位FILE*fp1;char*KeyWordTable[MAX_KEY_NUMBER]={"begin","end","if","then","else",KEY_WORD_END};/*查保留字表,判斷是否為關(guān)鍵字*/intlookup(char*token){ intn=0; while(strcmp(KeyWordTable[n],KEY_WORD_END))/*strcmp比較兩串是否相同,若相同返回0*/ { if(!strcmp(KeyWordTable[n],token))/*比較token所指向關(guān)鍵字和保留字表中哪個關(guān)鍵字相符*/ { returnn+1;/*依照單詞分類碼表I,設(shè)置正確關(guān)鍵字類別碼,并返回這類別碼值*/ break; } n++; } return0;}voidscanner_example(FILE*fp){ charch;inti,c,isd,cpoint;doubleo; ch=fgetc(fp);//fgetc函數(shù)在文件中讀取一個字符 if(isalpha(ch))/*itmustbeaidentifer!它必須是一個標(biāo)識符判斷字符ch是否為英文字母,若為小寫字母,返回2,若為大寫字母,返回1。若不是字母,返回0*/ { TOKEN[0]=ch; ch=fgetc(fp); i=1; while(isalnum(ch)||ch=='.')//isalnum函數(shù)判斷ch是否為空當(dāng)ch為數(shù)字0-9或字母a-z及A-Z時,返回非零值,不然返回零 { if(ch=='.'){ cpoint=-1;//標(biāo)志字符串中有小數(shù)點(diǎn) } TOKEN[i]=ch; i++; ch=fgetc(fp); } TOKEN[i]='\0'; if(ch=='<'||ch=='>'||ch=='='||ch==':'){ fseek(fp,-2,1); siagn=1; } elsefseek(fp,-1,1); //fseek(fp,-1,1);/*retractfseek函數(shù)每調(diào)用一次,就把掃描指示器回退一個字符位置(即退回多讀那個字符)*/ i=0; if(TOKEN[i]=='o'||TOKEN[i]=='O') { i++; if(TOKEN[i]=='x'||TOKEN[i]=='X') { i++; while(TOKEN[i]!='\0') { if(!isdigit(TOKEN[i])||TOKEN[i]!='a'||TOKEN[i]!='b'||TOKEN[i]!='c'||TOKEN[i]!='d'||TOKEN[i]!='e'||TOKEN[i]!='f' ||TOKEN[i]!='A'||TOKEN[i]!='B'||TOKEN[i]!='C'||TOKEN[i]!='D'||TOKEN[i]!='E'||TOKEN[i]!='F'||TOKEN[i]!='.') { isd=-1; } isd=16;//標(biāo)志字符串十六進(jìn)制 i++; } } elseif(TOKEN[i]=='0'||TOKEN[i]=='1'||TOKEN[i]=='2'||TOKEN[i]=='3'||TOKEN[i]=='4'||TOKEN[i]=='5'||TOKEN[i]=='6'||TOKEN[i]=='7'||TOKEN[i]=='.') { isd=8;//標(biāo)志字符串八進(jìn)制 i++; while(TOKEN[i]!='\0') { if(TOKEN[i]!='0'||TOKEN[i]!='1'||TOKEN[i]!='2'||TOKEN[i]!='3'||TOKEN[i]!='4'||TOKEN[i]!='5'||TOKEN[i]!='6'||TOKEN[i]!='7'||TOKEN[i]!='.') { isd=-1; } isd=8; i++; } } } if(isd==8){ strncpy(TOKEND,TOKEN+1,strlen(TOKEN)-1);//拷貝函數(shù) //printf("%o",atof(TOKEND)); o=octal(TOKEND); //printf("%g",o); sprintf(TOKENDO,"%g",octal(TOKEND)); out(OCTAL,TOKENDO); } elseif(isd==16){ strncpy(TOKEND,TOKEN+2,strlen(TOKEN)-2);//拷貝函數(shù) o=octal(TOKEND); //printf("%g",o); sprintf(TOKENDO,"%g",hex(TOKEND)); out(HEX,TOKENDO); } else { if(cpoint==-1) report_error();//當(dāng)字符串中有小數(shù)點(diǎn)時,為錯誤 else{ c=lookup(TOKEN);//looup查詢函數(shù)查找保留字 if(c==0) out(ID,TOKEN); else out(c,"");//out函數(shù)輸出功效 } } } else if(isdigit(ch))//isdigit函數(shù)檢驗(yàn)參數(shù)c是否為阿拉伯?dāng)?shù)字0到9。 { /*TOKEN[0]=ch; ch=fgetc(fp); i=1; while(isdigit(ch)||ch=='-'||ch=='E'||ch=='e'||ch=='.') { TOKEN[i]=ch; i++; ch=fgetc(fp); } TOKEN[i]='\0';*/ intClass; fseek(fp,-1,1); Class=LEX(fp); if(Class==1){ charpi[30]=""; itoa(ICON,pi,10); out(INT,pi); } elseif(Class==2){ charpd[30]=""; sprintf(pd,"%g",FCON); out(DOUBLE,pd); } else report_error(); //fseek(fp,-1,1); if(chf=='<'||chf=='>'||chf=='='||chf==':'||chf=='+'||chf=='-'||chf=='*'||chf=='/'){ fseek(fp,-2,1); siagn=1; } else { fseek(fp,-1,1); siagn=1; } } else switch(ch) { case'<': ch=fgetc(fp); if(ch=='='){ ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1);//假如符號后面不是空值則退后一步確保符號后能夠直接跟數(shù)字也能夠跟空格 siagn=1; out(LE,""); } elseif(ch=='>'){ ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(NE,"");} else { ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(LT,""); } break; case'=': ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(EQ,""); break; case'>': ch=fgetc(fp); if(ch=='='){ ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(GE,""); } else { ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(GT,""); } break; case':': ch=fgetc(fp); if(ch=='='){ ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(IS,""); } else report_error(); break; case'+': ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(PL,"");break; case'-': ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(MI,"");break; case'*': ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(MU,"");break; case'/': ch=fgetc(fp); if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1); siagn=1; out(DI,"");break; case'': break;//當(dāng)碰到空格時繼續(xù)向下走 default: report_error();break;//report_error函數(shù)單詞錯誤時輸出內(nèi)容 } if(ch==''||siagn==1){ fseek(fp,1,1);siagn=0; scanner_example(fp); } if(ch==EOF) return;//return;}voidreport_error(){ printf("error\n");}voidout(intc,char*vp){ char*cl=NULL; switch(c) { case1: cl="BEGIN";break; case2: cl="END";break; case3: cl="IF";break; case4: cl="THEN";break; case5: cl="ELSE";break; case6: cl="ID";break; case7: cl="UCON";break; case8: cl="LT";break; case9: cl="LE";break; case10:cl="EQ";break; case11:cl="NE";break; case12:cl="GT";break; case13:cl="GE";break; case14:cl="IS";break; case15:cl="PL";break; case16:cl="MI";break; case17:cl="MU";break; case18:cl="DI";break; case19:cl="UCON";break; case20:cl="DOUBLE";break; case21:cl="OCTAL";break; case22:cl="HEX";break; } printf("e(%s,%s)\n",cl,vp); fprintf(fp1,"e(%s,%s)\n",cl,vp); fseek(fp1,0,1);}voidmain(){ char*fname="test1.txt";//讀取為文件fpFILE*fp; if((fp1=fopen("asd.txt","w"))==NULL)/*建立文件寫入文件文件fp1*/{printf("\nopenfileerror");getchar();exit(1);} if((fp=fopen(fname,"r"))==NULL) { printf("\nSorry,Can'topenthefile!\n"); getchar(); exit(0); }else {scanner_example(fp);} fclose(fp); fclose(fp1);}本程序從文件test1.txt中讀入要分析單詞并把掃描結(jié)果輸入asd.txt文件中;利用gechar()方法從文件中一個個讀入字符,并采取遞歸方法對字符數(shù)次讀入直到讀到文件結(jié)尾停頓。字符讀入程序后采取圖一方法進(jìn)行分析處理。4)無符號常數(shù)識別針對掃描程序所得到數(shù)字我們能夠進(jìn)行無符號數(shù)處理。加入了語義過程說明識別無符號數(shù)狀態(tài)矩陣,編寫詞法分析程序,部分實(shí)當(dāng)代碼如程序二所表示。表2包含語義處理過程識別無符號數(shù)狀態(tài)矩陣程序2單詞分類碼為UCON無符號數(shù)識別程序7假定無符號常量類數(shù)為7#defineClassOther200#defineEndState-1intw,n,p,e,d;intClass=-1;//Usedtoindicateclassoftheword用于表示單詞類型1位int2為doubleintICON;doubleFCON;staticintCurrentState;//Usedtopresentcurrentstate,theinitialvalue:0用于當(dāng)前狀態(tài),初始值:0intGetChar(FILE*p);intEXCUTE(int,int);intLEX(FILE*p);intHandleOtherWord(void){ returnClassOther;}intHandleError(void){printf("Error!\n");return0;}intGetChar(FILE*p){chf=fgetc(p);if(isdigit(chf)){d=chf-'0';returnDIGIT;}if(chf=='.')returnPOINT;if(chf=='E'||chf=='e')returnPOWER;if(chf=='+')returnPLUS;if(chf=='-')returnMINUS;returnOTHER;}intEXCUTE(intstate,intsymbol){switch(state){case0:switch(symbol){caseDIGIT:n=0;p=0;e=1;w=d;CurrentState=1;break;casePOINT:w=0;n=0;p=0;e=1;CurrentState=3;break;default:HandleOtherWord();Class=ClassOther;CurrentState=EndState;}break;case1:switch(symbol){caseDIGIT:w=w*10+d;break;//CurrentState=1casePOINT:CurrentState=2;break;casePOWER:CurrentState=4;break;default:ICON=w;Class=1;CurrentState=EndState;}break;case2:switch(symbol){caseDIGIT:n++;w=w*10+d;break;casePOWER:CurrentState=4;break;default:FCON=w*pow(10,e*p-n);Class=2;CurrentState=EndState;}break;case3:switch(symbol){caseDIGIT:n++;w=w*10+d;CurrentState=2;break;default:HandleError();CurrentState=EndState;}break;case4:switch(symbol){caseDIGIT:p=p*10+d;CurrentState=6;break;caseMINUS:e=-1;CurrentState=5;break;casePLUS:CurrentState=5;break;default:HandleError();CurrentState=EndState;}break;case5:switch(symbol){caseDIGIT:p=p*10+d;CurrentState=6;break;default:HandleError();CurrentState=EndState;}break;case6:switch(symbol){caseDIGIT:p=p*10+d;break;default:FCON=w*pow(10,e*p-n);Class=2;CurrentState=EndState;}break;}returnCurrentState;}intLEX(FILE*p){intch;CurrentState=0;while(CurrentState!=EndState) { ch=GetChar(p); EXCUTE(CurrentState,ch); }returnClass;}5)八進(jìn)制與十六進(jìn)制數(shù)處理在無符號數(shù)處理過程中沒有設(shè)計八進(jìn)制與十六進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù),但為了方面以后使用我們進(jìn)入進(jìn)制轉(zhuǎn)換。設(shè)計思緒:判斷八進(jìn)制是以0開頭,十六進(jìn)制為0X開頭,而且判斷后面所跟數(shù)字是否超出八進(jìn)制或十六進(jìn)制范圍,若超出則錯誤,如不超出則用8或16轉(zhuǎn)換為對應(yīng)十進(jìn)制數(shù)字再次讀入寫個字符循環(huán),直到數(shù)字結(jié)束。程序3單詞分類碼為八進(jìn)制無符號數(shù)識別程序doubleoctal(char*TP){ intx,y=-1,ypoint=0;//計數(shù)ypoint=-1統(tǒng)計有小數(shù)點(diǎn)y統(tǒng)計是第幾位小數(shù) intm=0; doubleFINALL=0.0;//放結(jié)果 while(*TP!='\0'){ if(*TP=='.'){ ypoint=-1; } else{ x=*TP-'0'; if(ypoint!=-1){ FINALL=FINALL*8+x; } if(ypoint==-1){ FINALL=FINALL+x*pow(8,y); y--; } } TP++; } returnFINALL;程序4單詞分類碼為十六進(jìn)制無符號數(shù)識別程序doublehex(char*TP){ intx,y=-1,ypoint=0;//計數(shù)ypoint=-1統(tǒng)計有小數(shù)點(diǎn)y統(tǒng)計是第幾位小數(shù) intm=0; doubleFINALL=0.0;//放結(jié)果 while(*TP!='\0'){ if(*TP=='.'){ ypoint=-1; } else{ if(ypoint!=-1){ if(*TP>='0'&&*TP<='9'){ x=*TP-'0'; } elseif(*TP>='a'&&*TP<='f'){ x=*TP-'a'+1; } elseif(*TP>='A'&&*TP<='F'){ x=*TP-'a'+1; } FINALL=FINALL*16+x; } if(ypoint==-1){ if(*TP>='0'&&*TP<='9'){ x=*TP-'0'; } elseif(*TP>='a'&&*TP<='f'){ x=*TP-'a'+1; } elseif(*TP>='A'&&*TP<='F'){ x=*TP-'a'+1; } FINALL=FINALL+x*pow(16,y); y--; } } TP++; } returnFINALL;}2、語法分析程序設(shè)計與實(shí)現(xiàn)語法分析,采取是算符優(yōu)先文法實(shí)現(xiàn);重點(diǎn)與難點(diǎn)為依照文法求出FirstVt與LastVt集合,結(jié)構(gòu)出算符表。語法分析程序輸入結(jié)構(gòu)為詞法分析輸出結(jié)果。數(shù)字標(biāo)志位都設(shè)為i如(i,25.8);運(yùn)算符標(biāo)志位為其本身如(+,)其余符號暫不計算,以方便語法分析程序編寫。算符優(yōu)先總流程圖圖2開始開始初始化FIRSTVT集和LASTVT集求出文法終止符集是否為文法輸出非終止符FIRSTVT集和LASTVT集生成并輸出算法分析表輸入需要驗(yàn)證字符串,以#結(jié)束輸出結(jié)果輸出結(jié)果結(jié)束輸入文法規(guī)則和數(shù)目NY判斷是否為算符文法程序5//judge1是判斷是否是算符文法:若產(chǎn)生式中含有兩個相繼非終止符則不是算符文法intjudge1(intn){ intj=3,flag=0; for(inti=0;i<=n;i++) while(str[i][j]!='\0') { chara=str[i][j]; charb=str[i][j+1]; if(IsLetter(a)&&IsLetter(b)) {flag=1;break;} elsej++; }if(flag==1) return0;else return1;}結(jié)果:輸入文件輸入結(jié)果判斷是否為算符優(yōu)先文法程序5judge2是判斷文法G是否為算符優(yōu)先文法:若不是算符文法或若文法中含空字或終止符優(yōu)先級不唯一則不是算符優(yōu)先文法voidjudge2(intn){ for(inti=0;i<=n;i++) if(str[i][3]=='~'||judge1(n)==0||FLAG==1)//'~'代表空字 {cout<<"該文法不是算符優(yōu)先文法!"<<endl;FF=0;break;} if(i>n) cout<<"該文法是算符優(yōu)先文法!"<<endl;}求FristVt()和LastVt()集合程序6//createF函數(shù)是用F數(shù)組存放每個終止符與非終止符和組合,而且值每隊標(biāo)志位為0;F數(shù)組是一個結(jié)構(gòu)體voidcreateF(intn){intk=0,i=1;charg;chart[10];//t數(shù)組用來存放非終止符t[0]=str[0][0];while(i<=n){if(t[k]!=str[i][0]){k++;t[k]=str[i][0];g=t[k];i++;}elsei++;}kk=0;charc;for(i=0;i<=n;i++){intj=3;while(str[i][j]!='\0'){c=str[i][j];if(IsLetter(c)==0){if(!search1(r,kk,c))r[kk]=c;kk++;//r數(shù)組用來存放終止符}j++;}}m=0;for(i=0;i<k;i++)for(intj=0;j<kk-1;j++){F[m].R=t[i];F[m].r=r[j];F[m].flag=0;m++;}}//search函數(shù)是將在F數(shù)組中尋找到終止符與非終止符正確標(biāo)志位值為1voidsearch(charLodew){for(inti=0;i<m;i++)if(F[i].R==w.E&&F[i].r==w.e){F[i].flag=1;break;}}voidFirstVT(intn)//求FirstVT{charstacksta;charLodew;inti=0;Initstack(sta);while(i<=n){intk=3;w.E=str[i][0];chara=str[i][k];charb=str[i][k+1];if(!IsLetter(a))//產(chǎn)生式后選式第一個字符就是終止符情況{w.e=a;push(sta,w);search(w);i++;}elseif(IsLetter(a)&&b!='\0'&&!IsLetter(b))//產(chǎn)生式后選式第一個字符是非終止符情況{w.e=b;push(sta,w);search(w);i++;}elsei++;}charLodeww;while(!IsEmpty(sta)){pop(sta,ww);for(i=0;i<=n;i++){w.E=str[i][0];if(str[i][3]==ww.E&&str[i][4]=='\0'){w.e=ww.e;push(sta,w);search(w);break;}}}p=0;intk=1;i=1;while(i<m){if(F[i-1].flag==1){arr[p][0]=F[i-1].R;arr[p][k]=F[i-1].r;}while(F[i].flag==0&&i<m)i++;if(F[i].flag==1){if(F[i].R==arr[p][0])k++;else{arr[p][k+1]='\0';p++;k=1;}i++;}}}voidLastVT(intn)//求LastVT{charstacksta;charLodew;for(inti=0;i<m;i++)F[i].flag=0;i=0;Initstack(sta);while(i<=n){intk=strlen(str[i]);w.E=str[i][0];chara=str[i][k-1];charb=str[i][k-2];if(!IsLetter(a)){w.e=a;push(sta,w);search(w);i++;}elseif(IsLetter(a)&&!IsLetter(b)){w.e=b;push(sta,w);search(w);i++;}elsei++;}charLodeee;while(!IsEmpty(sta)){pop(sta,ee);for(i=0;i<=n;i++){w.E=str[i][0];if(str[i][3]==ee.E&&str[i][4]=='\0'){w.e=ee.e;push(sta,w);search(w);}}}intk=1;i=1;ppp=0;while(i<m){if(F[i-1].flag==1){brr[ppp][0]=F[i-1].R;brr[ppp][k]=F[i-1].r;}while(F[i].flag==0&&i<m)i++;if(F[i].flag==1){if(F[i].R==arr[ppp][0])k++;else{brr[ppp][k+1]='\0';ppp++;k=1;}i++;}}}計算FIRSTVE和LASTVT集合FirstVT(E)={+,*,(,i}LastVT(E)={+,*,),i}FirstVT(T)={*,(,i}LastVT(T)={*,),i}FirstVT(F)={(,i}LastVT(F)={),i}FirstVT(Q)={#}LastVT(Q)={#}生成算法分析表程序7voidcreateYXB(intn)//結(jié)構(gòu)優(yōu)先表{inti,j;for(j=1;j<=kk;j++)ccrr1[0][j]=r[j-1];for(i=1;i<=kk;i++)ccrr2[i][0]=r[i-1];for(i=1;i<=kk;i++)for(j=1;j<=kk;j++)crr[i][j]=0;intI=0,J=3;while(I<=n){if(str[I][J+1]=='\0'){I++;J=3;}else{while(str[I][J+1]!='\0'){charaa=str[I][J];charbb=str[I][J+1];if(!IsLetter(aa)&&!IsLetter(bb))//優(yōu)先及等于情況,用1值表示等于{for(i=1;i<=kk;i++){if(ccrr2[i][0]==aa)break;}for(j=1;j<=kk;j++){if(ccrr1[0][j]==bb)break;}if(crr[i][j]==0)crr[i][j]=1;else{FLAG=1;I=n+1;}J++;}if(!IsLetter(aa)&&IsLetter(bb)&&str[I][J+2]!='\0'&&!IsLetter(str[I][J+2]))//優(yōu)先及等于情況{for(i=1;i<=kk;i++){if(ccrr2[i][0]==aa)break;}for(intj=1;j<=kk;j++){if(ccrr1[0][j]==str[I][J+2])break;}if(crr[i][j]==0)crr[i][j]=1;else{FLAG=1;I=n+1;}}if(!IsLetter(aa)&&IsLetter(bb))//優(yōu)先及小于情況,用2值表示小于{for(i=1;i<=kk;i++){if(aa==ccrr2[i][0])break;}for(j=0;j<=p;j++){if(bb==arr[j][0])break;}for(intmm=1;arr[j][mm]!='\0';mm++){for(intpp=1;pp<=kk;pp++){if(ccrr1[0][pp]==arr[j][mm])break;}if(crr[i][pp]==0)crr[i][pp]=2;else{FLAG=1;I=n+1;}}J++;}if(IsLetter(aa)&&!IsLetter(bb))//優(yōu)先及大于情況,用3值表示大于{for(i=1;i<=kk;i++){if(ccrr1[0][i]==bb)break;}for(j=0;j<=ppp;j++){if(aa==brr[j][0])break;}for(intmm=1;brr[j][mm]!='\0';mm++){for(intpp=1;pp<=kk;pp++){if(ccrr2[pp][0]==brr[j][mm])break;}if(crr[pp][i]==0)crr[pp][i]=3;else{FLAG=1;I=n+1;}}J++;}}}}}+*()i#+><<><>*>><><>(<<<=<)>>>>i>>>>#<<<<=算符優(yōu)先分析流程:在輸入符號棧中,有兩個指針。一個指向頂端(p1),另一個指向最頂端非終止符(p2)。當(dāng)為規(guī)約時將p2到p1之間單詞去除換成非終止符N,令p1指向p2。程序8主程序voidmain(){intn,i,j;charcharfp;char*fname="cc2.txt";//讀取為文件fpFILE*fp; if((fp=fopen(fname,"r"))==NULL)//從文件中讀入文法 { printf("\nSorry,Can'topenthefile!\n"); getchar(); exit(1); }else {charfp=fgetc(fp); i=0;j=0; while(charfp!=EOF){算符優(yōu)先分析流程圖圖3k:=k+1k:=k+1s[k]=a置初值塊:k:=1,s[k]:=”#”下一個輸入符讀入as[k]∈VTYNj:=kj:=k-1s[j]>a?Q:=s[j]s[j]<a?s[j-1]∈VTYNj:=j-1j:=j-1s[j]< Q?YNYNs[j-1]…s[k]規(guī)約為Nk:=j+1s[k]:=Ns[j]=a?s[j]=#?YNNY犯錯Y檢驗(yàn)是否正常結(jié)束結(jié)束YN犯錯流程圖說明:k:表示是符號棧S使用深度S:用來存放終止符和非終止符符號棧Vt:存放該文法中全部終止符If(charfp=='\n'){ str[i][j]='\0'; i++;j=0; } else{ str[i][j]=charfp; j++; } charfp=fgetc(fp); } n=i+1;} fclose(fp); i++;str[i][0]='Q';str[i][1]='-';str[i][2]='>';str[i][3]='#';str[i][4]=str[0][0];str[i][5]='#';str[i][6]='\0'; cout<<n<<endl;cout<<"您定義產(chǎn)生式以下:"<<endl;for(i=0;i<=n;i++)cout<<str[i]<<endl;if(judge1(n)==0)//判斷文法G是否為算符文法cout<<"文法G不是算符文法!"<<endl;if(judge1(n)==1){cout<<"文法G是算符文法!"<<endl;createF(n);FirstVT(n);LastVT(n);createYXB(n);}judge2(n);//判斷文法G是否為算符優(yōu)先文法if(FLAG==0){for(i=0;i<=p;i++)//打印FirstVT{cout<<"FirstVT("<<arr[i][0]<<")={";for(intl=1;arr[i][l+1]!='\0';l++)cout<<arr[i][l]<<",";cout<<arr[i][l]<<"}"<<endl;}cout<<"FirstVT(Q)={#}"<<endl;for(i=0;i<=ppp;i++)//打印LastVT{cout<<"LastVT("<<arr[i][0]<<")={";for(intl=1;brr[i][l+1]!='\0';l++)cout<<brr[i][l]<<",";cout<<brr[i][l]<<"}"<<endl;}cout<<"LastVT(Q)={#}"<<endl;cout<<"優(yōu)先表以下:"<<endl;for(i=1;i<kk;i++)//打印優(yōu)先關(guān)系表{cout<<"";cout<<ccrr1[0][i];}cout<<endl;for(i=1;i<kk

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論