编译原理实验文法的判断
编译原理课程设计_LL(1)文法的判定

课程设计报告课程:编译原理课程设计学号:姓名:班级:教师:时间:2015.05.20-2015.07.02计算机学院图4 输入LL(1)文法并测试图7 测试非LL(1)文法附录:程序代码#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/ char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0) return(0);for(i=0;;i++){if(p[i]==c) return(1); /*若在,返回1*/if(i==strlen(p)) return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1) c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,k,m=0,n=3;char ch,temp[20];ch=c(); /*得到一个不是非终结符的符号*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果'|'后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0') temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);/*从temp所指向的内存单元顺序取m个字节复制到右部*/right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果'|'后的首符号和左部不同*/left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|') temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/******************************************* 分解不含有左递归的产生式********************************************/ void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|') temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/******************************************* 读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]){char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("请输入文法的非终结符号串:");scanf("%s",vn);//getchar(); /*取出缓冲区剩余的回车键,不要也可*/ i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("\n请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("\n请输入文法的开始符号:");scanf("%c",&s);//getchar();printf("\n请输入文法产生式的条数:");scanf("%d",&i);//getchar();for(j=1;j<=i;j++){printf("\n请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){printf("\nInput error!\n");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0]) recur(p[k]);else non_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){/*d是目标串s是源串,type=1,源串中的'^'并入目串;type=2,源串中的'^'不并入目串*/ int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j]) break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出‘^’的符号********************************************/void emp(char c){ /*即求所有由'^'推出的符号*/char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}/*******************************************求某一符号能否推出‘^’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1) return(1);for(i=0;;i++){if(i==count) return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1) return(1);else if(j==1&&in(right[i][0],termin)==1) return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1) mark=1;if(mark==1) continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count) continue;else if(result==1&&i<count) return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nLeft error!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为'^',报错*/printf("\nRight error!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST集********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,ch='^',temp[20];int j,k,m;c=v[i];emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c) continue;for(k=0;;k++)if(v[k]==right[j][0]) break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1]) break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}else break;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST集********************************************/ void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/{if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0]) break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0]) break;if(i>=0) merge(first[i],first1[j],2);else merge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1]) break;if(i>=0) merge(first[i],first1[m],2);else merge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0) merge(first[i],temp,1);else merge(TEMP,temp,1);}else if(_emp(p[k])==0) break;}}}/******************************************* 求各产生式左部的FOLLOW集********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c) break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j]) break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++) temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/ first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++) first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++) printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n_emp:");for(j=0;j<=strlen(v)-1;j++) printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++) FIRST(i,right[i]); /*求FIRST集*/for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW集*/ if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++) printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++) printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i]) break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i])) return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++) M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i]) break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j]) break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch,S[50],str[50];printf("\n请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1]) break;for(k=0;;k++){if(termin[k]==ch) break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^') S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--) S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("S:%s str:",S);for(p=j;p<=strlen(str)-1;p++) printf("%c",str[p]);printf(" \n");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y') menu();}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++) printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++) printf("%c ",left[i]);if(validity==1) validity=judge();printf("\nvalidity=%d",validity);if(validity==1){ll=ll1();printf("\nll=%d",ll);if(ll==0) printf("\n该文法不是一个LL(1)文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);menu();}}}。
编译原理之OPG实验报告

编译原理之算符优先文法分析——**学院1105班安雨雅班级:11**学号:11****实验语法分析实验报告一、实验题目算符优先文法分析程序二、实验内容及要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕和文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:(OPG文件中还有其他文法可作为测试) B~BoT|TT~TaF|FF~nF|(B)|t|f(4)分析的句子为:ntofat#三、设计思想之重点:构造算符优先表:①求FirstVT集和LastVT集②判断是否是算符文法③判断是否是算符优先文法算符优先分析:I、求最左素短语II、根据算符优先分析表分析(“<”或”=”时移进;“>”时归约)四、程序源代码(C语言)#include "stdio.h"#include "string.h"#include "stdlib.h"#define STR_MAX 80 //串的最大长度#define MAX_NUM 100 //符号的最大个数#define MAX 32767 //文件中符号的最大个数#define N 20//栈的长度class stack{ //符号栈private:char s[N];int top;public:stack();void push(char);void pop();int TOP(); //返回top的值char *S(); //返回s的值};stack::stack(){ top=-1; }void stack::push(char ch) //进栈操作{ s[++top]=ch;s[top+1]='\0'; }void stack::pop() //出栈操作{ top--; }int stack::TOP() //返回top的值{ return top; }char * stack::S() //返回s的值{ return s; }char M[MAX_NUM][MAX_NUM];struct PRO{//产生式类型char left;char right[STR_MAX];};struct VNstru{char vn;char firstVT[MAX_NUM];char lastVT[MAX_NUM];};char SOUR[STR_MAX];//源文件名char OBJ[STR_MAX]; //目标文件名char ERR[STR_MAX]; //错误信息文件名FILE *INF; //源程序文件指针FILE *OUTF; //分析结果文件指针FILE *ERRF; //错误信息文件指针char OG[MAX]; //存放上下文无关文法int OGlen; //上下文无关文法长度VNstru VN[MAX_NUM]; //非终结符数组int VN_CNT; //非终结符个数char VT[MAX_NUM]; //终结符数组int VT_CNT; //终结符个数char S0; //开始符号PRO P[MAX_NUM]; //产生式数组int P_CNT; //产生式个数bool isIN(char ch,VNstru arr[]); //判别符号ch是否在arr数组中int isVN(char ch); //判别符号ch是否在VN数组中,存在则返回下标,否则返回-1 int isVT(char ch); //判别符号ch是否在VT数组中,存在则返回下标,否则返回-1 void getOG(); //从源文件取得OG文法串void getVN_VT_S_P(); //从OG文法提取VN,VT,S,Pvoid FirstVT(char ch,char firstVT[]); //求FirstVT[]集firstVT void LastVT(char ch,char lastVT[]); //求LastVT[]集lastVTbool O_G(); //判别是否是OG文法bool O_P_G(); //判别是否是OPG文法void leftphase(char str[],char substr[],char a); //求最左素短语substrvoid left_str(char w[],char subw[],int ip); //求剩余输入串subwbool isIN(char ch,VNstru arr[])//判别符号ch是否在arr数组中{for(int i=0;i<VN_CNT;i++)if(ch==arr[i].vn)return 1;return 0;}int isVN(char ch)//判别符号ch是否在VN数组中,存在则返回下标,否则返回-1 {for(int i=0;i<VN_CNT;i++){if(ch==VN[i].vn)return i;}return -1;}int isVT(char ch)//判别符号ch是否在VT数组中,存在则返回下标,否则返回-1 {for(int i=0;i<VT_CNT;i++){if(ch==VT[i])return i;}return -1;}void getOG()//从源文件取得OG文法串{OGlen=0;char ch;while(!feof(INF)){ch=fgetc(INF);if(ch!=' ')OG[OGlen++]=ch;}OG[OGlen]='\0';printf("The Grammar is :\n"); //将文法输出到屏幕puts(OG);fprintf(OUTF,"The Grammar is :\n");fputs(OG,OUTF); //将文法输出到文件}void getVN_VT_S_P()//从OG文法提取VN,VT,S,P{VN_CNT=0;VT_CNT=0;P_CNT=0;int newPF=0; //是否进入新产生式的标志int rightLen=0;char prech,ch,nextch;for(int i=0;i<OGlen;i++){if(i!=0) prech=OG[i-1]; //取文法文件中的前一个符号ch=OG[i]; //取文法文件中的当前符号nextch=OG[i+1]; //取文法文件中的下一个符号if(nextch=='~') //下一个符号是~,代表箭头{if(isVN(ch)==-1){ //当前符号不是已经识别到的VN VN[VN_CNT].vn=ch; //加入VNVN_CNT++;}P[P_CNT].left=ch; //记入新产生式的左部if(P_CNT==0)S0=ch; //第一条产生式的左部是开始符号i++; //跳过~}if(prech=='~'||prech=='|'){newPF=1; //进入新的产生式rightLen=0;}if(newPF==1){P[P_CNT].right[rightLen++]=ch;}if(nextch=='\n'||nextch=='|'){newPF=0; //一条产生式结束P_CNT++; //产生式个数加1P[P_CNT].left=P[P_CNT-1].left;i++; //跳过回车和|}}for(int j=0;j<OGlen;j++){ch=OG[j];if(ch!='~'&&ch!='|'&&ch!='\n'&&isVN(ch)==-1&&isVT(ch)==-1&&ch!=' ') VT[VT_CNT++]=ch;}VT[VT_CNT++]='#';VT[VT_CNT]='\0';//输出VNprintf("\nVN:\t");fprintf(OUTF,"\nVN:\t");for(int x=0;x<VN_CNT;x++){printf("%c",VN[x].vn);fprintf(OUTF,"%c",VN[x].vn);}//输出VTprintf("\nVT:\t%s\n",VT);fprintf(OUTF,"\nVT:\t%s\n",VT);//输出Sprintf("S0:\t%c\n\n",S0);fprintf(OUTF,"S0:%c\n\n",S0);//输出Pfor(int k=0;k<P_CNT;k++){printf("P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);fprintf(OUTF,"P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);}printf("\n");fprintf(OUTF,"\n");}//FIRSTVT(B)={b|B=>b...或B=>Cb...}int f=0;void FirstVT(char ch,char firstVT[])//求非终结符的FirstVT集,存至firstVT中{if(isIN(ch,VN))for(int i=0;i<P_CNT;i++){if(ch==P[i].left){int j=0;char a=P[i].right[j];//B->b...if(isVT(a)!=-1){firstVT[f++]=a;firstVT[f]='\0';}//B->Cb...if(isVN(a)!=-1 && isVT(P[i].right[j+1])!=-1){firstVT[f++]=P[i].right[j+1];firstVT[f]='\0';}//B->C,C->b...||Db...if(isVN(a)!=-1 && strlen(P[i].right)==1)FirstVT(a,firstVT);}}f=0; //f清零,便于重复调用此函数}//LASTVT(B)={a|B=>...a或B=>...aC}int l=0;void LastVT(char ch,char lastVT[])//求非终结符的LastVT集,存放至lastVT中{if(isIN(ch,VN))for(int i=0;i<P_CNT;i++){if(ch==P[i].left){int j=strlen(P[i].right)-1; //'j'记录右部的最后一个字符位置char a=P[i].right[j];//B->...a;if(isVT(a)!=-1){lastVT[l++]=a;lastVT[l]='\0';}//B->...aC;if(isVN(a)!=-1 && isVT(P[i].right[j-1])!=-1){lastVT[l++]=P[i].right[j-1];lastVT[l]='\0';}//B->C,C->...a||...aD;if(isVN(a)!=-1 && j==0)LastVT(a,lastVT);}}l=0;//l清零,便于重复调用此函数}bool O_G() //判别是否是OG文法[没有两个连续的非终结符,即形如A->...BC...的产生式] {//求所有非终结符的firstVT集for(int i=0;i<VN_CNT;i++){char fvt[STR_MAX];FirstVT(VN[i].vn,fvt);strcpy(VN[i].firstVT,fvt);printf("FirstVT(%c)={ ",VN[i]);fprintf(OUTF,"FirstVT(%c)={ ",VN[i]);for(int j=0;j<(int)strlen(fvt);j++){printf("%c ",fvt[j]);fprintf(OUTF,"%c ",fvt[j]);}printf("}\n");fprintf(OUTF,"}\n");}printf("\n");fprintf(OUTF,"\n");//求所有非终结符的lastVT集for(i=0;i<VN_CNT;i++){char lvt[STR_MAX];LastVT(VN[i].vn,lvt);strcpy(VN[i].lastVT,lvt);printf("LastVT(%c)={ ",VN[i]);fprintf(OUTF,"LastVT(%c)={ ",VN[i]);for(int j=0;j<(int)strlen(lvt);j++){printf("%c ",lvt[j]);fprintf(OUTF,"%c ",lvt[j]);}printf("}\n");fprintf(OUTF,"}\n");}//判别是否是OG文法for(i=0;i<P_CNT;i++){int j=0;while(P[i].right[j+1]!='\0'){char ch=P[i].right[j];char nextch=P[i].right[j+1];if(isVN(ch)!=-1 && isVN(nextch)!=-1)return 0;elsej++;}}return 1;}bool O_P_G()//判别是否是OPG文法 [不含空产生式或任意两个终结符a,b之间至多有一种(<,>,=)关系]{for(int m=0;m<MAX_NUM;m++) //初始化M数组for(int n=0;n<MAX_NUM;n++)M[m][n]=' ';for(int i=0;i<P_CNT;i++){int j=0;char prech=' ',ch=' ',nextch=' '; //当进入新的产生式时,要清空三字符的值;while(P[i].right[j]!='\0'){if(j!=0)prech=ch;ch=P[i].right[j];nextch=P[i].right[j+1];if(isVT(ch)!=-1 && isVT(nextch)!=-1) //A->..ab.. (a=b){if(M[isVT(ch)][isVT(nextch)]==' ') //当M[][]为空时赋号{M[isVT(ch)][isVT(nextch)]='=';j++;continue;}else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",ch,nextch);fprintf(ERRF,"\n%c,%c有两种关系!",ch,nextch);return 0;}}if(isVT(ch)!=-1 && isVN(nextch)!=-1) //A->..aB... (a<FirstVT[B]){FirstVT(nextch,VN[isVN(nextch)].firstVT);for(int m=0;VN[isVN(nextch)].firstVT[m]!='\0';m++){if(M[isVT(ch)][isVT(VN[isVN(nextch)].firstVT[m])]==' ')M[isVT(ch)][isVT(VN[isVN(nextch)].firstVT[m])]='<';else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",ch,VN[isVN(nextch)].firstVT[m]);fprintf(ERRF,"\n%c,%c有两种关系!",ch,VN[isVN(nextch)].firstVT[m]);return 0;}}j++;continue;}if(isVT(prech)!=-1 && isVN(ch)!=-1 && isVT(nextch)!=-1) //A->..aBb.. (a=b) {if(M[isVT(prech)][isVT(nextch)]==' ')M[isVT(prech)][isVT(nextch)]='=';else{printf("\n%c,%c有两种关系!",prech,nextch);fprintf(ERRF,"\n%c,%c有两种关系!",prech,nextch);return 0;}}if(isVN(ch)!=-1 && isVT(nextch)!=-1) //A->..Bb..(LastVT[B]>b){LastVT(ch,VN[isVN(ch)].lastVT);for(int m=0;VN[isVN(ch)].lastVT[m]!='\0';m++){if(M[isVT(VN[isVN(ch)].lastVT[m])][isVT(nextch)]==' ')M[isVT(VN[isVN(ch)].lastVT[m])][isVT(nextch)]='>';else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",VN[isVN(ch)].lastVT[m],nextch);fprintf(ERRF,"\n%c,%c有两种关系!",VN[isVN(ch)].lastVT[m],nextch);return 0;}}j++;continue;}elsej++;}//(while)}//(for)M[VT_CNT-1][VT_CNT-1]='='; //#=#for(int x=0;x<(int)strlen(VN[isVN(S0)].firstVT);x++) //# < FirstVT(S0);M[VT_CNT-1][isVT(VN[isVN(S0)].firstVT[x])]='<';for(x=0;x<(int)strlen(VN[isVN(S0)].lastVT);x++) //LastVT(S0) > #M[isVT(VN[isVN(S0)].lastVT[x])][VT_CNT-1]='>';return 1;}void leftphase(char str[],char substr[],char a) //求最左素短语,用substr储存{int slen=strlen(str);int begin,end=slen-1;for(int i=slen-1;i>0;i--){if(M[isVT(str[i])][isVT(a)]=='>'){if(M[isVT(str[i-1])][isVT(str[i])]=='<')begin=i;else{begin=i-1;continue;}}if(isVN(str[i]))continue;}int j=0;int b=begin; //必须将begin的值记录,因为while的循环条件与begin有关,否则会影响素短语的取值。
编译原理实验报告

《编译原理》实验报告软件131 陈万全132852一、需求分析通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。
通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。
1、词法分析程序设计与实现假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。
输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。
输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。
对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。
2、语法分析程序设计与实现选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。
G2[<算术表达式>]:<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表达式>)若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。
编译原理实验报告5_语法分析程序的设计(2)

实验5 语法分析程序的设计(2)一、实验目的通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中算法优先分析方法。
二、实验内容设计一个文法的算法优先分析程序,判断特定表达式的正确性。
三、实验要求1、给出文法如下:G[E]E->T|E+T;T->F|T*F;F->i|(E);2、计算机中表示上述优先关系,优先关系的机内存放方式有两种1)直接存放,2)为优先关系建立优先函数,这里由学生自己选择一种方式;1、给出算符优先分析算法如下:k:=1; S[k]:=‘#’;REPEAT把下一个输入符号读进a中;IF S[k]∈V T THEN j:=k ELSE j:=k-1;WHILE S[j] a DOBEGINREPEATQ:=S[j];IF S[j-1]∈V T THEN j:=j-1 ELSE j:=j-2UNTIL S[j] Q把S[j+1]…S[k]归约为某个N;k:=j+1;S[k]:=N;END OF WHILE;IF S[j] a OR S[j] a THENBEGINk:=k+1;S[k]:=aENDELSE ERRORUNTIL a=‘#’1、根据给出算法,利用适当的数据结构实现算符优先分析程序;2、利用算符优先分析程序完成下列功能:1)手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束;2)读入文本文件中的表达式;3)调用实验2中的词法分析程序搜索单词;4)把单词送入算法优先分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息;5)完成上述功能,有余力的同学可以对正确的表达式计算出结果。
四、实验环境PC微机DOS操作系统或 Windows 操作系统Turbo C 程序集成环境或 Visual C++ 程序集成环境五、实验步骤1、分析文法中终结符号的优先关系;2、存放优先关系或构造优先函数;3、利用算符优先分析的算法编写分析程序;4、写测试程序,包括表达式的读入和结果的输出;5、程序运行效果,测试数据可以参考下列给出的数据。
编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。
基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。
然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。
若不为“#”且不与当前输入符号一样,则出错。
若栈顶符号为非终结符时,查看预测分析表,看栈顶符号和当前输入符号是否构成产生式,若产生式的右部为ε,则将栈顶符号出栈,取出栈顶符号进入下一个字符的分析。
若不为ε,将产生式的右部逆序的入栈,取出栈顶符号进入下一步分析。
程序流程图:本程序中使用以下文法作对用户输入的字符串进行分析:E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→i|(E)该文法的预测分析表为:1、显示预测分析表,提示用户输入字符串2、输入的字符串为正确的句子:3、输入的字符串中包含了不属于终结符集的字符4、输入的字符串不是该文法能推导出来的句子程序代码:package ;import java.io.*;public class LL {String Vn[] = { "E", "E'", "T", "T'", "F" }; // 非终结符集String Vt[] = { "i", "+", "*", "(", ")", "#" }; // 终结符集String P[][] = new String[5][6]; // 预测分析表String fenxi[] ; // 分析栈int count = 1; // 步骤int count1 = 1;//’分析栈指针int count2 = 0, count3 = 0;//预测分析表指针String inputString = ""; // 输入的字符串boolean flag;public void setCount(int count, int count1, int count2, int count3){this.count = count;this.count1 = count1;this.count2 = count2;this.count3 = count3;flag = false;}public void setFenxi() { // 初始化分析栈fenxi = new String[20];fenxi[0] = "#";fenxi[1] = "E";}public void setP() { // 初始化预测分析表for (int i = 0; i < 5; i++) {for (int j = 0; j < 6; j++) {P[i][j] = "error";}}P[0][0] = "->TE'";P[0][3] = "->TE'";P[1][1] = "->+TE'";P[1][4] = "->ε";P[1][5] = "->ε";P[2][0] = "->FT'";P[2][3] = "->FT'";P[3][1] = "->ε";P[3][2] = "->*FT'";P[3][4] = "->ε";P[3][5] = "->ε";P[4][0] = "->i";P[4][3] = "->(E)";// 打印出预测分析表System.out.println(" 已构建好的预测分析表");System.out.println("----------------------------------------------------------------------");for (int i=0; i<6; i++) {System.out.print(" "+Vt[i]);}System.out.println();System.out.println("----------------------------------------------------------------------");for (int i=0; i<5; i++) {System.out.print(" "+Vn[i]+" ");for (int j=0; j<6; j++) {int l = 0;if (j>0) {l = 10-P[i][j-1].length();}for (int k=0; k<l; k++) {System.out.print(" ");}System.out.print(P[i][j]+" ");}System.out.println();}System.out.println("----------------------------------------------------------------------"); }public void setInputString(String input) {inputString = input;}public boolean judge() {String inputChar = inputString.substring(0, 1); // 当前输入字符boolean flage = false;if (count1 >= 0) {for (int i=0; i<6; i++) {if (fenxi[count1].equals(Vt[i])) { // 判断分析栈栈顶的字符是否为终结符flage = true;break;}}}if (flage) {// 为终结符时if (fenxi[count1].equals(inputChar)) {if (fenxi[count1].equals("#")&&inputString.length()==1) { // 栈顶符号为结束标志时// System.out.println("最后一个");String fenxizhan = "";for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" " + count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println("接受");flag = true;return true;} else {// 分析栈栈顶符号不为结束标志符号时String fenxizhan = "";for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" "+count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println("\"" + inputChar + "\"" + "匹配");// 将栈顶符号出栈,栈顶指针减一fenxi[count1] = null;count1 -= 1;if (inputString.length() > 1) { // 当当前输入字符串的长度大于1时,将当前输入字符从输入字符串中除去inputString = inputString.substring(1, inputString.length());} else { // 当前输入串长度为1时inputChar = inputString;}// System.out.println(" "+count+" "+fenxizhan+"// "+inputString +" "+P[count3][count2]);// System.out.println(count + inputChar + "匹配");count++;judge();}}else { // 判断与与输入符号是否一样为结束标志System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}} else {// 非终结符时boolean fla = false;for (int i=0; i<6; i++) { // 查询当前输入符号位于终结符集的位置if (inputChar.equals(Vt[i])) {fla = true;count2 = i;break;}}if(!fla){System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}for (int i=0; i<5; i++) { // 查询栈顶的符号位于非终结符集的位置if (fenxi[count1].equals(Vn[i])) {count3 = i;break;}}if (P[count3][count2] != "error") { // 栈顶的非终结符与输入的终结符存在产生式时String p = P[count3][count2];String s1 = p.substring(2, p.length()); // 获取对应的产生式if (s1.equals("ε")) { // 产生式推出“ε”时String fenxizhan = "";for (int i=0; i<=P.length; i++) {if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" " + count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println(fenxi[count1] + P[count3][count2]);// 将栈顶符号出栈,栈顶指针指向下一个元素fenxi[count1] = null;count1 -= 1;count++;judge();} else { // 产生式不推出“ε”时int k = s1.length();String fenxizhan = "";for (int i=0; i<=P.length; i++) {if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" "+count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.println(fenxi[count1] + P[count3][count2]);for (int i=1; i<=k; i++) { // 将产生式右部的各个符号入栈String s2 = s1.substring(s1.length() - 1, s1.length());s1 = s1.substring(0, s1.length() - 1);if (s2.equals("'")) {s2 = s1.substring(s1.length() - 1, s1.length())+ s2;i++;s1 = s1.substring(0, s1.length() - 1);}fenxi[count1] = s2;if (i < k)count1++;// System.out.println("count1=" + count1);}// System.out.println(" "+count+" "+fenxizhan+"// "+inputString +" "+P[count3][count2]);count++;// System.out.println(count);judge();}} else {System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}}return flag;}public static void main(String args[]) {LL l = new LL();l.setP();String input = "";boolean flag = true;while (flag) {try {InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);System.out.println();System.out.print("请输入字符串(输入exit退出):");input = br.readLine();} catch (Exception e) {e.printStackTrace();}if(input.equals("exit")){flag = false;}else{l.setInputString(input);l.setCount(1, 1, 0, 0);l.setFenxi();System.out.println();System.out.println("分析过程");System.out.println("----------------------------------------------------------------------");System.out.println(" 步骤| 分析栈| 剩余输入串| 所用产生式");System.out.println("----------------------------------------------------------------------");boolean b = l.judge();System.out.println("----------------------------------------------------------------------");if(b){System.out.println("您输入的字符串"+input+"是该文发的一个句子");}else{System.out.println("您输入的字符串"+input+"有词法错误!");}}}}}。
编译原理词法分析,语法分析实验报告

编译原理实验报告一.LL(1)文法分析1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。
2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。
3.流程图开始读入文法有效?是是LL(1)文法?是判断句型报错结束4.源程序/*******************************************语法分析程序作者:xxx学号:xxx********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/ char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序二.词法分析一、问题描述识别简单语言的单词符号识别简单语言的基本字、标识符、无符号整数、运算符和界符。
编译原理词法分析和ll(1)文法判定

struct SYMINFO//词法分析信息结构体
{
int num;
struct SYM sym[MAX_SYM];
struct FORM form;
};
//取词函数(返回读字符数量,如果是0则表示结束,lin表示当前行数)
int __stdcall getsym(const char *in,struct SYM *out,int *ln,struct FORM *form);
#include <stdlib.h>//For memset()
#include <string.h>//For strcpy()
#define ISLETTER(c)((c)>='A'&&(c)<='Z'||(c)>='a'&&(c)<='z')
#define ISNUMBER(c)((c)>='0'&&(c)<='9')
#define IDC_INPUT 1001
#define IDC_OUTPUT 1003
#define IDC_ERRPUT 1004
#define IDC_BUTTON1 1005
#define ID_START 40001
#define ID_ABOUT 40003
#define ID_OPEN 40005
out->id=ERR_OVERNUMFORM;
return m+n;
}
form->numf[form->numnum].id=form->numnum;
编译原理实验Chomsky文法类型判断

1.实验目的输入:一组任意的规则。
输出:相应的Chomsky 文法的类型。
2.实验原理1.0型文法(短语文法)如果对于某文法G,P中的每个规则具有下列形式:u:: = v其中u∈V+,v∈V*,则称该文法G为0型文法或短语文法,简写为PSG。
这种0型文法或短语结构文法的相应语言称为0型语言或短语结构语言L文法由于没有其他任何限制,因此0型文法也称为无限制文法,其相应的语言称为无限制性语言。
任何0型语言都是递归可枚举的,故0型语言又称递归可枚举集。
这种语言可由图灵机(Turning)来识别。
2.1型文法(上下文有关文法)如果对于某文法G,P中的每个规则具有下列形式:xUy:: = xuy;u∈V+;x,y∈V*,则称该文法G为1型文法或上下文有关文法,其中U∈VN也称上下文敏感文法,简写为CSG。
1型文法的规则左部的U和右部的u具有相同的上文x和下文y,利用该规则进行推导时,要用u替换U,必须在前面有x和后面有y的情况下才能进行,显示了上下文有关的特性。
,1型语言可由线性有界自动机来识别。
1型文法所确定的语言为1型语言L13.2型文法(上下文无关文法)如果对于某文法G,P中的每个规则具有下列形式:U :: = u;u∈V+,则称该文法G为2型文法或上下文无关文法,简写为其中U∈VNCFG。
按照这条规则,对于上下文无关文法,利用该规则进行推导时,无需考虑非终结符U所在的上下文,总能用u替换U,或者将u归约为U,显示了上下文无关的特点。
2型文法所确定的语言为2型语言L,2型语言可由非确定的下推自动机来2识别。
一般定义程序设计语言的文法是上下文无关的。
如C语言便是如此。
因此,上下文无关文法及相应语言引起了人们较大的兴趣与重视。
4.3型文法(正则文法,线性文法)如果对于某文法G,P中的每个规则具有下列形式:U :: = T 或 U :: = WT其中T∈VT ;U,W∈VN,则称该文法G为左线性文法。
如果对于某文法G,P中的每个规则具有下列形式:U :: = T 或 U :: = TW其中T∈VT ;U, W∈VN,则称该文法G为右线性文法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文法类型的判断和推导序列的生成目录一、实验名称 (2)二、实验目的 (2)三、实验原理 (2)1、文法G定义为四元组(Vn,Vt,P,S) (2)2、文法类型的判断 (2)四、实验思路 (2)1、接受产生式 (3)2、文法类型的判断 (3)3、将文法以四元组形式输出 (4)五、实验小结 (4)1、文法类型的判断条件 (4)2、产生式的存储问题 (5)3、文法以四元组形式输出问题 (5)六、附件 (5)1、源代码 (5)2、运行结果截图 (10)一、实验名称文法类型的判断和推导序列的生成二、实验目的输入:一组任意的文法规则和任意符号串。
输出:相应的Chomsky文法类型和推导。
三、实验原理1、文法G定义为四元组(Vn,Vt,P,S)其中Vn为非终结符(或语法实体,或变量)集:Vt为终结符集;P为规则(α->β)的集合,α∈(Vn∪Vt)*且至少包含一个非终结符,β∈(Vn∪Vt)*;Vn,Vt和P是非空有穷集。
S称作识别符或开始符,它是一个非终结符,至少要在一条规则中作为左部出现。
2、文法类型的判断a.设G=(Vn,Vt,P,S)为一文法,若P中的每一个产生式α->β均满足|β|>=|α|,仅仅S->ε除外,则文法G是1型或上下文有关的。
b.设G=(Vn,Vt,P,S),若P中的每一个产生式α->β满足: α是一个非终结符,β∈(Vn∪Vt)*,则此文法称为2型的或上下文无关的。
c. 设G=(Vn,Vt,P,S),若P中的每一个产生式的形式都是A->αB或A->α,其中A和B都是终结符,α∈Vt*,则G是3型文法或正规文法。
四、实验思路本实验采取C++来完成,用大写字母A到Z表示非终结符,小写字符a到z 表示终结符。
实验流程图1、接受产生式首先建立一个结构体siyuanzu,其成员有非终结符集合数组Vn,终结符集合数组Vt以及产生式集合数组rule,通过函数input来接受从键盘输入的产生式,并且存储于string类字符串数组rule中。
函数input实现接受产生式功能的思路为:先确定要输入的产生式数目n,用for循环实现产生式的存储。
2、文法类型的判断函数Grammer实现判断文法类型的功能并且输出文法的类型。
其实现功能的思路为:a.对rule数组中每一个产生式进行判断,以“->”中的“-”作为判断条件,将产生式分为左部和右部分别计算左部和右部的长度。
若youb小于左部则不是1型文法。
输出0型文法;若右部大于或等于左部,则继续判断。
b.判断文法是否为2型文法,经过a步骤的执行,若文法为1型文法,只需在此基础上判断文法的左部是否只有一个非终结符。
通过判断条件zuo==1&&'A'<=a.rule[i][zuo-1]&&a.rule[i][zuo-1]<='Z'确定是否为2型文法,若不满足判断条件则为1型文法,进行输出,若满足则继续判断。
c.判断文法是否为3型文法,经过b步骤的执行,若文法为2型文法,只需在此基础上判断文法的右部是否为αB或α形式或者是Bα或α形式。
通过判断条件一((you==2)&&(a.rule[i][num+1]>='a')&&(a.rule[i][num+1]<='z')&&(a.rule[i][num+2]>=' A')&&(a.rule[i][num+2]<='Z'))||((you==1)&&(a.rule[i][num+1]>='a')&&(a.rule[i][num +1]<='z'))判断是否满足αB或α形式,通过判断条件二((you==2)&&(a.rule[i][num+1]>='A')&&(a.rule[i][num+1]<='Z')&&(a.rule[i][num+2]>=' a')&&(a.rule[i][num+2]<='z'))||((you==1)&&(a.rule[i][num+1]>='a')&&(a.rule[i][num+ 1]<='z'))判断是否满足Bα或α形式。
若所有产生式同时满足判断条件一或者同时满足判断条件二,则为3型文法进行输出。
否则为2型文法进行输出。
3、将文法以四元组形式输出函数output实现输出文法四元组形式的功能。
具体思路为:a.将存放产生式的string类数组rule一分为二,用x数组存放rule中所有的大写字母即非终结符,用y数组存放rule中所有的小写字母即终结符。
b.用双重for循环给x和y数组中重复的字符标记,重复的字符全部赋值为“!”c.将x数组中非“!”元素赋值给非终结符集Vn,将y数组中非“!”元素赋值给终结符集Vt。
d.按照格式分别输出非终结符集Vn,终结符集Vt,产生式P以及开始符S。
五、实验小结我运用C++解决了此次实验的文法类型判断的问题,在实际解决问题的过程中,主要遇到了以下几个问题:1、文法类型的判断条件《编译原理》书本上给出了几类文法类型的定义,但是在实际的解决问题过程中,需要将书本上给的判断条件转换为C++语言中的判断条件,这需要对文法类型的定义有很好的理解。
我通过判断产生式右部是否大于等于左部确定1型文法,在此基础上判断产生式左部是否为一个非终结符确定2型文法,最后在2型文法的基础上判断产生式是否全部满足αB或α形式或者是Bα或α形式确定3型文法。
最终解决了文法类型判断条件的问题。
2、产生式的存储问题实验要求最少输入五条产生式,我最初是选择用C语言解决存储问题,但是发现C语言中对于字符串的处理不够灵活,于是选择了C++来解决。
C++中可以用string类型来定义字符串数组,并且可以通过length函数求每个字符串的长度,这样给每条产生式的判断都带来了极大的便捷。
3、文法以四元组形式输出问题实验需要输出文法的四元组,即需要输出非终结符集Vn,终结符集Vt,产生式P以及开始符S,由于我将产生式存储在string类数组rule中,因此,需要将rule中的元素分为两类,大写字母为非终结符,小写字母为终结符。
但是分好类的数组存在元素重复的问题,我通过一个双重for循环给重复元素标记为“!”,再将非“!”元素赋值给字符数组Vn和Vt,解决了元素重复问题。
最后需要安排一下输出的格式即解决了这个问题。
通过本次实验,我深入的了解了文法类型的判断,对于文法类型的判断也更加的熟练。
同时,对于文法的四元组的定义更加的熟悉,并且对于运用C++解决编译原理的问题有了一定的基础。
六、附件1、源代码#include<iostream>#include<string>using namespace std;struct siyuanzu{char Vn[50];char Vt[50];string rule[20];};int input(siyuanzu *a){int n,i;cout<<"请输入产生式数目:";cin>>n;cout<<"请输入产生式:\n";for(i=0;i<n;i++)cin>>(*a).rule[i];return n;}void output(siyuanzu a,int n){int i,j,length,k1=0,k2=0,m1=0,m2=0;char x[50],y[50];for(i=0;i<n;i++){length=a.rule[i].length();for(j=0;j<length;j++){if(a.rule[i][j]!='-'&&a.rule[i][j]!='>'){if(a.rule[i][j]>='A'&&a.rule[i][j]<='Z'){x[k1]=a.rule[i][j];k1++;}else{y[k2]=a.rule[i][j];k2++;}}}}for(i=0;i<k1-1;i++)for(j=i+1;j<k1;j++){if(x[i]==x[j])x[j]='!';}for(i=0;i<k1;i++){if(x[i]!='!'){a.Vn[m1]=x[i];m1++;}}for(i=0;i<k2-1;i++)for(j=i+1;j<k2;j++){if(y[i]==y[j])y[j]='!';}for(i=0;i<k2;i++){if(y[i]!='!'){a.Vt[m2]=y[i];m2++;}}cout<<"四元组G=(Vn,Vt,P,S)"<<endl;cout<<"其中非终结符Vn={";for(i=0;i<m1-1;i++)cout<<a.Vn[i]<<",";cout<<a.Vn[m1-1];cout<<"}";cout<<endl;cout<<"终结符Vt={";for(i=0;i<m2-1;i++)cout<<a.Vt[i]<<",";cout<<a.Vt[m2-1];cout<<"}";cout<<endl;cout<<"P由下列产生式组成:"<<endl;for(i=0;i<n;i++)cout<<a.rule[i]<<endl;cout<<"开始符为:S"<<endl;}void Grammer(siyuanzu a,int n){int i,j,length,num,zuo,you;char c;for(i=0;i<n;i++){num=0;length=a.rule[i].length();for(j=0;j<length;j++){c=a.rule[i][j];num++;if(c=='-')break;}zuo=num-1;you=length-(num+1);if(you>=zuo)continue;elsebreak;}if(i==n){for(i=0;i<n;i++){num=0;length=a.rule[i].length();for(j=0;j<length;j++){c=a.rule[i][j];num++;if(c=='-')break;}zuo=num-1;if(zuo==1&&'A'<=a.rule[i][zuo-1]&&a.rule[i][zuo-1]<='Z') continue;elsebreak;}if(i==n){for(i=0;i<n;i++){num=0;length=a.rule[i].length();for(j=0;j<length;j++){c=a.rule[i][j];num++;if(c=='-')break;}you=length-(num+1);if(((you==2)&&(a.rule[i][num+1]>='a')&&(a.rule[i][num+1]<='z')&&(a.rule[i][num +2]>='A')&&(a.rule[i][num+2]<='Z'))||((you==1)&&(a.rule[i][num+1]>='a')&&(a.rule[i ][num+1]<='z')))continue;elsebreak;}if(i==n)cout<<"文法类型:3型文法"<<endl;else{for(i=0;i<n;i++){num=0;length=a.rule[i].length();for(j=0;j<length;j++){c=a.rule[i][j];num++;if(c=='-')break;}you=length-(num+1);if(((you==2)&&(a.rule[i][num+1]>='A')&&(a.rule[i][num+1]<='Z')&&(a.rule[i][nu m+2]>='a')&&(a.rule[i][num+2]<='z'))||((you==1)&&(a.rule[i][num+1]>='a')&&(a.rule [i][num+1]<='z')))continue;elsebreak;}if(i==n)cout<<"文法类型:3型文法"<<endl;elsecout<<"文法类型:2型文法"<<endl;}}elsecout<<"文法类型:1型文法"<<endl;}elsecout<<"文法类型:0型文法"<<endl;}int main(){int n,r;siyuanzu a;while(1){cout<<"--------------------文法类型判断(E21414020 陈国柱)--------------------"<<endl;cout<<" 1.输入产生式"<<endl;cout<<" 2.输出文法类型及四元组"<<endl;cout<<" 3.结束"<<endl;cout<<"输入功能号:"<<endl;cin>>r;if(r>3||r<1){do{cout<<"输入有误,重新输入"<<endl;cin>>r;}while(r<=3&&r>=1);}switch(r){case 1:n=input(&a);break;case 2:Grammer(a,n);output(a,n);break;case 3:exit(0);break;default:break;}}return 0;}2、运行结果截图a.实验开始图b.非1型文法c.1型文法d.2型文法e.3型文法f.实验结束图。