编译原理课程设计算术表达式的语法分析及语义分析程序设计 精品.docx
- 文档编号:24118453
- 上传时间:2023-05-24
- 格式:DOCX
- 页数:33
- 大小:133.87KB
编译原理课程设计算术表达式的语法分析及语义分析程序设计 精品.docx
《编译原理课程设计算术表达式的语法分析及语义分析程序设计 精品.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计算术表达式的语法分析及语义分析程序设计 精品.docx(33页珍藏版)》请在冰豆网上搜索。
编译原理课程设计算术表达式的语法分析及语义分析程序设计精品
课程设计任务书
学生姓名:
专业班级:
指导教师:
工作单位:
题目:
算术表达式的语法分析及语义分析程序设计
1.目的
通过设计、编制、调试一个算术表达式的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
2.设计内容及要求
算术表达式的文法:
(1)选择算符优先分析法完成以上任务,中间代码选用逆波兰式。
(2)写出算术表达式的符合分析方法要求的文法,给出分析方法的思想,完成分析程序设计。
(3)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
3.课程设计报告书的内容应包括:
(1)设计题目、班级、学号、姓名、完成日期;
(2)给出算术表达式的语法分析和语义分析的设计。
(3)简要的分析与概要设计;
(4)详细的算法描述;
(5)源程序清单;
(6)给出软件的测试方法和测试结果;
(7)设计的评价、收获与体会。
时间安排:
第18周,周1-周3下午,周5全天
指导教师签名:
年月日
系主任(或责任教师)签名:
年月日
1课设要求
设计题目算术表达式转换成逆波兰式(用算符优先分析法)
1.1课程设计的目的
课程设计是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。
通常,设计题中的问题比平时的练习题要复杂,也更接近实际。
编译原理这门课程安排的课程设计的目的是旨在要求学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容,选择合适的数据逻辑结构表示问题,然后编制算法和程序完成设计要求,从而进一步培养学生独立思考问题、分析问题、解决实际问题的动手能力。
要求学生在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法编制和程序代码的编写。
1.2设计内容及要求
算术表达式的文法:
〈无符号整数〉∷=〈数字〉{〈数字〉}
〈标志符〉∷=〈字母〉{〈字母〉|〈数字〉}
〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}
〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}
〈因子〉∷=〈标志符〉|〈无符号整数〉|‘(’〈表达式〉‘)’
〈加法运算符〉∷=+|-
〈乘法运算符〉∷=*|/
1.选择算符优先分析法完成以上任务,中间代码选用逆波兰式。
2.写出算术表达式的符合分析方法要求的文法,给出分析方法的思想,3.完成分析程序设计。
编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
2摘要
一个新的语言的出现,必然会有与之配套的编译器的产生。
编译器对于一个语言的重要性不言而喻。
编译过程分为词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成这六个阶段。
而语法分析和语义分析是最关键的核心部分。
要做好一个编译器必须要懂得如何根据构造的文法来识别出它的语法和语义。
语法分析的方法很多,而比较容易懂的就有算符优先分析法,本次课设的主题就是要弄懂算符优先分析发。
学习制作编译器不仅会让你弄懂这门课,还会让你提高写代码的能力,特别是写出高效,可靠性好的代码。
关键字:
算术表达式,算符优先文法,逆波兰式
3引言
逆波兰式又叫做后缀表达式,它的用途很多,譬如做计算器的时候可以对算术表达式采用这种形式来表示,从而可以很容易的来进行计算。
在编译原理中,生成中间代码的步骤里,逆波兰式也是中间代码的一种表示形式。
算符优先分析法是自底向上进行语法分析的一种方式。
自底向上分析的思想就是对输入的符号串自左向右的进行扫描,并将输入符逐个移入一个后进先出栈,边移入边分析,一旦栈顶符号串形成某个句型的句柄或可规约串时,就用该产生式左部的非终结符代替相应右部的文法符号串,这一步叫做规约。
重复这一过程直到规约到栈中只剩文法的开始符号时则规约成功,也就确认了这个输入串是文法的句子。
算符优先法规定了算符之间的优先关系,通过先于关系识别句柄尾,通过后于关系识别句柄头,以此来进行规约。
4正文
4.1需求分析
要通过算符优先分析方法进行将算术表达式转换成为逆波兰式,首先要经过词法分析,然后是语法分析,通过规约来输出算术表达式的逆波兰式。
故先要求出每个非终结符的FIRSTVT()集和LASTVT()集,然后求出终结符的算符优先矩阵,最后以此来规约。
因此程序应该能够提供输入一个任意的算符优先文法,并可以对输入的文法进行判断,还可以对文法进行改写,便于后面的分析。
自动求出每个非终结符的FIRSTVT()集和LASTVT()集,自动构造终结符的优先矩阵,然后自动规约,输出逆波兰式。
4.2理论基础
算符优先分析法是自底向上分析法法的一种,它的工作原理是先求出文法中每个非终结符的FIRSTVT()集和LASTVT()集,通过文法中每个产生式的右部非终结符所处的位置来确定每个非终结符之间的优先关系。
譬如S->AaB,则a后于A的LASTVT()集规约,也后于A的FIRSTVT()集规约。
然后求出非终结符的算符优先矩阵,根据矩阵所确定的优先关系进行规约。
为了将算符优先分析方法与输出逆波兰式联系起来,首先要明白算符优先方法规约的每一步是如何进行的,在确定某个终结符要规约时,应该将它保存起来,然后在最后输出这一串符号,即为所求的逆波兰式。
4.3总体设计
先改写文法,在求各个非终结符的FIRSTVT()集和LASTVT()集,确定优先关系矩阵后就进行规约。
系统流程图如下:
所要用到的数据结构及自定义函数如下:
chardata[20][20];//算符优先关系
chars[100];//模拟符号栈s
charlable[20];//文法终极符集
charinput[100];//文法输入符号串
charstring[20][10];//用于输入串的分析
intk;
chara;
intj;
charq;
intr;//文法规则个数
intr1;
intm,n,N;//转化后文法规则个数
charst[10][30];//用来存储文法规则
charfirst[10][10];//文法非终结符FIRSTVT集
charlast[10][10];//文法非终结符LASTVT集
intfflag[10]={0};//标志第i个非终结符的FIRSTVT集是否已求出
intlflag[10]={0};//标志第i个非终结符的LASTVT集是否已求出
intdeal();//对输入串的分析
intzhongjie(charc);//判断字符c是否是终极符
intxiabiao(charc);//求字符c在算符优先关系表中的下标
voidout(intj,intk,char*s);//打印s栈
voidfirstvt(charc);//求非终结符c的FIRSTVT集
voidlastvt(charc);//求非终结符c的LASTVT集
voidtable();//创建文法优先关系表
charshuchu[10];//存储逆波兰式
4.4详细设计
4.4.1判断文法是否正确
要对输入的文法进行判断是否为算符文法。
首先判断文法是否为上下文无关文法,然后判断是否为算符文法。
判断的过程比较简单,先看每个产生式的左部是否为非终结符(在这里人为规定大写字母表示非终结符,且不用进行判断),然后看产生式的右部是否有两个非终结符挨在一起的,若挨在一起,则不是算符文法,否则就是算符文法。
4.4.2改写文法
若产生式的右部有形如S->A+B|A-B的产生式,则应该改写为两条产生式:
(1)S->A+B;
(2)S->A-B;按此方式对文法改写后输出到屏幕上。
4.4.3求每个非终结符的FIRSTVT()集和LASTVT()集
对FIRSTVT()集的构造可以根据以下两条规则构造:
(1)若有产生式A->Ba...或A->a...,则a属于FIRSTVT(A);
(2)若a属于FIRSTVT(B)且有产生式A->B...则有a属于FIRSTVT(A)
部分代码如下:
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 { if(st[j][0]==st[i][m+1]) break; } for(k=0;k { intt; for(t=0;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()集也可以按照类似的方式构造。 4.4.4求算符优先矩阵 构造算符优先关系表。 算符优先矩阵在本程序中的作用是最大的,算符优先关系表是一个二维数组,用来存放任意两个终结符之间的优先关系。 首先构造表头,通过扫描所有产生式将终结符不重复的存放在一个一维数组中并置为优先关系表的行和列,并将优先关系表其他内容全部初始化为空。 接着遍历所有产生式,找出任意两个终结符之间存在的关系(可以没有关系),并判断任意两终结符是否至多存在一种优先关系,如发现优先关系表不为空,则证明该文法不是算符优先文法,否则,将相应的关系填入到相应的行列对应的单元中。 部分代码如下: for(i=0;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 { if(st[k][0]==text[i][j+1]) break; } m=xiabiao(text[i][j]); for(t=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 { if(st[k][0]==text[i][j]) break; } n=xiabiao(text[i][j+1]); for(t=0;t { m=xiabiao(last[k][t+1]); data[m][n]='>'; } } } 4.4.5输出逆波兰式 要想在规约的时候输出算术表达式的逆波兰式,确定规约的终结符后,用一个字符数组将这些终结符存起来,在规约成功输出这些字符串即为所求的逆波兰式 部分代码如下: if(data[x][y]=='>') { if(lable[x]! =')') shuchu[size++]=lable[x];//将要规约的终结符存起来 out(1,k,s); printf("%c",a); out(i+1,z,input); printf("规约\n"); 5调试及运行结果 更换文法后: 6心得体会 本次课程设计相对来来说不是很容易的,它的要求比较高,要将编译原理中所学的很多知识联系起来,并且要有比较良好的编程能力。 一开始看到题目的时候我也是没什么头绪,理不清思路,不明白为什么将算术表达式转换为逆波兰式与算符优先分析法有何种联系。 没办法,我只好在书本中寻找灵感,在看到确定了算符优先矩阵之后,每一步规约的终结符按先后顺序连接起来刚好是逆波兰式。 按照这个想法,我开始有了大概的规划,然后照着这个想法去做,终于做好了。 课程设计与一般的实验不同,与在课堂上学习理论知识更加不同,它是考查学习成果的一种手段,更加是检验你的能力和水平的一种方式。 将理论与实践结合起来才是王道。 当然,我的程序也存在着不足,没有进行词法分析,只是简单的默认了所输入的符号串都符合规定。 通过本次课程设计,不仅加强了我对编译原理的认识,掌握了很多知识,更加让我明白了动手能力的重要性。 在未来学习的道路上,应该继续发扬这种精神,将实践进行到底! 7源代码 #include"stdio.h" #include"stdlib.h" #include"iostream.h" chardata[20][20];//算符优先关系 chars[100];//模拟符号栈s charlable[20];//文法终极符集 charinput[100];//文法输入符号串 charstring[20][10];//用于输入串的分析 intk; chara; intj; charq; intr;//文法规则个数 intr1; intm,n,N;//转化后文法规则个数 charst[10][30];//用来存储文法规则 charfirst[10][10];//文法非终结符FIRSTVT集 charlast[10][10];//文法非终结符LASTVT集 intfflag[10]={0};//标志第i个非终结符的FIRSTVT集是否已求出 intlflag[10]={0};//标志第i个非终结符的LASTVT集是否已求出 intdeal();//对输入串的分析 intzhongjie(charc);//判断字符c是否是终极符 intxiabiao(charc);//求字符c在算符优先关系表中的下标 voidout(intj,intk,char*s);//打印s栈 voidfirstvt(charc);//求非终结符c的FIRSTVT集 voidlastvt(charc);//求非终结符c的LASTVT集 voidtable();//创建文法优先关系表 charshuchu[10];//存储逆波兰式 voidmain() { inti,j,k=0; printf("请输入文法规则数: "); scanf("%d",&r); printf("请输入文法规则: \n"); for(i=0;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 { 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 { 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 { printf("%c: ",st[i][0]); for(j=0;j { printf("%c",first[i][j+1]); } printf("\n"); } printf("每个非终结符的LASTVT集为: \n");//输出每个非终结符的LASTVT集 for(i=0;i { printf("%c: ",st[i][0]); for(j=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 { printf("%c\t",lable[i]); for(j=0;j { printf("%c\t",data[i][j]); } printf("\n"); } printf("请输入文法输入符号串以#结束: "); scanf("%s",input); deal(); cout<<"逆波兰式为: "; for(i=0;lable[i]! ='\0';i++) cout< cout< } voidtable() { chartext[20][10];//存储改写后的文法 inti,j,k,t,l,x=0,y=0; intm,n; x=0; for(i=0;i { firstvt(st[i][0]); lastvt(st[i][0]); } for(i=0;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 { printf("%s\n",text[i]); } for(i=0;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 { 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 { if(st[k
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译原理课程设计算术表达式的语法分析及语义分析程序设计 精品 编译 原理 课程设计 算术 表达式 语法分析 语义 分析 程序设计