文档介绍:该【计算机编译原理实验报告 】是由【1781111****】上传分享,文档一共【20】页,该文档可以免费在线阅读,需要了解更多关于【计算机编译原理实验报告 】的内容,可以使用淘豆网的站内搜索功能,选择自己适合的文档,以下文字是截取该文章内的部分文字,如需要获得完整电子版,请下载此文档到您的设备,方便您编辑和打印。:..实验一词法分析设计一、实验功能:1、对输入的txt文件内的内容进行词法分析:2、,对文件中的各类字符进行词法分析3、打印出分析后的结果;二、程序结构描述:(源代码见附录):..k[],s1[],s2[],s3[]构造关键字表,分界符表,算术运算符表和关系运算符表。2、boolisletter(){}用来判断其是否为字母,是则返回true,否则返回false;boolisdigit(){}用来判断其是否为数字,是则返回true,否则返回false;booliscalcu(){}用来判断是否为算术运算符,是则返回true,否则返回false;boolreserve(stringa[]){}用来判断某字符是否在上述四个表中,是则返回true,否则返回false;voidconcat(){}用来连接字符串;voidgetn(){}用来读取字符;voidgetb(){}用来对空格进行处理;voidretract(){}某些必要的退格处理;intanalysis(){}对一个单词的单词种别进行具体判断;在主函数中用switch决定输出。三、实验结果:..词法分析器一眼看上去很复杂,但深入的去做就会发现并没有一开始想象的那么困难。对于一个字符的种别和类型可以用bool函数来判断,对于关键字和标示符的识别(尤其是3b)则费了一番功夫,最后对于常数的小数点问题处理更是麻烦。另外,这个实验要设定好时候退格,否则将会导致字符漏读甚至造成字符重复读取。我认为,这个实验在程序实现上大体不算困难,但在细节的处理上则需要好好地下功夫去想,否则最后的程序很可能会出现看上去没有问题,但实际上漏洞百出的状况。将学过的知识应用到实际中并不简单,只有自己不断尝试将知识转化成程序才能避免眼高手低,对于知识的理解也必将更加深刻。实验二LL(1)分析法:..1、写出LL(1)分析法的思想:当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。实现LL(1)分析的一种有效的方法是使用一张分析表和一个站进行联合控制。预测分析表是一个M[A,a]形式的矩阵,存储着分析规则;栈STACK用于存放文法符号。从栈顶取符号,按照分析表给出的规则进行有步骤的分析。:(1)E->TG(2)G->+TG|TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i二、程序结构:stringM[5][8]用来定义分析表;charinput[50]用来存放输入的句子;vector<char>analysis用来存放分析栈;boolflag=true用来判断是否成功的标志;reference(chara,chari){}查询分析表,其中a为分析栈顶符号,i为输入串符号;pro(chara,charin){}用以做出具体的分析;:..运行程序,输入需要分析的语句,结果如下::..本次试验用代码实现了LL(1)文法,在过程中对于非终结符向终结符转换的过程中出现了一些问题,之后通过向同学请教得已解决。本代码中的分析表写在了主函数中,可以说本程序只对这一个文法有效,这也是这个程序的局限性。实验三LR(1)分析法一、实验原理LR(1)分析法实验设计思想及算法(1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。分析器的动作就是由栈顶状态和当前输入符号所决定。:..action[12][6]定义动作表;go[12][3]定义转换表;input[50]存放输入串;referaction(ints,chari){}查询action表,a为分析栈顶的状态,i为输入串的符号;refergo(ints,chari){}查询go表;reduce(intn){}就近规约;analysis(intst,charin){}具体分析;其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。?ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。动作有四种可能:(1)移进:action[i,a]=Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。(2)归约::..action[ia]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A-B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。(3):当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。(4)报错:当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。三、实验结果:输入需要规约的字符串,结果如下::..1、与算符优先分析方法比较,用LR分析时,设计特定出错处理子程序比较容易,因为不会发生不正确的归约。在分析表的每一个空项内,可以填入一个指示器,指向特定的出错处理子程序,第一类错误的处理一般采用插入、删除或修改的办法,但要注意,不能从栈内移去任何那种状态,它代表已成功地分析了程序中的某一部分。2、LR分析法的归约过程是规范推导的逆过程,所以LR分析过程是一种规范归约过程。LR分析法正是给出一种能根据当前分析栈中的符号串(通常以状态表示)和向右顺序查看输入串的K个(K≥0)符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约,因而也就能唯一地确定句柄。其中LR(0)分析器是在分析过程中不需向右查看输入符号,因而它对文法的限制较大,然而,它是构造其它LR类分析器的基础。因此,首先应学好LR(0)项目集规范族构造的基本原理和方法。当K=1时,已能满足当前绝大多数高级语言编译程序实现的需要。SLR(1)分析是为学****LR(1)分析做准备,LR(1)项目集族的构造是LALR(1)分析器的构造原理和基础。LALR(1)分析器是当前大多数高级程序设计语言编译程序所采用的语法分析技术,的实现基本原理。由此,LR(0)、SLR(1)、LALR(1)、LR(1)四种分析器的构造方法都必须深入理解和掌握。3、经过以上三个实验的锤炼,不得不说自己编译原理这门课的认识又提高了一个阶层,对编译原理的知识运用更加深入,编写过程中遇到不少的问题,结合课本及强大的网络资源,在完成的过程中得到很多收获,不仅来自于对知识点的了解更加深入,更是对自己编程能力的一次很好的锻炼,希望有更多这样实验的机会。4、本人很希望在完成实验后,老师可以根据自己讲的课本,将自己所写的程序花一段时间来讲解,我想这样会对不会编写的是一种教学,对会了的同学是一种榜样效应,可以让我们有个目标追求,这样我们收获了的也会更加准确与丰富。:..实验一源代码:#include<iostream>#include<string>#include<fstream>usingnamespacestd;关键字分界符算术运算符关系运算符stringid[100];stringci[100];ifstreamin;charch;introw=1,col=0;//行数与列数intidcount=0,cicount=0;stringstrtoken;boolisletter(){//用来判断其是否为字母if(ch>='A'&&ch<='z')returntrue;elsereturnfalse;}boolisdigit(){//用来判断其是否为数字if(ch>='0'&&ch<='9')returntrue;elsereturnfalse;}booliscalcu(){//用来判断是否为算术运算符if(ch=='+'||ch=='-'||ch=='*'||ch=='/')returntrue;elsereturnfalse;}:..voidinsertid(){id[idcount]=strtoken;idcount++;}voidinsertci(){ci[cicount]=strtoken;cicount++;}boolreserve(stringa[]){//intcount;count=8;for(inti=0;i<count;i++){if(a[i]==strtoken)returntrue;}returnfalse;}voidconcat(){//用来连接字符串strtoken+=ch;}voidgetn(){//(&ch,1);if(ch==''){(&ch,1);row++;col=1;}}voidgetb(){//空格处理while(ch=='')(&ch,1);}voidretract(){//某些必要的退格处理intsize=sizeof(ch);:..(-size*2,ios::cur);}intanalysis(){//col++;getn();getb();if(())return7;if(isletter()){while(isletter()||isdigit()){concat();getn();}retract();if(reserve(k)){return1;}else{insertid();return6;}}elseif(isdigit()){boolmultipoint=false;boolinsertpoint=false;while(isdigit()||ch=='.'){if(ch=='.'){if(insertpoint==false){concat();getn();insertpoint=true;}else{concat();getn();multipoint=true;}}if(isdigit()){concat();getn();}}boolhaveletter=false;while(isletter()){haveletter=true;concat();getn();}:..retract();if(haveletter)return0;if(multipoint)return0;insertci();return5;}elseif(iscalcu()){while(iscalcu()){concat();getn();}if(reserve(s2))return3;elsereturn0;}concat();if(reserve(s1))return2;elseif(reserve(s3)){getn();if(ch=='='){concat();if(reserve(s3))return4;}else{retract();return4;}}return0;}intmain(){if(!in){return1;}:..intcode;分析结果如下单词二元序列类型位置while(!()){code=analysis();switch(code){casek;case1:if(()<4)关键字else关键字break;case分界符break;case算术运算符break;case关系运算符break;case常数break;case标识符break;}}return0;}实验二源代码:#include<iostream>#include<string>#include<vector>:..#include<algorithm>usingnamespacestd;stringM[5][8];//charinput[50];//用来存放输入的句子vector<char>analysis;//用来存放分析栈boolflag=true;//用来判断是否成功的标志,false为成功inti=0;//输入串的指针stringreference(chara,chari){//查询分析表,其中a为分析栈顶符号,i为输入串符号intx,y;switch(a){case'E':x=0;break;case'T':x=1;break;case'F':x=2;break;case'G':x=3;break;case'S':x=4;break;}switch(i){case'(':y=0;break;case')':y=1;break;case'+':y=2;break;case'-':y=3;break;case'*':y=4;break;case'/':y=5;break;case'i':y=6;break;case'#':y=7;break;}returnM[x][y];}:..voidprint(chari){cout<<i;}voidprin(){//intj=i;cout<<input[j];}voidpro(chara,charin){//分析程序if(a==in)if(a=='#'){flag=false;分析已全部完成return;}else{i++;();for_each((),(),print);prin();return;}else{stringexpre=reference(a,in);();//出栈intj=()-1;while(expre[j]!='>'){(expre[j]);j--;}for_each((),(),print);prin();if(()>3)else}:..intmain(){M[4][1]=====('#');('E');#结束cin>>input;分析栈剩余输入串所用产生式动作for_each((),(),print);prin();初始化while(flag){pro((),input[i]);}return0;}实验三源代码:#include<iostream>#include<string>#include<vector>#include<algorithm>usingnamespacestd;:..};//文法intgo[12][3];//定义转换表charinput[50];//存放输入串inti=0;boolflag=true;//判断是否成功vector<char>symbol;//定义分析表vector<int>status;//定义符号栈stringreferaction(ints,chari){//查询action表,a为分析栈顶的状态,i为输入串的符号inty;switch(i){case'i':y=0;break;case'+':y=1;break;case'*':y=2;break;case'(':y=3;break;case')':y=4;break;case'#':y=5;break;}returnaction[s][y];}intrefergo(ints,chari){//查询go表inty;switch(i){case'E':y=0;break;case'T':y=1;break;case'F':y=2;break;}returngo[s][y];}voidprintint(intn){cout<<n;:..voidprintchar(charc){cout<<c;}voidprin(){//intj=i;cout<<input[j];}voidreduce(intn){//就近规约intj=grammer[n].size()-3;while(j--){();();}(grammer[n][0]);intstu=refergo((),());归约,(stu);}voidanalysis(intst,charin){stringac=referaction(st,in);if(ac[0]=='S'){(input[i]);intstat=ac[1]-48;(stat);i++;状态入栈return;}if(ac[0]=='r'){cout<<ac<<':';intg=ac[1]-48-1;:..reduce(g);return;}flag=false;}}intmain(){go[0][0]=1;go[0][1]=2;go[0][2]=3;go[4][0]=8;go[4][1]=2;go[4][2]=3;go[6][1]=9;go[6][2]=3;go[7][2]=10;('#');(0);输入语句,以#结束cin>>input;状态栈符号栈剩余输入串动作while(flag){analysis((),input[i]);}return0;}