编译原理-实验3算符优先分析法
- 格式:doc
- 大小:70.50 KB
- 文档页数:25
编译原理课程设计报告_算符优先分析法编译原理课程设计报告选题名称: 算符优先分析法系(院): 计算机工程学院专业: 计算机科学与技术班级:姓名: 学号:指导教师:学年学期: 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 课题来源算符文法:即它的任一产生式的右部都不含两个相继的非终结符的文法。
《编译原理》课程实验报告实验名称:算符优先文法姓名学号:地点:教师院系:计算机与通信工程学院专业:计算机科学与技术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; //以char作为栈中元素typedef struct //定义一个栈结构{datatype data[MAXSIZE];int top;}seqstack;seqstack OPR; //操作数栈OPRseqstack 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) //往操作数栈push一个操作数i{printf("上溢!");else {OPR.top++;OPR.data[OPR.top]=x;}}datatype OPRpop() //从操作数栈中pop出一个操作数{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) //往操作符栈push一个操作数{printf("上溢!");else{OPT.top++;OPT.data[OPT.top]=x;}}datatype OPTpop() //从操作数符中pop出一个操作数{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);//如果当前字符是操作数则入栈,只有i一种操作数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); //并将生成的t的序数压栈(t1,t2等);count++;opt=OPTpop();//将已规约的输出的操作符出栈opt=OPTtop();//取栈顶操作符跳转到继续下一步。
实验3《算符优先分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容在实验1的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验方法先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
四、实验步骤1.定义目标语言的语法规则;2.求解预测分析方法需要的符号集和分析表;3.依次读入实验一的分析结果,根据预测分析的方法进行语法分析,直到源程序结束;4.对遇到的语法错误做出错误处理。
五、实验结果六、实验结论#include "stdio.h"#include "stdlib.h"#include "iostream.h"char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1;int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集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]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/ 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();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集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");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集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]='=';}void firstvt(char c) //求FIRSTVT集{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;}}void lastvt(char c) //求LASTVT集{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(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}七、实验小结通过本次试验我知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给文法是否为算符优先文法。
编译原理算符优先分析法研究源程序目录1 课程设计的目的和要求 (2)1.1 课程设计的目的 (2)1.2 课程设计的要求 (2)2 系统描述 (2)2.1 自底向上分析方法的描述: (2)2.2 算符优先文法的描述: (2)3)输入符号串,进行移进-规约分析。
(3)3 概要设计 (3)3.1 设计思路 (3)3.2 系统功能结构 (4)3.3 技术路线或实现方法 (5)3.4 开发环境 (5)4 详细设计 (5)4.1 模块划分 (5)4.2 主要算法的流程图 (7)4.3 数据分析与定义 (8)4.4 系统界面设计 (8)5 测试方法和测试结果 (9)5.1 测试用例1 (9)5.2 测试用例2 (10)5.3 测试用例3 (11)5.4 测试用例4 (12)6 结论和展望 (13)结论 (13)展望 (13)学习编译技术课程的体会和对本门课程的评价 (13)7 参考文献 (13)8 源代码 (14)1 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2 课程设计的要求1、文法使用产生式来定义;2、用大写字母和小写字母分别表示非终结符和终结符;产生式使用->;3、文法中的空字符串统一使用@表示;4、分别给出每一个非终结符的FIRSTVT集和LASTVT集;5、画出算符优先关系表6、判定给定的文法是否是算符优先文法;7、给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。
2 系统描述本次实验使用windows vista操作系统下visual C++6.0平台,使用C语言,利用读文件方式将待分析的文法读入到程序中,通过定义数组和结构体作为具有一定意义或关系的表或栈,存放FIRSTVT、LASTVT、算符优先关系表的元素。
算符优先分析算法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。
编译原理之算符优先文法分析——**学院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有关,否则会影响素短语的取值。
华中师范大学计算机科学系算符优先分析法学号:2009210580姓名:王晔成绩:一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程2.1实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
1 若f(θ1)<=g(θ2),则θ2进算符栈,并继续顺序往下扫描,分析过程从头开始2 如f(θ1)>g(θ2),则产生对操作数栈顶的若干项进行θ1运算的中间代码,并从运算符栈顶移去θ1,并从操作数栈顶移去若干项,然后把执行θ1的结果压入操作数栈。
接着以运算符栈新的项目与θ2进行上述优先数的比较,即重复(1)(2),3 重复(1)(2)直到“$”与“$”配对为止。
关键代码#include <stdio.h>#include <string.h>#include <ctype.h>char calculator_stack[100],prog[1000];int operator_stack[100];int c_top=0,o_top=0,p;char ch;int f[255]={0};int g[255]={0};void Init(){f['*']=f['/']=5;f['+']=f['-']=3;f['$']=0;g['*']=g['/']=4;g['+']=g['-']=2;g['$']=0;}int main(){int i,sum=0,oper1,oper2,result;Init();calculator_stack[c_top++]='$';p=0;printf("请输入正确的代码,以#结束:\n"); do{ch=getchar();prog[p++]=ch;}while(ch!='#');prog[p]=0;printf("%s\n",prog);p=0;bool flag;for(i=0;prog[i];i++){if(isalpha(prog[i])){flag=1;continue;}else if(isdigit(prog[i])){if(flag)continue;else{sum=sum*10+prog[i]-'0';if(!isdigit(prog[i+1])){operator_stack[o_top++]=sum;sum=0;}flag=0;}}else if(prog[i]==' ' || prog[i]=='\t' || prog[i]=='\n'){flag=0;continue;}else if(prog[i]=='#')break;else{flag=0;if(prog[i]=='*' || prog[i]=='/' || prog[i]=='+' || prog[i]=='-' ||prog[i]=='$') {if(prog[i]!='$' && f[calculator_stack[c_top-1]]<=g[prog[i]]) calculator_stack[c_top++]=prog[i];else{while(1){oper2=operator_stack[--o_top];oper1=operator_stack[--o_top];ch=calculator_stack[c_top-1];if(ch=='*')result=oper1*oper2;else if(ch=='/'){if(oper2==0){printf("除零错误!\n");return 0;}result=oper1/oper2;}else if(ch=='+')result=oper1+oper2;else if(ch=='-')result=oper1-oper2;printf("%d = %d %c %d\n",result,oper1,ch,oper2); operator_stack[o_top++]=result;calculator_stack[--c_top];if(prog[i]=='$' && calculator_stack[c_top-1]=='$') return 0;if(f[calculator_stack[c_top-1]]<=g[prog[i]]){calculator_stack[c_top++]=prog[i];break;}}}}}}return 0;}。
实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
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”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
编译原理算符优先分析程序设计算符优先分析(Operator Precedence Parsing)是一种基于文法的自下而上的语法分析方法,用于构造一个将输入串转化为语法分析树的分析器。
它通过根据每一个终结符号和非终结符号之间的优先级关系,来判断是否可以进行规约操作。
算符优先分析的基本思想是,为每一个终结符和非终结符分配一个优先级,然后根据这些优先级来决定如何进行规约操作。
一般来说,基本的终结符都有一个固定的优先级,而非终结符的优先级则由其所对应的产生式右部中的终结符优先级来决定。
算符优先分析的核心在于构造一个优先级关系表,用于指导规约过程。
这个表一般由产生式构造得到,每个终结符和非终结符对应一行和一列,表中的每个元素表示两个符号之间的优先级关系。
算符优先分析的步骤如下:1.根据给定的文法,确定每个终结符号和非终结符号的优先级。
2.构造优先关系表,填入每两个符号之间的优先关系。
3.初始化分析栈和输入栈,将栈底符号设为文法开始符号,并将输入串入栈。
4.重复以下步骤,直到分析完成:a.查找栈顶和当前输入符号之间的优先关系。
b.如果栈顶符号的优先级较低或相等,则进行规约操作,将栈顶的符号替换为相应的非终结符号。
c.如果栈顶符号的优先级较高,则进行移进操作,将当前输入符号移入栈中。
d.如果找不到优先关系,则出现错误,分析失败。
算符优先分析的优点是简单明了,且规约过程中不需要回溯,效率较高。
然而,由于它只适用于算符优先文法,而不是所有的上下文无关文法,因此适用范围有限。
在实际编程中,我们可以通过编写算符优先分析程序来对给定的文法进行分析。
程序可以根据文法自动生成优先关系表,然后根据输入串和优先关系表进行分析。
下面是一个简单的算符优先分析程序设计:```python#定义终结符和非终结符的优先级priority = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0, ')': 0}#构造优先关系表def build_table(:table = {}for symbol1 in priority.keys(:row = {}for symbol2 in priority.keys(:if symbol1 == '(' and symbol2 == ')':row[symbol2] = 'r'elif symbol1 == ')' and symbol2 == '(':row[symbol2] = 'e'elif priority[symbol1] > priority[symbol2]:row[symbol2] = '>'elif priority[symbol1] < priority[symbol2]:row[symbol2] = '<'else:row[symbol2] = 'e'table[symbol1] = rowreturn table#算符优先分析程序def operator_precedence_parsing(table, input_str): input_stack = list(input_str)input_stack.append('#')analysis_stack = ['#']while len(analysis_stack) > 0:top = analysis_stack[-1]if top in priority.keys( and input_stack[0] in priority.keys(:relation = table[top][input_stack[0]]if relation == '>':analysis_stack.popprint('Reduce by', top)elif relation == '<':analysis_stack.append(input_stack.pop(0)) print('Shift', analysis_stack[-1])elif relation == 'e':analysis_stack.popinput_stack.pop(0)print('Error')returnelse:print('Error')returnelse:print('Error')return#测试代码table = build_tableinput_str = input('Please enter a valid expression: ')operator_precedence_parsing(table, input_str)```以上是一个简单的算符优先分析程序设计,实现了根据输入串和优先关系表进行分析的过程。
编译原理课程设计报告评分:签字:编译原理课程设计二——算符优先分析程序设计实验目的了解掌握算符优先分析的基本方法、内容;学会科学思考并解决问题,提高程序设计能力。
实验内容与要求用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
文法表示:S→v=E|E?|clearE→E+T|E-T|TT→T*F|T/F|FF→(E)|v|c单词种别码设计:= 1? 2+ 3- 4* 5/ 6(7)8v 9c 10clear 11# 12N 13实验环境系统环境为windows系统,编译环境为VS2015,编程语言为C++。
实验过程过程一:构建firstVT()和lastVT()算法分析:对于firstVT()构建,对于每个非终结符F的产生式,第一个终结符或者‘|’后的第一个终结符应该在其firstVT()集合内,且若非终结符T能推出非终结符F则firstVT(T)包含first(F)。
lastVT()的构造类似,对于每个非终结符F的产生式,非终结符后的第一个终结符都属于lastVT (F), 且若非终结符T能推出非终结符F则lastVT(T)包含first(F)。
算法实现主要函数:void get_firstVT()//求firstVT();void get_lastVT()//求lastVT();结果:FirstVT(S){=,?,l,+,-,*,/,(,v,c,}FirstVT(E){+,-,*,/,(,v,c,}FirstVT(T){*,/,(,v,c,}FirstVT(F){(,v,c,}LastVT(S){=,?,l,+,-,*,/,),v,c,}LastVT(E){+,-,*,/,),v,c,}LastVT(T){*,/,),v,c,}LastVT(F){),v,c,}过程二:构建优先符号表算法分析:(1)在产生式中两个相邻的终结符优先顺序相等(2)对于小于关系,首先扫描终结符a标记flag=1,再扫描到非终结符Q,此时判断若flag=1,则对所有b∈FristVT{Q},a<b.(3)对于大于关系,首先扫描非终结符Q在前标记flag=1,再扫描终结符a在后此时判断若flag=1,对所有b∈LastVT{Q},b>a.算法结果:其中-2表示不会出现,1表示>,-1表示<,0表示=.字母l表示clear.过程三:词法分析算法分析:详见课程设计一算法主要函数:int letter()//判断是否为字母int digit()//判断是否为数字int str_to_num()//数字字符串转化为整数int reserve(char **k)//处理保留字int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置void WordAnalyze( constnumber *con, identifier *id, char sentence[],int &point,int &syn,int &sym_point)//词法分析void Insert_to_symboltbl(int syn, int value, int &point)//把二元组加入symbol表算法结果:得到语句的所有单词二元组symbolTBL表,存放种别码syn及其值val,其中对于种别码为9的变量val为标志符的入口标志,对于种别码为10的的常量val为存放的值。
算符优先实验报告算符优先实验报告引言算符优先是一种用于描述和分析算术表达式的语法分析方法。
在本次实验中,我们将通过编写一个算符优先分析器来深入理解算符优先算法的原理和应用。
实验目的1. 了解算符优先算法的基本原理和概念;2. 掌握算符优先算法的具体实现方法;3. 实现一个简单的算符优先分析器,用于分析和判断输入的算术表达式是否符合文法规则。
实验过程1. 算符优先的基本原理算符优先算法是一种自底向上的语法分析方法,用于判断算术表达式中运算符的优先级关系。
它通过构建一个算符优先关系表来实现对表达式的分析和判断。
2. 算符优先的概念和定义算符优先表是一个二维表格,行和列分别表示算术表达式中的运算符。
表格中的每个元素表示两个运算符之间的优先关系,可以是大于、小于或等于。
根据这个表格,我们可以判断两个相邻的运算符之间的优先级关系。
3. 算符优先分析器的实现为了实现一个算符优先分析器,我们首先需要构建算符优先表。
算符优先表的构建需要根据文法规则和运算符的优先级来确定。
在本次实验中,我们假设算术表达式中只包含加法和乘法运算符,并且加法运算符的优先级高于乘法运算符。
4. 算符优先分析的过程算符优先分析的过程可以分为两个步骤:扫描和规约。
在扫描过程中,我们从左到右扫描输入的算术表达式,并将扫描到的运算符和操作数依次入栈。
在规约过程中,我们根据算符优先表中的优先关系,将栈中的符号进行规约,直到最终得到一个唯一的非终结符号。
实验结果与分析通过实验,我们成功实现了一个简单的算符优先分析器,并对不同的算术表达式进行了分析和判断。
实验结果表明,算符优先分析器能够准确地判断算术表达式的语法正确性,并且能够正确地处理运算符的优先级关系。
结论算符优先算法是一种常用的语法分析方法,能够有效地判断算术表达式的语法正确性。
通过本次实验,我们深入理解了算符优先算法的原理和应用,并成功实现了一个简单的算符优先分析器。
这对我们进一步学习和应用语法分析方法具有重要的意义。
编译原理之算符优先分析1.算符优先分析:1.1定义是⼀种简单直观、⼴泛使⽤、便于⼿⼯实现的⾃下⽽上的语法分析⽅法。
1.2原理定义算符之间的某种优先关系,寻找“归约串”,并进⾏归约1.3相关知识拓展1.3.1 算符⽂法:产⽣式的右部不包含两个相继的⾮终结符,即不包含形如:.....QR.....1.3.2 算符优先⽂法:任何终结符对(a,b)⾄多⼀种优先级关系。
1.3.3 构造优先关系表步骤:(1)写出FIRSTVT、LASTVTFIRSTVT(P)={a|P->a.....或P->Qa......}LASTVT(P)={a|P->.....a或P->......aQ} (2)列表,根据优先级填表 1.确定同⼀产⽣式的末尾终结符之间⽆优先关系 2.确定=,再使⽤FIRSTVT、LASTVT1.4 算符优先分析算法 素短语:⾄少包含⼀个终结符且不包含更⼩的终结符,如p*p或 i 最左素短语:最左侧的素短语 缺点:跳过了所有单⾮产⽣式所对应的归约步骤。
(单⾮产⽣式:形如:P->Q ,右部只有⼀个⾮终结符的产⽣式)1.5 构造优先函数使⽤构造优先函数代替优先表f:表⼊栈优先函数、g:表⽐较优先函数1.6 举例S→a|Λ|(T) T->T,S|S(1)基本了解:FIRSTVT(P)={a|P->a.... or Qa....}; LASTVT(P)={a|P->...a or P->....aQ}所以对于:S→a|Λ|(T) 则FIRSTVT(S)={a,Λ,(}对于:S→a|Λ|(T) 则LASTVT(S)={a,Λ,)}对于:T->T,S|S 则FIRSTVT(T)={, ,a,Λ,(}对于:T->T,S|S 则LASTVT(T)={, ,a,Λ,)}(2)优先关系aΛ(),a>>Λ>>(<<<=<)>>,<<<>>,<<<>>由于G[S]中任何终结符对(a,b)之多只有⼀种关系成⽴,所以,G[S]为算符优先⽂法。
编译原理实验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《算符优先分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容在实验1的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验方法先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
四、实验步骤1.定义目标语言的语法规则;2.求解预测分析方法需要的符号集和分析表;3.依次读入实验一的分析结果,根据预测分析的方法进行语法分析,直到源程序结束;4.对遇到的语法错误做出错误处理。
五、实验结果六、实验结论#include "stdio.h"#include "stdlib.h"#include "iostream.h"char data[20][20]; //算符优先关系char s[100]; //模拟符号栈s char lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1;int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集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]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/ first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/ 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();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集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");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集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(t ext[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]='=';}void firstvt(char c) //求FIRSTVT集{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;}}void lastvt(char c) //求LASTVT集{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(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}七、实验小结通过本次试验我知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给文法是否为算符优先文法。