欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    编译原理课程设计——算符优先分析法研究——附源程序.doc

    • 资源ID:28476697       资源大小:870.50KB        全文页数:61页
    • 资源格式: DOC        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    编译原理课程设计——算符优先分析法研究——附源程序.doc

    Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-date编译原理课程设计算符优先分析法研究附源程序目 录目 录1 课程设计的目的和要求21.1 课程设计的目的21.2 课程设计的要求22 系统描述22.1 自底向上分析方法的描述:22.2 算符优先文法的描述:23)输入符号串,进行移进-规约分析。33 概要设计33.1 设计思路33.2 系统功能结构43.3 技术路线或实现方法53.4 开发环境54 详细设计54.1 模块划分54.2主要算法的流程图74.3 数据分析与定义84.4 系统界面设计85 测试方法和测试结果95.1 测试用例195.2 测试用例2105.3测试用例3115.4 测试用例4126 结论和展望13结论13展望13学习编译技术课程的体会和对本门课程的评价137 参考文献138 源代码141 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。1.2 课程设计的要求1、文法使用产生式来定义;2、用大写字母和小写字母分别表示非终结符和终结符;产生式使用->;3、文法中的空字符串统一使用表示;4、分别给出每一个非终结符的FIRSTVT集和LASTVT集;5、画出算符优先关系表6、判定给定的文法是否是算符优先文法;7、给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。2 系统描述本次实验使用windows vista操作系统下visual C+6.0平台,使用C语言,利用读文件方式将待分析的文法读入到程序中,通过定义数组和结构体作为具有一定意义或关系的表或栈,存放FIRSTVT、LASTVT、算符优先关系表的元素。系统能够对由文件读入的文法进行分析,构造出FIRSTVT表和LASTVT表以及算符优先关系表。可以根据构造的优先关系表对输入的任意符号串进行分析,判断是否为本文法的句子,若是则打印规约过程。结果显示到DOS界面上。2.1 自底向上分析方法的描述:对输入的符号串自左向右进行扫描,并将输入符逐个移入栈中,边移入边分析,一旦栈顶符号串形成某个句型的句柄时(该句柄对应某个产生式的右部),就用该产生式的左部非终结符代替相应右部的文法符号串,这一过程称为规约。重复这一过程,直到栈中只剩下文法的开始符则分析成功。2.2 算符优先文法的描述:只规定算符之间的优先关系,也就是说只考虑终结符之间的优先关系。由于算富有先分析不考虑非终结符之间的优先关系,在规约过程中只要找到最左素短语就可以规约。如给定一个文法GS:S->#E#E->E+TE->TT->T*FT->FF->P/FF->PP->(E)P->i利用算符优先文法分析过程处理如下:1)计算给定文法中任意两个终结符对(a,b)之间的优先关系,首先计算两个集合FIRSTVT(B)=b|B->b或B->CbLASTVT(B)=a|B->a或B->aC表2-1FIRSTVT集和LASTVT集 SETFPFIRSTVT#+*/i(*/i(/i(i(LASTVT#+*/i)*/i)/i)i)2)计算三种优先关系,求出算符优先关系表:表2-2算符优先关系表+*/i()#+*/I()#3)输入符号串,进行移进-规约分析。3 概要设计3.1 设计思路1)首先在源程序相同的目录下创建一个txt文档,并在文档中输入待分析的文法。然后定义一个输入流文件,调用这个流文件中的open函数打开该txt文件,再定义一个二维数组通过循环接收读入的产生式。2)接着开始构造FIRSTVT、LASTVT、算符优先关系表。在构造表的时候首先定义了两个重要的结构体。一个结构体作为存放具有一定关系的一对非终结符和终结符,另一个结构体作为存放上述元素的栈,包括栈顶指针、栈底指针、栈的长度。既然定义了栈,就存在对栈的初始化、栈是否为空的判断、入栈、出栈操作,利用循环和指针的操作来定义这些函数,以完成元素的进栈和弹出。定义了这两个结构体,就可以用来构造FIRSTVT、LASTVT、算符优先关系表。在构造FIRSTVT表时,通过循环找出每条产生式中的非终结符的FIRSTVT集,并把该非终结符和终结符压栈,设置标志位,标志一对非终结符和终结符具有对应关系。LASTVT表的构造则是将求FIRSTVT的过程翻转过来,可以仅仅将函数中的参数稍作修改就能够完成。3)构造算符优先关系表。算符优先关系表是一个二维数组,用来存放任意两个终结符之间的优先关系。首先构造表头,通过扫描所有产生式将终结符不重复的存放在一个一维数组中并置为优先关系表的行和列,并将优先关系表其他内容全部初始化为空。接着遍历所有产生式,找出任意两个终结符之间存在的关系(可以没有关系),并判断任意两终结符是否至多存在一种优先关系,如发现优先关系表不为空,则证明该文法不是算符优先文法,否则,将相应的关系填入到相应的行列对应的单元中。4)输入串分析过程的设计。首先将大于、小于、等于和无关系分别定义成一种类型的数据表示,通过查询符号栈栈顶以及当前符号之间的优先关系来判断移进和规约的操作。3.2 系统功能结构图3-1 系统功能结构图函数功能:Main()函数:调用主函数,运行程序;FirstVt()函数:构造FIRSTVT表;LastVt()函数:构造LASTVT表;OpPrioTable()函数:构造算符优先关系表;InputAnalyse()函数:分析输入串是否为文法中的句子,并给出规约过程。3.3 技术路线或实现方法算符优先分析法的具体过程如下:1、首先先输入文件的路径,在readfile(char sencol)函数中,将需要分析的文法通过输入流文件打开函数open()复制到senrowcol中。2、然后利用FirstVt( )构造产生式senrowcol的FirstVt表。先找出形如A->a(a为第一个终结符)的产生式,把(A,a)压入Operator栈中。从Operator栈顶抛出项(A,a),填入first表相应位置。在找出形如B->A的产生式,把(B,a)压入Operator栈中。循环直到Operator栈为空,此时FirstVt表构造完毕。3、然后把产生式右部翻转,调用FirstVt函数求出LastVt表。4、接着调用OpPriotable()构造算符优先关系表opTable。先把产生式中所有终结符填入opTable表第一行和第一列,然后利用产生式和FirstVt表LastVt表分别找出满足=关系、<关系、>关系的算符填表。若相应位已有关系,说明两个终结符之间至少有两种优先关系,该文法不是算符优先文法。5、最后调用InputAnalyse()对输入串进行分析。初始化分析栈S,依次判断当前输入符a和分析栈中离栈顶最近的终结符S j 的关系,若S j < a ,则a移近,若S j > a ,则往前找到第一个S j >a,将S j -1到栈顶S k 规约,若S j = a ,如果S j =#,则接受,如果S j !=#,则移进。直到接受或者出错,算符优先分析结束。3.4 开发环境实验使用windows vista操作系统下的Microsoft Visual C+ 6.0平台,用C语言完成。4 详细设计4.1 模块划分实验分为五个模块,分别是:1、文件的导入:readfile(sen);2、FirstVt、LastVt集的构造:FirstVt(sen,first,sen_len,frist_len);LastVt(sen,last,sen_len,frist_len);3、 算符优先关系表OpPriotable的构造:OpPriotable(sen,first,last,opTable,sen_len,first_len,&opTable_len);4、算符优先分析过程的实现:InputAnalyse(opTablecol,stringcol,opTable_len);5、主函数:main()。4.2 主要算法的流程图图4-1 算符优先分析法程序流程图4.3 数据分析与定义1、文法(产生式):文法使用产生式来定义char senrowcol:用二维数组表示产生式;int sen_len:产生式的个数;2、FIRSTVT集:char firstrowcol:用二维数组构造FIRSTVT表int first_len: Firstvt表的行数;3、LASTVT集:char lastrowcol:用二维数组构造LASTVT表;int frist_len:LASTVT表的行数;4、算符优先关系表:char opTablerowcol:用二维数组表示算符优先关系表;int opTable_len:算符优先关系表的行数和列数;5、算符优先分析表char stringcol:用一维数组记录输入串;char SSIZE:用一维数组表示分析栈 ;char a:当前输入字符;6、其他数据结构:typedef structchar nonterm; /非终结符char term; /终结符StackElement;FIRSTVT表或LASTVT表中一个表项(A,a);7、typedef struct StackElement *top;StackElement *bottom;int stacksize;stack;以形如表项(A,a)为元素的栈,在构造FirstVt集的过程中用到;4.4 系统界面设计本实验没有考虑界面设计,将结果直接打印输出在DOS界面下。5 测试方法和测试结果5.1 测试用例1测试目的:使用算符优先分析法对一个算符文法中的句子进行分析。读入一个算符优先文法进行分析,给出文件路径D:coursesC_source_file成品算符优先文法1.txt。结果如下:图5-1 测试用例1运行截图1输入一个字符串,使得该字符串是该文法的一个句子。则输入字符串i+i*i/(i+i)#时运行结果为:图5-2 测试用例1运行截图25.2 测试用例2测试目的:使用算符优先分析法,分析一个字符串不是该文法的句子,并输出出错信息。输入一个字符串,使得该字符串不是文法的句子。图5-3 测试用例2运行截图5.3 测试用例3测试目的:读入一个文法,判断该文法不是算符优先文法。读入一个非算符优先文法进行分析,给出文件路径:D:coursesC_source_file成品非算符优先文法1.txt。运行结果如下:图5-4 测试用例3运行截图5.4 测试用例4测试目的:输入一个非算符文法,判断该文法不是算符文法。读入一个非算符文法,给出路径:D:coursesC_source_file成品非算符文法.txt。运行结果如下:图5-5 测试用例4运行截图-6 结论和展望结论本次实验我们基本完成了实验题目的要求。求出了一个文法中每一个非终结符的FIRSTVT集和LASTVT集,画出算符优先关系表,并判定出给定的文法是否是算符优先文法。当给定一个符号串时,能够判定是否是文法中的句子,并能够将分析过程打印出来。通过算符优先分析方法,可以对任意一个文法进行自底向上的分析。同时,算符优先分析法也存在不足之处,由于忽略文法中的非终结符,会将本不属于文法的句子正确规约,从而引起错误。展望本次实验完成了题目的要求,准确把握了将文法通过读文件形式、手动输入分析字符串的题目要求,并在满足要求的基础上进行了创新,添加了对算符文法的判断功能。实验中,小组成员的分工与合作充分体现了软件工程的思想。需求分析理解准确,小组成员任务明确,统一函数头、参数,各自完成分内工作,整合工作快速、高效。同时,实验中还存在很多不足。调试程序中的错误占用了大部分时间,以至于没有考虑使用界面展示结果。虽然使用C+开发工具,但实质上还是在使用C编代码。在今后的实践中还需注意。学习编译技术课程的体会和对本门课程的评价在上编译课的时候,小组成员都觉得自己对算符优先文法已经掌握了,但等真正用程序去实现时,才发现有很多细节我当时没有注意到。也正以为没有注意到这些细节,导致成员们编程时会出现各种错误,大部分都是在循环时下标或者循环次数的控制上出错。在进行到一定阶段后发现犯的低级错误越来越少了,对算符优先文法也愈发的吃透了,编程水平也有了进一步的提高。编译原理如果要深入研究,那会是一门非常深奥的学问,对于现阶段只有60多学时的本科生来说,只能涉及到它一些最基本的原理,和最宏观的方法,要想微观的去研究,还需要在以后的时间里去钻研。在这次实验中,小组成员也只是用高级语言模拟了编译的一个小方法,在完成实验的过程中,小组成员对编译原理有了进一步的了解,更提高了动手编程能力,是一次经验和知识的积累。7 参考文献 1 张素琴编译原理(第2版)M. 北京:清华大学出版社,2005.6,102-121.2 陈维兴C+面向对象程序设计教程M. 北京:清华大学出版社,2004.8,258-272.8 源代码#include<iostream.h>#include<stdlib.h>#include <fstream.h>#define row 50#define col 50#define SIZE 50/两个重要结构体的定义/FIRSTVT表或LASTVT表中一个表项(A,a)结构体的初始化typedef structchar nonterm; /非终结符char term; /终结符StackElement;/存放(A,a)的栈的初始化typedef struct StackElement *top;StackElement *bottom;int stacksize;stack;/初始化(A,a)栈void InitStack(stack &S) S.bottom = new StackElementSIZE; if(!S.bottom) cout<<"存储空间分配失败!"<<endl; S.top = S.bottom; S.stacksize = SIZE;/判断(A,a)栈是否为空bool ifEmpty(stack S)if(S.top=S.bottom) return true; /如果栈为空,则返回trueelse return false; /否则不为空,返回false/插入栈顶(A,a)元素void Insert(stack &S,StackElement e)if(S.top-S.bottom>=S.stacksize)cout<<"栈已满,无法插入!"<<endl;elseS.top->nonterm=e.nonterm;S.top->term=e.term;S.top+;/弹出栈顶(A,a)元素StackElement Pop(stack &S)StackElement e;e.nonterm = '0'e.term = '0'if(S.top=S.bottom)cout<<"栈为空,无法进行删除操作!"<<endl; return e;elseS.top-; e.nonterm=S.top->nonterm;e.term=S.top->term;return e;/终结符与非终结符的判断函数(布尔类型)bool TerminalJud(char c)if(c>='A'&&c<='Z')return false; /非终结符返回falseelse return true; /终结符返回true/判断非终结符在first表中是否已存在bool ItemJud(char firstcol,int frist_len,char C)for(int i=0;i<frist_len;i+)if(firsti0=C) return true; /如果first表中已存在此非终结符,则返回true return false;/读文件函数int readfile(char sencol)char addr50;cout<<"请输入要读文件的地址(用表示):"<<endl;cin>>addr;ifstream fin;fin.open(addr,ios:in);if(!fin)cout<<"Cannot open file!n"<<endl;for(int i=0;!fin.eof();i+)fin>>seni;cout<<seni<<endl;return i;/FIRSTVT表和LASTVT表中表项(非终结符)的初始化void ItemInit(char sencol,char firstcol,char lastcol,int sen_len,int &frist_len)int i;frist_len=1;first00=sen00;last00=sen00;for(i=1;i<sen_len;i+)if(TerminalJud(seni0)=false && ItemJud(first,frist_len,seni0)=false) /k是当前first和last表的长度firstfrist_len0=seni0;lastfrist_len0=seni0;frist_len+;void FirstVt(char sencol,char firstcol,int sen_len,int frist_len) / frist_len 是 first 表的行数 sen_len是产生式的个数StackElement DFS,recordSIZE;stack Operator; /创建存放(A,a)的栈InitStack(Operator); int i,j,r=0;for(i=0;i<sen_len;i+) /第一次扫描,将能直接得出的first(A,a)放进栈中for(j=3;senij!='0'j+)if(TerminalJud(senij)=true) /遇到的第一个终结符压入int exist=0;DFS.nonterm=seni0;DFS.term=senij;for(int i1=0;i<r;i+)if(recordi1.nonterm=seni0&&recordi1.term=senij)exist=1;break;recordr.nonterm=seni0;recordr.term=senij;if(exist=0)Insert(Operator,DFS);/A-aB A-aC (A,a)压栈两次?recordr.nonterm=seni0;recordr.term=senij;r+;break;int locationcol; /辅助数组,用来记录first表中放入终结符的位置for(i=0;i<frist_len;i+) locationi=1;while(!ifEmpty(Operator)int exist=0; /标志位,记录即将入栈的元素是否已经存在StackElement IDElement,DElement;DElement=Pop(Operator); /弹出栈顶元素for(i=0;i<frist_len;i+)if(firsti0=DElement.nonterm)int n=locationi;firstin=DElement.term; /将终结符填入相应的first表中locationi+;break;for(j=0;j<sen_len;j+) if(senj3=DElement.nonterm) /找出能推出当前非终结符的产生式的左部 IDElement.nonterm=senj0;IDElement.term=DElement.term;/判断将要放进栈里的元素曾经是否出现过,若没有,才压入栈for(int r0=0;r0<r;r0+) /r记录record数组中的元素个数if(recordr0.nonterm=IDElement.nonterm && recordr0.term=IDElement.term) exist=1;break; if(exist=0)Insert(Operator,IDElement);recordr.nonterm=IDElement.nonterm;recordr.term=IDElement.term;r+;/if/for/whilevoid LastVt(char sencol,char lastcol,int sen_len,int frist_len) /firstvt表与lastvt表行数一样 first_len表示last 表的行数int i,j,i1,j1;char c,recordrowcol='0'for(i=0;i<sen_len;i+) for(j=0;senij!='0'j+)recordij=senij;j=j-1; for(i1=3,j1=j;i1<j1;i1+,j1-) /做翻转,就可以用求first的方法求lastc=recordii1;recordii1=recordij1;recordij1=c;/forFirstVt(record,last,sen_len,frist_len);/判断非终结符在term表中是否已存在bool TermTableJud(char termcol,int term_len,char C) for(int i=0;i<term_len;i+)if(termi=C) return true; /如果first表中已存在此非终结符,则返回1 return false;/构造算符优先关系表bool OpPriotable(char sencol,char firstcol,char lastcol,char opTablecol,int sen_len,int first_len,int &opTable_len) int i,j,term_len=0;int i2,i3,opr,opc;char c1,c2,c3;char termSIZE='0'for(i=0;i<sen_len;i+) /一维数组term记录关系表中存在的所有终结符for(j=3;senij!='0'j+)if(TerminalJud(senij)=true) if(TermTableJud(term,term_len,senij)=false) /term_len记录term表的长度 termterm_len=senij; term_len+; /得到终结符表 for(i=0;i<term_len+1;i+) /给优先关系表赋初值,都等于空for(j=0;j<term_len+1;j+)opTableij=' 'for(i=1;i<term_len+1;i+) /设置优先关系表的表头opTablei0=termi-1; opTable0i=termi-1; for(i=0;i<sen_len;i+) /找等于关系for(j=5;senij!='0'j+)if(TerminalJud(senij-2)=true&&TerminalJud(senij-1)=false&&TerminalJud(senij)=true)c1=senij-2; c2=senij; for(opr=1;opr<term_len+1;opr+) /在opTable表中找到该存入的行标oprif(opTableopr0=c1)break;for(opc=1;opc<term_len+1;opc+) /在opTable表中找到该存入的列标opcif(opTable0opc=c2)break;if(opTableopropc!=' ')cout<<"不是算符优先文法!"<<endl;return false;elseopTableopropc='='/if/for(j)for(j=4;senij!='0'j+)if(TerminalJud(senij-1)=true&&TerminalJud(senij)=true)c1=senij-1;c2=senij;for(opr=1;opr<term_len+1;opr+) /在opTable表中找到该存入的行标oprif(opTableopr0=c1)break;for(opc=1;opc<term_len+1;opc+) /在opTable表中找到该存入的列标j2if(opTable0opc=c2)break;if(opTableopropc!=' ')cout<<"不是算符优先文法!"<<endl;return false;elseopTableopropc='='/for(i)for(i=0;i<sen_len;i+) /找小于关系for(j=3;senij!='0'j+)if(TerminalJud(senij)=true&&TerminalJud(senij+1)=false)c1=senij; /c1记录终结符c2=senij+1; /c2记录非终结符 for(opr=1;opr<term_len+1;opr+) /在opTable表中找到该存入的行标oprif(opTableopr0=c1)break;for(opc=0;opc<first_len;opc+) /找出非终结符在first表中的列标opcif(firstopc0=c2)break;for(i2=1;firstopci2!='0'i2+)c3=firstopci2;for(i3=1;i3<term_len+1;i3+)if(opTable0i3=c3)if(opTableopri3!=' ')cout<<"不是算符优先文法!"<<endl;return false;elseopTableopri3='<'break;/if/for(j)/for(i)for(i=0;i<sen_len;i+) /找大于关系for(j=3;senij!='0'j+)if(TerminalJud(senij)=false&&senij+1

    注意事项

    本文(编译原理课程设计——算符优先分析法研究——附源程序.doc)为本站会员(豆****)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开