华北水利水电学院编译原理实验报告一、实验题目:语法分析(算符优先分析程序)(1)选择最有代表性的语法分析方法算符优先法;(2)选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
二、实验内容(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句子为:(i+i)*i和i+i)*i三、程序源代#include<stdlib.h>#include<stdio.h>#include<string.h>#include<iostream.h>#define SIZE 128char priority[6][6]; //算符优先关系表数组char input[SIZE]; //存放输入的要进行分析的句子char remain[SIZE]; //存放剩余串char AnalyseStack[SIZE]; //分析栈void analyse();int testchar(char x); //判断字符X在算符优先关系表中的位置void remainString(); //移进时处理剩余字符串,即去掉剩余字符串第一个字符int k;void init()//构造算符优先关系表,并将其存入数组中{priority[0][3]='<';priority[0][4]='>';priority[0][5]='>';priority[1][0]='>';priority[1][1]='>';priority[1][2]='<';priority[1][3]='<';priority[1][4]='>';priority[1][5]='>';priority[2][0]='>';priority[2][1]='>';priority[2][2]='$';//无优先关系的用$表示priority[2][3]='$';priority[2][4]='>';priority[2][5]='>';priority[3][0]='<';priority[3][1]='<';priority[3][2]='<';priority[3][3]='<';priority[3][4]='=';priority[3][5]='$';priority[4][0]='>';priority[4][1]='>';priority[4][2]='$';priority[4][3]='$';priority[4][4]='>';priority[4][5]='>';priority[5][0]='<';priority[5][4]='$';priority[5][5]='=';}void analyse()//对所输入的句子进行算符优先分析过程的函数{FILE *fp;fp=fopen("li","a");int i,j,f,z,z1,n,n1,z2,n2;int count=0;//操作的步骤数char a; //用于存放正在分析的字符char p,Q,p1,p2;f=strlen(input); //测出数组的长度for(i=0;i<=f;i++){a=input[i];if(i==0)remainString();if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'||Analy seStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')j=k;elsej=k-1;z=testchar(AnalyseStack[j]);//从优先关系表中查出s[j]和a的优先关系if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#')n=testchar(a);else //如果句子含有不是终结符集合里的其它字符,不合法{printf("错误!该句子不是该文法的合法句子!\n");break;}if(p=='$'){printf("错误!该句子不是该文法的合法句子!\n");return;}if(p=='>'){ for( ; ; ){Q=AnalyseStack[j];if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'||Ana lyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')j=j-1;elsej=j-2;z1=testchar(AnalyseStack[j]);n1=testchar(Q);p1=priority[z1][n1];if(p1=='<') //把AnalyseStack[j+1]~AnalyseStack[k]归约为N{count++;printf("(%d) %s\t%10c\t%5c%17s\t 归约\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"归约");k=j+1;i--;AnalyseStack[k]='N';int r,r1;r=strlen(AnalyseStack);for(r1=k+1;r1<r;r1++)AnalyseStack[r1]='\0';break;}else}}else{if(p=='<') //表示移进{count++;printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"移进");k=k+1;AnalyseStack[k]=a;remainString();}else{if(p=='='){z2=testchar(AnalyseStack[j]);n2=testchar('#');p2=priority[z2][n2];if(p2=='='){count++;printf("(%d) %s\t%10c\t%5c%17s\t 接受\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"接受");printf("该句子是该文法的合法句子。
\n");fprintf(fp,"%s","该句子是该文法的合法句子。
\n");break;}else{printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"移进");k=k+1;AnalyseStack[k]=a;remainString();}}else{printf("错误!该句子不是该文法的合法句子!\n");fprintf(fp,"%s","错误!该句子不是该文法的合法句子。
\n");break;}}}}fclose(fp);}int testchar(char x){int m;if(x=='+')m=0;if(x=='*')m=1;if(x=='i')m=2;if(x=='(')m=3;if(x==')')m=4;if(x=='#')return m;}void remainString(){int i,j;i=strlen(remain);for(j=0;j<i;j++)remain[j]=remain[j+1];remain[i-1]='\0';}void main(){int m,n;char s1[6]={ '+','*','i','(',')','#'};init();printf("文法为:\n");printf("(0)E'->#E#\n");printf("(1)E->E+T\n");printf("(2)E->T\n");printf("(3)T->T*F\n");printf("(4)T->F\n");printf("(5)F->(E)\n");printf("(6)F->i\n");FILE *fp;fp=fopen("li","w");fprintf(fp,"%s","要分析的文法为:\n");fprintf(fp,"%s","(0)E'->#E#\n");fprintf(fp,"%s","(1)E->E+T\n");fprintf(fp,"%s","(2)E->T\n");fprintf(fp,"%s","(3)T->T*F\n");fprintf(fp,"%s","(4)T->F\n");fprintf(fp,"%s","(5)F->(E)\n");fprintf(fp,"%s","(6)F->i\n");fprintf(fp,"%s"," + * i ( ) #\n");for(m=0;m<6;m++){fprintf(fp,"%c ",s1[m]);for(n=0;n<6;n++){fprintf(fp,"%c ",priority[m][n]);}fprintf(fp,"%s","\n");}printf("-----------------------------------------\n");printf(" 算符优先关系表\n");printf(" + * i ( ) #\n");printf(" + > < < < > >\n");printf(" * > > < < > >\n");printf(" i > > > >\n");printf(" ( < < < < = \n");printf(" ) > > > >\n");printf(" # < < < < =\n");printf("-----------------------------------------\n");printf("请输入要进行分析的句子(以#号结束输入):\n");gets(input);//将输入的字符串存到数组中fprintf(fp,"%s","需要分析的字符串为:\n");fprintf(fp,"%s",input);fprintf(fp,"%s","\n");fclose(fp);printf("步骤栈优先关系当前符号剩余输入串移进或归约\n");k=0;AnalyseStack[k]='#';AnalyseStack[k+1]='\0';int length,i; //初始化剩余字符串数组为输入串length=strlen(input);//for(i=0;i<length;i++)remain[i]='\0';analyse();//对所输入的句子进行算符优先分析过程的函数}四、测试结果输入串(i+i)*i的算符优先分析过程输入串i+i)*i的算符优先分析过程五、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)本次实验是算符优先分析法,这种方法特别有利于表达式分析,宜于手工实现。