编译原算符优先分析实验报告
编译原理课程设计报告_算符优先分析法

编译原理课程设计报告_算符优先分析法编译原理课程设计报告选题名称: 算符优先分析法系(院): 计算机工程学院专业: 计算机科学与技术班级:姓名: 学号:指导教师:学年学期: 7>2012 ~ 2013 学年第 1 学期2012年 12 月 04 日设计任务书课题名称算符优先分析法设计目的通过一周的课程设计,对算符优先分析法有深刻的理解,达到巩固理论知识、锻炼实践能力、构建合理知识结构的目的。
实验环境Windows2000以上操作系统,Visual C++6.0编译环境任务要求1.判断文法是否为算符优先文法,对相应文法字符串进行算符优先分析;2.编写代码,实现算符优先文法判断和相应文法字符串的算符优先分析;3.撰写课程设计报告;4提交报告。
工作进度计划序号起止日期工作内容1 理论辅导,搜集资料2 ~编写代码,上机调试3 撰写课程设计报告4 提交报告指导教师(签章):年月日摘要:编译原理是计算机专业重要的一门专业基础课程,内容庞大,涉及面广,知识点多。
本次课程设计的目的正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。
我们这次课程设计的主要任务是编程实现对输入合法的算符优先文法的相应的字符串进行算符优先分析,并输出算符优先分析的过程。
算符优先分析法特别有利于表达式的处理,宜于手工实现。
算符优先分析过程是自下而上的归约过程,但这种归约未必是严格的规范归约。
而在整个归约过程中,起决定作用的是相继连个终结符之间的优先关系。
因此,所谓算符优先分析法就是定义算符之间的某种优先关系,并借助这种关系寻找句型的最左素短语进行归约。
通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。
同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷。
关键字:编译原理;归约;算符优先分析;最左素短语;目录1 课题综述 11.1 课题来源 11.2课题意义 11.3 预期目标 11.4 面对的问题 12 系统分析 22.1 基础知识 22.2 解决问题的基本思路 52.3 总体方案 53 系统设计 63.1 算法实现 63.2 流程图74 代码编写85 程序调试116 运行与测试12总结13致谢14参考文献151 课题综述1.1 课题来源算符文法:即它的任一产生式的右部都不含两个相继的非终结符的文法。
编译原理实验4算符优先算法

一、实验目的与任务算术表达式和赋值语句的文法可以是(你可以根据需要适当改变):S→i=EE→E+E|E-E|E*E|E/E|(E)|i根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。
二、实验涉及的相关知识点算符的优先顺序。
三、实验内容与过程如参考C语言的运算符。
输入如下表达式(以分号为结束):(1)a = 10;(2)b = a + 20;注:此例可以进行优化后输出(不作要求):(+,b,a,20)(3)c=(1+2)/3+4-(5+6/7);四、实验结果及分析(1)输出:(=, a,10,-)(2)输出:(=,r1,20,-)(+,r2,a,r1)(=,b,r2,-)(3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-)五、实验有关附件(如程序、附图、参考资料,等)......h == '#') o][Peek(n0).No];if(r == '<') h == 'E'&& Peek(1).ch == '#' && Token[ipToken].ch == '#')return TRUE;elsereturn FALSE;}h){k = TRUE; h == 'E'){n ++;}return n;}词结束(遇到“#”号),无法移进,需要规约,返回:1词没有结束,需判断是否可以移进栈单词<=单词:移进后返回:2栈单词>单词:不能移进,需要规约,返回:1单词没有优先关系:出错,返回:-1int MoveIn(){SToken s,t; h = '#';Token[TokenNumber].No = O_NUL;return TRUE; h = '+';Token[TokenNumber].No = O_PLUS;GetChar();break;case '-':Token[TokenNumber].ch = '-';Token[TokenNumber].No = O_MINUS;GetChar();break;case '*':Token[TokenNumber].ch = '*';Token[TokenNumber].No = O_TIMES;GetChar();break;case '/':Token[TokenNumber].ch = '/';Token[TokenNumber].No = O_SLASH;GetChar();break;case '(':Token[TokenNumber].ch = '(';Token[TokenNumber].No = O_L_PAREN;GetChar();break;case ')':Token[TokenNumber].ch = ')';Token[TokenNumber].No = O_R_PAREN;GetChar();break;default:if(ch >= '0' && ch <= '9') h = 'i';Token[TokenNumber].No = O_IDENT;}else{return ! MakeErr("表达式中含有非法字符。
编译原理算符优先报告及代码

cout<<"******此文法的算符优先矩阵如下所示*******"<<endl;
for(int i=0;i<=8;i++) //输出算符优先矩阵
{
for(int j=0;j<=8;j++)
{
if(ch>='a'&&ch<='z')
return 1;
if(ch>='('&&ch<='+')
return 1;
if(ch=='#')
return 1;
if(ch=='/')
return 1;
if(ch=='-')
return 1;
{
for(int i=0;i<len;i++)
ch[i]=array[size-len+i];
size-=len;
return len;
}
else
{
cout<<"参数错误!"<<endl;
return 0;
}
return -1;
}
if(ch1=='*'||ch1=='/')
实验二 编译原理语法分析(算符优先)

实验二语法分析算符优先分析程序一.实验要求⑴选择最有代表性的语法分析方法算符优先法;⑵选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
⑶实习时间为6学时。
二.实验内容及要求(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 "stdafx.h"#include "stdio.h"#include "stdlib.h"#include "iostream.h"int k;char a;int j;char q;int r;int r1;char st[10][30];char data[20][20];char s[100];char lable[20];char input[100];char string[20][10];char first[10][10];char last[10][10];int fflag[10]={0};int lflag[10]={0};int deal();int zhongjie(char c);int xiabiao(char c);void out(int j,int k,char *s);void firstvt(char c);void lastvt(char c);void table();void main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]);first[i][0]=0;last[i][0]=0;}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|') lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();//输出每个非终结符的FIRSTVT集printf("每个非终结符的FIRSTVT集为:\n"); for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}//输出每个非终结符的LASTVT集printf("每个非终结符的LASTVT集为:\n"); for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)printf("\t%c",lable[i]);printf("\n");for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;//输出转化后的文法规则串printf("转化后的文法为:\n");for(i=0;i<x;i++) {printf("%s\n",text[i]);}for(i=0;i<x;i++){string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])) {m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}//求FIRSTVT集void firstvt(char c) { int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++){int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}//求LASTVT集{void lastvt(char c)int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z;k=1;s[k]='#';for(i=0;input[i]!='\0';i++);z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1;m<=k;m++){for(N=0;N<r1;N++)for(n=1;string[N][n]!='\0';n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])) {if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}elseif(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; } }elseif(data[x][y]=='<'||data[x][y]=='='){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}//判断字符c是否是终极符int zhongjie(char c){int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}//求字符c在算符优先关系表中的下标{int xiabiao(char c)int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}四、实验结果输入串为#(i+i)/i#存放于Read.txt文件中五、实验总结经过此次试验对算符优先分析的原理有了深入的理解,熟悉了算符分析的过程,掌握了算符优先分析的有关处理,能够使用一种高级语言构造算符优先的语法分析器。
编译原理算符优先分析算法

算符优先分析算法1.该实验实现算符优先分析算法,由于时间关系,尚未实现用程序计算FIRSTVT,LASTVT,因此本实验的各种非终结符及其之间的优先关系人为初始化。
本实验参考例4.12及其优先关系表。
2.算符优先关系表参考课本74页表4.4+ * id ( ) #+ > < < < > >* > > < < > >id > > > >( < < < < =) > > > ># < < < < =3.结果如图4.源代码# include<stdio.h># include<stdlib.h># include<string.h># define MAX 50 //定义最大长度为50,可以变化struct sst{char s[MAX];int ps;//栈顶终结符指针int top;//栈顶指针};struct inputst{char in[MAX];int pin;//当前字符指针};//定义算符及其优先关系表char ch[6] = {'+','*','i','(',')','#'};char chrelation[6][6]={'>','<','<','<','>','>','>','>','<','<','>','>','>','>','@','@','>','>','<','<','<','<','=','@','>','>','@','@','>','>','<','<','<','<','@','=', };char rela(char c1,char c2){int i = 0,j = 0;while(ch[i] != c1)i++;while(ch[j] != c2)j++;return chrelation[i][j];}int is_VN(char c1){//判断是否为非终结符int i = 0;while(i < 6){if(ch[i] == c1)return 0;i++;}return 1;}void main(){struct sst S;for(int i = 0;i < MAX;i++){S.s[i] = ' ';}S.s[0] = '#';S.ps = 0;S.top = 0;struct inputst input;printf("请输入需分析的字符串,以#结尾,最大长度为%d:\n",MAX);scanf("%s",input.in);printf("%s\n",input.in);input.pin = 0;printf("s栈优先关系当前符号输入流动作\n");int cursor;while(1){if(rela(S.s[S.ps],input.in[input.pin]) == '<' || rela(S.s[S.ps],input.in[input.pin]) == '=') { for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++)printf("%c",input.in[cursor]);if(S.s[S.ps] == '#' && S.s[S.top] == 'N' &&rela(S.s[S.ps],input.in[input.pin]) == '=') {printf(" 接受\n");return;}else{ printf(" 移进\n");S.top++;S.ps = S.top;S.s[S.top] = input.in[input.pin++];}}else if(rela(S.s[S.ps],input.in[input.pin]) == '>'){for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++)printf("%c",input.in[cursor]);if(S.ps >0 && S.ps < S.top){if( is_VN(S.s[S.ps-1]) && is_VN(S.s[S.ps+1])){S.s[S.ps-1] = 'N';S.top = S.ps-1;S.ps = S.top -1;}printf(" 归约\n");}else{S.s[S.top] = 'N';S.ps = S.top -1;printf(" 归约\n");}}else{for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++) printf("%c ",input.in[cursor]);printf(" 出错!");return;}}}5.问题不知如何用计算机程序得到FIRSTVT,LASTVT。
编译原理之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有关,否则会影响素短语的取值。
编译原算符优先分析实验报告 (2)

编译原理实验报告——算符优先文法分析指导教师:***学号:**********姓名:***【实验名称】算符优先文法分析【实验目的】掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析,翻译成等价的四元式表示。
【实验内容】1.算术表达式的文法可以是:(1)S->#E# (2)E->E+T (3)E->T (4)T->T*F (5)T->F (6)F->P^F (7)F->P (8)P->(E) (9)P->i2.根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。
【设计思想】(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立算符优先关系表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用算符优先文法分析算法进行表达式处理:根据优先关系表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
【流程图】【源码】#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[10];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空char G[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->(E)","F->i"};//存储文法中的产生式char VN[6]={'E','R','T','W','F'};//存储非终结符char VT[6]={'i','+','*','(',')','#'};//存储终结符char SELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集char Right[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"};stack <char> stak,stak1,stak2;bool compare(char *a,char *b){int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i++)for(j=0;j<lb;j++){if(a[i]==b[j])return 1;}return 0;}char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}char * Analyse(char * word){char p,action[10],output[10];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();stak.push('#');stak.push('E');printf("_________________________________________________________________________ _______\n");printf("\n 对符号串%s的分析过程\n",word);printf(" 步骤栈顶元素剩余输入串推到所用产生式或匹配\n");p=stak.top();while(p!='#'){printf("%7d ",i++);p=stak.top();stak.pop();printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);if(p==word[k]){if(p=='#'){printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}if(strcmp(output,"#")!=0)return "ERROR";}int main (){freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);char source[100];int i,j,flag,l,m;printf("\n为了方便编写程序,用R代表E',W代表T',e代表空\n\n");printf("该文法的产生式如下:\n");for(i=0;i<8;i++)printf(" %s\n",G[i]);printf("\n该文法的SELECT集如下:\n");for(i=0;i<8;i++){printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]);}//判断是否是LL(1)文法flag=1;for(i=0;i<8;i++){for(j=i+1;j<8;j++){if(G[i][0]==G[j][0]){if(compare(SELECT[i],SELECT[j])){flag=0;break;}}}if(j!=8)break;}if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。
编译原理_实验报告实验二__语法分析(算符优先) 2

华北水利水电学院编译原理实验报告一、实验题目:语法分析(算符优先分析程序)(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][2]='<';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][3]='<';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'||AnalyseStack[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("该句子是该文法的合法句子。
实验四算符优先分析算法

实验四:算符优先分析算法1.实验目的:掌握算符优先分析析程序的分析、设计与实现的基本技术与一般方法。
2.实验题目:编写并上机调试完成识别由下列文法所定义的表达式的算符优先分析程序。
E→E+T | E-T | TT→T*F | T/F |FF→(E) | i3.实验步骤(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, - , * , / , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , / , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }(3)程序参考源码/****************************************/ /* 程序名称:算符优先分析程序*/ /* 程序用途:编译原理实验(四) */ /* 编写日期:2005年11月15日*/ /* 实验题目:对下列文法*/ /* E->E+T|E-T|T */ /* T->T*F|T/F|F */ /* F->(E)|i */ /* 编写算符优先分析程序*/ /* 程序版本: 1.0 Final */ /* 程序作者:黄记瑶B0226047 */ /* 作者邮箱:****************/ /****************************************//****************************************//* 程序相关说明*//* 0=+ 1=- 2=* 3=/ 4=( 5=) 6=i 7=# *//* *//* 算符优先关系表*//* ------------------------------------------------------*//* + - * / ( ) i # *//* + > > < < < > < > *//* - > > < < < > < > *//* * > > > > < > < > *//* / > > > > < > < > *//* ( < < < < < = < ? *//* ) > > > > ? > ? > *//* i > > > > ? > ? > *//* # < < < < < ? < = *//* ------------------------------------------------- *//****************************************/#include "stdio.h"#include "malloc.h"struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;int table[8][8]={{1,1,-1,-1,-1,1,-1,1},{1,1,-1,-1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{-1,-1,-1,-1,-1,-1,-1,0},{1,1,1,1,0,1,0,1},{1,1,1,1,0,1,0,1},{-1,-1,-1,-1,-1,0,-1,-1}};/*存储算符优先关系表,大于为1,小于或等于为-1,其它为0表示出错*/char curchar;char curcmp;int right;/*设置开关项,当出错时为0*/int i,j;int k;/*比较字符在栈的位置*/void push(char pchar)/*入栈函数*/{temp=malloc(sizeof(Lchar));temp->char_ch=pchar;temp->next=top;top=temp;}void pop(void)/*出栈函数*/{if(top->char_ch!='#')top=top->next;}int changchartoint(char ch)/*将字符转为数字,以得到算符优先值*/ {int t;switch(ch){case '+':t=0;break;case '-':t=1;break;case '*':t=2;break;case '/':t=3;break;case '(':t=4;break;case ')':t=5;break;case 'i':t=6;break;case '#':t=7;}return t;}void dosome(void){k=1;for(;;){curchar=h->char_ch;temp=top;for(;;){if(temp->char_ch=='N'){temp=temp->next;k++;}else{curcmp=temp->char_ch;break;}}printf("\n%d\t%d\t",table[i][j],k);temp=top;for(;;)/*打印栈*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}printf("\t");temp=h;for(;;)/*打印待比较的字符*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}i=changchartoint(curcmp);j=changchartoint(curchar);if(table[i][j]==0)/*算符优先值为空*/{printf("\n%d\t%d\t%c\t%c\terror1",table[i][j],k,curcmp,curchar);right=0;break;}else/*算符优先值不为空*/{if(table[i][j]<0)/*算符优先值为-1,移进*/{if(curchar=='#')/*待比较字符为空*/{if(k==2)/*当前比较字符在栈的位置为两个元素*/break;else{printf("\n%d\t%d\t%c\t%c\terror2",table[i][j],k,curcmp,curchar);right=0;break;}}push(curchar);h=h->next;}else/*算符优先值为1,归约*/{if(curcmp=='i')/*当前比较为i,出栈一次*/pop();else/*当前比较不为i,出栈三次*/{pop();pop();pop();}push('N');/*归约到N*/k=1;}}}}void main(void){char ch;right=1;base=malloc(sizeof(Lchar));base->next=NULL;base->char_ch='#';top=base;h=malloc(sizeof(Lchar));h->next=NULL;p=h;do{ /*输入待比较字符串,以'#'结束*/ch=getch();putch(ch);if(ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#'){temp=malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=ch;h->next=temp;h=h->next;}else{temp=p->next;printf("\nInput a wrong char!Input again:\n");for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsebreak;temp=temp->next;}}}while(ch!='#');/*输入待比较字符串,以'#'结束*/p=p->next;h=p;dosome();/*开始识别*/if(right)printf("\nOK!\n");elseprintf("\nError!\n");getch();}。
编译原理 算符优先分析实验报告

实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[E]:E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
说明:终结符号i 为用户定义的简单变量,即标识符的定义。
(1)构造该算符优先文法的优先关系矩阵或优先函数;(2)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(3)算符优先分析过程应能发现输入串出错。
(4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
备注:程序中判断该输入串是否为该文法定义的算术表达式的结果,若是则输出“accept”,若不是则输出“error”。
该二元式序列要以“#”为结尾。
主要数据结构描述
程序结构描述
程序测试:
测试1:(i+i*i)
输出:
输入二:i+i*ii
输出:
学习总结
算符优先文法关键点就在于判断各个终结符号的优先级,构造算符优先矩阵是个难点,程序里面没有实现,而是直接定义了优先矩阵,这是需要完善的地方,试试能不能在程序中动态地构造优先矩阵。
另外对于算符优先文法,失败的条件是比较两个非终结符的优先关系,若优先关系表中为空,就返回error.。
算符优先_实验报告

一、实验目的1. 理解算符优先分析法的原理和过程。
2. 掌握算符优先分析法的实现方法。
3. 通过实验加深对自底向上语法分析方法的理解。
二、实验内容1. 算符优先分析法原理介绍算符优先分析法是一种自底向上的语法分析方法,它通过比较相邻算符的优先次序来识别句型中的句柄,进而执行归约。
该方法的核心是确立文法的终结符之间的优先关系。
2. 实验步骤(1)判断文法是否为OG文法:OG文法要求所有产生式右部至少有一个终结符。
(2)判断文法是否为OPG文法:计算FIRSTVT集、LASTVT集,并构建算符优先矩阵。
(3)对句子进行分析:根据分析表判断句子是否为文法的句子。
(4)实现程序:从文件和键盘读取输入,将结果输出到指定文件和屏幕,并具有一致性。
3. 实验数据(1)文法:g[e]:e->e+t|t(2)测试句子:12+t, t+12, 12+13t, 12+t13三、实验过程1. 判断文法是否为OG文法根据给定的文法,我们可以看到所有产生式右部至少有一个终结符,因此该文法为OG文法。
2. 判断文法是否为OPG文法,并构建算符优先矩阵(1)计算FIRSTVT集FIRSTVT(e) = {t}FIRSTVT(t) = {t}(2)计算LASTVT集LASTVT(e) = {t}LASTVT(t) = {t}(3)构建算符优先矩阵| + - ( ) t e $+ > - - - > > -- > - - - > > -> > > > > > >( > > > > > > >) - - - - - - -t - - - - - - -e - - - - - - -$ - - - - - - -3. 对句子进行分析(1)分析句子“12+t”根据分析表,我们可以得到以下分析过程:12+t -> 12+t -> 12+t -> t -> t(2)分析句子“t+12”根据分析表,我们可以得到以下分析过程:t+12 -> t+12 -> t+12 -> t+12 -> t+12 -> t -> t (3)分析句子“12+13t”根据分析表,我们可以得到以下分析过程:12+13t -> 12+13t -> 12+13t -> 12+13t -> 12+13t -> t -> t(4)分析句子“12+t13”根据分析表,我们可以得到以下分析过程:12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> t13 -> t13 -> t13 -> t -> t四、实验结果1. 测试句子“12+t”分析结果:正确2. 测试句子“t+12”分析结果:正确3. 测试句子“12+13t”分析结果:正确4. 测试句子“12+t13”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
算符优先文法实验报告

《编译原理》课程实验报告实验名称:算符优先文法姓名学号:地点:教师院系:计算机与通信工程学院专业:计算机科学与技术09-2一.实验目的设计、编制并调试一个算符优先法分析程序,加深对算符优先法分析原理的理解。
二.实验内容算术表达式的文法:(1).E → E +T | E -T | T(2).T → T * F | T / F | F(3).F → i |(E)转化后的文法:(1).E → E +T(2).E → E -T(3).E → T(4).T → T * F(5).T →T / F(6).T →F(7).F → i(8).F →(E)根据表达式的文法,首先计算每个非终结符的FIRSTVT和LASTVT:执行算法逐条扫描文法规则,从而构造出文法的算符优先关系表如图所示用算符优先分析法法对该文法进行分析,在每次归约成功后则输出四元式。
四元式形式如下:(op,arg1,arg2,result)其中op是运算符,arg1,arg2分别是第一和第二个运算对象,当op是一目运算时,常常将运算对象定义为arg1.例如,表达式-C和赋值语句X=a的四元式可分别表示为(i)(@,C,-,T)(j)(=,a,-,X)三.源代码:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXSIZE 64#define N -10typedef char datatype;typedef struct{datatype data[MAXSIZE];int top;}seqstack;seqstack OPR;seqstack OPT;char *p;int matrix[7][7]={{N,-1,-1,-1,-1,N,1},{N,1,-1,-1,-1,1,1},{N,1,1,-1,-1,1,1},{1,1,1,N,N,1,1},{N,-1,-1,-1,-1,0,N},{N,1,1,N,N,1,1},{-1,N,N,-1,N,N,0}}; int row,line;int count=1;int compare(char m,char n){switch(m){case '=':row=0;break;case '+':row=1;break;case '*':row=2;break;case 'i':row=3;break;case '(':row=4;break;case ')':row=5;break;case '$':row=6;break;default: return -100;break;}switch(n){case '=':line=0;break;case '+':line=1;break;case '*':line=2;break;case 'i':line=3;break;case '(':line=4;break;case ')':line=5;break;case '$':line=6;break;default: return -100;break;}return matrix[row][line];}void OPRsetnull(){OPR.top=-1;}bool OPRempty(){if(OPR.top>=0)return false;elsereturn true;}void OPRpush(char x){if(OPR.top==MAXSIZE-1)printf("上溢!");else {OPR.top++;OPR.data[OPR.top]=x;}}datatype OPRpop(){if(OPRempty()){printf("下溢!");return NULL;}else{OPR.top--;return(OPR.data[OPR.top+1]);}}datatype OPRtop(){if(OPRempty()){return NULL;}elsereturn(OPR.data[OPR.top]); }void OPTsetnull(){OPT.top=-1;}bool OPTempty(){if(OPT.top>=0)return false;elsereturn true;}void OPTpush(char x){if(OPT.top==MAXSIZE-1)printf("上溢!");else{OPT.top++;OPT.data[OPT.top]=x;}}datatype OPTpop(){if(OPTempty()){printf("下溢!");return NULL;}else{OPT.top--;return(OPT.data[OPT.top+1]);}}datatype OPTtop(){if(OPTempty()){return NULL;}else return(OPT.data[OPT.top]);}void output(char opt,char op1,char op2,int num){if(op1=='i'&&op2=='i') printf("(%c,%c,%c,t%d)\n",opt,op1,op2,num);if(op1!='i'&&op2=='i') printf("(%c,t%d,%c,t%d)\n",opt,op1,op2,num);if(op2!='i'&&op1=='i') printf("(%c,%c,t%d,t%d)\n",opt,op1,op2,num);if(op1!='i'&&op2!='i') printf("(%c,t%d,t%d,t%d)\n",opt,op1,op2,num); }void scan(){char opt;char op1,op2;if(*p=='$') OPTpush(*p);p++;while(*p!='$'){if(*p=='i') OPRpush(*p);else {opt=OPTtop();P: switch(compare(opt,*p)){case -1: OPTpush(*p); break;case N: break;case 0: OPTpop(); break;case 1: op1=OPRpop();op2=OPRpop();output(opt,op1,op2,count);OPRpush(count);count++;opt=OPTpop();opt=OPTtop();goto P; break;}}p++;}while(!OPTempty()&&!OPRempty()&&(OPTtop()!='$')){ op1=OPRpop();op2=OPRpop();opt=OPTpop();if(opt!='='){output(opt,op1,op2,count);OPRpush(char(count));count++;}if(opt=='=') printf("(%c,t%d, ,i)\n",opt,count-1);}}void main(){int d;OPRsetnull();OPTsetnull();char ch[]="$i=i*(i*(i+i))*i$";printf("分析语句:");printf("%s\n",ch);p=ch;scan();}四.实验步骤调试程序的结果:。
C.4-算符优先分析法-实验报告

学号
成绩
实 验 报 告
实验题目:算符优先分析法
课程名称:编译原理
主讲教师:
班 级:
实验日期:
提交日期:
1、
实验目的:
采用算符优先分析法对表达式(不包含括号运算)进行分析,并给出四元式。
二、实验内容
在实验1、2的基础上,用算符优先分析法编制语法分析程序。
分析过程:先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。分析过程从头开始,并重复进行;若读来的是运算符θ2 则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
结果
四、我的感想
这次试验可以说是前两个试验的综合了,程序中也很多用到了前两次的代码。对于我自己来说,最难的部分在于将这些思想转换成代码实现出来,很大一部分在于自己平时没有多打代码以及就是对算符优先分析的思想理解得还不够透彻。在写main函数时,因为要调用很多函数,刚开始写的时候陷入了死循环,以及栈函数的各种调用发生错误,说明自己思路还不够清晰。因为这次实验是在考完试后做的,之前对算符优先分析以及四元式的理解不够明白,在这个实验实现成功后,自己能够透彻地了解,知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给出的文法是否为算符优先文法。同时我也算符优先文法的优缺点以及实际应用中的局限性。
三、程序的改写:
因为这次的实验与前面两次的实验有很大的重合,所以会用到很多之前两次的代码。首先,定义函数:
其中本次需要写的函数有:入栈优先函数f,比较优先函数g,compare,middle,栈函数以及主函数。
1.入栈优先函数f
书上已经给出了入栈优先函数的表,根据输入的符号赋予数值,以便后面方便比较。
算符优先实验报告

算符优先实验报告算符优先实验报告引言算符优先是一种用于描述和分析算术表达式的语法分析方法。
在本次实验中,我们将通过编写一个算符优先分析器来深入理解算符优先算法的原理和应用。
实验目的1. 了解算符优先算法的基本原理和概念;2. 掌握算符优先算法的具体实现方法;3. 实现一个简单的算符优先分析器,用于分析和判断输入的算术表达式是否符合文法规则。
实验过程1. 算符优先的基本原理算符优先算法是一种自底向上的语法分析方法,用于判断算术表达式中运算符的优先级关系。
它通过构建一个算符优先关系表来实现对表达式的分析和判断。
2. 算符优先的概念和定义算符优先表是一个二维表格,行和列分别表示算术表达式中的运算符。
表格中的每个元素表示两个运算符之间的优先关系,可以是大于、小于或等于。
根据这个表格,我们可以判断两个相邻的运算符之间的优先级关系。
3. 算符优先分析器的实现为了实现一个算符优先分析器,我们首先需要构建算符优先表。
算符优先表的构建需要根据文法规则和运算符的优先级来确定。
在本次实验中,我们假设算术表达式中只包含加法和乘法运算符,并且加法运算符的优先级高于乘法运算符。
4. 算符优先分析的过程算符优先分析的过程可以分为两个步骤:扫描和规约。
在扫描过程中,我们从左到右扫描输入的算术表达式,并将扫描到的运算符和操作数依次入栈。
在规约过程中,我们根据算符优先表中的优先关系,将栈中的符号进行规约,直到最终得到一个唯一的非终结符号。
实验结果与分析通过实验,我们成功实现了一个简单的算符优先分析器,并对不同的算术表达式进行了分析和判断。
实验结果表明,算符优先分析器能够准确地判断算术表达式的语法正确性,并且能够正确地处理运算符的优先级关系。
结论算符优先算法是一种常用的语法分析方法,能够有效地判断算术表达式的语法正确性。
通过本次实验,我们深入理解了算符优先算法的原理和应用,并成功实现了一个简单的算符优先分析器。
这对我们进一步学习和应用语法分析方法具有重要的意义。
编译原理实验4 算符优先语法分析

归约时找最左素短语
栈底
串头
可归约串
串尾
#…aj-1 aj aj+1 … ai-1 ai ai+1…
优先关系: ⋖
=·
⋗
串头与串尾之间为可归约串(素短语), 包括其间的及左右两边的非终结符。
核心问题
• 分析栈的数据结构、出栈操作、入栈操作 • 分析表的存储结构、读取操作
步骤1
• 判断给定的文法是否是OPG文法
步骤3:构造算符优先分析表
优先关系:
设G是一个不含 产生式的算符文法,令 a、b是任意两个VT , P、Q、R ∈ VN ,则:
(1) ab 当且仅当文法G中含有形如P …ab…或P …aQb…的产生式 (2) a<b 当且仅当G中含有形如P …aR…的产生式,R而Rb… 或R Qb… (3) a>b 当且仅当G中含有形如P …Rb…的产生式,R而R…a 或R …aQ
步骤6
• 完成主分析程序
符号栈的初始化
for( 从左到右扫描输入符号串 ) {
i = 获取当前的输入符号 j = 获取栈顶的终结符号 switch(table[i][j]) //比较优先关系 { case 9: // 语法错误 case 0: // 移进 case -1: // 移进 case 1: // 归约 } }
{ k = k+1 ; S[ k ] = a ;
} else error( ); } while ( a != ‘#’ ) ; // end of do
// 判断符号栈是否出现成功标志 or 出错
在正确的情况下,算法工作完毕时符号栈将呈现 #N,输入 符号为# 。
步骤7
• 测试语法分析的结果
分析过程
编译原理 实验3 算符优先分析

编译原理实验3 算符优先分析一、实验目的通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。
二、实验内容1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。
2. 构造算符优先表。
3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。
三、程序思路在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。
文法结束再输入一行G->#E#1. 先做文法判断,即可判断文法情况。
2. 若是算符优先文法,则在优先表栏显示优先表。
3. 写入要分析的句子,按回车即可。
4. 在分析过程栏,可以看到整个归约过程情况四、实验结果FunctorFirst.h#include<afx.h>#include<iostream>#include<fstream>#include<string>using namespace std;#define rightlength 20#define product_num 20 // 产生式最多个数#define num_noterminal 26 // 非终结符最多个数#define num_terminal 26 // 终结符最多个数struct Production{char Left;char Right[rightlength];int num;};struct VT{bool vt[num_noterminal][num_terminal];};struct Stack{char P;char a;};class CMyDlg{public:CMyDlg();void InputRule();CString showLastVT();CString showFirstVT();CString shownoTerminal(char G[]);CString showTerminal(char g[]);CString showLeftS(char S[], int j, int k);void InitAll();CString showSentence(CString sen, int start);CString showStack(char S[], int n);void Initarry(char arry[], int n);CString ProdtoCStr(Production prod);int selectProd(int i, int j, char S[]);void preFunctor(CString sen);void insertFirstVT(Stack S[], int &sp, char P, char a);void insertLastVT(Stack S[], int &sp, char P, char a);void ShowPreTable();void createPreTable();char pretable[num_terminal][num_terminal];bool like_Q(Production prod, char Q);void createLastVT();bool likeQ_(Production prod, char Q);bool likeQa_(Production prod);bool like_aQ(Production prod);bool like_a(Production prod);bool likea_(Production prod);bool Dignose(char c);int findg(char c);int findG(char c);void createFirstVT();void createTerminal();void createnoTerminal();void buildProduction(CString s);bool test(CString s);void parse(); // 语法分析CString gram; // 存放文法;Production production[product_num];VT FirstVT;VT LastVT;int locProduct; // 已有产生式个数char G[num_noterminal];char g[num_terminal];int i_G;int i_g;CString m_sen;};FunctorFirst.cpp#include"FunctorFirst.h"CMyDlg::CMyDlg(){}bool CMyDlg::test(CString s) // 测试是否是算符优先文法{bool t = 1;for (int i = 0;i < s.GetLength() - 1;i++)if (s[i] > 64 && s[i] < 91 && s[i + 1]>64 && s[i + 1] < 91){t = 0;break;}return t;}void CMyDlg::InputRule(){string infile;string line;cout <<" 请输入语法文件的路径:";cin >> infile;cout << endl;ifstream input(infile.c_str());if (!input){cout << endl <<"###打不开文件,请确认输入的路径有效###"<< endl;cout <<"请再次运行本程序"<< endl << endl;exit(0);}while (getline(input, line)){if (test(line.c_str()) == 0){cout << endl <<"这不是算符优先文法!"<< endl;exit(0);}buildProduction(line.c_str());}cout << endl <<"这是算符优先文法!"<< endl;input.close();}void CMyDlg::buildProduction(CString s){int i = 0;int j = 0;int k = 0;for (k = 0;k < s.GetLength();k++) // 得到左部{if (s[k] != ' '){production[locProduct].Left = s[k];break;}}for (i = k + 1;i < s.GetLength();i++){if (s[i - 1] == '-'&&s[i] == '>')break;}int temp = i;for (i = temp + 1;i < s.GetLength();i++){if (s[i] != '|'){if (s[i] != ' '){production[locProduct].Right[j] = s[i];j++;production[locProduct].num = j;}}else{locProduct++;production[locProduct].Left = production[locProduct - 1].Left;j = 0;}}locProduct++;}void CMyDlg::createnoTerminal() // 建立非终结符索引{i_G = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (j = 0;j < i_G;){if (production[i].Left != G[j])j++;elsebreak;}if (j > i_G - 1){G[i_G] = production[i].Left;i_G++;}}}void CMyDlg::createTerminal() // 建立终结符索引{i_g = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (int k = 0;k < production[i].num;k++){char temp = production[i].Right[k];if (Dignose(temp)){for (j = 0;j < i_g;){if (temp != g[j])j++;elsebreak;}if (j > i_g - 1){g[i_g] = temp;i_g++;}}}}}void CMyDlg::createFirstVT() // production已完成,创建FirstVT{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVTfor (j = 0;j < i_g;j++)FirstVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (likea_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[0]);if (likeQa_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[1]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (likeQ_(production[i], Q))insertFirstVT(S, sp, production[i].Left, a);}}}void CMyDlg::createLastVT() // 创建Last集{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVT for (j = 0;j < i_g;j++)LastVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (like_a(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 1]);if (like_aQ(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 2]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (like_Q(production[i], Q))insertLastVT(S, sp, production[i].Left, a);}}}int CMyDlg::findG(char c) // 定位c在G中的下标{int i = 0;for (i = 0;i < i_G;i++)if (c == G[i])break;return i;}int CMyDlg::findg(char c) // 定位c在g中的下标{int i = 0;for (i = 0;i < i_g;i++)if (c == g[i])break;return i;}bool CMyDlg::Dignose(char c) // 判断c 是终结符还是非终结符,终结符true,非终结符 false{if (c > 64 && c < 91)return false;elsereturn true;}bool CMyDlg::likea_(Production prod){if (Dignose(prod.Right[0]))return true;elsereturn false;}bool CMyDlg::like_a(Production prod) // 形如P->…a型产生式{if (Dignose(prod.Right[prod.num - 1]))return true;else}bool CMyDlg::like_aQ(Production prod) // 形如P->…aQ型产生式{if (prod.num < 1)return false;else{if (Dignose(prod.Right[prod.num - 2]) && (!Dignose(prod.Right[prod.num - 1])))return true;elsereturn false;}}bool CMyDlg::likeQa_(Production prod){if (prod.num < 1)return false;else{if (Dignose(prod.Right[1]) && (!Dignose(prod.Right[0])))return true;elsereturn false;}}bool CMyDlg::likeQ_(Production prod, char Q){if (prod.Right[0] == Q)return true;elsereturn false;}bool CMyDlg::like_Q(Production prod, char Q){if (prod.Right[prod.num - 1] == Q)return true;else}void CMyDlg::createPreTable() // 创建优先表{// 初始化优先表pretableint i, j;for (i = 0;i < i_g;i++)for (j = 0;j < i_g;j++)pretable[i][j] = ' '; // 表错误for (j = 0;j < locProduct;j++){for (i = 0;i < production[j].num - 1;i++){char xi, xi1, xi2;xi = production[j].Right[i];xi1 = production[j].Right[i + 1];xi2 = production[j].Right[i + 2];if (Dignose(xi) && Dignose(xi1))pretable[findg(xi)][findg(xi1)] = '=';if (i < production[j].num - 2 && Dignose(xi) && Dignose(xi2) && (!Dignose(xi1)))pretable[findg(xi)][findg(xi2)] = '=';if (Dignose(xi) && (!Dignose(xi1))){int N = findG(xi1);for (int k = 0;k < i_g;k++)if (FirstVT.vt[N][k] == true)pretable[findg(xi)][k] = '<';}if ((!Dignose(xi)) && Dignose(xi1)){int N = findG(xi);for (int k = 0;k < i_g;k++)if (LastVT.vt[N][k] == true)pretable[k][findg(xi1)] = '>';}}}}void CMyDlg::ShowPreTable() // 显示相关集合和优先表{CString str = "";str = str +"终结符"+ showTerminal(g) +"\r\n";str = str +"非终结符"+ shownoTerminal(G) +"\r\n";str = str +"First集合:\r\n"+ showFirstVT();str = str +"Lasst集合:\r\n"+ showLastVT();str = str +" | ";int i, j;for (i = 0;i < i_g;i++)str = str + g[i] +" | ";str = str +"\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";for (i = 0;i < i_g;i++){str = str + g[i] +" | ";for (j = 0;j < i_g;j++)str = str + pretable[i][j] +" | ";str +="\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";}cout << str.GetBuffer(1000);}void CMyDlg::insertFirstVT(Stack S[], int &sp, char P, char a) {if (FirstVT.vt[findG(P)][findg(a)] == false){FirstVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::insertLastVT(Stack S[], int &sp, char P, char a){if (LastVT.vt[findG(P)][findg(a)] == false){LastVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::preFunctor(CString sen) // 算符优先分析过程实现{bool tagbreak = true;char S[100];int k = 0;S[k] = '#';int i = 0; // 表下次读入位置int j = 0;//char a;CString show = "";CString temp = "";temp.Format("%-15s %s %15s %-15s%-10s%-15s\r\n\r\n", "符号栈", "关系", "输入串", "最左素短语", "使用产生式", "下步动作");show = show + temp;temp ="";CString s_stack, s_sentence, s_lefts, s_prod, s_action;char s_presymbol;do{a = sen[i];if (Dignose(S[k]))j = k;elsej = k - 1;while (pretable[findg(S[j])][findg(a)] == '>'){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);char Q;do{Q = S[j];if (Dignose(S[j - 1]))j = j - 1;elsej = j - 2;} while (pretable[findg(S[j])][findg(Q)] == '>' ||pretable[findg(S[j])][findg(Q)] == '=');int n = selectProd(j + 1, k, S);if (n > -1 && n < locProduct){s_lefts = showLeftS(S, j + 1, k);k = j + 1;S[k] = production[n].Left;s_prod = ProdtoCStr(production[n]);s_action ="归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="无法归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n",s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';tagbreak = false;break;}}if (!tagbreak)break;if (pretable[findg(S[j])][findg(a)] == '<' ||pretable[findg(S[j])][findg(a)] == '='){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);s_action ="入栈";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;k = k + 1;S[k] = a;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="出错";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';break;}i++;} while (a != '#');show = show +"完成";cout << show.GetBuffer(1000) << endl << endl;}void CMyDlg::parse(){string sen;cout << endl << endl <<" 请输入分析的句子:";cin >> sen;cout << endl << endl;m_sen = sen.c_str();}int CMyDlg::selectProd(int i, int j, char S[]) // 查找产生式{int n = -1;int k = 0;for (k = 0;k < locProduct;k++){if (j - i == production[k].num - 1){int si = i;for (int m = 0;m < production[k].num;m++){if (S[si] == production[k].Right[m] || ((!Dignose(S[si])) &&(!Dignose(production[k].Right[m]))))si++;elsebreak;}if (si == j + 1){n = k;break;}}}return n;}CString CMyDlg::ProdtoCStr(Production prod){CString str = "";str = str +prod.Left +"->";for (int i = 0;i < prod.num;i++)str = str +prod.Right[i];return str;}void CMyDlg::Initarry(char arry[], int n)//初始化数组{for (int i = 0;i < n;i++)arry[i] = ' ';}CString CMyDlg::showStack(char S[], int n)//显示符号栈,n表栈大小{CString str = "";for (int i = 0;i <= n;i++)str = str +S[i];return str;}CString CMyDlg::showSentence(CString sen, int start){CString str = "";for (int i = start;i < sen.GetLength();i++)str = str +sen[i];return str;}void CMyDlg::InitAll(){gram ="";i_G = 0;i_g = 0;locProduct = 0;}// 以下是为了便于显示,将数组型转换成CString型CString CMyDlg::showLeftS(char S[], int j, int k) {CString str = "";for (int i = j;i <= k;i++)str = str +S[i];return str;}CString CMyDlg::showTerminal(char g[]){CString str = "{";for (int i = 0;i < i_g;i++)str = str +g[i] +" ";return str +"}";}CString CMyDlg::shownoTerminal(char G[]){CString str = "{";for (int i = 0;i < i_G;i++)str = str +G[i] +" ";return str +"}";}CString CMyDlg::showFirstVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"FirstVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (FirstVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}CString CMyDlg::showLastVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"LastVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (LastVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}FFmain.cpp#include"FunctorFirst.h"void main(){CMyDlg ff;ff.gram ="";ff.locProduct = 0; // 已有产生式个数ff.InputRule();ff.createnoTerminal(); // 建立非终结符索引ff.createTerminal(); // 建立终结符索引ff.createFirstVT(); // 建立FirstVTff.createLastVT(); // 建立LastVTff.createPreTable(); // 建立优先表ff.ShowPreTable();ff.parse();if (ff.m_sen[ff.m_sen.GetLength() - 1] != '#') ff.m_sen = ff.m_sen +'#';ff.preFunctor(ff.m_sen);}。
编译原理算符优先算法语法分析实验报告

编译原理算符优先算法语法分析实验报告实验报告:算符优先算法的语法分析一、实验目的本次实验旨在通过算符优先算法对给定的文法进行语法分析,实现对给定输入串的分析过程。
通过本次实验,我们能够了解算符优先算法的原理和实现方式,提升对编译原理的理解和应用能力。
二、实验内容1.完成对给定文法的定义和构造2.构造算符优先表3.实现算符优先分析程序三、实验原理算符优先算法是一种自底向上的语法分析方法,通过构造算符优先表来辅助分析过程。
算符优先表主要由终结符、非终结符和算符优先关系组成,其中算符优先关系用1表示优先关系,用2表示不优先关系,用0表示无关系。
算符优先分析程序的基本思路是:根据算符优先关系,依次将输入串的符号压栈,同时根据优先关系对栈内符号进行规约操作,最终判断输入串是否属于给定文法。
四、实验步骤1.定义和构造文法在本次实验中,我们假设给定文法如下:1)E->E+T,T2)T->T*F,F3)F->(E),i2.构造算符优先表根据给定文法,构造算符优先表如下:+*()i#+212112*222112(111012222122i222222#1112203.实现算符优先分析程序我们可以用C语言编写算符优先分析程序,以下是程序的基本框架:```c#include <stdio.h>//判断是否为终结符int isTerminal(char c)//判断条件//匹配符号int match(char stack, char input)//根据算符优先关系表进行匹配//算符优先分析程序void operatorPrecedence(char inputString[]) //定义栈char stack[MAX_SIZE];//初始化栈//将#和起始符号入栈//读入输入串//初始化索引指针//循环分析输入串while (index <= inputLength)//判断栈顶和输入符号的优先关系if (match(stack[top], inputString[index])) //栈顶符号规约} else//符号入栈}//计算新的栈顶}//判断是否成功分析if (stack[top] == '#' && inputString[index] == '#')printf("输入串符合给定文法!\n");} elseprintf("输入串不符合给定文法!\n");}```五、实验结果经过实验,我们成功实现了算符优先算法的语法分析。
编译原理算符优先算法语法分析实验报告

数学与计算机学院编译原理实验报告年级专业学号姓名成绩实验题目算符优先分析法分析器的设计实验日期一、实验目的:设计一个算符优先分析器,理解优先分析方法的原理。
二、实验要求:设计一个算符优先分析器三、实验内容:使用算符优先分析算法分析下面的文法:E’→#E#E →E+T | TT →T*F | FF →P^F | PP →(E) | i其中i可以看作是一个终结符,无需作词法分析。
具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。
四、实验结果及主要代码:1.主要代码void operatorp(){char s[100];char a,Q;int k,j,i,l;string input,temp;cin>>input;cout<<"步骤"<<'\t'<<"栈"<<'\t'<<"优先关系"<<'\t'<<"当前符号"<<'\t'<<"剩余输入串"<<'\t'<<"移进或归约"<<endl;k=1;s[k]='#';i=1;do{a=input[0];temp="";for(l=1;l<();l++)temp+=input[l];input=temp;if(svt(s[k])) j=k;else j=k-1;while (search(s[j],a)=='>'){cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈cout<<'>'<<'\t'<<setw(10); //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串i++;for(;;){Q=s[j];if(svt(s[j-1])) j=j-1;else j=j-2;if(search(s[j],Q)=='<'){cout<<"归约"<<endl;//归约break;}}temp="";for(l=j+1;l<k+1;l++)temp+=s[l];for(l=0;l<6;l++)if(temp==key[l]){k=j+1;s[k]=v[l];break;}}cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈if(search(s[j],a)=='<'){cout<<'<'<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"移进"<<endl;i++;k=k+1;s[k]=a;} //移进else if(search(s[j],a)=='Y'){cout<<'='<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"接受"<<endl;i++;}else{cout<<''<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"出错"<<endl;exit(0);}//出错}while(a!='#');}2.实验结果。
编译基本知识实验3算符优先分析

编译原理实验3 算符优先分析一、实验目的通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。
二、实验内容1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。
2. 构造算符优先表。
3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。
三、程序思路在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。
文法结束再输入一行G->#E#1. 先做文法判断,即可判断文法情况。
2. 若是算符优先文法,则在优先表栏显示优先表。
3. 写入要分析的句子,按回车即可。
4. 在分析过程栏,可以看到整个归约过程情况四、实验结果FunctorFirst.h#include<afx.h>#include<iostream>#include<fstream>#include<string>using namespace std;#define rightlength 20#define product_num 20 // 产生式最多个数#define num_noterminal 26 // 非终结符最多个数#define num_terminal 26 // 终结符最多个数struct Production{char Left;char Right[rightlength];int num;};struct VT{bool vt[num_noterminal][num_terminal];};struct Stack{char P;char a;};class CMyDlg{public:CMyDlg();void InputRule();CString showLastVT();CString showFirstVT();CString shownoTerminal(char G[]);CString showTerminal(char g[]);CString showLeftS(char S[], int j, int k);void InitAll();CString showSentence(CString sen, int start);CString showStack(char S[], int n);void Initarry(char arry[], int n);CString ProdtoCStr(Production prod);int selectProd(int i, int j, char S[]);void preFunctor(CString sen);void insertFirstVT(Stack S[], int &sp, char P, char a);void insertLastVT(Stack S[], int &sp, char P, char a); void ShowPreTable();void createPreTable();char pretable[num_terminal][num_terminal];bool like_Q(Production prod, char Q);void createLastVT();bool likeQ_(Production prod, char Q);bool likeQa_(Production prod);bool like_aQ(Production prod);bool like_a(Production prod);bool likea_(Production prod);bool Dignose(char c);int findg(char c);int findG(char c);void createFirstVT();void createTerminal();void createnoTerminal();void buildProduction(CString s);bool test(CString s);void parse(); // 语法分析CString gram; // 存放文法;Production production[product_num];VT FirstVT;VT LastVT;int locProduct; // 已有产生式个数char G[num_noterminal];char g[num_terminal];int i_G;int i_g;CString m_sen;};FunctorFirst.cpp#include"FunctorFirst.h"CMyDlg::CMyDlg(){}bool CMyDlg::test(CString s) // 测试是否是算符优先文法{bool t = 1;for (int i = 0;i < s.GetLength() - 1;i++)if (s[i] > 64 && s[i] < 91 && s[i + 1]>64 && s[i + 1] < 91){t = 0;break;}return t;}void CMyDlg::InputRule(){string infile;string line;cout <<" 请输入语法文件的路径:";cin >> infile;cout << endl;ifstream input(infile.c_str());if (!input){cout << endl <<"###打不开文件,请确认输入的路径有效###"<< endl;cout <<"!!!请再次运行本程序!!!"<< endl << endl;}while (getline(input, line)){if (test(line.c_str()) == 0){cout << endl <<"这不是算符优先文法!"<< endl;exit(0);}buildProduction(line.c_str());}cout << endl <<"这是算符优先文法!"<< endl;input.close();}void CMyDlg::buildProduction(CString s){int j = 0;int k = 0;for (k = 0;k < s.GetLength();k++) // 得到左部{if (s[k] != ' '){production[locProduct].Left = s[k];break;}}for (i = k + 1;i < s.GetLength();i++){if (s[i - 1] == '-'&&s[i] == '>')break;}int temp = i;for (i = temp + 1;i < s.GetLength();i++){if (s[i] != '|'){if (s[i] != ' '){production[locProduct].Right[j] = s[i];j++;production[locProduct].num = j;}}else{locProduct++;production[locProduct].Left = production[locProduct - 1].Left;j = 0;}}locProduct++;}void CMyDlg::createnoTerminal() // 建立非终结符索引{i_G = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (j = 0;j < i_G;){if (production[i].Left != G[j])j++;elsebreak;}if (j > i_G - 1){G[i_G] = production[i].Left;i_G++;}}}void CMyDlg::createTerminal() // 建立终结符索引{i_g = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (int k = 0;k < production[i].num;k++){char temp = production[i].Right[k];if (Dignose(temp)){for (j = 0;j < i_g;){if (temp != g[j])j++;elsebreak;}if (j > i_g - 1){g[i_g] = temp;i_g++;}}}}}void CMyDlg::createFirstVT() // production已完成,创建FirstVT {int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVTfor (j = 0;j < i_g;j++)FirstVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (likea_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[0]);if (likeQa_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[1]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (likeQ_(production[i], Q))insertFirstVT(S, sp, production[i].Left, a);}}}void CMyDlg::createLastVT() // 创建Last集{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVT for (j = 0;j < i_g;j++)LastVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (like_a(production[i]))insertLastVT(S, sp, production[i].Left, production[i].Right[production[i].num - 1]);if (like_aQ(production[i]))insertLastVT(S, sp, production[i].Left, production[i].Right[production[i].num - 2]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (like_Q(production[i], Q))insertLastVT(S, sp, production[i].Left, a);}}}* * int CMyDlg::findG(char c) // 定位c在G中的下标{int i = 0;for (i = 0;i < i_G;i++)if (c == G[i])break;return i;}int CMyDlg::findg(char c) // 定位c在g中的下标{int i = 0;for (i = 0;i < i_g;i++)if (c == g[i])break;return i;}bool CMyDlg::Dignose(char c) // 判断c 是终结符还是非终结符,终结符true,非终结符falseif (c > 64 && c < 91)return false;elsereturn true;}bool CMyDlg::likea_(Production prod){if (Dignose(prod.Right[0]))return true;elsereturn false;}bool CMyDlg::like_a(Production prod) // 形如P->…a型产生式{if (Dignose(prod.Right[prod.num - 1]))return true;elsereturn false;bool CMyDlg::like_aQ(Production prod) // 形如P->…aQ型产生式{if (prod.num < 1)return false;else{if (Dignose(prod.Right[prod.num - 2]) && (!Dignose(prod.Right[prod.num - 1])))return true;elsereturn false;}}bool CMyDlg::likeQa_(Production prod){if (prod.num < 1)return false;else{if (Dignose(prod.Right[1]) && (!Dignose(prod.Right[0]))) return true;elsereturn false;}}bool CMyDlg::likeQ_(Production prod, char Q){if (prod.Right[0] == Q)return true;elsereturn false;}bool CMyDlg::like_Q(Production prod, char Q){if (prod.Right[prod.num - 1] == Q)return true;elsereturn false;}void CMyDlg::createPreTable() // 创建优先表{// 初始化优先表pretableint i, j;for (i = 0;i < i_g;i++)for (j = 0;j < i_g;j++)pretable[i][j] = ' '; // 表错误for (j = 0;j < locProduct;j++){for (i = 0;i < production[j].num - 1;i++){char xi, xi1, xi2;xi = production[j].Right[i];xi1 = production[j].Right[i + 1];xi2 = production[j].Right[i + 2];if (Dignose(xi) && Dignose(xi1))pretable[findg(xi)][findg(xi1)] = '=';if (i < production[j].num - 2 && Dignose(xi) && Dignose(xi2) && (!Dignose(xi1)))pretable[findg(xi)][findg(xi2)] = '=';if (Dignose(xi) && (!Dignose(xi1))){int N = findG(xi1);for (int k = 0;k < i_g;k++)if (FirstVT.vt[N][k] == true)pretable[findg(xi)][k] = '<';}if ((!Dignose(xi)) && Dignose(xi1)){int N = findG(xi);for (int k = 0;k < i_g;k++)if (LastVT.vt[N][k] == true)pretable[k][findg(xi1)] = '>';}}}}void CMyDlg::ShowPreTable() // 显示相关集合和优先表{CString str = "";str = str +"终结符"+ showTerminal(g) +"\r\n";str = str +"非终结符"+ shownoTerminal(G) +"\r\n";str = str +"First集合:\r\n"+ showFirstVT();str = str +"Lasst集合:\r\n"+ showLastVT();str = str +" | ";int i, j;for (i = 0;i < i_g;i++)str = str + g[i] +" | ";str = str +"\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";for (i = 0;i < i_g;i++){str = str + g[i] +" | ";for (j = 0;j < i_g;j++)str = str + pretable[i][j] +" | ";str +="\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";}cout << str.GetBuffer(1000);}void CMyDlg::insertFirstVT(Stack S[], int &sp, char P, char a) {if (FirstVT.vt[findG(P)][findg(a)] == false){FirstVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::insertLastVT(Stack S[], int &sp, char P, char a) {if (LastVT.vt[findG(P)][findg(a)] == false){LastVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::preFunctor(CString sen) // 算符优先分析过程实现{bool tagbreak = true;char S[100];int k = 0;S[k] = '#';int i = 0; // 表下次读入位置int j = 0;//char a;CString show = "";CString temp = "";temp.Format("%-15s %s %15s %-15s%-10s%-15s\r\n\r\n", "符号栈", "关系", "输入串", "最左素短语", "使用产生式", "下步动作");show = show + temp;temp ="";CString s_stack, s_sentence, s_lefts, s_prod, s_action;char s_presymbol;do{a = sen[i];if (Dignose(S[k]))j = k;elsej = k - 1;while (pretable[findg(S[j])][findg(a)] == '>'){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);char Q;do{Q = S[j];if (Dignose(S[j - 1]))j = j - 1;elsej = j - 2;} while (pretable[findg(S[j])][findg(Q)] == '>' || pretable[findg(S[j])][findg(Q)] == '=');int n = selectProd(j + 1, k, S);if (n > -1 && n < locProduct){s_lefts = showLeftS(S, j + 1, k);k = j + 1;S[k] = production[n].Left;s_prod = ProdtoCStr(production[n]);s_action ="归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="无法归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';tagbreak = false;break;}}if (!tagbreak)break;if (pretable[findg(S[j])][findg(a)] == '<' || pretable[findg(S[j])][findg(a)] == '='){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);s_action ="入栈";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;k = k + 1;S[k] = a;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="出错";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';break;}i++;} while (a != '#');show = show +"完成";cout << show.GetBuffer(1000) << endl << endl; }void CMyDlg::parse(){string sen;cout << endl << endl <<" 请输入分析的句子:";cin >> sen;cout << endl << endl;m_sen = sen.c_str();}int CMyDlg::selectProd(int i, int j, char S[]) // 查找产生式{int n = -1;int k = 0;for (k = 0;k < locProduct;k++){if (j - i == production[k].num - 1){int si = i;for (int m = 0;m < production[k].num;m++){if (S[si] == production[k].Right[m] || ((!Dignose(S[si])) && (!Dignose(production[k].Right[m]))))si++;elsebreak;}if (si == j + 1){n = k;break;}}}return n;}CString CMyDlg::ProdtoCStr(Production prod) {CString str = "";str = str +prod.Left +"->";for (int i = 0;i < prod.num;i++)str = str +prod.Right[i];return str;}void CMyDlg::Initarry(char arry[], int n)//初始化数组{for (int i = 0;i < n;i++)arry[i] = ' ';}CString CMyDlg::showStack(char S[], int n)//显示符号栈,n表栈大小{CString str = "";for (int i = 0;i <= n;i++)str = str +S[i];return str;}CString CMyDlg::showSentence(CString sen, int start){CString str = "";for (int i = start;i < sen.GetLength();i++)str = str +sen[i];return str;}void CMyDlg::InitAll()gram ="";i_G = 0;i_g = 0;locProduct = 0;}// 以下是为了便于显示,将数组型转换成CString型CString CMyDlg::showLeftS(char S[], int j, int k) {CString str = "";for (int i = j;i <= k;i++)str = str +S[i];return str;}CString CMyDlg::showTerminal(char g[]){CString str = "{";for (int i = 0;i < i_g;i++)str = str +g[i] +" ";return str +"}";CString CMyDlg::shownoTerminal(char G[]) {CString str = "{";for (int i = 0;i < i_G;i++)str = str +G[i] +" ";return str +"}";}CString CMyDlg::showFirstVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"FirstVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (FirstVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}CString CMyDlg::showLastVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"LastVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (LastVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}FFmain.cpp#include"FunctorFirst.h"void main(){CMyDlg ff;ff.gram ="";ff.locProduct = 0; // 已有产生式个数ff.InputRule();ff.createnoTerminal(); // 建立非终结符索引ff.createTerminal(); // 建立终结符索引ff.createFirstVT(); // 建立FirstVTff.createLastVT(); // 建立LastVTff.createPreTable(); // 建立优先表ff.ShowPreTable();ff.parse();if (ff.m_sen[ff.m_sen.GetLength() - 1] != '#')ff.m_sen = ff.m_sen +'#';ff.preFunctor(ff.m_sen);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学号E10714103专业计算机科学与技术姓名万学进实验日期2010-5-25教师签字成绩实验报告【实验名称】算符优先文法分析【实验目的】掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析,翻译成等价的四元式表示。
【实验内容】1.算术表达式的文法可以是:(1)S->#E# (2)E->E+T (3)E->T (4)T->T*F (5)T->F (6)F->P^F (7)F->P (8)P->(E) (9)P->i2.根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。
【设计思想】(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立算符优先关系表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用算符优先文法分析算法进行表达式处理:根据优先关系表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
【流程图】【源代码】#include<stdio.h>#include<stdlib.h>#include<string.h>char Grammar[20][10]; char VN[10],VT[10];char BoolArray[10][10]; char FirstBoolArray[10][10]; char LastBoolArray[10][10]; char RelationShip[10][10]; #define StackSize 100;int vtNum,vnNum;int grammarNum;int scount=0;int VNum[20];int GF[2][10];typedef struct {char vt;char vn;}array;typedef struct {array *base;array *top;int stacksize;}SqStack;typedef struct{char s[20];int step;char curInVt;}CharType;typedef struct{CharType *base;CharType *top; }Stack;typedef struct{int x;int y;}Position;SqStack S;Stack CS;SqStack InitStack(){int i,j;S.base=(array*)malloc(100*sizeof(array));if(!S.base)exit(1);S.top=S.base;S.stacksize=StackSize;array temp;printf("初始化栈:\n");for(i=1;i<=vnNum;i++){for(j=1;j<=vtNum;j++){if(BoolArray[i][j]=='1'){temp.vt=BoolArray[0][j];temp.vn=BoolArray[i][0];*S.top=temp;S.top++;printf("%c,%c\n",temp.vn,temp.vt);}}}return S;}int vNumCount(){for(int i=0;i<=grammarNum;i++){int j=1;while(Grammar[i][j]!='\0'){j++;}VNum[i]=j;printf("%d ",VNum[i]);}printf("\n");return 0;}int ScanGrammar(){FILE *fp=fopen("算符优先文法.txt","r");FILE *tp;char singleChar,nextChar;int i=0,j=0,k,count;while(!feof(fp)){fscanf(fp,"%c",&singleChar);if(singleChar=='?'){Grammar[i][j]='\0';break;}if(singleChar=='\n'){Grammar[i][j]='\0';i++;j=0;continue;}if(singleChar=='-'){tp=fp;fscanf(tp,"%c",&nextChar);if(nextChar=='>'){fp=tp;continue;}}if(singleChar=='|'){Grammar[i+1][0]=Grammar[i][0];Grammar[i][j]='\0';i++;j=1;continue;}Grammar[i][j]=singleChar;if(singleChar>='A'&&singleChar<='Z'){count=0;while(VN[count]!=singleChar&&VN[coun t]!='\0'){count++;}if(VN[count]=='\0'){VN[count]=singleChar;vnNum=count+1;}}else{count=0;while(VT[count]!=singleChar&&VT[coun t]!='\0'){count++;}if(VT[count]=='\0'){VT[count]=singleChar;vtNum=count+1;}}j++;}printf("输入的文法:\n");for(k=0;k<=i;k++){j=0;while(Grammar[k][j]!='\0'){if(j==1){printf("->");}printf("%c",Grammar[k][j]);j++;}printf("\n");}printf("vnNum:%d\n",vnNum);printf("vtNum:%d\n",vtNum);printf("%d\nVN:",i);count=0;while(VN[count]!='\0'){BoolArray[count+1][0]=VN[count];LastBoolArray[count+1][0]=VN[count];printf("%d%c",count+1,BoolArray[count+1][0]);count++;}printf("\nVT:");count=0;while(VT[count]!='\0'){BoolArray[0][count+1]=VT[count];LastBoolArray[0][count+1]=VT[count];printf("%d%c",count+1,BoolArray[0][count+1]);count++;}printf("\n");fclose(fp);return i;}int print(){for(int i=1;i<=vnNum;i++)for(int j=1;j<=vtNum;j++){if(BoolArray[i][j]=='1')printf("%c %c\n",BoolArray[i][0],BoolArr ay[0][j]);}return 0;}int printlast(){for(int i=1;i<=vnNum;i++)for(int j=1;j<=vtNum;j++){if(LastBoolArray[i][j]=='1')printf("%c %c\n",LastBoolArray[i][0],Las tBoolArray[0][j]);}return 0;}int BoolArrayInitial(char vn,char vt){int row=1,column=1;while(BoolArray[row][0]!=vn){row++;}while(BoolArray[0][column]!=vt){column++;}if(BoolArray[row][column]=='1'){return 0;}BoolArray[row][column]='1';printf("%d %d\n",row,column);return 0;} int LastBoolArrayInitial(char vn,char vt) {int row=1,column=1;while(LastBoolArray[row][0]!=vn){row++;}while(LastBoolArray[0][column]!=vt){column++;}if(LastBoolArray[row][column]=='1'){return 0;}LastBoolArray[row][column]='1';printf("%d %d\n",row,column);return 0;}int FirstInitial(int grammarNum){int i;for(i=0;i<=grammarNum;i++){if(Grammar[i][1]<'A'||Grammar[i][1]>'Z') {BoolArrayInitial(Grammar[i][0],Grammar [i][1]);continue;}if(Grammar[i][1]>='A'&&Grammar[i][1]<= 'Z'&&Grammar[i][2]!='\0'){if(Grammar[i][2]<'A'||Grammar[i][2]>'Z')BoolArrayInitial(Grammar[i][0],Grammar [i][2]);}}printf("文法表中各行文法字符数:");vNumCount();return 0;}int LastInitial(int grammarNum){int i,count;for(i=0;i<=grammarNum;i++){count=VNum[i]-1;if(Grammar[i][count]<'A'||Grammar[i][co unt]>'Z'){LastBoolArrayInitial(Grammar[i][0],Gra mmar[i][count]);continue;}if(count<=1)continue;if(Grammar[i][count]>='A'&&Grammar[i] [count]<='Z'&&Grammar[i][count-1]!='\0'){if(Grammar[i][count-1]<'A'||Grammar[i][ count-1]>'Z')LastBoolArrayInitial(Grammar[i][0],Gra mmar[i][count-1]);}}printlast();return 0;}Position GetPos(array temp){for(int i=1;i<=vnNum;i++){if(BoolArray[i][0]==temp.vn)break;}for(int j=1;j<=vtNum;j++){if(BoolArray[0][j]==temp.vt)break;}Position pos;pos.x=i;pos.y=j;return pos;}int PrintStack(){array *p=S.top,scan;scount++;printf("scount %d:\n",scount);while(p!=S.base){scan=*p;printf("%c %c\n",scan.vn,scan.vt);p--;}return 0;}int Insert(array pushTemp){Position pos;array scan;pos=GetPos(pushTemp);if(BoolArray[pos.x][pos.y]=='\0'){BoolArray[pos.x][pos.y]='1';array *p=S.base;while(p!=S.top){scan=*p;if(scan.vn==pushTemp.vn && scan.vt==pushTemp.vt)break;p++;}if(p==S.top){S.top++;*S.top=pushTemp;PrintStack();}}return 1;}int PushPop(){int i;array temp,pushTemp;while(S.top!=S.base){temp=*S.top;S.top--;for(i=0;i<=grammarNum;i++){if(Grammar[i][1]==temp.vn){pushTemp.vn=Grammar[i][0];pushTemp.vt=temp.vt;Insert(pushTemp);}}}print();return 0;}int LastPushPop(){int i,count;array temp,pushTemp;while(S.top!=S.base){temp=*S.top;S.top--;for(i=0;i<=grammarNum;i++){count=VNum[i]-1;if(Grammar[i][count]==temp.vn){pushTemp.vn=Grammar[i][0];pushTemp.vt=temp.vt;Insert(pushTemp);}}}print();return 0;}int ResetStack(){int i,j;array temp;while(S.top!=S.base){S.top--;}printf("\n");for(i=1;i<=vnNum;i++){for(j=1;j<=vtNum;j++){if(BoolArray[i][j]=='1'){temp.vt=BoolArray[0][j];temp.vn=BoolArray[i][0];*S.top=temp;S.top++;printf("%c,%c\n",temp.vn,temp.vt);}}}return 0;}int Judge(int i,int j){if(Grammar[i][j+1]=='\0')return -1;if(Grammar[i][j]>='A'&&Grammar[i][j]<=' Z'&&(Grammar[i][j+1]<'A'||Grammar[i][j+1]>'Z '))return 0;else return 1;}Position GetOpPos(char vni,char vnj){for(int i=1;i<=vtNum;i++)if(RelationShip[i][0]==vni)break;for(int j=1;j<=vtNum;j++){if(RelationShip[0][j]==vnj)break;}Position pos;pos.x=i;pos.y=j;return pos;}int GetVtPos(char vt){for(int i=1;i<=vtNum;i++)if(LastBoolArray[i][0]==vt)break;return i;}int RelEqual(){Position pos;int j;for(int i=0;i<=grammarNum;i++){j=1;while(Grammar[i][j]!='\0'){if(Grammar[i][j+2]=='\0')break;if((Grammar[i][j]<'A'||Grammar[i][j]>'Z')& &(Grammar[i][j+2]<'A'||Grammar[i][j+2]>'Z')){pos=GetOpPos(Grammar[i][j],Grammar[i ][j+2]);RelationShip[pos.x][pos.y]='=';//2表示=}j++;}}return 0;}int RelShBlanket(){int row;Position pos;int i,j;for(i=1;i<=vtNum;i++){RelationShip[i][0]=BoolArray[0][i];RelationShip[0][i]=BoolArray[0][i];}for(i=0;i<=grammarNum;i++){j=1;while(Grammar[i][j]!='\0'){if(Judge(i,j)==-1)break;if(Judge(i,j)==0){row=GetVtPos(Grammar[i][j]);for(int ii=1;ii<=9;ii++){if(LastBoolArray[row][ii]=='1'){pos=GetOpPos(LastBoolArray[0][ii],Gra mmar[i][j+1]);RelationShip[pos.x][pos.y]='>';//3表示大于}}}if(Judge(i,j)==1){row=GetVtPos(Grammar[i][j+1]);for(int ii=1;ii<=9;ii++){if(FirstBoolArray[row][ii]=='1'){pos=GetOpPos(Grammar[i][j],FirstBool Array[0][ii]);RelationShip[pos.x][pos.y]='<';//1表示小于}}}j++;}}RelEqual();printf("表达式文法算符优先关系表:\n");RelationShip[0][0]=' ';for(i=0;i<=vtNum;i++){for(int j=0;j<=vtNum;j++){if(RelationShip[i][j]=='\0')RelationShip[i][j]='0';printf("%4c",RelationShip[i][j]);}printf("\n");}return 0;}int ChangeValue(){ int change=0;int i,j;for(i=1;i<=vtNum;i++)for(j=1;j<=vtNum;j++){if(RelationShip[i][j]=='>'){if(GF[0][i]<=GF[1][j]){GF[0][i]=GF[1][j]+1;change=1;}}if(RelationShip[i][j]=='<'){if(GF[0][i]>=GF[1][j]){GF[1][j]=GF[0][i]+1;change=1;}}if(RelationShip[i][j]=='='){if(GF[0][i]!=GF[1][j]){if(GF[0][i]>GF[1][j]){GF[1][j]=GF[0][i];change=1;}if(GF[0][i]<GF[1][j]){GF[0][i]=GF[1][j];change=1;}}}}if(change==1){ChangeValue();}return 0;}int PreFunction(){int change=0,j;for(int i=1;i<=vtNum;i++){GF[0][i]=1;GF[1][i]=1;}ChangeValue();printf("优先函数:\n");for(i=0;i<=1;i++){for(j=1;j<=vtNum;j++){printf("%3d",GF[i][j]);}printf("\n");}return 0;}int PrintCStack(){CharType *p=CS.top,scan;while(p!=CS.base){scan=*p;printf("%d %c %s\n",scan.step,scan.curIn Vt,scan.s);p--;}return 0;}int JudgeVt(char a){for(int j=1;j<=vtNum;j++){if(a==BoolArray[0][j])return 1;}return 0;}int JudgeRela(char a,char b)//判断优先关系{int apos,bpos;for(int i=1;i<=vtNum;i++){if(a==BoolArray[0][i])apos=i;if(b==BoolArray[0][i])bpos=i;}if(GF[0][apos]>GF[1][bpos])return 1;if(GF[0][apos]<GF[1][bpos])return -1;else return 0;}int Reduction(){int count=1,i=0,k=1,j,p,sign;char prerela;char operate[5];char q;char S[100]={'\0'},Input[20];S[0]=' ';scanf("%s",Input);S[k]='#';printf("步骤栈优先关系当前符号剩余输入串移进或规约\n");while(Input[i]!='\0'){if(JudgeVt(S[k]))j=k;else j=k-1;sign=JudgeRela(S[j],Input[i]);if(sign==1){L: q=S[j];if(JudgeVt(S[j-1]))j--;else j-=2;if(JudgeRela(S[j],q)==-1){memcpy(operate,"归约",5*sizeof(char));p=k;while(p!=j){S[p]='\0';p--;}k=j+1;S[k]='N';}else goto L;}if(sign==0){if(JudgeRela(S[j],'#')==0){memcpy(operate,"接受",5*sizeof(char));// break;}k++;S[k]=Input[i];memcpy(operate,"移进",5*sizeof(char));}if(sign==-1){k++;S[k]=Input[i];memcpy(operate,"移进",5*sizeof(char));}if(sign==1)prerela='>';if(sign==0)prerela='=';if(sign==-1)prerela='<';printf("%d\t%s\t%c\t\t%c\t%s\t\t%s\n", count,S,prerela,Input[i],Input,operate);count++;i++;}printf("规约结束!");return 0;}int main(){grammarNum=ScanGrammar();FirstInitial(grammarNum);InitStack();PushPop();memcpy(FirstBoolArray,BoolArray,100* sizeof(char));LastInitial(grammarNum);memcpy(BoolArray,LastBoolArray,100*s izeof(char));scount=0;ResetStack();LastPushPop();memcpy(LastBoolArray,BoolArray,100*s izeof(char));RelShBlanket();PreFunction();Reduction();return 0;}【运行结果】。