编译原理实验-递归子程序法
编译原理用递归下降法进行表达式分析实验报告
![编译原理用递归下降法进行表达式分析实验报告](https://img.taocdn.com/s3/m/0b3bbb81f121dd36a32d825b.png)
《编译原理》课程实验报告题目用递归下降法进行表达式分析专业班级学号姓名一.实验题目用递归下降法进行语法分析的方法二.实验日期三.实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四.实验内容(实验要求)词法分析程序和语法分析程序已经提供。
此语法分析程序能够实现:正确的输入可以给出结果。
例:输入表达式串为:(13+4)*3则应给出结果为51。
要求:(1)读懂源代码,理解内容写入实验报告(语法分析及语法分析程序和词法分析程序的接口)(2)把语法分析中使用的yyval,用yytext实现。
(3)在语法分析程序用加入出错处理(尽量完整,包括出错的位置,出错的原因,错误的重定位)五.实验步骤1.生成lex.yy.c文件:将已给的mylexer.l文件打开,先理解,然后再在DOS环境下用flex运行此文件,这时会生成一个lex.yy.c文件。
2.创建工程:打开C-Free 5.0(注:用C-Free 4.0会出错),在菜单栏中的“工程(project)”菜单下选择“新建”;在新建工程中选择“控制台程序”,添加工程名字为“myleb”和保存位置后点“确定”;第1步选择“空的程序”点“下一步”;第2步再点“下一步”;最后点击“完成”。
3.在创建的工程中添加文件:在Source files文件夹中添加之前生成的lex.yy.c文件和syn.c文件,然后找到parser.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
如图:4.理解并修改syn.c文件:首先,将num = yyval.intval修改成num = atoi(yytext);将num = yyval.fval修改成num = atof(yytext)。
可以这样修改的原因:在.l文件中所写的规则中,有{DIGIT}+ { yyval.intval = atoi(yytext);return INTEGER; }和{DIGIT}+"."{DIGIT}* {yyval.fval = atof(yytext); return DOUBLE; } 这两句代码,其中yyval.intval = atoi(yytext)和yyval.fval = atof(yytext)就说明两者可以相互替代。
编译原理实验语法器递归下降子程序实现解析
![编译原理实验语法器递归下降子程序实现解析](https://img.taocdn.com/s3/m/1bdfa0ef08a1284ac8504335.png)
编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机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 输出:思考问题回答:在递归下降子程序中要注意对于错误情况的处理,以防程序无限循环,无法结束。
编译原理-实验报告2-递归下降分析法
![编译原理-实验报告2-递归下降分析法](https://img.taocdn.com/s3/m/02578797ba1aa8114531d91b.png)
计算机硬件实验室实验报告一、实验目的:根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验要求:对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:(1)递归下降分析程序,编制人:姓名,学号,班级(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i#(3)输出结果:i+i*i#为合法符号串备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);三、实验过程:程序设计:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
程序编写:1.定义部分:定义常量、变量、数据结构。
2.初始化:从文件将输入符号串输入到字符缓冲区中。
3.利用递归下降分析法,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。
四、实验结果(1)程序流程图(2)运行结果示例程序:#include <>#include<>#include<>#include<>char a[50] ,b[50],d[500],e[10];char ch;int n1,i1=0,flag=1,n=5;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();void main() /*递归分析*/{int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';printf("递归下降分析程序,编制人:武普泉,20号,1020562班\n");printf("输入一以#结束的符号串(包括+ - * / ( ) i #,且长度小于50):");do{scanf("%c",&ch);a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];printf("文法\t分析串\t\t\t分析字符\t\t剩余串\n");f=E1();if(f==0) return ;if (ch=='#'){ printf("accept\n");p=0;x=d[p];// {// printf("%c",x);p=p+1;x=d[p]; /*输出推导式*/ // }while(a[p]!='#')printf("%c",a[p++]);printf("为合法字符!\n");}else {// printf("error\n");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");printf("回车返回\n");getchar();getchar();return;}printf("\n");printf("回车返回\n");getchar();getchar();}int E1(){ int f,t;printf("E-->TG\t");flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int E(){ int f,t;printf("E-->TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#';output();flag=1;input();input1();f=T();if (f==0)return(0);t=G();if (t==0) return(0);else return(1);}int T(){ int f,t;printf("T-->FS\t");e[0]='T';e[1]='=';e[2]='>';e[3]='F';e[4]='S';e[5]='#';output();flag=1;input();input1();f=F();if (f==0)return(0);t=S();if (t==0) return(0);else return(1);}int G(){int f;if(ch=='+'){b[i1]=ch;printf("G-->+TG\t");e[0]='G';e[1]='=';e[2]='>';e[3]='+';e[4]='T';e[5]='G';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0)return(0);f=G();if(f==0)return 0;else return 1;}else if(ch=='-'){b[i1]=ch;printf("G-->-TG\t");e[0]='G';e[1]='=';e[2]='>';e[3]='-';e[4]='T';e[5]='G';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0){// printf("G=%d\n",f);return(0);}f=G();if(f==0)return 0;else return 1;}else{printf("G-->^\t");e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;input();input1();return(1);}}int S(){int f,t;if(ch=='*'){b[i1]=ch;printf("S-->*FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='*';e[4]='F';e[5]='S';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0)return(0);t=S();if (t==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]='F';e[5]='S';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0)return(0);t=S();if (t==0)return(0);else return(1);}else{printf("S-->^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}}int F(){ int f;int j;if(ch=='('){b[i1]=ch;printf("F-->(E)\t");e[0]='F';e[1]='=';e[2]='>';e[3]='(';e[4]='E';e[5]=')';e[6]='#';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");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");return(0);}}else if(ch=='i'){b[i1]=ch;printf("F-->i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {printf("error\n");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");return(0);}return(1);}void input(){int j=0;for (;j<=i1-flag;j++)printf("%c",b[j]); /*输出分析串*/printf("\t\t\t");printf("%c\t\t\t",ch); /*输出分析字符*/ }void input1(){int j;for (j=i1+1-flag;j<n1;j++)printf("%c",a[j]); /*输出剩余字符*/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]='#';n=n+2;i=n;i=i-2;while(d[i]!='>'&&i!=0) i=i-1;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]='#';}。
汇编语言——子程序的递归
![汇编语言——子程序的递归](https://img.taocdn.com/s3/m/861f17878762caaedd33d49c.png)
递归子程序的基本模式是: 若参数满足问题的最简条件,则 直接求解答案,作为本次子程序调用的结果 否则 求解分解出的小问题中可直接求解者; 对小问题中的同型者,以较简单的参数调用自身; 把各个小问题的答案拼装,作为本次调用结果。 下面是Pascal语言的一个递归子程序,用于求n!。 FUNCTION fact(n:INTEGER):INTEGER; BEGIN IF n<=1 THEN fact:=1 ELSE fact:=n*fact(n-1); END;
0001 0002 03F0 001A 0001 0002 0003 03FA 001A 0002 003D 0003 0000 0040 0003 (g)
处理完最简情况后,已在AX中准备好最深层调用的结 果,即出口参数值,再由第13行转到第20行,连续三条出栈 指令,从图6.7(g)所示的栈中依次取出三个字0001、0002和 03F0H,分别给DX、BX及BP,此时栈的情况又回到图6.7(f)。 现在,递归调用开始从最深一层逐步返回,并在每一层返回 过程中要完成本层答案的组装。在求阶乘问题中组装就是做 本层参数与深一层调用结果的乘法操作。
code SEGMENT CS:CODE,SS:s fact PROC NEAR PUSH BP MOV BP,SP PUSH BX PUSH DX
MOV BX,[BP+4] CMP BX,1 JG f1
; (9)0005 ;(10)0008 ;(11)000B ;(12)000D ;(13)0010 ;(14)0013 ;(15)0015 ;(16)0016 ;(17)0017 ;(18)001A ;(19)001B
模块化程序设计是编写大型软件时的常用方法。汇编 语言的一个模块由若干个段和一个结束伪指令END构成, 并且只有主模块的END伪指令后面需要入口地址。各模块 可以各自用汇编程序进行翻译,得到各自的目标文件,再 用LINK软件连接成一个完整的程序。各个模块间相互通讯 时,要用PUBLIC和EXTRN伪指令说明标识符是公共的或 外部的。除了建立子程序库文件(.LIB)之外,还有其它方法 可以实现多个程序段间的拼接。 汇编语言的子程序可以进行递归调用,递归子程序在 编写上有其特殊性,需要把问题进行分解,找出最简情况, 对最简情况下的问题直接求解,非最简情况则递归调用进 一步分解。分解后的各个子问题最终还要拼装在一起,构 成原问题的解。
编译原理实验报告:实验二编写递归下降语法分析程序
![编译原理实验报告:实验二编写递归下降语法分析程序](https://img.taocdn.com/s3/m/049acd45f242336c1eb95eed.png)
编译原理实验报告实验名称:实验二编写递归下降语法分析器实验类型:验证型实验指导教师:何中胜专业班级:13软件四姓名:丁越学号:13030504电子邮箱:862245792@实验地点:秋白楼B720实验成绩:日期:2016年4 月1 日一、实验目的通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。
通过本实验,应达到以下目标:1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
2、掌握词法分析的实现方法。
3、上机调试编出的语法分析程序。
二、实验过程1、分析对象分析算术表达式的 BNF 定义如下:〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉〈项〉→〈因式〉|〈项〉*〈因式〉|〈项〉/〈因式〉〈因式〉→〈变量〉│(〈算术表达式〉)〈变量〉→i用符号表示如下:E→T|E+T|E-TT→F|T*F|T/FF→i│(E)递归下降分析程序实现思想简单易懂。
程序结构和语法产生式有直接的对应关系。
因为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。
递归下降分析程序的实现思想是:识别程序由一组子程序组成。
每个子程序对应于一个非终结符号。
每一个子程序的功能是:选择正确的右部,扫描完相应的字。
在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。
自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。
分析速度慢。
而无回溯的自上向下分析技术,当选择某非终结符的产生时,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。
无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
无左递归:既没有直接左递归,也没有间接左递归。
无回溯:对于任一非终结符号 U 的产生式右部x1|x2|…|xn,其对应的字的首终结符号两两不相交。
2. 递归下降语法分析流程图实验分为五个模块,分别是:E( )函数,E1( )函数,T( )函数,T1( )函数,F( )函数。
编译原理语法分析递归下降子程序实验报告
![编译原理语法分析递归下降子程序实验报告](https://img.taocdn.com/s3/m/bf1050ceac51f01dc281e53a580216fc700a53dc.png)
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
编译原理实验-递归子程序法
![编译原理实验-递归子程序法](https://img.taocdn.com/s3/m/dfd70c3a5a8102d276a22fbe.png)
递归子程序法:#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);}。
【编译原理实验】递归下降子程序设计
![【编译原理实验】递归下降子程序设计](https://img.taocdn.com/s3/m/22540153a9956bec0975f46527d3240c8447a1ef.png)
【编译原理实验】递归下降⼦程序设计实验内容给定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’->ε。
编译原理递归子程序
![编译原理递归子程序](https://img.taocdn.com/s3/m/6c7d073da32d7375a417806d.png)
#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();}。
编译原理之递归下降语法分析程序(实验)
![编译原理之递归下降语法分析程序(实验)](https://img.taocdn.com/s3/m/aed6ff1b78563c1ec5da50e2524de518964bd32f.png)
编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤C语⾔编制递归下降分析程序,并对简单语⾔进⾏语法分析。
编制⼀个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
⼆、实验原理每个⾮终结符都对应⼀个⼦程序。
该⼦程序根据下⼀个输⼊符号(SELECT集)来确定按照哪⼀个产⽣式进⾏处理,再根据该产⽣式的右端:每遇到⼀个终结符,则判断当前读⼊的单词是否与该终结符相匹配,若匹配,再读取下⼀个单词继续分析;不匹配,则进⾏出错处理每遇到⼀个⾮终结符,则调⽤相应的⼦程序三、实验要求说明输⼊单词串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:输⼊begin a:=9;b:=2;c:=a+b;b:=a+c end #输出success输⼊a:=9;b:=2;c:=a+b;b:=a+c end #输出‘end' error四、实验步骤1.待分析的语⾔的语法(参考P90)2.将其改为⽂法表⽰,⾄少包含–语句–条件–表达式E -> E+T | TT -> T*F | FF -> (E) | i3. 消除其左递归E -> TE'E' -> +TE' | εT -> FT'T' -> *FT' | εF -> (E) | i4. 提取公共左因⼦5. SELECT集计算SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *}SELECT(E'->+TE')=FIRST(+TE')={+}SELECT(E'->ε)=follow(E')=follow(E)={#, )}SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i}SELECT(T'->*FT')=FRIST(*FT')={*}SELECT(T'->ε)=follow(T')=follow(T)={#, ), +}SELECT(F->(E))=FRIST((E)) ={(}SELECT(F->i)=FRIST(i) ={i}6. LL(1)⽂法判断 其中SELECT(E'->+TE')与SELECT(E'->ε)互不相交,SELECT(T'->*FT')与SELECT(T'->ε)互不相交,SELECT(F->(E))与SELECT(F->i)互不相交,故原⽂法为LL(1)⽂法。
递归子程序实验报告(3篇)
![递归子程序实验报告(3篇)](https://img.taocdn.com/s3/m/7679d9031fd9ad51f01dc281e53a580216fc50e5.png)
第1篇一、实验目的1. 理解递归的概念和原理;2. 掌握递归子程序的设计方法;3. 学会递归子程序在实际问题中的应用;4. 提高编程能力和算法设计能力。
二、实验原理递归是一种编程技巧,它允许函数调用自身。
递归子程序通常具有以下特点:1. 递归基准:确定递归结束的条件;2. 递归步骤:确定递归调用时的参数变化;3. 递归终止:当递归基准条件满足时,递归调用停止。
递归子程序在解决一些具有“分治”特点的问题时非常有效,如阶乘计算、斐波那契数列、汉诺塔等。
三、实验内容本次实验主要设计以下递归子程序:1. 计算阶乘;2. 计算斐波那契数列;3. 求汉诺塔问题的解。
1. 计算阶乘阶乘是指一个正整数n的阶乘,记作n!,表示为n×(n-1)×(n-2)×...×1。
计算阶乘的递归子程序如下:```cint factorial(int n) {if (n == 0) {return 1;} else {return n factorial(n - 1);}}```2. 计算斐波那契数列斐波那契数列是指这样一个数列:0, 1, 1, 2, 3, 5, 8, 13, ...,其中第n项是前两项的和。
计算斐波那契数列的递归子程序如下:```cint fibonacci(int n) {if (n == 0 || n == 1) {return n;} else {return fibonacci(n - 1) + fibonacci(n - 2);}}```3. 求汉诺塔问题的解汉诺塔问题是一个经典的递归问题,其目的是将n个盘子从一个柱子移动到另一个柱子,每次只能移动一个盘子,且在移动过程中大盘子不能放在小盘子上面。
求汉诺塔问题的解的递归子程序如下:```cvoid hanoi(int n, char from_rod, char to_rod, char aux_rod) {if (n == 1) {printf("Move disk 1 from rod %c to rod %c\n", from_rod, to_rod); return;}hanoi(n - 1, from_rod, aux_rod, to_rod);printf("Move disk %d from rod %c to rod %c\n", n, from_rod, to_rod); hanoi(n - 1, aux_rod, to_rod, from_rod);}```四、实验步骤1. 编写计算阶乘的递归子程序;2. 编写计算斐波那契数列的递归子程序;3. 编写求汉诺塔问题的解的递归子程序;4. 测试递归子程序的正确性;5. 分析递归子程序的性能。
编译原理实验报告二递归下降语法分析程序 (1)
![编译原理实验报告二递归下降语法分析程序 (1)](https://img.taocdn.com/s3/m/2278efa02cc58bd63186bd72.png)
编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期: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");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。
编译原理递归下降子程序 (1)
![编译原理递归下降子程序 (1)](https://img.taocdn.com/s3/m/c33ee17633687e21af45a9a7.png)
递归下降分析器计算机093-20 李盼一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求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语句的嵌套,将错误分为三种类型。
编译原理实验二:LL(1)语法分析器
![编译原理实验二:LL(1)语法分析器](https://img.taocdn.com/s3/m/c625d5e6b9f67c1cfad6195f312b3169a451ea8c.png)
编译原理实验⼆:LL(1)语法分析器⼀、实验要求 1. 提取左公因⼦或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下⾯我贴出实验的⼀些关键代码和算法思想。
⼆、基于预测分析表法的语法分析 2.1 代码结构 2.1.1 Grammar类 功能:主要⽤来处理输⼊的⽂法,包括将⽂法中的终结符和⾮终结符分别存储,检测直接左递归和左公因⼦,消除直接左递归,获得所有⾮终结符的First集,Follow集以及产⽣式的Select集。
#ifndef GRAMMAR_H#define GRAMMAR_H#include <string>#include <cstring>#include <iostream>#include <vector>#include <set>#include <iomanip>#include <algorithm>using namespace std;const int maxn = 110;//产⽣式结构体struct EXP{char left; //左部string right; //右部};class Grammar{public:Grammar(); //构造函数bool isNotTer(char x); //判断是否是终结符int getTer(char x); //获取终结符下标int getNonTer(char x); //获取⾮终结符下标void getFirst(char x); //获取某个⾮终结符的First集void getFollow(char x); //获取某个⾮终结符的Follow集void getSelect(char x); //获取产⽣式的Select集void input(); //输⼊⽂法void scanExp(); //扫描输⼊的产⽣式,检测是否有左递归和左公因⼦void remove(); //消除左递归void solve(); //处理⽂法,获得所有First集,Follow集以及Select集void display(); //打印First集,Follow集,Select集void debug(); //⽤于debug的函数~Grammar(); //析构函数protected:int cnt; //产⽣式数⽬EXP exp[maxn]; //产⽣式集合set<char> First[maxn]; //First集set<char> Follow[maxn]; //Follow集set<char> Select[maxn]; //select集vector<char> ter_copy; //去掉$的终结符vector<char> ter; //终结符vector<char> not_ter; //⾮终结符};#endif 2.1.2 AnalyzTable类 功能:得到预测分析表,判断输⼊的⽂法是否是LL(1)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。
编译原理-递归下降子程序-课程设计报告
![编译原理-递归下降子程序-课程设计报告](https://img.taocdn.com/s3/m/08576d28c8d376eeafaa3132.png)
编译原理课程设计报告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的各个产生式的候选首符集两两不相交。
【编译原理实验】递归子程序法
![【编译原理实验】递归子程序法](https://img.taocdn.com/s3/m/e15f8327a22d7375a417866fb84ae45c3b35c2de.png)
【编译原理实验】递归⼦程序法⽂法: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)。
#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()
{
disp);
E();
puts(string);
printf("为合法字符串!\n");
system("pause");
{
printf("S->/FS \n");
match('/');
}
else
{
printf("S->ε \n");
}
}
void F()
{
if(lookhead=='(')
{
printf("F->(E) \n");
match('(');
E();
match(')');
}
else if(lookhead=='i')
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')
{
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;
}
void display()
{
printf("班级:10级计本一班\n");
printf("学号:1004011026\n");
printf("姓名:王晓龙\n");
}
LL(1)分析方法:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
{
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");
{
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");
}
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;
char S,X,a; //S文法的开始符号,X当前栈顶符号的工作单元,a当前输入符号的工作单元
char string[10]; //存放输入的句型
int count=0;//计数器
int step=0; //记录步骤
char M[16][6]; //存放产生式
int record; //记录当前找到的M中产生式的下标
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);
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()
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");
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(");
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("%c",string[i]);
i++;
}
printf("\n");
analyse();
system("pasue");
}
void error()
{
printf("分析失败!\n");
system("pause");
exit(0);
}
void init() //初始化预测分析表-已经产生式右部反转过来