编译原理实验文法的判断

合集下载

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

编译原理课程设计_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实验报告

编译原理之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)

实验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)文法分析器实验(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)文法判定

编译原理词法分析和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文法类型判断

编译原理实验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、对输入的txt文件内的内容进行词法分析:2、由文件流输入test.txt中的内容,对文件中的各类字符进行词法分析3、打印出分析后的结果;二、程序结构描述:(源代码见附录)1、分别利用k[],s1[],s2[],s3[]构造关键字表,分界符表,算术运算符表和关系运算符表。

2、bool isletter(){} 用来判断其是否为字母,是则返回true,否则返回false;bool isdigit(){} 用来判断其是否为数字,是则返回true,否则返回false;bool iscalcu(){} 用来判断是否为算术运算符,是则返回true,否则返回false;bool reserve(string a[]){} 用来判断某字符是否在上述四个表中,是则返回true,否则返回false;void concat(){} 用来连接字符串;void getn(){} 用来读取字符;void getb(){} 用来对空格进行处理;void retract(){}某些必要的退格处理;int analysis(){} 对一个单词的单词种别进行具体判断;在主函数中用switch决定输出。

三、实验结果四、实验总结词法分析器一眼看上去很复杂,但深入的去做就会发现并没有一开始想象的那么困难。

对于一个字符的种别和类型可以用bool函数来判断,对于关键字和标示符的识别(尤其是3b)则费了一番功夫,最后对于常数的小数点问题处理更是麻烦。

另外,这个实验要设定好时候退格,否则将会导致字符漏读甚至造成字符重复读取。

我认为,这个实验在程序实现上大体不算困难,但在细节的处理上则需要好好地下功夫去想,否则最后的程序很可能会出现看上去没有问题,但实际上漏洞百出的状况。

将学过的知识应用到实际中并不简单,只有自己不断尝试将知识转化成程序才能避免眼高手低,对于知识的理解也必将更加深刻。

实验二LL(1)分析法一、实验原理:1、写出LL(1)分析法的思想:当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。

编译原理语法分析实验报告

编译原理语法分析实验报告

实验二语法分析实验报告一、实验内容1.1 实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析.1.2 实验要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析1.2.1待分析的简单语言的词法用扩充的BNF表示如下:(1) <程序>::={<声明序列><语句序列>}(2)<语句串>::=<语句>{;<语句>}(3) <语句>::=<赋值语句>(4) <赋值语句>::=ID:= <表达式>(5) <表达式>::=<项>{(+<项>|-<项>}(6) <项>::=<因子>{*<因子>|/<因子>}(7) <因子>::=ID|NUM|(<算术表达式>)1.2.2实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。

二、实验程序的总体结构框架图1. 语法分析主程序示意图图2.递归下降分析程序示意图图5. expression表达式分析函数示意图图6.term分析函数示意图三、关键技术的实现方法Scanner函数定义已在实验一给出,本实验不再重复给出void Irparser(){kk=0;if(syn==1){scaner();yucu();if(syn==6){scaner();if(syn==0 && (kk==0)) cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else {cout<<"缺begin!"<<endl;kk=1;}return;}void yucu(){statement();while(syn==26){scaner();statement();}return;}void statement() {if(syn==10){scaner();if(syn==18){scaner();expression();}else{cout<<"赋值号错误"<<endl;kk=1;}}else{cout<<"语句错误"<<endl;kk=1;}return;}void expression(){term();while((syn==13)||(syn==14)){scaner();term();}return;}void term(){factor();while((syn==15)||(syn==16)){scaner();factor();}return;}void factor(){if((syn==10)||(syn==11))scaner();else if(syn==27){scaner();expression();if(syn==28)scaner();else{cout<<")错误"<<endl;kk=1;}}else{cout<<"表达式错误"<<endl;kk=1;}return;}void main(){p=0;cout<<"Please input string"<<endl;do{cin.get(ch);if(ch!=”\n”)prog[p++]=ch;}while(ch!='#');p=0;scaner();Irparser();}四、实验心得语法分析是编译过程的核心部分,它的主要功能是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备。

编译原理语法分析实验报告

编译原理语法分析实验报告

编译原理语法分析实验报告一、实验目的本实验主要目的是学习和掌握编译原理中的语法分析方法,通过实验了解和实践LR(1)分析器的实现过程,并对比不同的文法对语法分析的影响。

二、实验内容1.实现一个LR(1)的语法分析器2.使用不同的文法进行语法分析3.对比不同文法对语法分析的影响三、实验原理1.背景知识LR(1)分析器是一种自底向上(bottom-up)的语法分析方法。

它使用一个分析栈(stack)和一个输入缓冲区(input buffer)来处理输入文本,并通过移进(shift)和规约(reduce)操作进行语法分析。

2.实验步骤1)构建文法的LR(1)分析表2)读取输入文本3)初始化分析栈和输入缓冲区4)根据分析表进行移进或规约操作,直至分析过程结束四、实验过程与结果1.实验环境本实验使用Python语言进行实现,使用了语法分析库ply来辅助实验。

2.实验步骤1)构建文法的LR(1)分析表通过给定的文法,根据LR(1)分析表的构造算法,构建出分析表。

2)实现LR(1)分析器使用Python语言实现LR(1)分析器,包括读取输入文本、初始化分析栈和输入缓冲区、根据分析表进行移进或规约操作等功能。

3)使用不同的文法进行语法分析选择不同的文法对编写的LR(1)分析器进行测试,观察语法分析的结果。

3.实验结果通过不同的测试案例,实验结果表明编写的LR(1)分析器能够正确地进行语法分析,能够识别出输入文本是否符合给定文法。

五、实验分析与总结1.实验分析本实验通过实现LR(1)分析器,对不同文法进行语法分析,通过实验结果可以观察到不同文法对语法分析的影响。

2.实验总结本实验主要学习和掌握了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程,并通过实验提高了对语法分析的理解。

六、实验心得通过本次实验,我深入学习了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程。

在实验过程中,我遇到了一些问题,但通过查阅资料和请教老师,最终解决了问题,并完成了实验。

LL(1)语法分析 任意输入一个文法符号串,并判断它是否为文法的一个句子

LL(1)语法分析 任意输入一个文法符号串,并判断它是否为文法的一个句子

电子信息工程学系实验报告课程名称:编译原理成绩:实验项目名称:LL(1)语法分析实验时间:2009.04.02指导教师(签名):班级:计算机061 姓名:林世宁学号:610704120实验目的:根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析,加深对预测分析LL(1)分析法的理解。

实验环境:PC机,软件开发工具如TC,visualc++实验内容及过程:构造LL(1)语法分析程序,任意输入一个文法符号串,并判断它是否为文法的一个句子。

程序要求为该文法构造预测分析表,并按照预测分析算法对输入串进行语法分析,判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。

实验步骤:1.定义目标语言的语法规则;2.求解预测分析方法需要的符号集和分析表;3.依次读入给定文法符号串,根据预测分析的方法进行语法分析,直到源程序结束;4.对遇到的语法错误做出错误处理;5.算法流程图参考:实验结果及分析:该LL(1)语法分析程序,能对输入的文法符号串,进行分析并判断它是否为文法的一个句子。

实验心得:通过本次实验加深对预测分析LL(1)分析法的理解,能撑握编写LL(1)分析程序对任意输入的符号串进行分析。

附录:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];char B[20];char v1[20]={'i','+','*','(',')','#'};char v2[20]={'E','G','T','S','F'};int j=0,b=0,top=0,l;typedef struct type{char origin;char array[5];int length;}type;type e,t,g,g1,s,s1,f,f1;type C[10][10];void print(){ int a;for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}void print1(){ int j;for(j=0;j<b;j++)printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}void main(){ int m,n,k=0,flag=0,finish=0;char ch,x;type cha;e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)for(n=0;n<=5;n++)C[m][n].origin='N'; C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n"); printf("请输入要分析的字符串:");do{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;ch=B[0];A[top]='#'; A[++top]='E';printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");do{x=A[top--];printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)if(x==v1[j]){flag=1;break;}if(flag==1){if(x=='#'){finish=1;printf("acc!\n");getchar();getchar();exit(1);}if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];flag=0;}else{print();print1();printf("%c出错\n",ch);exit(1);}}else{for(j=0;j<=4;j++)if(x==v2[j]){ m=j;break;}for(j=0;j<=5;j++)if(ch==v1[j]){ n=j;break;}cha=C[m][n];if(cha.origin!='N'){print();print1();printf("%c->",cha.origin);for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--) A[++top]=cha.array[j]; if(A[top]=='^')top--;}else{ print();print1();printf("%c出错\n",x);exit(1);}}}while(finish==0);}备注:以上各项空白处若填写不够,可自行扩展。

编译原理文法例题

编译原理文法例题

1. 计算以下文法的FIRST集和FOLLOW集:
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
解:首先,我们需要确定每个非终结符的FIRST集。

对于E来说,它的FIRST集是{(, E}, {+, T};对于T来说,它的FIRST集是{*, F}, {(, E};对于F来说,它的FIRST集是{), id}。

接下来,我们需要确定每个非终结符的FOLLOW集。

对于E来说,它的FOLLOW集是{+, $};对于T来说,它的FOLLOW集是{$};对于F来说,它的FOLLOW集是{$}。

2. 判断以下文法是否为LL(1)文法:
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
解:根据LL(1)文法的定义,如果一个文法是LL(1)文法,那么它必须满足以下条件:
1. 每个非终结符的FIRST集包含终结符ε。

2. 每个产生式的右部的第一个终结符α在对应的非终结符的FIRST集中。

3. 如果α是一个终结符,那么它的FOLLOW集包含ε。

4. 如果α是一个非终结符A->β,并且存在一个终结符a∈β,使得A->a是产生式,那么a不能出现在A->β中的其他符号前面。

根据以上条件,我们可以判断该文法不是LL(1)文法。

因为对于产生式E->E+T和T->T*F,它们的右部的第一个终结符+和*都不在对应的非终结符的FIRST集中。

因此,该文法不是LL(1)文法。

XXX-编译原理-命题作业-LL(1)文法的判断(完整答案)

XXX-编译原理-命题作业-LL(1)文法的判断(完整答案)

XXX-编译原理-命题作业-LL(1)文法的判断(完整答案)LL(1)文法的判断LL(1)文法本质含义是第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式进行推导。

给定文法G:E ->TE'E'->+E|εT ->FT'T' ->T|εF-。

PF'F'-。

*F'|εP->(E)|a|b|^1) 计算该文法每个非终结符的FIRST集和FOLLOW集。

首先计算FIRST集合:FIRST(E) = FIRST(T) = FIRST(F) = FIRST(P) = {(。

a。

b。

^)}FIRST(E') = {+。

ε}FIRST(T') = FIRST(T) + {ε} = {(。

a。

b。

^。

ε)}FIRST(F') = {*。

ε}FIRST(P) = {(。

a。

b。

^)}然后计算FOLLOW集合:FOLLOW(E) = {)。

#}FOLLOW(E') = FOLLOW(E) = {)。

#}FOLLOW(T) = FIRST(E') ∪ FOLLOW(E) = {+。

)。

#}FOLLOW(T') = FOLLOW(T) = FIRST(E') ∪ FOLLOW(E) = {+。

)。

#}FOLLOW(F) = FIRST(T') ∪ FOLLOW(T) = {(。

a。

b。

^。

+。

)。

#}FOLLOW(F') = FOLLOW(F) = FIRST(T') ∪ FOLLOW(T) = {(。

a。

b。

^。

+。

)。

#}FOLLOW(P) = FIRST(F') ∪ FOLLOW(F) = {*。

(。

a。

b。

^。

+。

)。

#}2) 证明该方法是LL(1)的。

语法分析

语法分析

编译原理实验二·语法分析一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

二、实验内容及要求对某特定语言A ,构造其语法规则。

该语言的语法单位如下:实现识别该语言的语法分析器, 可以选用:细化的递归下降程序,或者预测分析程序等。

按语法单位出现的顺序,返回识别出的语法单位序列出现的语法错误,可以指出错误位置,及错误原因。

出现的标识符存放在标识符表,整型常数存放在常数表三、实验过程1、文法描述语言A的文法的描述如下:程序P的文法:P → program ID;语句S文法:S → SA | SD | SW | SC | SIF赋值语句的文法:SA → ID := E | ID := NUM定义语句的文法:SD → var int ID D’D’→ ,ID D’|ε循环语句的文法:SW → while B do S判断语句的文法:SIF → if B then S | if B then S else S复合语句的文法:SC → begin S C’C’→ ;S C’| ;end布尔表达式B的文法:B → TB′B′→ and TB′|εT → FT′T′→ or FT′|εF → not F |(B)| E rop E | Erop → > | < | >= | <= | <> | =算术表达式E的文法(此中的T、T’和F与上面不同):E → TE'E'→ + TE' | εT → FT'T' → * FT' | εF → (E) | I注:ID与NUM的文法与语法分析器中的定义相同。

2、单词种别定义3、运行环境本次实验采用win-tc进行代码的编写和编译及运行程序的运行环境为windows4、关键算法描述本程序采用细化的递归下降程序进行描述,所用到的主要函数有:main() //主函数,程序的入口P() //程序P文法判定函数S(int i) //语句S文法实现程序,i表示递归层数,下同SA(int i) //赋值语句文法实现程序SD(int i) //定义语句文法实现程序SW(int i) //循环语句文法实现语句SIF(int i) //判断语句文法实现语句SC(int i) //复合语句文法实现判断语句E() //算数表达式B() //布尔表达式errProc(int type) //出错处理语句,参数type表示错误类型,此函数与词法分析中的出错函数相同,是在原函数的基础上添加新的错误类型struct binary *lexicalAnalyze() //词法分析主函数,本程序通过此函数实现了与词法分析程序的连接语句S的程序流程图如下所示:主函数main()程序流程图如下所示:其他的文法分析函数SA()、SD()、SW()、SIF()、SC()、E()、B()和P()按照文法的产生式就可以得到具体的代码了。

编译原理-文法的判断

编译原理-文法的判断

编译原理-⽂法的判断四种⽂法的判断就是规定产⽣式左边和右边的字符组成规则不同⽽已。

从0型到3型,其限制条件越来越多。

判断时从最复杂的3型进⾏判断,若不符合,依次向下。

✔3型⽂法(正规⽂法或右线性⽂法)
A->α或A->αB
①左边有且仅有⼀个⾮终结符。

②右边有⼀个或两个字符。

若有⼀个字符,是终结符;
若有两个字符,左边终结符,右边⾮终结符。

✔2型⽂法(上下⽂⽆关⽂法)
①左边有且仅有⼀个⾮终结符。

②右边可以有若⼲个(有限)字符。

✔1型⽂法(上下⽂有关⽂法)
α->β
①左边⾄少有⼀个⾮终结符。

②|α|≤|β|,仅S->ε除外
✔0型⽂法(⽆限制⽂法)
左边⾄少有⼀个⾮终结符
判断时,取其最⾼的符合规则。

Chomsky 文法类型判断试验报告-推荐下载

Chomsky 文法类型判断试验报告-推荐下载

如果对于某文法 G,P 中的每个规则具有下列形式: U :: = u
其中 U∈VN;u∈V+,则称该文法 G 为 2 型文法或上下文无关文法,简 写为 CFG。
按照这条规则,对于上下文无关文法,利用该规则进行推导时,无需考虑 非终结符 U 所在的上下文,总能用 u 替换 U,或者将 u 归约为 U,显示了上下 文无关的特点。
for(j=0;j<p[i].left.length();j++) //遍历产生式左部每一个字 符
{ if(p[i].left[j]>='A'&&p[i].left[j]<='Z') //判断字符是否 是非终结符 break; } if(j==p[i].left.length()) { cout<<"该文法不是0型文法"<<endl; return 0; break;
2 型文法所确定的语言为 2 型语言 L2,2 型语言可由非确定的下推自动机 来识别。
一般定义程序设计语言的文法是上下文无关的。如 C 语言便是如此。因此, 上下文无关文法及相应语言引起了人们较大的兴趣与重视。
4.3 型文法(正则文法,线性文法) 如果对于某文法 G,P 中的每个规则具有下列形式:
U :: = T 或 U :: = WT 其中 T∈VT;U,W∈VN,则称该文法 G 为左线性文法。 如果对于某文法 G,P 中的每个规则具有下列形式:
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电通,力1根保过据护管生高线产中0不工资仅艺料可高试以中卷解资配决料置吊试技顶卷术层要是配求指置,机不对组规电在范气进高设行中备继资进电料行保试空护卷载高问与中题带资2负料2,荷试而下卷且高总可中体保资配障料置各试时类卷,管调需路控要习试在题验最到;大位对限。设度在备内管进来路行确敷调保设整机过使组程其高1在中正资,常料要工试加况卷强下安看与全22过,22度并22工且22作尽22下可护都能1关可地于以缩管正小路常故高工障中作高资;中料对资试于料卷继试连电卷接保破管护坏口进范处行围理整,高核或中对者资定对料值某试,些卷审异弯核常扁与高度校中固对资定图料盒纸试位,卷置编工.写况保复进护杂行层设自防备动腐与处跨装理接置,地高尤线中其弯资要曲料避半试免径卷错标调误高试高等方中,案资要,料求编试技5写、卷术重电保交要气护底设设装。备备置管4高调、动线中试电作敷资高气,设料中课并技3试资件且、术卷料中拒管试试调绝路包验卷试动敷含方技作设线案术,技槽以来术、及避管系免架统不等启必多动要项方高方案中式;资,对料为整试解套卷决启突高动然中过停语程机文中。电高因气中此课资,件料电中试力管卷高壁电中薄气资、设料接备试口进卷不行保严调护等试装问工置题作调,并试合且技理进术利行,用过要管关求线运电敷行力设高保技中护术资装。料置线试做缆卷到敷技准设术确原指灵则导活:。。在对对分于于线调差盒试动处过保,程护当中装不高置同中高电资中压料资回试料路卷试交技卷叉术调时问试,题技应,术采作是用为指金调发属试电隔人机板员一进,变行需压隔要器开在组处事在理前发;掌生同握内一图部线纸故槽资障内料时,、,强设需电备要回制进路造行须厂外同家部时出电切具源断高高习中中题资资电料料源试试,卷卷线试切缆验除敷报从设告而完与采毕相用,关高要技中进术资行资料检料试查,卷和并主检且要测了保处解护理现装。场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。

编译原理之判断文法

编译原理之判断文法

名称:技术交流QQ群群号:244566092题目:1 设文法G[A]的规则如下:A→A1|Aa|Ac|a|b|c ,该文法的句子是() 。

A.acbB.bbbbC.bcbcD.klkld描述:根据以上的一个简单题目,群主通过源代码实现,用户任意输入字符串,判断是否属于该文法。

如下图源代码如下:/******************************************************************** created: 2011/08/11filename: JudgeGrammarauthor: ChengMinpurpose:设文法G[A]的规则如下:A->A1 | A0 | Aa | Ac | a | b | c,判断输入的字符串是否是该文法的句子********************************************************************/#include "stdafx.h"#include <string.h>#include <string>#include <iostream>using namespace std;/***************************************** @brief 判断输入的字符串是在文法规则中* @param dest 存储文法规则的字符串* @param _size 文法规则字符串长度* @param str 被查找的字符串* @retval 返回true 表示查找成功,否则返回false****************************************/bool FindRegu(char** dest,int _size,char* str){for (int n = 0;n < _size;n++){if(strcmp(dest[n],str) == 0)return true;}return false;}/***************************************** @brief 通过递归调用本函数,来判断用户输入的句子是否是输入文法G[A]* @param dest 存储文法规则的字符串* @param _size 文法规则字符串长度* @param str 用户输入的字符串* @retval 返回true 表示成功,否则返回false****************************************/ bool JudgeGra(char** dest,int _size,char* str,int len) {bool index = false;char temp[256] = {0};for (int n = 0; n < len;n++){strncpy(temp,str,n + 1);index = FindRegu(dest,_size,temp);if (index){*(str + n) = 'A';int len2 = len - n;if(memcmp("A",str + n,len2) == 0)return true;if( !JudgeGra(dest,_size,str + n,len2))return false;elsereturn true;}}return false;}int _tmain(int argc, _TCHAR* argv[]){cout<<"设文法G[A]的规则如下:A->A1 | Aa | Ac | a | b | c,判断输入的字符串是否是该文法的句子\n\n";char* regulation[] = {"A1","Aa","Ac","a","b","c"};while(true){string input;cout<< "请您输入字符串: ";getline(cin,input);cout<<input;int len = input.size();char temp[256]= {0};memcpy(temp,input.c_str(),input.size());if (JudgeGra(regulation,sizeof(regulation)/sizeof(regulation[0]),temp,input.size())){cout<<"是文法G[A]的句子\n\n\n";}elsecout<<"不是文法G[A]的句子\n\n\n";}return 0;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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.实验结束图。

相关文档
最新文档