编译原理实验报告--递归子程序
编译原理实验报告——实验二 递归下降分析
printf("T'->*FT'\t"); printf("#E'T'F*\t\t"); print(); } else { printf("T'->/FT'\t"); printf("#E'T'F/\t\t"); print(); }
7
myAdvance(); printf("\t\t"); printf("#E'T'F\t\t"); print(); myF(); } if( sym!='*'||sym!='/') { printf("T'->^\t\t"); printf("#E'\t\t"); print(); } return(1); } else return(0); } /*判断是否是表达式或者括号*/ int myF() { int p; if (sym >= 'A' && sym <= 'Z' || sym >= 'a' && sym <= 'z' ) { printf("F->i\t\t"); printf("#E'T'i\t\t"); print(); myAdvance(); printf("\t\t"); printf("#E'T'\t\t"); print(); return(1); } else{
python递归实验报告
python递归实验报告Python递归实验报告引言:递归是计算机科学中一种重要的编程技术,它在解决问题时能够简化代码逻辑,并提高代码的可读性和可维护性。
Python作为一种高级编程语言,提供了强大的递归支持,本文将通过实验来探讨Python递归的特性和应用。
一、递归的概念与原理递归是一种通过调用自身的方式解决问题的方法。
在递归过程中,问题被分解为更小的子问题,直到子问题足够简单可以直接求解。
递归的基本原理是将一个大问题转化为一个或多个与原问题相似但规模更小的子问题,通过递归调用解决子问题,最终得到原问题的解。
二、递归的实现方式在Python中,递归可以通过函数调用自身来实现。
递归函数通常包含两个部分:基准情况和递归情况。
基准情况是递归函数的结束条件,当满足基准情况时,递归函数将不再调用自身,而是返回一个特定的值。
递归情况是指递归函数在未满足基准情况时,调用自身来处理更小规模的子问题。
三、递归的应用场景1. 阶乘计算阶乘是指从1到给定数之间所有整数的乘积。
递归可以很方便地实现阶乘计算,如下所示:```pythondef factorial(n):if n == 0:return 1else:return n * factorial(n-1)```2. 斐波那契数列斐波那契数列是指从第三项开始,每一项都等于前两项之和。
递归可以很容易地实现斐波那契数列的计算,如下所示:```pythondef fibonacci(n):if n <= 1:return nelse:return fibonacci(n-1) + fibonacci(n-2)```3. 文件夹遍历递归还可以用于文件夹的遍历,通过递归调用实现对文件夹内所有文件的查找和处理。
例如,可以编写一个函数来计算指定文件夹下所有文件的总大小:```pythonimport osdef get_folder_size(folder):size = 0for item in os.listdir(folder):item_path = os.path.join(folder, item)if os.path.isfile(item_path):size += os.path.getsize(item_path)elif os.path.isdir(item_path):size += get_folder_size(item_path)return size```四、递归的优缺点递归的优点在于能够简化问题的解决过程,提高代码的可读性和可维护性。
编译原理递归下降子程序
北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx _ 作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求1.针对算术表达式文法:E→TE’E’→ +TE’|εT→FT’T’→*FT’ |εF→(E) |i为其编写递归下降子程序,判定某个算术表达式是否正确:如j+k*m,j*k+m输入:其输入数据应该为词法分析器输出的记号形式:i+i*i,i*i+i输出:分析结果:算术表达式结构正确或结构错误。
三、实验程序设计说明1.实验方案设计各个函数之间的调用关系如下图所示:2.程序源代码源代码如下:#include<stdio.h>#include<iostream>#include<fstream>#include<string>char a[10];int lookahead=0;void E1();void T();void T1();void F();void E(){printf("E->TE'\n");T();E1();}void E1(){if(a[lookahead]=='+'){printf("E'->+TE'\n");lookahead++;T();E1();}elseprintf("T'->ε\n"); }void T(){printf("T->FT'\n");F();T1();}void T1(){if(a[lookahead]=='*'){printf("T'->*FT'\n");lookahead++;F();T1();}elseprintf("T'->ε\n"); }void F(){if(a[lookahead]=='i'){printf("F->i\n");lookahead++;}else if (a[lookahead]=='('){lookahead++;E();if(a[lookahead]==')'){printf("F->(E)\n");lookahead++;}else{printf("\n括号不匹配分析失败!\n");exit (0);}}else{printf("括号不匹配,分析失败!\n");exit(0);}}int main(){while(1){printf("请输入算数表达式(以#键结束):");scanf("%s",a);E();if((a[lookahead]=='#'))printf("句子结构正确\n");elseprintf("无结束标志,分析失败\n");}return 0;}3.程序的执行结果程序运行结果如下所示:四、实验中出现的问题及解决方法1.错误处理:最初程序只是将所有的错误都简单的显示为句子结构错误,并没有进行具体详细的说明和解释,最后通过修改程序,细化错误类型,使用了对if语句的嵌套,将错误分为三种类型。
编译原理实验语法器递归下降子程序实现解析
编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机1306班姓名:张涛学号:20133967 实验目标:用递归下降子程序设计实现表达式语法分析器实验内容:⑴概要设计:通过对实验一的此法分析器的程序稍加改造,使其能够输出正确的表达式的token序列。
然后利用LL(1)分析法实现语法分析。
⑵数据结构:int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'}; //运算符char bound[2]={'(',')'}; //界符struct Token{int code;char ch[10];}; //Token定义struct Token tokenlist[50]; //Token数组struct Token tokentemp; //临时Token变量⑶流程图:⑷关键函数:int IsLetter(char ch) //判断ch是否为字母int IsDigit(char ch) //判断ch是否为数字int Iskey(char *string) //判断是否为关键字int Isbound(char ch) //判断是否为界符int Isboundnum(char ch) //给出界符所在token值void T(); //分析子程序void F(); //分析子程序void E1(); //分析子程序void E(); //分析子程序void T1(); //分析子程序源程序代码:(加入注释)#include<stdio.h>#include<string.h>#include<ctype.h>#include<windows.h>int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'};char bound[2]={'(',')'};struct Token{int code;char ch[10];};struct Token tokenlist[50];struct Token tokentemp;void T();void F();void E1();void E();void T1();int IsLetter(char ch) //判断ch是否为字母{int i;for(i=0;i<=45;i++)if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))return 1;return 0;}int IsDigit(char ch) //判断ch是否为数字{int i;for(i=0;i<=10;i++)if (ch>='0'&&ch<='9')return 1;return 0;}int Isbound(char ch){int i;for(i=0;i<2;i++){if(ch==bound[i]){return i+1;}}return 0;}int Isoperate(char ch){int i;for(i=0;i<4;i++){if(ch==operate[i]){return i+3;}}return 0;}int main(){FILE *fp;int q=0,m=0;char sour[200]=" ";printf("请将源文件置于以下位置并按以下方式命名:F:\\2.txt\n");if((fp=fopen("F:\\2.txt","r"))==NULL){printf("文件未找到!\n");}else{while(!feof(fp)){if(isspace(ch=fgetc(fp)));else{sour[q]=ch;q++;}}}int p=0;printf("输入句子为:\n");for(p;p<=q;p++){printf("%c",sour[p]);}printf("\n");int state=0,nowlen=0;BOOLEAN OK=TRUE,ERR=FALSE;int i,flagpoint=0;for(i=0;i<q;i++){switch(state){case 0:ch=sour[i];if(Isbound(ch)){if(ERR){printf("无法识别\n");ERR=FALSE;OK=TRUE;}else if(!OK){printf("<10,%s>标识符\n",nowword);tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}state=4;}else if(IsDigit(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;state=3;OK=FALSE;break;}else{nowword[nowlen]=ch;nowlen++;}}else if(IsLetter(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;OK=FALSE;if(sour[i+1]=='#'){printf("<10,%s>标识符\n",nowword);struct Token tokentemp;tokentemp.code=10;int i=0;for(i;i<=nowlen;i++)tokentemp.ch[i]=nowword[i];tokenlist[m]=tokentemp;}}else{nowword[nowlen]=ch;nowlen++;}}else if(Isoperate(ch)){if(!OK){printf("<10,%s>标识符\n",nowword);tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}printf("<%d,%c>运算符\n",Isoperate(ch),ch);tokentemp.code=Isoperate(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;}break;case 3:if(IsLetter(ch)){printf("错误\n");nowword[nowlen]=ch;nowlen++;ERR=FALSE;state=0;break;}if(IsDigit(ch=sour[i])){nowword[nowlen]=ch;nowlen++;}else if(sour[i]=='.'&&flagpoint==0){flagpoint=1;nowword[nowlen]=ch;nowlen++;}else{printf("<20,%s>数字\n",nowword);i--;state=0;OK=TRUE;tokentemp.code=20;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;}break;case 4:i--;printf("<%d,%c>界符\n",Isbound(ch),ch);tokentemp.code=Isbound(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;state=0;OK=TRUE;break;}}int io=0;for(io;io<=m;io++){printf("tokenlist%d.code值为%d\n",io,tokenlist[io].code);}E();if(op==m)printf("OK!!!");elseprintf("WRONG!!!");return 0;}void E(){T();E1();}void E1(){if(tokenlist[op].code==3||tokenlist[op].code==4){tokenlist[op++];T();E1();}}void T1(){if(tokenlist[op].code==5||tokenlist[op].code==6){tokenlist[op++];F();T1();}}void T(){F();T1();}void F(){if(tokenlist[op].code==10||tokenlist[op].code==20) {tokenlist[op++];}else{if(tokenlist[op].code==1){tokenlist[op++];E();if(tokenlist[op].code==2){tokenlist[op++];}else{printf("WRONG!!!!!!");//exit(1);}}else{printf("WRONG!!!!!!");//exit(1);}}}程序运行结果:(截屏)输入:((Aa+Bb)*(88.2/3))#注:如需运行请将文件放置F盘,并命名为:2.txt 输出:思考问题回答:在递归下降子程序中要注意对于错误情况的处理,以防程序无限循环,无法结束。
编译原理-实验4递归下降分析法
实验4《递归下降分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验内容程序输入/输出示例(以下仅供参考):对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E-TG(2)G-+TG|—TG(3)G-ε(4)T-FS(5)S-*FS|/FS(6)S-ε(7)F-(E)(8)F-i输出的格式如下:(3)备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符I,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好)。
三、实验方法用C语言,根据递归下降分析法的规则编写代码,并测试。
四、实验步骤1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3.对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;五、实验结果六、实验结论#include<stdio.h>#include<dos.h>#include<stdlib.h>#include<string.h>char a[50],b[50],d[200],e[10];char ch;int numOfEq,i1=0,flag=1,n=6;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();//================================================ void main()/*递归分析*/{ int foe1,i=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='?';d[4]='T';d[5]='G';d[6]='#';printf("请输入字符串(以#号结束)\n");do{ scanf("%c",&ch);a[i]=ch;i++;}while(ch!='#');numOfEq=i;ch=b[0]=a[0];printf("文法\t分析串\t\t分析字符\t剩余串\n");if (foe1==0) return;if (ch=='#'){ printf("accept\n");i=0;x=d[i];while(x!='#'){ printf("%c",x);i=i+1;x=d[i];/*输出推导式*/}printf("\n");}else{ printf("error\n");printf("回车返回\n");getchar();getchar();return;}}//================================================ int E1(){ int fot,fog;printf("E->TG\t");flag=1;input();input1();fot=T();if (fot==0) return(0);fog=G();if (fog==0) return(0);else return(1); }//================================================ int E(){ int fot,fog;printf("E->TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='?';e[4]='T';e[6]='#';output();flag=1;input();input1();fot=T();if (fot==0) return(0);fog=G();if (fog==0) return(0);else return(1); }//================================================ int T(){ int fof,fos;printf("T->FS\t");e[0]='T';e[1]='=';e[2]='>';e[3]='?';e[4]='F';e[5]='S';e[6]='#';output();flag=1;input();input1();fof=F();if (fof==0) return(0);fos=S();if (fos==0) return(0);else return(1); }//================================================ int G(){ int fot;if(ch=='+'){ b[i1]=ch;printf("G->+TG\t");e[0]='G';e[2]='>';e[3]='?';e[4]='+';e[5]='T';e[6]='G';e[7]='#';output();flag=0;input();input1();ch=a[++i1];fot=T();if (fot==0) return(0); G();return(1);}else if(ch=='-'){ b[i1]=ch;printf("G->-TG\t"); e[0]='G';e[1]='=';e[2]='>';e[3]='?';e[4]='-';e[5]='T';e[6]='G';e[7]='#';output();flag=0;input();input1();ch=a[++i1];fot=T();if (fot==0) return(0); G();return(1); }printf("G->^\t");e[1]='=';e[2]='>';e[3]='?';e[4]='^';e[5]='#';output();flag=1;input();input1();return(1);}//================================================ int S(){ int fof,fos;if(ch=='*'){ b[i1]=ch;printf("S->*FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='*';e[5]='F';e[6]='S';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];fof=F();if (fof==0)return(0);fos=S();if (fos==0) return(0);else return(1); }else if(ch=='/'){ b[i1]=ch;printf("S->/FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='/';e[5]='F';e[6]='S';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];fof=F();if (fof==0) return(0);fos=S();if (fos==0) return(0);else return(1); }printf("S->^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='^';e[5]='#';output();flag=1;a[i1]=ch;input();input1();return(1); }//================================================ int F(){int f;if(ch=='('){ b[i1]=ch;printf("F->(E)\t");e[0]='F';e[1]='=';e[2]='>';e[3]='?';e[3]='(';e[4]='E';e[5]=')';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0); if(ch==')'){ b[i1]=ch;printf("F--(E)\t");flag=0;input();input1();ch=a[++i1]; }else{ printf("error\n");return(0);}}else if(ch=='i'){b[i1]=ch;printf("F->i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='?';e[4]='i';e[5]='#';output();flag=0;input();input1();ch=a[++i1];}else{printf("error\n");return(0);}return(1);}//================================================ void input(){ int i=0;for (;i<=i1-flag;i++)printf("%c",b[i]);/*输出分析串*/printf("\t\t");printf("%c\t\t",ch);/*输出分析字符*/}//================================================ void input1(){ int i;for (i=i1+1-flag;i<numOfEq;i++)printf("%c",a[i]);/*输出剩余字符*/printf("\n");}//================================================ void output(){/*推导式计算*/int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='?';d[n+3]='#';n=n+3;i=n;i=i-2;while(d[i]!='?'&&i!=0)i--;i=i+1;while(d[i]!=e[0])i=i+1;q=i;m=q;k=q;while(d[m]!='?')m=m-1;m=m+1;while(m!=q){d[n]=d[m];m=m+1;n=n+1;}d[n]='#';for(j=3;e[j]!='#';j++){d[n]=e[j];n=n+1;}k=k+1;while(d[k]!='='){d[n]=d[k];n=n+1;k=k+1;}d[n]='#';}七、实验小结通过本次试验实践掌握了自上而下语法分析法的特点。
WHILE语句的翻译—递归子程序法—三地址表示——编译原理课程设计报告
课程设计题目WHILE循环语句的翻译程序设计(递归下降法、输出三地址表示)学院计算机科学与技术学院专业计算机科学与技术班级0806姓名张方纪指导教师郭羽成2010 年 1 月7 日课程设计任务书学生姓名:张方纪专业班级:计算机0806班指导教师:郭羽成工作单位:计算机科学与技术学院题目: WHILE循环语句的翻译程序设计(递归下降法、输出三地址表示)初始条件:理论:学完编译课程,掌握一种计算机高级语言的使用。
实践:计算机实验室提供计算机及软件环境。
如果自己有计算机可以在其上进行设计。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)(1)写出符合给定的语法分析方法的文法及属性文法。
(2)完成题目要求的中间代码三地址表示的描述。
(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5)设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:1 系统描述(问题域描述);2 文法及属性文法的描述;3 语法分析方法描述及语法分析表设计;4 按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;5 编译系统的概要设计;6 详细的算法描述(流程图或伪代码);7 软件的测试方法和测试结果;8 研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);9 参考文献(按公开发表的规范书写)。
时间安排:设计安排一周:周1、周2:完成系统分析及设计。
周3、周4:完成程序调试及测试。
周5:撰写课程设计报告。
设计验收安排:设计周的星期五第1节课开始到实验室进行上机验收。
设计报告书收取时间:设计周的次周星期一上午10点。
指导教师签名: 2010年 11月 23日系主任(或责任教师)签名: 2010年 11月 23日WHILE循环语句的翻译程序设计(递归下降法、输出三地址表示)1任务使用C++语言编写一个while循环语句的翻译程序,使用递归下降法进行语法分析,输出三地址码表示。
编译原理-实验二-递归下降分析程序构造
编译原理-实验⼆-递归下降分析程序构造集美⼤学计算机⼯程学院实验报告课程名称:编译原理指导教师:付永钢实验成绩:实验编号:实验⼆实验名称:递归下降分析程序构造班级:计算12姓名:学号:上机实践⽇期:2014.11上机实践时间: 4学时⼀、实验⽬的通过设计、编制、调试⼀个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进⾏语法检查和结构分析,掌握常⽤的语法分析⽅法。
通过本实验,应达到以下⽬标:(1) 掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序内部表⽰⽂件的⽅法;(2)掌握语法分析的实现⽅法;(3)上机调试编出的语法分析程序。
⼆、实验环境Windows7 x64、VC6.0三、实验原理递归下降法是语法分析中最易懂的⼀种⽅法。
它的主要原理是,对每个⾮终结符按其产⽣式结构构造相应语法分析⼦程序,其中终结符产⽣匹配命令,⽽⾮终结符则产⽣过程调⽤命令。
因为⽂法递归相应⼦程序也递归,所以称这种⽅法为递归⼦程序下降法或递归下降法。
其中⼦程序的结构与产⽣式结构⼏乎是⼀致的。
递归下降分析程序的实现思想是:识别程序由⼀组⼦程序组成。
每个⼦程序对应于⼀个⾮终结符号。
每⼀个⼦程序的功能是:选择正确的右部,扫描完相应的字。
在右部中有⾮终结符号时,调⽤该⾮终结符号对应的⼦程序来完成。
⾃上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。
分析速度慢。
⽽⽆回溯的⾃上向下分析技术,可根据输⼊串的当前符号以及各产⽣式右部⾸符,选择某⾮终结符的产⽣式,效率⾼,且不易出错。
⽆回溯的⾃上向下分析技术可⽤的先决条件是:⽆左递归和⽆回溯。
即:假设A 的全部产⽣式为A →α1|α2|……|αn ,则必须满⾜如下条件才能保证可以唯⼀的选择合适的产⽣式First(A →αi )∩First (A →αj )=Φ,当i≠j.⽆左递归:既没有直接左递归,也没有间接左递归。
⽆回溯:对于⼈以⾮中介符号U 的产⽣式右部n x x x |...||21,其对应的字的⾸终结符号两两不相交。
编译原理语法分析递归下降子程序实验报告
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行FirstVT集及LastVT集的分析,并对输入的字符串进行规约输出规约结果成功或失败。
二、设计内容及步骤内容:在C++ 6.0中编写程序代码实现语法分析功能,调试得到相应文法的判断结果:是算符优先或不是。
若是,则输出各非终结符的FirstVT与LastVT集的结果,还可进行字符串的规约,输出详细的规约步骤,程序自动判别规约成功与失败。
步骤:1.看书,找资料,了解语法分析器的工作过程与原理2.分析题目,列出基本的设计思路1定义栈,进栈,出栈函数○2栈为空时的处理○3构造函数判断文法是否是算符文法,算符优先文法○4构造FirstVT和LastVT函数对文法的非终结符进行分析○5是算符优先文法时,构造函数对其可以进行输入待规约○串,输出规约结果○6构造主函数,对过程进行分析3.上机实践编码,将设计的思路转换成C++语言编码,编译运行4.测试,输入不同的文法,观察运行结果详细的算法描述详细设计伪代码如下:首先要声明变量,然后定义各个函数1.void Initstack(charstack &s){//定义栈s.base=new charLode[20];s.top=-1; }2. void push(charstack&s,charLode w){//字符进栈s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}3. void pop(charstack&s,charLode &w){//字符出栈w.E=s.base[s.top].E; 三、w.e=s.base[s.top].e;s.top--;}4. int IsEmpty(charstack s){//判断栈是否为空if(s.top==-1)return 1;else return 0;}5.int IsLetter(char ch){//判断是否为非终结符if(ch='A'&&ch= 'Z')return 1;else return 0;}6.int judge1(int n){ //judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法}7. void judge2(int n){//judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法8.int search1(char r[],int kk,char a){ //search1是查看存放终结符的数组r中是否含有重复的终结符}9.void createF(int n){ //createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体}10.void search(charLode w){ //search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1 }分情况讨论://产生式的后选式的第一个字符就是终结符的情况//产生式的后选式的第一个字符是非终结符的情况11.void LastVT(int n){//求LastVT}12.void FirstVT(int n){//求FirstVT}13.void createYXB(int n){//构造优先表分情况讨论://优先级等于的情况,用1值表示等于}//优先级小于的情况,用2值表示小于//优先级大于的情况,用3值表示大于}14.int judge3(char s,char a){//judge3是用来返回在归约过程中两个非终结符相比较的值}15.void print(char s[],charSTR[][20],int q,int u,int ii,int k){//打印归约的过程}16. void process(char STR[][20],int ii){//对输入的字符串进行归约的过程}四、设计结果分两大类,四种不同的情况第一类情况:产生式的候选式以终结符开始候选式以终结符开始经过存在递归式的非终结符后再以终结符结束篇二:编译原理递归下降子程序北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx_作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
编译原理实验-递归子程序法
递归子程序法:#include "stdio.h"#include "stdlib.h"void display();char read(); //读取字符函数void write();char lookhead;void E();void T();void G();void S();void F();void match(char ch);void error(); //出错处理char string[10];int top;int main(){display();write();lookhead=read();E();puts(string);printf("为合法字符串!\n");system("pause");return 0;}void E(){printf("E->TG \n");T();G();}void G(){if(lookhead=='+'){printf("G->+TG \n");match('+');T();G();}else if(lookhead=='-'){printf("G->-TG \n");match('-');T();G();}else{printf("G->ε \n");}}void T(){printf("T->FS \n");F();S();}void S(){if(lookhead=='*'){printf("s->*FS \n");match('*');F();S();}else if(lookhead=='/'){printf("S->/FS \n");match('/');}else{printf("S->ε \n");}}void F(){if(lookhead=='('){printf("F->(E) \n");match('(');E();match(')');}else if(lookhead=='i'){match('i');}else error();}void match(char ch){lookhead=read();}void write(){char cha;top=0;printf("请输入待分析字符串:\n");do{scanf("%c",&cha);string[top]=cha;top++;}while(cha!='#');top=0;}char read(){char cha;cha=string[top];top++;return cha;}void error(){puts(string);printf("为非法字符串!\n");system("pause");exit(0);}void display(){printf("班级:10级计本一班\n");printf("学号:1004011026\n");printf("姓名:王晓龙\n");}LL(1)分析方法:#include "stdio.h"#include "stdlib.h"#include "string.h"char S,X,a; //S文法的开始符号,X当前栈顶符号的工作单元,a当前输入符号的工作单元char string[10]; //存放输入的句型int count=0; //计数器int step=0; //记录步骤char M[16][6]; //存放产生式int record; //记录当前找到的M中产生式的下标char stack[10]; //栈int top;char Vt[9]="i+-*/()"; //终结符号int i;void error(); //出错函数void init(); //初始化预测分析表int judge(char x,char a);void analyse();void main(){init(); //初始化预测分析表int i;int mark1=0;char ch;top=-1;printf("请输入要分析的字符串:\n");string[0]='#';i=1;do{scanf("%c",&ch);string[i]=ch;i++;}while(ch!='#');printf("步骤\t\t分析栈\t\t剩余字符串\n");top++;stack[top]=string[0];count++;top++;stack[top]='E';step++;printf("%d\t\t",step);for(int i=0;i<=top;i++)printf("%c",stack[i]);printf("\t\t");i=1;while(string[i]!='\0'){printf("%c",string[i]);i++;}printf("\n");analyse();system("pasue");}void error(){printf("分析失败!\n");system("pause");exit(0); }void init() //初始化预测分析表-已经产生式右部反转过来{strcpy(M[0],"EiGT");strcpy(M[1],"E(GT");strcpy(M[2],"G+GT+");strcpy(M[3],"G)$");strcpy(M[4],"G#$");strcpy(M[5],"G-GT-");strcpy(M[6],"TiSF");strcpy(M[7],"T(SF");strcpy(M[8],"S+$");strcpy(M[9],"S*SF*");strcpy(M[10],"S)$");strcpy(M[11],"S#$");strcpy(M[12],"S/SF/");strcpy(M[13],"S-$");strcpy(M[14],"Fii");strcpy(M[15],"F()E(");}int judge(char x,char b){for(int i=0;i<16;i++){if(M[i][0]==x && M[i][1]==b){record=i;return 1;}}return 0;}void analyse(){int mark1=0;a=string[count];X=stack[top];top--;for(int i=0;i<=8;i++){if(X==Vt[i]){if(X==a){count++;}else error();mark1=1;break;}}if(mark1==0){if(X=='#'){if(X==a){printf("分析成功!\n");system("pause");exit(0);}else error();}if(X!='#'){if(!judge(X,a)){error();}else{for(int i=2;i<5;i++){if(M[record][i]!='\0' && M[record][i]!='$'){top++;stack[top]=M[record][i];}}}}}step++;printf("%d\t\t",step);for(int i=0;i<=top;i++){printf("%c",stack[i]);}printf("\t\t");i=count;while(string[i]!='\0'){printf("%c",string[i]);i++;}printf("\n");analyse();}算符优先文法:#include <stdio.h> #include <string.h> #include <stdlib.h>char data[9][9]={ ' ','+','-','*','/','(',')','i','#','+','>','>','<','<','<','>','<','>','-','>','>','<','<','<','>','<','>','*','>','>','>','>','<','>','<','>','/','>','>','>','>','<','>','<','>','(','<','<','<','<','<','=','<',' ',')','>','>','>','>',' ','>',' ','>','i','>','>','>','>',' ','>',' ','>','#','<','<','<','<','<','','<','='};void analyse(char a[],int n){int i=0,j=0,k=0,t=0,h=0,g=0;char ch,r; //当前符号char A[30];//符号栈A[0]='#';ch=a[0];while(ch!='\0'){do{while(A[k]=='N'){k--;}while(A[k]!=data[0][j]){j++;}while(ch!=data[i][0]){i++;}r=data[j][i];if(r=='>'){g=k;if(A[g-1]=='N'){g--;A[g]='N';}elseA[g]='N';k=g;for(h=0;h<=g;h++){printf("%c",A[h]);}printf("\n");}else if(r=='='){if(k==0){printf("分析成功!\n");system("pause");return ;}else{printf("分析失败!\n");exit(0);}}i=0,j=0;}while(r!='<');g++;A[g]=ch;k=g;t++;ch=a[t];j=0,i=0;for(h=0;h<=k;h++){printf("%c",A[h]);}printf("\n");}}void main(){char a[30],B[30];FILE * fp;char c,ch;int i=0,j=1;printf("请输入待分析字符串:\n");for(;;){scanf("%s",a);if((fp=fopen("F://a.txt","r"))!=NULL)break;elseprintf("Error!\n");}while((c=fgetc(fp))!=EOF){B[i]=c;i++;}B[i]='\0';rewind(fp);ch=fgetc(fp);printf("%s\n",B);analyse(B,i);fclose(fp);}。
【编译原理实验】递归下降子程序设计
【编译原理实验】递归下降⼦程序设计实验内容给定CP语⾔中简单算术表达式⽂法G[E]:E→TE’E’→ATE’|εT→FT’T’→MFT’ |εF→(E) | iA → + | -M → * | /根据该⽂法,编写递归下降分析⼦程序。
【说明】:终结符号i为⽤户定义的简单变量,即专题1中标识符的定义。
实验要求(1)为每个⾮终结符号写⼀个函数,选择合适的数据结构来存储产⽣式规则。
(2)输⼊:是词法分析输出的⼆元组序列,即任意简单算术表达式经过专题1程序输出后得到的结果。
(3)输出:判定输⼊串是否为该⽂法定义的合法算术表达式。
(4)测试数据⾄少包含3组正确输⼊和2组错误输⼊。
设计思路先将上篇词法分析器的⼆元组输出作为输⼊读⼊到⼆维字符数组中,再将每个⼆元组的单词和编号提取出来存⼊结构体中(这⾥记录编号是为了能实现将题意中的i识别为任意的标识符)。
根据题⽬给出的产⽣式规则为每个⾮终结符号编写递归下降分析函数,使⽤变量p标记当前的单词并开始逐步分析,若分析过程中出错则直接停⽌。
若执⾏完所有的函数后p指向了结构体的末尾,则该输⼊串是该⽂法的合法算数表达式。
程序结构(1)主要数据结构:⼆维字符数组ch:⽤于读⼊输⼊的⼆元组。
结构体struct node{string str;string code;}:记录⼆元组中的单词及其编号。
(2)函数定义:void E():⾮终结符E的函数,输出E的产⽣式规则,并向下进⾏T()和E1()。
void E1():⾮终结符E’的函数,若此时的单词为“+”或“-”,则输出E’->ATE’这条产⽣式,并依次向下进⾏A()、T()和E1(),否则直接输出E’->ε。
void T():⾮终结符T的函数,输出T的产⽣式规则,并向下进⾏F()和T1()。
void T1():⾮终结符T’的函数,若此时的单词为“*”或“/”,则输出T’->MFT’这条产⽣式,并依次向下进⾏M()、F()和T1(),否则直接输出T’->ε。
编译原理递归子程序
#include<stdio.h>#include<conio.h>char str[50]; //保存输入的字符串char ch;int strLength=0; //字符串的长度int point=1; //标记当前判断的是第几个字符int T();int G();int F();int S();int wrong1(){ int i,j=1;for(i=1;i<strLength;i++){if(str[i]=='('){j=j+1;}if(str[i]==')'){j=j-1;}}if(j!=1){ printf("()需成对出现!\n");return 1;}}int wrong() //判断某些输入非法的情况{int i;for(i=1;i<strLength;i++) //不能两个i一起{if(str[i]==str[i+1]){printf("不能连续输入两个相同字符!\n");return 1;}}if(str[1]!='(' && str[1]!='i') //必须是以(或i开头{printf("首字符错误!\n");return 1;}if(str[strLength]!='i' && str[strLength]!=')') //必须是以)或i结尾{printf("最后一个字符错误!\n");return 1;}else return 0;}void nextchar() //前进一个字符函数{point++;ch=str[point];}int E() //E->TG{if(T()==1){if(G()==1) return 1;else return 0;}else return 0;}int G() //G->+TG|-TG G->ε{ch=str[point];if(ch=='+' || ch=='-'){nextchar();if(T()==1){if(G()==1) return 1;else return 0;}else return 0;}else return 1; //有ε的时候当ch无法配对也不能返回错误}int T() //T->FS{if(F()==1){if(S()==1) return 1;else return 0;}else return 0;}int S() //S->*FS|/FS S->ε{ch=str[point];if(ch=='*' || ch=='/'){nextchar();if(F()==1){if(S()==1) return 1;else return 0;}else return 0;}else return 1;//有ε的时候当ch无法配对也不能返回错误}int F() //F->(E) F->i{ch=str[point];if(ch=='('){nextchar();if(E()==1){if(ch==')'){nextchar();return 1;}else return 0;}else return 0;}else if(ch=='i'){nextchar();return 1;}else return 0;}void main(){int i;printf("\t递归下降分析程序\n");printf("*************************************************\n");printf("\t张英1104011024 11计本(1)班\n\n");printf("请输入待分析字符串(以#结束):");//输入提示scanf("%c",&ch);while(ch!='#'){strLength++;str[strLength]=ch;scanf("%c",&ch);}str[strLength+1]='#';printf("\n");if(wrong1()==1) //检查输入是否有误{printf("错误输入!\n");}else{if(wrong()==1) //初步检查输入是否合法{printf("输入错误!\n");}else{for(i=1;i<=strLength;i++)printf("%c",str[i]);ch=str[1];if(E()==1) printf(" 是合法符号串!\n");else printf(" 是非法符号串!\n");}}getch();}。
编译原理实验报告二递归下降语法分析程序 (1)
编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期:201 年 5 月 25 日一、实验目的通过设计、调试递归下降语法分析程序,实现用词法分析从源程序中分出各种单词并对词法分析程序提供的单词序列进行语法检查和结构分析,熟悉并掌握常用的语法分析方法。
明确语法分析器的功能,在词法分析的基础上进一步分析程序;加深对课堂教学的理解;提高语法分析方法的实践能力;通过本实验,应达到以下目标:1、掌握递归下降的结构模型。
2、掌握语法分析的实现方法。
3、上机调试编出的语法分析程序。
二、实验过程有了第一次的经验,这次还是先画出流程图。
流程图如下:三、实验结果语法分析实验成功。
赋值时少写数字:缺少括号时:附(txt文档内容):程序运行后写入的:四、讨论与分析这个程序是在实验一的基础上写的,用的递归下降的方法。
不止能识别,还能判断一些语法的正误。
刚看书上附录的代码时,头都大了,觉得自己完成不了。
但是真正一步一步看下去,画出了流程图,就很清晰明白了。
一个函数嵌套一个函数,一步一步往细处走,刚开始是大体轮廓,然后就深入,直到最低层的判断。
书上的程序还是有一些漏洞,比如要写多个语句时,if,for,while在语句内不能加括号,不然只能分析至第一个,遇到“}”就结束了,所以在txt文件里写程序代码的时候要注意不能加{},这样才可以全部printf出来。
五、附录:关键代码(给出适当注释,可读性高)全部代码附vc++,这里粘贴主程序,以及各类函数。
int TESTparse();int TESTscan();int program();int compound_stat();int statement();int expression_stat();int expression();int bool_expr();int additive_expr();int term();int factor();int if_stat();int while_stat();int for_stat();int write_stat();int read_stat();int declaration_stat();int declaration_list();int statement_list();int compound_stat();#include<stdio.h>#include<ctype.h>int TESTscan();int TESTparse();FILE *fin,*fout;void main(){int es=0;es=TESTscan();if(es>0)printf("词法分析有错!编译停止!\n");else{printf("词法分析成功!\n");}if(es==0){es=TESTparse();if(es==0)printf("语法分析成功!\n");elseprintf("语法分析错误!\n");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。
递归实验报告分析总结
递归实验报告分析总结递归是一种非常重要的编程思想和技巧,对于理解和解决问题具有非常大的帮助。
通过递归,我们可以将一个问题分解成为更小的子问题,从而简化问题的复杂度和难度。
在本次实验中,我深入学习了递归的原理和应用,并实践了一些递归算法。
通过这些实验,我对递归有了更深入和全面的理解,掌握了递归的使用方法和注意事项。
在实验中,我首先学习了递归的概念和原理。
递归是一种将大问题分解成小问题的算法思想,通过不断调用自己来解决问题。
递归算法通常包含两个部分:基本情况和递归情况。
基本情况是递归终止的条件,递归情况是递归调用自身的条件。
通过合理设置这两个条件,我们可以确保递归算法能够得到正确的结果并正常终止。
然后,我练习了递归的应用。
在实验中,我实现了一些常见的递归算法,如计算阶乘、斐波那契数列等。
通过这些实践,我更加熟悉了递归的写法和思维模式。
递归算法的核心思想是将大问题分解成小问题,然后通过递归调用解决这些小问题,最终得到整个问题的解。
这种思维模式非常灵活和高效,对于解决一些复杂和抽象的问题非常有帮助。
在实验过程中,我也遇到了一些递归算法的常见问题和注意事项。
例如,递归算法容易出现堆栈溢出的问题,因为每次递归调用都会占用一定的内存空间,如果递归层数过多,就容易导致栈溢出。
为了解决这个问题,我们可以在递归算法中加入递归深度的限制条件,或者考虑使用迭代算法等其他算法思想。
此外,递归算法的时间复杂度一般比较高,因为递归算法需要不断的调用自身,导致函数的调用次数非常多。
为了提高递归算法的效率,我们可以尝试使用尾递归优化、记忆化搜索等技巧。
尾递归优化是指在递归函数的最后一步调用中,直接返回递归函数的结果,而不再进行其他操作。
这样可以有效避免函数调用的堆栈积累,提高程序的性能。
总的来说,通过本次递归实验,我对递归算法有了更深入的理解和掌握。
递归是一种非常强大和灵活的算法思想,可以用来解决各种复杂的问题。
通过合理设置递归的基本情况和递归情况,我们可以通过递归算法简化问题的复杂度和难度,高效地解决问题。
编译原理实验递归下降分析器的设计(含源代码和运行结果)
《编译原理》实验报告实验3 递归下降分析器的设计姓名学号班级计科1001班时间: 2012/4/15 地点:文波同组人:无指导教师:朱少林实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写递归下降语法分析程序的方法。
实验内容a.运用所学知识,编程实现递归下降语法分析程序。
使用递归下降分析算法分析表达式是否符合下文法:exp → exp addop term | termAddop →+ | -term→ term mulop factor | factormulop → * | /factor → (exp) | id | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到id 和number的值。
b.从数据文件中读出符号串,输出表达式并给出其正误评判。
实验数据文件中应该有多个表达式,可能有正确的也应该有错误的表达式;表达式有形式简单的也应该有复杂的。
每个表达式写在一行,以回车结束。
实验环境软件:VC++6.0实验前准备1、方案设计:①准备模拟数据:本实验中使用“work..cpp”②程序思想:为了使用递归向下的分析,为每个非终结符根据其产生式写一个分析程序,由于写入读出的操作频繁。
所以程序中还有一个match(char t)函数,该函数是将字符写入文件打印输出同时从文件中读取下一个字符,而由于id和number可能是多个字符构成,故写了number()和id()来分析数字和标识符,它们的功能仅仅是把整个number或id完整的读取出来并写入文件,打印输出。
由于分析的文件中可能出现非法字符,而一旦发现非法字符就无需再接着分析,所以在每次读取一个字符时调用islegal函数判断是否是合法字符,并返回0或1.在main()函数中,while((lookahead=='\n'||lookahead==' ')&&lookahead!=EOF) fscanf(resource,"%c",&lookahead);是为了忽略分析文件中的换行或空格,之后进入分析阶段,根据返回值判断是否是合法的表达式。
python递归实验报告
python递归实验报告《Python递归实验报告》引言Python是一种功能强大的编程语言,它具有许多强大的特性,其中之一就是递归。
递归是一种解决问题的方法,通过将问题分解成更小的子问题来解决。
在本实验报告中,我们将探讨Python中递归的使用,并进行一些实验来展示其强大的功能。
递归的基本概念在计算机科学中,递归是一种解决问题的方法,其中函数调用自身来解决更小的子问题。
递归函数通常包含两部分:基本情况和递归情况。
基本情况是指最小的问题实例,它们可以直接解决而不需要再次调用函数。
递归情况是指问题的一般情况,它需要调用函数本身来解决更小的子问题。
Python中的递归Python是一种非常适合使用递归的语言,因为它具有简洁的语法和灵活的函数调用机制。
在Python中,函数可以直接调用自身,这使得编写递归函数变得非常简单。
此外,Python还提供了一些内置的递归函数,如`factorial`和`fibonacci`等,这些函数可以帮助我们更好地理解递归的工作原理。
实验设计与结果为了展示Python中递归的使用,我们设计了一些实验来演示其功能。
首先,我们编写了一个递归函数来计算阶乘。
通过不断调用函数本身,并将问题分解成更小的子问题,我们成功地计算出了给定数字的阶乘。
接下来,我们编写了一个递归函数来生成斐波那契数列。
通过递归调用函数来计算前两个数的和,并将结果作为下一个数的输入,我们成功地生成了斐波那契数列。
结论通过本次实验,我们深入了解了Python中递归的使用。
我们发现递归是一种非常强大的解决问题的方法,它可以帮助我们简洁地解决复杂的问题。
然而,递归也需要谨慎使用,因为它可能会导致性能问题和栈溢出。
因此,在实际应用中,我们需要仔细考虑是否使用递归来解决问题。
总而言之,Python中的递归是一种非常有用的功能,它可以帮助我们解决各种复杂的问题。
通过深入研究和实验,我们可以更好地理解递归的工作原理,并充分发挥其潜力。
编译原理-递归下降子程序-课程设计报告
编译原理课程设计报告2011 年 12 月 2 日设计题目 递归下降分析程序的实现 学号专业班级 计算机科学与技术学生姓名指导教师一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:递归下降分析程序的实现设计内容及要求:对文法 G: E→E+T|T构造出G的递归下降分析程序。
程序显示输出T→T*F|F匹配过程(即自上而下生成语法分析树的步骤,F→(E)|i 输出各匹配产生式序号即可)。
三、设计思路:(1)语法分析:语法分析是编译程序的核心部分,任务是分析一个文法的句子结构。
递归下降分析程序的实现的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。
(2)自上而下分析:从文法的开始符号出发,向下推导,推出句子。
可分为带“回溯”的和不带回溯的递归子程序(递归下降)分析方法。
它的主旨是对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下地为输入串建立一棵语法树。
或者说,为输入串寻找一个最左推导。
也即从文法的开始符号出发,反复使用各种产生式,寻找"匹配"的推导。
(3)递归下降分析法:对每一语法变量(非终结符)构造一个相应的子程序,每个子程序识别一定的语法单位,通过子程序间的信息反馈和联合作用实现对输入串的识别。
(4)分析过程中遇到的问题:a. 分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。
出错时,不得不“回溯”。
b.文法左递归问题。
含有左递归的文法将使自上而下的分析陷入无限循环。
(5)构造不带回溯的自上而下分析算法:a.要消除文法的左递归性:一个文法可以消除左递归的条件是①不含以 为右部的产生式②不含回路。
b.克服回溯,构造不带回溯的自上而下分析的文法条件(6)满足LL(1)文法的三个条件:①. 文法不含左递归,②. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。
递归实验报告
递归实验报告篇一:字符串,递归实验报告宁波工程学院电信学院计算机教研室实验报告一、实验目的1)熟悉串的定义和串的基本操作。
2)加深对串数据结构的理解,逐步培养解决实际问题的编程能力。
3)熟悉递归的定义和递归的算法设计。
4)加深对递归算法的理解,逐步培养解决实际问题的编程能力。
二、实验环境装有Visual C++6.0的计算机。
三、实验内容1、凯撒加密算法凯撒密码(caeser)是罗马扩张时期朱利斯?凯撒(Julius Caesar)创造的,用于加密通过信使传递的作战命令。
它将字母表中的字母移动一定位置而实现加密。
他的原理很简单,说到底就是字母与字母之间的替换。
每一个字母按字母表顺序向后移3位,如a加密后变成d,b加密后变成e,······x加密后变成a,y加密后变成b,z加密后变成c。
例如:“baidu”用凯撒密码法加密后字符串变为“edlgx”。
试写一个算法,将键盘输入的文本字符串(只包含a~z 的字符)进行加密后输出。
另写一个算法,将已加密后的字符串解密后输出。
提示:? 如果有字符变量c加密后则=’a’+(c-‘a’+3)%26? 采用顺序结构存储串,键盘输入字符串后保存到顺序串中;输出用顺序串的输出函数。
程序:#include#define MaxSize 100typedef struct //串的类型定义char ch[MaxSize];//存放串字符int len; //串长}SqString;void SetString(SqString &s) //设置源码{int i;printf("请输入原字符串:");scanf("%s",s.ch);for(i=0;s.ch[i]!='\0';i++); //计算串的长度s.len=i;}void TranString(SqString s,SqString &t)//开始加密{int i;for(i=0;i {if(s.ch[i]>='a'&&s.ch[i] t.ch[i]='a'+(s.ch[i]-'a'+3)%26; //将每一个字母按字母表顺序向后移3位elset.ch[i]=s.ch[i];//如果字符不是字母a~z,则原样保留}t.len=s.len;}void RecoverString(SqString s,SqString &t) //开始解密{int i;for(i=0;i {if(s.ch[i]>='d'&&s.ch[i] t.ch[i]=s.ch[i]-3;else if(s.ch[i]>='a'&&s.ch[i] t.ch[i]=s.ch[i]+23;elset.ch[i]=s.ch[i]; //如果字符不是字母a~z,则原样保留 }t.len=s.len;}void DispString(SqString s) //输出字符串int i=0;while(i {printf("%c",s.ch[i]); //字母的逐个输出i++;}printf("\n");}int main(){SqString s1,s2,s3; //s1是源码,s2是加密后密码,s3是解密后密码SetString(s1); //输入字符串DispString(s1); //输出字符串TranString(s1,s2);//加密DispString(s2); //加密后输出字符串RecoverString(s2,s3);//解密DispString(s3); //解密后输出字符串return 0;}按实验要求首先定义顺序串,实验的难点在于密码的加密和解密的实现,特别是再解密时,字母的溢出问题,在参考网上程序后很好地解决了这个问题。
递归算法的实验报告
递归算法的实验报告递归算法的实验报告引言:递归算法作为一种重要的问题解决方法,在计算机科学领域发挥着重要的作用。
本次实验旨在通过实际编程实现递归算法,并对其性能进行评估和分析,以探讨递归算法的优势和局限性。
一、递归算法的基本原理递归算法是一种将问题分解为更小规模的子问题来解决的方法。
其基本原理是在解决一个问题的过程中,调用自身来解决更小规模的相同问题,直到达到基本情况,然后将结果合并得到最终解。
递归算法的核心是找到递归的边界条件和递推关系。
二、实验设计与实现本次实验选择了经典的递归问题——计算斐波那契数列。
斐波那契数列是一个典型的递归问题,其定义如下:F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) (n >= 2)。
为了实现递归算法,我们设计了一个名为fibonacci的函数。
该函数接受一个整数n作为输入,返回斐波那契数列的第n个元素。
函数的实现如下:```pythondef fibonacci(n):if n == 0:return 0elif n == 1:return 1else:return fibonacci(n-1) + fibonacci(n-2)```三、实验结果与分析我们首先对fibonacci函数进行了功能测试,通过计算前几个斐波那契数列的元素来验证函数的正确性。
实验结果表明,函数能够正确计算出斐波那契数列的元素。
接下来,我们对递归算法的性能进行了评估。
我们分别计算了斐波那契数列的前30个元素,并记录了每次计算所花费的时间。
实验结果显示,随着n的增大,递归算法的计算时间呈指数级增长。
这是因为递归算法在计算过程中会重复计算相同的子问题,导致计算量呈指数级增加。
因此,在处理大规模问题时,递归算法的效率较低。
为了进一步验证递归算法的性能,我们将fibonacci函数与迭代算法进行了比较。
迭代算法是一种通过循环来解决问题的方法,相比递归算法,迭代算法不会出现重复计算的情况。
【编译原理实验】递归子程序法
【编译原理实验】递归⼦程序法⽂法:E->TGG->+TG|-TG|^T->FSS->*FS|/FS|^F->i|(E)表达式串的每个数符必须以i代替(懒得优化)1 #include<stdio.h>2 #include<iostream>3 #include<string.h>4 #include<stdlib.h>5using namespace std;678int step_Counter=0;//计数第⼏步9char in[82];//存储输⼊串10char analized_str[82];int top=-1;//存储分析过的字符串11char *ch;//指向当前正在分析的字符12char * left_Function(char[]);//计算并返回剩余串的起始地址⽼师请注意:left:剩余,不是左边1314char finished_dri[82];int t_f=-1;//推导式中的已经完成分析的字符串和其栈顶指针15char unfinished_dri[82];int t_uf=-1;//推到是中的未完成分析的字符串和其栈顶指针16char record_div[10000];//记录推导过程的数组17void add(char arr[],char arr1[]);//add⽅法将未完成部分的栈倒序装⼊record_div记录数组1819int E();20int T();21int F();22int S();23int G();2425int main()26 {27 cout<<"请输⼊长度不⼤于81的表达式:";28 cin>>in;29//cout<<strlen(in)<<endl;30char const_str[10]="分析串";31 printf("步骤\t⽂法\t%-40s分析字符\t剩余串\n",const_str);32 ch=in;3334 unfinished_dri[++t_uf]='E';//初始化⾮终结符栈35 strcat(record_div,"E\0");//记录第⼀条推导363738int flag=E();39if(flag==0)40 cout<<endl<<"\t\t\tERROR !"<<endl;41else42 {43 cout<<endl<<"\t\t\tACCEPT !"<<endl;44 cout<<"推导过程:"<<endl;45 cout<<record_div<<endl;46 }47return0;48 }49int E()50 {51 t_uf--;//⾮终结符栈栈顶元素出栈52 unfinished_dri[++t_uf]='G';//⾮终结符倒序⼊⾮终结符栈53 unfinished_dri[++t_uf]='T';5455 unfinished_dri[t_uf+1]='\0';//给栈顶元素增加结束标识,以免出错56 strcat(record_div,"\n=>");//以下三条是记录推导的语句57 strcat(record_div,finished_dri);58 add(record_div,unfinished_dri);//因为⾮终结符栈是倒序的,所以不能直接使⽤strcat函数,要进⾏⼀次颠倒才能进⾏连接 59//以上解释使⽤于下⾯的⼏个函数,故不再解释606162 step_Counter++;//标识第⼏步的变量63 analized_str[top+1]='\0';//为第⼀次调⽤此函数做准备64char * left_str=left_Function(analized_str);//得到剩余串的起始地址65 printf("%d\tE=>TG\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str);//格式打印输出66//cout<<"调⽤了函数E"<<endl;67if(*ch=='#')68return1;69int flag=T();70if(flag==0)71return0;72else73 {74 flag=G();75if(flag==0)76return0;77else78 {79return1;80 }81 }82 }83int T()84 {85 t_uf--;86 unfinished_dri[++t_uf]='S';87 unfinished_dri[++t_uf]='F';8889 unfinished_dri[t_uf+1]='\0';90 finished_dri[t_f+1]='\0';91 strcat(record_div,"\n=>");92 strcat(record_div,finished_dri);93 add(record_div,unfinished_dri);949596 step_Counter++;97 analized_str[top+1]='\0';98char * left_str=left_Function(analized_str);99 printf("%d\tT=>FS\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 100//cout<<"调⽤了函数T"<<endl;101if(*ch=='#')102return1;103int flag=F();104if(flag==0)105return0;106else107 {108 flag=S();109if(flag==0)110return0;111else112 {113return1;114 }115 }116 }117int F()118 {119if(*ch=='#')120return1;121//cout<<"调⽤了函数F"<<endl;122if(*ch=='i')123 {124 t_uf--;//未完成的部分栈顶出栈125 finished_dri[++t_f]='i';//完成的部分⼊栈126 unfinished_dri[t_uf+1]='\0';127 finished_dri[t_f+1]='\0';128 strcat(record_div,"\n=>");129 strcat(record_div,finished_dri);130 add(record_div,unfinished_dri);131132133134 top++;135 analized_str[top]='i';136 analized_str[top+1]='\0';137 step_Counter++;138char * left_str=left_Function(analized_str);139 printf("%d\tF=>i\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str);140//cout<<++step_Counter<<"i匹配"<<endl;141 ch++;142return1;143 }144else if(*ch=='(')145 {146147148 t_uf--;//未完成的部分F栈顶出栈149 finished_dri[++t_f]='(';//完成的部分⼊栈150 unfinished_dri[++t_uf]=')';//未完成的部分倒序⼊栈151 unfinished_dri[++t_uf]='E';//未完成的部分倒序⼊栈152 unfinished_dri[t_uf+1]='\0';153 finished_dri[t_f+1]='\0';154 strcat(record_div,"\n=>");155 strcat(record_div,finished_dri);156 add(record_div,unfinished_dri);157158159 top++;160 analized_str[top]='(';161 analized_str[top+1]='\0';162 step_Counter++;163char * left_str=left_Function(analized_str);164 printf("%d\tF=>(E)\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 165//cout<<++step_Counter<<"(匹配"<<endl;166 ch++;167int flag=E();168if(flag==0)169return0;170else171 {172if(*ch==')')173 {174 t_uf--;//完成部分出栈175 finished_dri[++t_f]=')';//完成部分⼊栈176177178 unfinished_dri[t_uf+1]='\0';179 finished_dri[t_f+1]='\0';180 strcat(record_div,"\n=>");181 strcat(record_div,finished_dri);182 add(record_div,unfinished_dri);183184 top++;185 analized_str[top]=')';186 analized_str[top+1]='\0';187 step_Counter++;188char * left_str=left_Function(analized_str);189 printf("%d\tF=>(E)\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 190// cout<<++step_Counter<<")匹配"<<endl;191 ch++;192return1;193 }194else195return0;196 }197 }198else199 {200return0;201 }202 }203int S()204 {205//cout<<"调⽤了函数S"<<endl;206if(*ch=='*')207 {208 t_uf--;//⾮终结符S出栈209 finished_dri[++t_f]='*';//终结符⼊栈210 unfinished_dri[++t_uf]='S';//⾮终结符倒序⼊栈211 unfinished_dri[++t_uf]='F';212 unfinished_dri[t_uf+1]='\0';213 finished_dri[t_f+1]='\0';214 strcat(record_div,"\n=>");215 strcat(record_div,finished_dri);216 add(record_div,unfinished_dri);217218219220 top++;221 analized_str[top]='*';222 analized_str[top+1]='\0';223 step_Counter++;224char * left_str=left_Function(analized_str);225 printf("%d\tS=>*FS\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 226// cout<<++step_Counter<<"*匹配"<<endl;227 ch++;228int flag=F();229if(flag==0)230return0;231else232 {233 flag=S();234if(flag==1)235return1;236else237return0;238 }239 }240else if(*ch=='/')241 {242 t_uf--;//⾮终结符S出栈243 finished_dri[++t_f]='/';//终结符⼊栈244 unfinished_dri[++t_uf]='S';245 unfinished_dri[++t_uf]='F';246 unfinished_dri[t_uf+1]='\0';247 finished_dri[t_f+1]='\0';248 strcat(record_div,"\n=>");249 strcat(record_div,finished_dri);250 add(record_div,unfinished_dri);251252253 top++;254 analized_str[top]='/';255 analized_str[top+1]='\0';256 step_Counter++;257char * left_str=left_Function(analized_str);258 printf("%d\tS=>/FS\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 259// cout<<++step_Counter<<"/匹配!"<<endl;260 ch++;261int flag=F();262if(flag==0)263return0;264else265 {266 flag=S();267if(flag==1)268return1;269else270return0;271 }272 }273else274 {275 t_uf--;//⾮终结符S出栈276 finished_dri[++t_f]='^';//终结符⼊栈277 unfinished_dri[t_uf+1]='\0';278 finished_dri[t_f+1]='\0';279 strcat(record_div,"\n=>");280 strcat(record_div,finished_dri);281 add(record_div,unfinished_dri);282283284 step_Counter++;285char * left_str=left_Function(analized_str);286 printf("%d\tS=>^\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 287return1;288 }289 }290int G()291 {292//cout<<"调⽤了函数G"<<endl;293if(*ch=='+')294 {295 t_uf--;//⾮终结符S出栈296 finished_dri[++t_f]='+';//终结符⼊栈297 unfinished_dri[++t_uf]='G';298 unfinished_dri[++t_uf]='T';299 unfinished_dri[t_uf+1]='\0';300 finished_dri[t_f+1]='\0';301 strcat(record_div,"\n=>");302 strcat(record_div,finished_dri);303 add(record_div,unfinished_dri);304305306307 top++;308 analized_str[top]='+';309 analized_str[top+1]='\0';310 step_Counter++;311char * left_str=left_Function(analized_str);312 printf("%d\tG=>+TG\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 313// cout<<++step_Counter<<"+匹配"<<endl;314 ch++;315int flag=T();316if(flag==0)317return0;318else319 {320 flag=G();321if(flag==1)322return1;323else324return0;325 }326 }327else if(*ch=='-')328 {329330 t_uf--;//⾮终结符S出栈331 finished_dri[++t_f]='-';//终结符⼊栈332 unfinished_dri[++t_uf]='G';333 unfinished_dri[++t_uf]='T';334 unfinished_dri[t_uf+1]='\0';335 finished_dri[t_f+1]='\0';336 strcat(record_div,"\n=>");337 strcat(record_div,finished_dri);338 add(record_div,unfinished_dri);339340341342 top++;343 analized_str[top]='-';344 analized_str[top+1]='\0';345 step_Counter++;346char * left_str=left_Function(analized_str);347 printf("%d\tG=>-TG\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 348// cout<<++step_Counter<<"-匹配"<<endl;349 ch++;350int flag=T();351if(flag==0)352return0;353else354 {355 flag=G();356if(flag==1)357return1;358else359return0;360 }361 }362else363 {364365 t_uf--;366 finished_dri[++t_f]='^';367 unfinished_dri[t_uf+1]='\0';368 finished_dri[t_f+1]='\0';369 strcat(record_div,"\n=>");370 strcat(record_div,finished_dri);371 add(record_div,unfinished_dri);372373 step_Counter++;374char * left_str=left_Function(analized_str);375 printf("%d\tG=>^\t%-40s%c\t\t%s\n",step_Counter,analized_str,*ch,left_str); 376return1;377 }378 }379380381char * left_Function(char aim[])//获取剩余的字符串⽼师请注意:left:剩余,不是左边382 {383char * left;384int length=strlen(aim);385 left=&in[length];386return left;387 }388389void add(char aim[],char source[])390 {391char temp[1000];int top=-1;392int len=strlen(source);393for(int i=len-1;i>=0;i--)394 {395 temp[++top]=source[i];396 }397 temp[++top]='\0';398 strcat(aim,temp);399 }400401//测试数据:((i*i+i)*i/i)-(i*i*(i+i)/i-i-i)*i/i+i-i# View Code。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验
姓名:尹莉
学号:E31314022 专业:13级网络工程
语法分析器1
一、实现方法描述
所给文法为G【E】;
E->TE’
E’->+TE’|空
T->FT’
T’->*FT’|空
F->i|(E)
递归子程序法:
首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。
定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。
从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。
在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。
以分号作为结束符。
二、实现代码
头文件shiyan3.h
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define num 100
char vocabulary[num];
char *ch;
void judge_EE();
void judge_T();
void judge_TT();
void judge_F();
源文件
#include"shiyan3.h"
void judge_E()
{
if(*ch==';')
{
cout<<"该句子符合此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
else
if(*ch=='('||*ch=='i')
{
judge_T();
judge_EE();
}
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
{
if(*ch==';')
{
cout<<"该句子符合此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
if(*ch=='+')
{
ch++;
judge_T();
judge_EE();
}
else
if(*ch=='#'||*ch==')')
return;
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
void judge_T()
{
if(*ch==';')
{
cout<<"该句子符合此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
if(*ch=='('||*ch=='i')
{
judge_F();
judge_TT();
}
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
void judge_TT()
{
if(*ch==';')
{
cout<<"该句子符合此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
if(*ch=='*')
{
ch++;
judge_F();
judge_TT();
}
else
if(*ch==')'||*ch=='+'||*ch=='#')
return;
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
void judge_F()
{
if(*ch==';')
{
cout<<"该句子符合此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
if(*ch=='(')
{
ch++;
judge_E();
if(*ch==')')
{
ch++;
}
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
else
if(*ch=='i')
{
ch++;
//cout<<*ch;
}
else
{
cout<<"该句子不匹配此文法!"<<endl;
int a=0;
cout<<"按1结束程序"<<endl;
cin>>a;
if(a==1)
exit(0);
}
}
void main()
{
//char *ch;
cout<<"**********************欢迎使用语法分析器************************"<<endl;
cout<<"请输入一个句子:"<<endl;
cin.getline(vocabulary,15);
ch=vocabulary;
judge_E();
cout<<endl;
cout<<"************************结束使用,再见!**************************"<<endl;
}
三、运行结果
四、心得体会
此次实验使用的是递归子程序法,用这个方法最大的问题就是函数里
的递归调用,一不小心就把人绕糊涂了。
所以在写的时候注意力需十分集中。
虽然在函数的实际调用过程中比较复杂,但是只要理清思路,在编写代码时,根据产生式来判断调用,每个部分都相对简单一点。