编译原理实验代码:对于任意给定的文法,判断其是否是算符优先文法。
代码如下:#include<iostream>#include<stdlib.h>#include <fstream>#define row 50#define col 50#define SIZE 50using namespace std;//两个重要结构体的定义//FIRSTVT表或LASTVT表中一个表项(A,a)结构体的初始化typedef struct{char nonterm; //非终结符char term; //终结符}StackElement;//存放(A,a)的栈的初始化typedef struct{StackElement *top;StackElement *bottom;int stacksize;}stack;//初始化(A,a)栈void InitStack(stack &S){S.bottom = new StackElement[SIZE];if(!S.bottom)cout<<"存储空间分配失败!"<<endl;S.top = S.bottom;S.stacksize = SIZE;}//判断(A,a)栈是否为空bool ifEmpty(stack S){if(S.top==S.bottom) return true; //如果栈为空,则返回true else return false; //否则不为空,返回false}//插入栈顶(A,a)元素void Insert(stack &S,StackElement e){if(S.top-S.bottom>=S.stacksize)cout<<"栈已满,无法插入!"<<endl;else{S.top->nonterm=e.nonterm;S.top->term=e.term;S.top++;}}//弹出栈顶(A,a)元素StackElement Pop(stack &S){StackElement e;e.nonterm = '\0';e.term = '\0';if(S.top==S.bottom){cout<<"栈为空,无法进行删除操作!"<<endl;return e;}else{S.top--;e.nonterm=S.top->nonterm;e.term=S.top->term;return e;}}//终结符与非终结符的判断函数(布尔类型)bool TerminalJud(char c){if(c>='A'&&c<='Z') return false; //非终结符返回false //else if(c>='a'&&c<='z') return false;else return true; //终结符返回true}//判断非终结符在first表中是否已存在bool ItemJud(char first[][col],int frist_len,char C){for(int i=0;i<frist_len;i++){if(first[i][0]==C)return true; //如果first表中已存在此非终结符,则返回true }return false;}//读文件函数int readfile(char sen[][col]){char addr[50];cout<<"请输入要读文件的地址(\\用\\\\表示):"<<endl;cin>>addr;ifstream fin;fin.open(addr,ios::in);if(!fin){cout<<"Cannot open file!\n"<<endl;}int i,mm,l,z,k,j;char D[100][100];for(i=0;!fin.eof();i++){fin>>D[i];cout<<D[i]<<endl;}k=0;//cout<<i<<" iiii"<<endl;//cout<<k<<endl;//for(j=0;j<i;j++)//cout<<D[j]<<"ggg"<<endl;for(z=0;z<i;z++){mm=0;l=0;for(j=0;j<=strlen(D[z]);j++){if(D[z][j]=='|'){sen[k][l]='\0';mm=1;k++;sen[k][0]=D[z][0];sen[k][1]='-';sen[k][2]='>';l=3;j++;}if(mm==0){sen[k][l]=D[z][j];l++ ;}if(mm==1){sen[k][l]=D[z][j];l++ ;}}k++;}//cout<<k<<" kkkkkk"<<endl;//for(i=0;i<k;i++)//cout<<sen[i]<<endl;return k;}//FIRSTVT表和LASTVT表中表项(非终结符)的初始化void ItemInit(char sen[][col],char first[][col],char last[][col],int sen_len,int &frist_len){int i;frist_len=1;first[0][0]=sen[0][0];last[0][0]=sen[0][0];for(i=1;i<sen_len;i++){if(TerminalJud(sen[i][0])==false &&ItemJud(first,frist_len,sen[i][0])==false) //k是当前first和last表的长度{first[frist_len][0]=sen[i][0];last[frist_len][0]=sen[i][0];frist_len++;}}}void FirstVt(char sen[][col],char first[][col],int sen_len,int frist_len) // frist_len 是first 表的行数sen_len是产生式的个数{StackElement DFS,record[SIZE];//StackElement char nonterm; //非终结符char term; //终结符stack Operator; //创建存放(A,a)的栈StackElement*top; StackElement *bottom; int stacksize;InitStack(Operator);int i,j,r=0;for(i=0;i<sen_len;i++) //第一次扫描,将能直接得出的first(A,a)放进栈中{for(j=3;sen[i][j]!='\0';j++){if(TerminalJud(sen[i][j])==true) //遇到的第一个终结符压入{int exist=0;DFS.nonterm=sen[i][0];DFS.term=sen[i][j];for(int i1=0;i<r;i++){if(record[i1].nonterm==sen[i][0]&&record[i1].term==sen[i][j]){exist=1;break;}record[r].nonterm=sen[i][0];record[r].term=sen[i][j];if(exist==0){Insert(Operator,DFS);//A-aB A-aC (A,a)压栈两次?record[r].nonterm=sen[i][0];record[r].term=sen[i][j];r++;}break;}}}int location[col]; //辅助数组,用来记录first表中放入终结符的位置for(i=0;i<frist_len;i++)location[i]=1;while(!ifEmpty(Operator)){int exist=0; //标志位,记录即将入栈的元素是否已经存在StackElement IDElement,DElement;DElement=Pop(Operator); //弹出栈顶元素for(i=0;i<frist_len;i++){if(first[i][0]==DElement.nonterm){int n=location[i];first[i][n]=DElement.term; //将终结符填入相应的first表中location[i]++;break;}}for(j=0;j<sen_len;j++){if(sen[j][3]==DElement.nonterm) //找出能推出当前非终结符的产生式的左部{IDElement.nonterm=sen[j][0];IDElement.term=DElement.term;//判断将要放进栈里的元素曾经是否出现过,若没有,才压入栈for(int r0=0;r0<r;r0++) //r记录record数组中的元素个数{if(record[r0].nonterm==IDElement.nonterm &&record[r0].term==IDElement.term)exist=1;break;}}if(exist==0){Insert(Operator,IDElement);record[r].nonterm=IDElement.nonterm;record[r].term=IDElement.term;r++;}}}}}void LastVt(char sen[][col],char last[][col],int sen_len,int frist_len) //firstvt 表与lastvt表行数一样first_len表示last 表的行数{int i,j,i1,j1;char c,record[row][col]={'\0'};for(i=0;i<sen_len;i++){for(j=0;sen[i][j]!='\0';j++){record[i][j]=sen[i][j];}j=j-1;for(i1=3,j1=j;i1<j1;i1++,j1--) //做翻转,就可以用求first的方法求last{c=record[i][i1];record[i][i1]=record[i][j1];record[i][j1]=c;}}//forFirstVt(record,last,sen_len,frist_len);}//判断非终结符在term表中是否已存在bool TermTableJud(char term[col],int term_len,char C)for(int i=0;i<term_len;i++){if(term[i]==C)return true; //如果first表中已存在此非终结符,则返回1}return false;}//构造算符优先关系表bool OpPriotable(char sen[][col],char first[][col],char last[][col],char opTable[][col],int sen_len,int first_len,int &opTable_len){int i,j,term_len=0;int i2,i3,opr,opc;char c1,c2,c3;char term[SIZE]={'\0'};for(i=0;i<sen_len;i++) //一维数组term记录关系表中存在的所有终结符{for(j=3;sen[i][j]!='\0';j++){if(TerminalJud(sen[i][j])==true)if(TermTableJud(term,term_len,sen[i][j])==false) //term_len记录term表的长度{term[term_len]=sen[i][j];term_len++;}}} //得到终结符表for(i=0;i<term_len+1;i++) //给优先关系表赋初值,都等于空for(j=0;j<term_len+1;j++)opTable[i][j]=' ';for(i=1;i<term_len+1;i++) //设置优先关系表的表头{opTable[i][0]=term[i-1];opTable[0][i]=term[i-1];}opTable[i][0]='$';opTable[0][i]='$';for(i=0;i<sen_len;i++) //找等于关系{for(j=4;sen[i][j]!='\0';j++)if(TerminalJud(sen[i][j-1])==true&&TerminalJud(sen[i][j])==true){c1=sen[i][j-1];c2=sen[i][j];for(opr=1;opr<term_len+1;opr++) //在opTable表中找到该存入的行标opr{if(opTable[opr][0]==c1)break;}for(opc=1;opc<term_len+1;opc++) //在opTable表中找到该存入的列标j2{if(opTable[0][opc]==c2)break;}if(opTable[opr][opc]!=' '){if(opTable[opr][opc]!='='){cout<<"不是算符优先文法!"<<endl;return false;}}else{opTable[opr][opc]='=';}}}for(j=5;sen[i][j]!='\0';j++){if(TerminalJud(sen[i][j-2])==true&&TerminalJud(sen[i][j-1])==false&&Ter minalJud(sen[i][j])==true){c1=sen[i][j-2];c2=sen[i][j];for(opr=1;opr<term_len+1;opr++) //在opTable表中找到该存入的行标opr{if(opTable[opr][0]==c1)break;}for(opc=1;opc<term_len+1;opc++) //在opTable表中找到该存入的列标opc{if(opTable[0][opc]==c2)break;}if(opTable[opr][opc]!=' ') //表示存在多种关系不满足条件{if(opTable[opr][opc]!='='){cout<<"不是算符优先文法!"<<endl;return false;}}else{opTable[opr][opc]='=';}}//if}//for(j)}//for(i)for(i=0;i<sen_len;i++) //找小于关系{for(j=3;sen[i][j]!='\0';j++){if(TerminalJud(sen[i][j])==true&&TerminalJud(sen[i][j+1])==false){c1=sen[i][j]; //c1记录终结符c2=sen[i][j+1]; //c2记录非终结符for(opr=1;opr<term_len+1;opr++) //在opTable表中找到该存入的行标opr{if(opTable[opr][0]==c1)break;}for(opc=0;opc<first_len;opc++) //找出非终结符在first表中的列标opc {if(first[opc][0]==c2)break;for(i2=1;first[opc][i2]!='\0';i2++){c3=first[opc][i2];for(i3=1;i3<term_len+1;i3++)if(opTable[0][i3]==c3){if(opTable[opr][i3]!=' '){if(opTable[opr][i3]!='<'){cout<<"不是算符优先文法!"<<endl;return false;}}else{opTable[opr][i3]='<';}break;}}}}}for(i=0;i<sen_len;i++) //找大于关系{for(j=3;sen[i][j]!='\0';j++){if(TerminalJud(sen[i][j])==false&&sen[i][j+1]!='\0'&&TerminalJud(sen[i][j +1])==true){c1=sen[i][j]; //c1记录非终结符c2=sen[i][j+1]; //c2记录终结符for(opr=1;opr<term_len+1;opr++) //在opTable表中找到该存入的列标j1{if(opTable[0][opr]==c2)break;for(opc=0;opc<first_len;opc++) //找出非终结符在last表中的行标j2 {if(last[opc][0]==c1)break;}for(i2=1;last[opc][i2]!='\0';i2++){c3=last[opc][i2];for(i3=1;i3<term_len+1;i3++)if(opTable[i3][0]==c3){if(opTable[i3][opr]!=' '){if(opTable[i3][opr]!='>'){cout<<"不是算符优先文法!"<<endl;return false;}}else{opTable[i3][opr]='>';}break;}}}}}opTable_len=term_len+1;return true;}//判断两算符优先关系并给出类型供构造分析表int RelationshipJud(char c1,char c2,char opTable[][col],int opTable_len) {int i,j;for(i=1;i<opTable_len;i++){if(opTable[i][0]==c1)break;}for(j=1;j<opTable_len;j++){if(opTable[0][j]==c2)break;}if(opTable[i][j]=='<')return 1;else if(opTable[i][j]=='=')return 2;else if(opTable[i][j]=='>')return 3;else return 4;}//判断输入串是不是优先文法bool PrioGramJud(char sen[][col],int sen_len){int i,j;for(i=0;i<sen_len;i++){for(j=4;sen[i][j]!='\0';j++)//gfhgfhggggggggggggggggggggggggggggggggg ggggggggggggggggggg{if(TerminalJud(sen[i][j-1])==false&&TerminalJud(sen[i][j])==false){cout<<"输入的不是算符文法!"<<endl;return false;}}}return true;}//开始分析输入串void InputAnalyse(char opTable[][col],char string[col],intopTable_len) //opTable_len是opTable表的长度{char a,Q,S[SIZE]={'\0'}; //S是分析栈char cho1,cho2;int i,j,relation;int k=0;S[k]='#';cho2='y';cout<<"\t\t\t\t分析过程如下:"<<endl;cout<<"-----------------------------------------------------------------------------"<<endl;//cout<<" 栈\t当前字符\t优先关系\t移进或规约"<<endl;//cout<<"分析过程如下:"<<endl;cout.width(10);cout<<"栈";cout.width(15);cout<<"当前字符";cout.width(20);cout<<"剩余符号串";cout.width(15);cout<<"优先关系";cout.width(15);cout<<"移进或规约"<<endl;char* p;p=string;p++;for(i=0;string[i]!='\0'&&cho2=='y';i++,p++){a=string[i]; //读入当前字符cho1='n'; //可否接受while(cho1=='n'){if(TerminalJud(S[k])==true) j=k; //规约使栈内有非终结符else j=k-1;relation=RelationshipJud(S[j],a,opTable,opTable_len);if(relation==3) //S[j]>a{//cout<<" "<<S<<"\t"<<" "<<a<<"\t\t >\t\t";cout.setf(ios::left);cout.width(10);cout<<S;cout.unsetf(ios::left);cout.width(15);cout<<a;cout.width(20);cout<<p;cout.width(15);cout<<">";do{Q=S[j];if(TerminalJud(S[j-1])==true) j=j-1;else j=j-2;}while(RelationshipJud(S[j],Q,opTable,opTable_len)!=1);//cout<<" "<<S[j]<<"归约"<<endl;cout.width(11);cout<<S[j];cout.width(4);cout<<"归约"<<endl;k=j+1;S[k]='N';for(int l=k+1;l<SIZE;l++){S[l]='\0';}}else if(relation==1) //S[j]<a{cho1='y';//cout<<" "<<S<<"\t"<<" "<<a<<"\t\t <\t\t 移进"<<endl;cout.setf(ios::left);cout.width(10);cout<<S;cout.unsetf(ios::left);cout.width(15);cout<<a;cout.width(20);cout<<p;cout.width(15);cout<<"<";cout.width(15);cout<<"移进"<<endl;k=k+1;S[k]=a;}else if(relation==2) //S[j]=a{cho1='y';//cout<<" "<<S<<"\t"<<" "<<a<<"\t\t =\t\t";cout.setf(ios::left);cout.width(10);cout<<S;cout.unsetf(ios::left);cout.width(15);cout<<a;cout.width(20);cout<<p;cout.width(15);cout<<"=";cout.width(15);if(RelationshipJud(S[j],'#',opTable,opTable_len)==2) {cout<<" 接受"<<endl;break;}else{cout<<" 移进"<<endl;k=k+1;S[k]=a;}}else{cho1='y';//cout<<" "<<S<<"\t"<<a<<"\t\t出错"<<endl;cout<<S<<" "<<a<<" 出错"<<endl;cout<<"对不起!字符串有错!"<<endl;cho2='n';break;}}//while}//for}//int main(){char choice='y';while(choice=='y'){system("cls");charsen[row][col]={'\0'},first[row][col]={'\0'},last[row][col]={'\0'},opTable[row ][col]={'\0'};char string[col];int i,k,p,q;p=readfile(sen);if(PrioGramJud(sen,p)==true){ItemInit(sen,first,last,p,q); //j记录FIRSTVT和LASTVT表的长度FirstVt(sen,first,p,q);cout<<"\t\t各非终结符FIRSTVT集"<<endl;cout<<"------------------------------------------------"<<endl;for(i=0;i<p;i++){for(int h=0;h<col;h++)cout<<first[i][h]<<" ";cout<<endl;}// cout<<endl;LastVt(sen,last,p,q);cout<<"\t\t各非终结符LASTVT集"<<endl;cout<<"-------------------------------------------------"<<endl;for(i=0;i<p;i++){for(int h=0;h<col;h++)cout<<last[i][h]<<" ";cout<<endl;}// cout<<endl;int flag=0 ,j;if(OpPriotable(sen,first,last,opTable,p,q,k)==true) //k记录opTable表的长度{for(i=1;i<=k;i++){flag=0;for(j=0;j<p;j++){for(int h=0;h<col;h++){if(last[j][h]==opTable[i][0]){opTable[i][k]='>';flag=1;break;}}if(flag=1) break;}}for(i=1;i<=k;i++){flag=0;for(j=0;j<p;j++){for(int h=0;h<=col;h++){if(first[j][h]==opTable[0][i]){opTable[k][i]='<';flag=1;break;}}if(flag=1) break;}}opTable[k][k]='=';cout<<"\t\t优先关系表:"<<endl;cout<<"----------------------------------------------"<<endl;for(i=0;i<=k;i++){for(int h=0;h<=k;h++)cout<<opTable[i][h]<<" ";cout<<endl;}// cout<<endl;cout<<"请输入要分析的串,以$结束:"<<endl;cin>>string;InputAnalyse(opTable,string,k); //k是opTable表的长度}}cout<<"是否继续?y/n"<<endl;cin>>choice;}system("pause");}。