编译原理 用递归下降法进行表达式分析实验报告
实验报告四递归下降语法分析程序设计
![实验报告四递归下降语法分析程序设计](https://img.taocdn.com/s3/m/c6a7197202768e9951e738ae.png)
《编译原理》实验报告实验序号: 4 实验项目名称:递归下降语法分析程序设计SELECT(E’ →ε)={ε,),#}对T SELECT(T→FT’)={(,i}对T’ SELECT(T’ →*FT’)={ * }SELECT(T’ →∕FT’)={ ∕ }SELECT(T’ →ε)={ε,+,−,),#}对F SELECT(F→(E) )={ ( }SELECT(F→i)={ i }∴SELECT(E’ →+TE’)∩SELECT(E’ →−TE’)∩SELECT(E’ →ε)=ΦSELECT(T’ →*FT’)∩SELECT(T’ →∕FT’)∩SELECT(T’ →ε)=ΦSELECT(F→(E) )∩SELECT(F→i)= Φ由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL (1)文法。
因此,转化后的文法可以用递归下降分析法作语法分析。
(2)设计这里采用递归下降分析法形象描述递归子程序。
程序中将要用到的几个重要数据如下:一个全局变量ch,存放由文件输入得到的字符。
一个函数宏READ(ch),实现读取文件中的字符。
五个子函数:P(E)、P(E’)、P(T)、P(T’)、P(F)。
(3)程序代码如下/******************************************************************** ***** 文件名:ana.c* 文件描述:递归下降语法分析器。
分析如下方法:* E->E+T | E-T | T* T->T*F | T/F |F* F->(E) | i* 输入:每行含一个表达式的文本文件。
* 输出:分析成功或不成功信息。
* 创建人:余洪周<nickhome@> 2006-12-8* 版本号:1.0********************************************************************* **/#include<stdio.h>#include<malloc.h>#define READ(ch) ch=getc(fp) /*宏:READ(ch)*/char ch; /*声明为全局变量*/int right=0;FILE *fp;struct struCH{char ch;struct struCH *next;}struCH,*temp,*head,*shift;/*head指向字符线性链表的头结点*//*shift指向动态建成的结点(游标)*/void main(int argc,char *argv[]){void E (); /* P(E) */void E1(); /* P(E')*/void T (); /* P(T) */void T1(); /* P(T')*/void F (); /* P(F) */int errnum=0,k=0,m=0,countchar=0,rownum;int charerr=0; /*开关控制量*//************************以只读方式打开文件*********************/ if((fp=fopen(argv[1],"r"))==NULL){printf("\n\tCan not open file %s,or not exist it!\n",argv[1]);exit(0); /*文件不存在or打不开时,正常退出程序*/}else printf("\n\tSuccess open file: %s\n",argv[1]); /*成功打开文件*//******************遍历整个文件检测是否有非法字符********************//*如果用while(!feof(fp))语言,将会多出一个字符*所以这里采用以下方法遍历整个文件检测其否有非法字符*//*[1]计算文件中字符数量*/while(!feof(fp)){READ(ch); /*这里读取字符只是让文件指针往前移*/countchar++; /*统计文件中的字符数(包括换行符及文件结束符)*/}rewind(fp); /*将fp文件指针重新指向文件头处,以备后面对文件的操作*/if(countchar==0){ /*空文件*/printf("\t%s is a blank file!\n",argv[1]);exit(0); /*正常退出本程序*/}/*[2]开始遍历文件*/while(k<(countchar-1)){ /*加换行符后countchar仍多了一个,不知为何*/ ch=getc(fp);if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='\n')){ charerr=1;errnum++; /*charerror出错标记,errnum统计出错个数*/}k++;}rewind(fp); /*将fp文件指针重新指向文件头处,以备后面的建链表操作*/if(charerr==1){ /*文件中有非法字符*/printf("\n\t%d Unindentify characters in file %s \n",errnum,argv[1]);exit(0); /*正常退出本程序*/}/*******************非空且无非法字符,则进行识别操作*****************/for(rownum=1;m<(countchar-1);rownum++){ /*识别所有行,rownum记录行号*//*初始变量及堆栈和*/right=1;/*初始存放待识别的表达式的线性链表头*/shift=malloc(sizeof(struCH));/**/shift->next=NULL;head=shift;/*读取一行形成线性链表*/READ(ch);putchar(ch);m++;while(ch!='\n'&&m<(countchar)){ /*行末or到文件尾。
编译原理实验报告——实验二 递归下降分析
![编译原理实验报告——实验二 递归下降分析](https://img.taocdn.com/s3/m/0b7bb8355727a5e9856a6144.png)
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{
编译原理 递归下降词法分析
![编译原理 递归下降词法分析](https://img.taocdn.com/s3/m/fba7a94133687e21af45a9eb.png)
编译原理实验报告—递归下降分析法程序实验2.1 递归下降分析法一、实验目的1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。
2. 本次实验的目的是加深对递归下降分析法的理解。
二、实验平台Windows + VC++6.0范例程序: “递归下降分析法.cpp ”三、实验内容对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E→TG(2)G→+TG|-TG(3)G→ε(4)T→FS(5)S→*FS|/FS(6)S→ε(7)F→(E)(8)F→i1.程序功能:输入: 一个以# 结束的符号串(包括+ - * / ()i # ):例如:i+i*i-i/i#输出:(1) 详细的分析步骤,每一步使用的产生式、已分析过的串、当前分析字符、剩余串,第一步, 产生式E->TG的第一个为非终结字符,所以不输出分析串,此时分析字符为i,剩余字符i+i*i-i/i#;第二步,由第一步的E->TG的第一个为非终结字符T,可进行对产生式T->FS 分析,此时第一个仍为非终结字符F,所以不输出分析串,分析字符仍为i, 剩余字符i+i*i-i/i#;第三步,使用产生式F->i,此时的分析串为i,,分析字符为i,匹配成功,剩余字符串+i*i-i/i#;第四步,因为使用了产生式T->FS,F->i,第一个字符i匹配成功,接着分析字符+,使用产生式S->ε,进行下步;第五步,使用产生式G->+TG,此时的分析串包含i+,分析字符为+,剩余字符串+i*i-i/i#;第六步,重复对产生式T->FS,F->i的使用,对第二个i进行匹配,此时分析串i+i,分析字符为i,剩余串*i-i/i#;第七步,分析字符*,使用产生式S->*FS, 分析串i+i*,剩余串i-i/i#;第八步,字符*匹配成功后,使用产生式F->i,匹配第三个字符i,,此时剩余串-i/i#;第九步,分析字符-,只有产生式G->-TG可以产生字符-。
编译原理递归下降预测分析
![编译原理递归下降预测分析](https://img.taocdn.com/s3/m/50503238360cba1aa911da0a.png)
《编译原理》课程实验报告课程实验题目:作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:作者学号:作者姓名:指导教师姓名:一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求1.给定文法:S→(T)|a+S|aT→T,S|S改写文法,使其可以使用递归下降子程序方法进行分析,编写递归下降子程序,判断句子:(((a+a+a),a+a),a)是否符合该文法。
输入:(((a+a+a),a+a),a)输出:结构正确或结构错误2.编写程序调试运行;考虑如果将你的程序改为识别其他的文法,你的递归下降子程序可否通用,考虑递归下降子程序方法的优缺点。
三、实验程序设计说明1.实验方案设计1.match;函数:从文件中依次读字符2.S函数:判断表达式是否满足S→(T)|aS1。
3.S1函数:判断表达式是否满足S1→(a+)S1|e4.T函数:判断表达式是否满足T→ST15.T1函数:判断表达式是否满足T1→,ST1|e6.error函数:输出错误信息到屏幕2.程序源代码#include<iostream.h>#include<stdlib.h>void match(char t);void S();void S1();void T();void T1();void error();char lookahead;char a[100];int i=0;int j=0;int x=0;void match(char t){if(lookahead==t)lookahead=a[++j];else error();}void S(){if(lookahead=='('){match('(');T();if(lookahead==')')match(')');else error();}else if(lookahead=='a'){match('a');S1();}else error();}void S1(){if(lookahead=='+'){match('+');S();}}void T(){S();T1();}void T1(){if(lookahead==','){match(',');S();T1();}}void error()x=-1;}void main(){cout<<"请输入一个表达式(((a+a+a),a+a),a)(以@结束):";char c;cin>>c;char s;cin>>s;while(s!='@'){a[i]=s;i++;cin>>s;}lookahead=*a;S();if(x==-1)cout<<"不匹配"<<endl;if(x==0)cout<<"匹配"<<endl;}3.程序的执行结果4.实验程序的优点和特色1.输入是以读文件的方式进行,避免了输入时的繁琐;2.递归下降子程序的健壮性较好,能准确分析出表达式错误的位置等;3.采用C语言极其部分函数编写,易懂。
编译原理用递归下降法进行表达式分析实验报告
![编译原理用递归下降法进行表达式分析实验报告](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/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/bbd60d75876fb84ae45c3b3567ec102de3bddf57.png)
一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
编译原理实验报告二递归下降语法分析程序 (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");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。
递归下降分析实验报告
![递归下降分析实验报告](https://img.taocdn.com/s3/m/7e120fe6ed3a87c24028915f804d2b160b4e86d2.png)
一、实验目的通过本次实验,加深对递归下降分析法的理解,掌握递归下降分析法的原理和应用,并能够根据给定的文法编写相应的递归下降分析程序。
二、实验原理递归下降分析法是一种自顶向下的语法分析方法,它将文法中的每个非终结符对应一个递归过程(函数),分析过程就是从文法开始符触发执行一组递归过程(函数),向下推到直到推出句子。
递归下降分析法的前提是文法应满足以下条件:1. 消除二义性:确保文法中每个产生式都只有一个确定的意义。
2. 消除左递归:避免产生式出现如A -> A...A的形式。
3. 提取左因子:将产生式中的左因子提取出来,避免出现左递归。
4. 判断是否为LL(1)文法:LL(1)文法是指文法满足左递归和右递归的文法。
三、实验内容1. 根据给定的文法编写递归下降分析程序。
2. 对输入的符号串进行分析,判断其是否属于该文法。
3. 输出分析过程和结果。
四、实验步骤1. 阅读相关资料,了解递归下降分析法的原理和应用。
2. 根据给定的文法,设计递归下降分析程序的结构。
3. 编写递归下降分析程序,实现分析过程。
4. 编写测试用例,验证递归下降分析程序的正确性。
5. 分析实验结果,总结实验经验。
五、实验结果与分析1. 实验结果根据给定的文法,编写了递归下降分析程序,并进行了测试。
以下为部分测试用例及结果:(1)输入:eBaA输出:分析成功,属于该文法。
(2)输入:abAcB输出:分析成功,属于该文法。
(3)输入:dEdaC输出:分析成功,属于该文法。
(4)输入:edc输出:分析成功,属于该文法。
2. 实验分析通过本次实验,我们深入了解了递归下降分析法的原理和应用。
在编写递归下降分析程序的过程中,我们学会了如何根据文法设计程序结构,以及如何实现分析过程。
同时,我们还掌握了如何对输入的符号串进行分析,并输出分析结果。
实验过程中,我们遇到了一些问题,如消除二义性、消除左递归、提取左因子等。
通过查阅资料和不断尝试,我们成功解决了这些问题。
编译原理实验(递归向下语法分析法实验)
![编译原理实验(递归向下语法分析法实验)](https://img.taocdn.com/s3/m/5c4f2568561252d380eb6eac.png)
//定义一个数组大小常量
char string[N];
//定义一个用于存储算式字符串的数组
char *p;
//定义一个全局字符指针变量
函数说明:
1) 非终结符函数 E()
函数功能描述:根据以上文法要求 E->TG,所以从主函数开始调入第一个非终结符函数
执行,显示调用产生式,依次嵌套调用非终结符函数 T()和 G(),进行递归向下分析。
void E(){printf("E--->TG..............%c\n",ch);
T();
G();}
2) 非终结符函数 T()
函数功能描述:根据以上文法要求 T->FS,首先显示算式匹配所用的显示调用的产生式,
依次嵌套调用非终结符函数 F()和 S(),进行递归向下分析。
void T(){
(3)G->ε
(4)T->FS
(5)S->*FS| / FS
(6)S->ε
(7)F->(E)
(8)F->i
输入出的格式如下:
(1)E 盘建立一个文本文档" 222.txt"存储一个以#结束的符号串(包括+—*/()i#),在此
位置输入符号串例如:i+i*i#
(2)输出结果:i+i*i#为合法符号串
备注:输入一符号串如 i+i*#,要求输出为“非法的符号串”
此法分析,通过实验我对本章的语法分析也有了深刻的认识。同时通过本次编程,让我深刻
认识编程应该注重细节,编程之前首先要做好分析准备。
五、程序源代码
#include<stdio.h>
#include<stdlib.h>
编译原理语法分析实验报告
![编译原理语法分析实验报告](https://img.taocdn.com/s3/m/a0883da5846a561252d380eb6294dd88d0d23dad.png)
实验二语法分析实验报告一、实验内容1.1 实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析.1.2 实验要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析1.2.1待分析的简单语言的词法用扩充的BNF表示如下:(1) <程序>::={<声明序列><语句序列>}(2)<语句串>::=<语句>{;<语句>}(3) <语句>::=<赋值语句>(4) <赋值语句>::=ID:= <表达式>(5) <表达式>::=<项>{(+<项>|-<项>}(6) <项>::=<因子>{*<因子>|/<因子>}(7) <因子>::=ID|NUM|(<算术表达式>)1.2.2实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
二、实验程序的总体结构框架图1. 语法分析主程序示意图图2.递归下降分析程序示意图图5. expression表达式分析函数示意图图6.term分析函数示意图三、关键技术的实现方法Scanner函数定义已在实验一给出,本实验不再重复给出void Irparser(){kk=0;if(syn==1){scaner();yucu();if(syn==6){scaner();if(syn==0 && (kk==0)) cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else {cout<<"缺begin!"<<endl;kk=1;}return;}void yucu(){statement();while(syn==26){scaner();statement();}return;}void statement() {if(syn==10){scaner();if(syn==18){scaner();expression();}else{cout<<"赋值号错误"<<endl;kk=1;}}else{cout<<"语句错误"<<endl;kk=1;}return;}void expression(){term();while((syn==13)||(syn==14)){scaner();term();}return;}void term(){factor();while((syn==15)||(syn==16)){scaner();factor();}return;}void factor(){if((syn==10)||(syn==11))scaner();else if(syn==27){scaner();expression();if(syn==28)scaner();else{cout<<")错误"<<endl;kk=1;}}else{cout<<"表达式错误"<<endl;kk=1;}return;}void main(){p=0;cout<<"Please input string"<<endl;do{cin.get(ch);if(ch!=”\n”)prog[p++]=ch;}while(ch!='#');p=0;scaner();Irparser();}四、实验心得语法分析是编译过程的核心部分,它的主要功能是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备。
递归下降分析算法
![递归下降分析算法](https://img.taocdn.com/s3/m/b5c282ece009581b6bd9eb89.png)
数学与计算机学院编译原理实验报告年级09软工学号姓名成绩专业软件工程实验地点主楼指导教师湛燕实验项目递归下降分析算法实验日期2012.6.10一、实验目的和要求使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。
重点和难点:本实验的重点是理解自顶向下分析方法的原理;难点是如何把文法改写成EBNF形式。
二、实验内容1、使用递归下降分析算法分析表达式文法:exp ::= expaddop term | termaddop ::= + | -term ::= term mulop factor | factormulop ::= * | /factor ::= (exp) | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到number的值。
2、该词法分析器以子程序形式出现,当需要进行词法分析时进行调用;3、能够识别正确和错误的表达式;4、在进行语法分析的过程中,计算输入表达式的值。
三、程序设计主要变量有:boolIsDigit(char ch);//判断字符是否是数字static string s;//staticinti=0;//staticint flag=0;//staticint result;//主要函数有:staticintexp();//staticint exp1(int temp);//staticint term();//staticint term1(int temp);//staticint factor();//static intReadNum();//提取数字递归下降的主要原理是:对每个非终结符按其产生结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。
因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。
五、代码和截图自己写程序如下:#include<stdio.h>#include<conio.h>#include<cstdlib>#include<string>#include <iostream>#include <fstream>#include <stdlib.h>using namespace std;staticintexp();staticint exp1(int temp);staticint term();staticint term1(int temp);staticint factor();staticintReadNum();boolIsDigit(char ch);static string s;staticinti=0;staticint flag=0;staticint result;int main(){cout<<"请输入一个语句,以“#”结束,输入“#”退出"<<endl;while(1){cin>>s;s+='#';if(s[0]=='#')return 0;result = exp();if (flag == 0){cout<<"结果是"<<endl<<result<<endl;}}return 1;}staticboolIsDigit(char ch){if (ch>= 48 &&ch<= 57)return true;elsereturn false;}staticintReadNum(){int add = 0;stringstr = "";while (s[i]!= '#'){if (s[i] == '+'||s[i] =='-'||s[i]=='*'||s[i]=='/'||s[i]==')'){break;}else if (s[i]>= 48&&s[i]<=57){str +=s[i];}else{flag= 1;cout<<"输入了错误的字符!"<<endl;return -1;}i++;}str += "!";int n = 0;while (str[n] != '!'){cout<<str<<"(数字)"<<endl;n++;}int m = 0;while (str[m] != '!'){add += (int)(str[m] - 48);add *= 10;m++;}add = add / 10; cout<<add<<endl;return add;}staticintexp(){int temp;temp = term();temp = exp1(temp);return temp;}staticint exp1(int temp) {if(s[i]=='+'){++i;temp += term(); temp = exp1(temp);}else if(s[i]=='-'){++i;temp -= term(); temp = exp1(temp);}return temp;}staticint term(){int temp;temp = factor();temp = term1(temp); return temp;}staticint term1(int temp) {if(s[i]=='*'){++i;temp *= factor();temp = term1(temp);}else if(s[i]=='/'){++i;temp /= factor();temp = term1(temp);}return temp;}staticint factor(){int temp = 0;if (IsDigit(s[i])){temp = ReadNum();}else if(s[i]=='('){++i;temp=exp();if(s[i]==')')++i;else{flag = 1;cout<<"缺少右括号!"<<endl;}}else{flag = 1;cout<<"请输入正确的格式!"<<endl;}return temp;}输入的句子不正确时,提示,如下图:输入了正确的句子后,分析如下图:。
编译原理实验报告3
![编译原理实验报告3](https://img.taocdn.com/s3/m/e22c9c9e64ce0508763231126edb6f1aff00712f.png)
编译原理实验报告3编译原理实验报告——表达式语法分析——表达式语法分析表达式语法分析实验报告一、实验题目设计一个简单的表达式语法分析器(采用递归下降方法设计实现)二、实验目的1、了解形式语言基础及其文法运算;2、熟悉语法分析原理及 4 种常用的语法分析方法;其中:四种算法为(1)设计算术表达式的递归下降子程序分析算法(2)设计算术表达式的 LL(1) 分析算法(3)设计算术表达式的简单优先分析算法(4)设计算术表达式的SLR(1) 分析算法3、选择上述一种方法并设计一个表达式的语法分析器。
(本实验设计的是递归下降的表达式语法分析器)三、实验内容1.设计递归下降语法分析器算法;2.编写代码并上机调试运行通过; 3、写出试验体会及心得。
四、实验要求1、给出算术表达式文法2、进行适当的文法变换3、选择一种语法分析的方法,并说明其原理4、根据原理给出相应的算法设计,说明主要的数据结构并画出算法流程图5、编写代码并上机调试运行通过6、写出程序运行结果7、写出相应的文档以及代码注释8、输入——表达式;输出——表达式语法是否正确。
五、递归下降的表达式语法分析器设计概要1.算术表达式文法.G(E):E T F 2.文法变换:文法变换:G’(E): E->TE' E'->+TE'|ε T->FT' T'->*FT'|ε F->(E)|I E +T | T T* F | F i | (E)3. 递归下降子程序框图:递归下降子程序框图:六、实验设计源程序#includechar inputstream[50]; int temp=0; int right; void e(); void e1(); void t(); void t1(); void f(); void main() { right=1;//存储输入句子//数组下标 //判断输出信息cout<<"请输入您要分析的字符串以#结束(^为空字符):"<>inputstream; e(); if((inputstream[temp]=='#')&&right) cout<<"分析成功"<<<"e-="" cout<<"分析失败"<TE'"<<<"e'-="" e1()="" e1();="" if(inputstream[temp]="='+')" t();="" void="" {="" }="">+TE'"<e1(); } else if (inputstream[temp]!='#'||inputstream[temp]!=')') { cout<<"T'->^"<<<"t-="" else="" return="" right="0;" t()="" void="" {="" }="">FT'"<<<"t'-="" f();="" if(inputstream[temp]="='*')" t1()="" t1();="" void="" {="" }="">*FT'"<<<"t'-="" else="" f();="" if="" t1();="" temp++;="" {="" }="">^"<} } void f() { if(inputstream[temp]=='i') { cout<<"F->i"<if(inputstream[temp]=='(') { cout<<"F->(E)"<<<"f-="" e();="" if(inputstream[temp]="=')')" temp++;="" {="">(E)"<七、运行结果八、实验思考题语法分析的任务是什么?语法分析的任务是什么?答:语法分析器的任务是识别和处理比单词更大的语法单位,如:程序设计语言中的表达式、各种说明和语句乃至全部源程序,指出其中的语法错误;必要时,可生成内部形式,便于下一阶段处理。
递归下降语法分析实验报告
![递归下降语法分析实验报告](https://img.taocdn.com/s3/m/c8b58d1a10a6f524ccbf8567.png)
编译原理实验报告一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:S→a|∧|(T)T→T,S|S三、设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。
四、设计分析这个题目属于比较典型的递归下降语法分析。
需要先将原算术表达式方法改写为LL(1)文法为:S→a|∧|(T)T→ST’T’→,ST’|ε然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。
具体方法为:(1)当遇到终结符a时,则编写语句If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到终结符∧时,则编写语句If(当前读到的输入符号==∧)读入下一个输入符号(3)当遇到终结符﹙时,则编写语句If(当前读到的输入符号==﹙)读入下一个输入符号(4)当遇到非终结符T时,则编写scaner()函数读取下一个单词符号并将它放在全程变量sym中(5)当遇到非终结符S时,则编写S()函数(6)当遇到非终结符T’时,则编写T’()(7)当遇到终结符,时,则编写语句If(当前读到的输入符号==,)读入下一个输入符号(8)当遇到非终结符T时,则编写T()五、实验代码#include"stdio.h"void S();void T();void scaner();void error();char sym;char s[100];int i=0;int main(){printf("请输入一个语句,以#号结束语句(直接输入#号推出)\n");scanf("%s",&s);scaner();S();if (sym=='#'){printf("success");return 1;}else{printf("fail");return 0;}}void scaner(){sym=s[i];i++;}void T'(){if(sym==','){scaner();S();T'();}else if(sym!=')')error();}void error(){printf("语句有误!\n");}void T(){S();T'();}void S(){if (sym=='a'||sym=='^')scaner();else if(sym=='('){scaner();T();if(sym==')')scaner();elseerror();}elseerror();}六、测试用例和实验结果(1)输入a,预期显示语句正确!(2)输入∧,预期显示语句正确!(3)输入(a,b),预期显示语句有误!(4)输入(a ,a),预期显示语句正确!(5)输入(a,(a,a)),预期显示语句正确!七、测试结果截图(1)输入a的测试结果(2)输入^的测试结果(3)输入(a,b)的测试结果(4)输入(a ,a)的测试结果(5)输入(a,(a,a))测试结果八、实验总结通过该实验,我深入的学习了递归下降分析法的内容和原理,它是确定的自上而下的分析法,这种分析法是要求文法是LL(1)的,它的基本思想是对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该终结符所表示的语法成分,由于描述语言的文法常常是递归定义的,因此相应的这组函数必然是相互递归的方式进行调用的,所以将此种分析法称为递归下降分析法。
实验二递归下降分析法实验报告
![实验二递归下降分析法实验报告](https://img.taocdn.com/s3/m/c165940252ea551810a6878d.png)
信息商务学院实验报告课程:编译原理实验名称:递归下降分析学号: *************名:***指导老师:***日期:2014年5月13日实验二递归下降分析法一、实验目的和要求1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。
2. 本次实验的目的是加深对递归下降分析法的理解。
二、实验内容(1)功能描述对下列文法,用递归下降分析法对任意输入的符号串进行分析,看是否能匹配成功:(1)E→TG(2)G→+TG|-TG(3)G→ε(4)T→FS(5)S→*FS|/FS(6)S→ε(7)F→(E)(8)F→i(2)程序结构描述本程序的实现方法主要就是函数的递归调用,在程序前面先对文法中所涉及到的非终结符对应的函数进行声明,以免在用到的时候提示函数无声明的错误提示,程序从开始符E开始,根据文法,E可以推出T和G,就在函数E()中调用T()和G(),其他的也是类似,这属于文法中只涉及到非终结符;遇到有终结符的情况则不同,想函数G(),因为G可以推出+TG或者-TG,所以在函数G()中,要分两种情况,先判断当前的字符是否是+,是则调用T()和G(),如果当前字符为-,就调用T()和G(),否则就是ε字符;按照这种方法,把文法所涉及到的非终结符都写成对应的函数,并正确调用其他函数。
等所有的函数都描述之后就在mian()里判断当前字符是否分析到结束符#,是则说明此字符串是合法字符,否则说明此字符串为不合法字符。
(3)程序部分代码#include<string.h>#include<stdio.h>#include<stdlib.h>FILE *fp;char ch;#define N 20char string[N];char *p;void E();void T();void G();void F();void S();void E(){printf("E-->TG...%c\n",ch);T();G();}void F(){if(ch=='i'){printf("F-->i...%c\n",ch);*p=ch;p++;ch=fgetc(fp);}else if(ch=='('){printf("F-->(E)...%c\n",ch);*p=ch;p++;ch=fgetc(fp);E();if(ch==')'){*p=ch;p++;ch=fgetc(fp);}else{printf("没有右括号“)”匹配不成功!\n");exit(0);}}else{printf("算式匹配不成功!\n");exit(0);}}void G(){if(ch=='+'){printf("G-->+TG...%c\n",ch);*p=ch;p++;ch=fgetc(fp);T();G();}else if(ch=='-'){printf("G-->+TG...%c\n",ch);*p=ch;p++;ch=fgetc(fp);T();G();}elseprintf("G-->空...%c\n",ch); }void T(){printf("T-->FS...%c\n",ch);F();S();}void S(){if(ch=='*'){printf("S-->*FS...%c\n",ch);*p=ch;p++;ch=fgetc(fp);F();S();}else if(ch=='/'){printf("S-->/FS...%c\n",ch);*p=ch;p++;ch=fgetc(fp);F();S();}elseprintf("S-->空...%c\n",ch);}void main(){if((fp=fopen("D:\\3.txt","r"))==NULL){ //读取文件内容,并返回文件指针,该指针指向文件的第一个字符fprintf(stderr,"error opening.\n");exit(1);}ch=fgetc(fp);p=string;printf("调用分析程序所用产生式:\n");E();if(ch=='#'){*p=ch;printf("算法匹配成功!\n算法结果:%s\n",string);}else{printf("算法匹配不成功!\n");}fclose(fp);}三、实验结果测试数据一:D盘的一个名为ceshi.txt的文本文件里文件里输入字符串:(*i)+i#,运行结果如图1所示。
华工编译原理实验报告
![华工编译原理实验报告](https://img.taocdn.com/s3/m/963968b5e109581b6bd97f19227916888486b98c.png)
一、实验目的通过本次实验,加深对编译原理中语法分析部分的理解,掌握递归下降分析法和LR(1)分析法的原理和实现方法,并能够运用所学知识对简单的文法进行语法分析。
二、实验内容本次实验主要分为两个部分:1. 递归下降分析法- 实验要求:针对给定的文法,编写递归下降分析程序,实现对输入的字符串进行语法分析。
- 文法示例:```S -> A BA -> a A | εB -> b B | ε```- 实现过程:- 定义文法的非终结符号、终结符号和开始符号。
- 设计递归下降分析函数,按照文法的产生式进行递归调用。
- 处理输入字符串,调用递归下降分析函数进行语法分析。
2. LR(1)分析法- 实验要求:针对给定的文法,编写LR(1)分析程序,实现对输入的字符串进行语法分析。
- 文法示例:```S -> A BA -> a A | εB -> b B | ε```- 实现过程:- 求解文法的 FIRST 集和 FOLLOW 集。
- 构建LR(1)分析表,包括状态转移函数、接受状态和错误处理函数。
- 设计LR(1)分析程序,根据分析表进行状态转移和语法分析。
三、实验步骤1. 递归下降分析法- 步骤一:定义文法的非终结符号、终结符号和开始符号。
- 步骤二:设计递归下降分析函数,按照文法的产生式进行递归调用。
- 步骤三:编写主函数,读取输入字符串,调用递归下降分析函数进行语法分析。
2. LR(1)分析法- 步骤一:求解文法的 FIRST 集和 FOLLOW 集。
- 步骤二:构建LR(1)分析表,包括状态转移函数、接受状态和错误处理函数。
- 步骤三:设计LR(1)分析程序,根据分析表进行状态转移和语法分析。
四、实验结果1. 递归下降分析法- 对于输入字符串 "aaabbb",程序能够正确分析并输出分析结果。
2. LR(1)分析法- 对于输入字符串 "aaabbb",程序能够正确分析并输出分析结果。
实验三递归下降分析器设计与实现编译原理实验报告
![实验三递归下降分析器设计与实现编译原理实验报告](https://img.taocdn.com/s3/m/5802827766ec102de2bd960590c69ec3d5bbdbf0.png)
实验三递归下降分析器设计与实现编译原理实验报告一、引言递归下降分析器是编译原理中常用的一种语法分析方法。
它根据文法规则和输入的源代码,递归地进行语法分析,判断源代码是否符合给定的文法规则。
本实验旨在通过设计与实现一个简单的递归下降分析器,加深对编译原理中语法分析的理解。
二、实验目的1.学习递归下降分析器的原理和设计方法;2.掌握使用递归下降分析器进行简单语法分析的过程;3.加深对编译原理中文法规则和语法分析的理解。
三、实验过程1.设计文法规则:根据实验要求,设计一个简单的算术表达式文法规则。
例如,我们可以采用以下文法规则:```E->E+T,E-T,TT->T*F,T/F,FF -> ( E ) , num```2.设计分析器:根据设计的文法规则,设计递归下降分析器的结构和算法。
我们可以使用编程语言实现一个类,其中包含递归下降分析器所需要的方法和数据结构。
3. 实现分析器:根据设计的分析器结构和算法,使用编程语言实现递归下降分析器的代码。
可以选择常用的编程语言,如C++、Java、Python等。
4.进行语法分析:编写测试代码,使用实现的递归下降分析器对输入的算术表达式进行语法分析。
根据分析结果,判断输入的算术表达式是否符合给定的文法规则。
五、实验结果实验结果根据设计的分析器的实现和测试代码的编写而定。
例如,对于以下输入的算术表达式:(3+4)*5-2,经过递归下降分析器的分析,应该能正确判断其是否符合给定的文法规则。
六、实验总结递归下降分析器是编译原理中常用的一种语法分析方法。
通过实验三,我深入理解了递归下降分析器的原理和设计方法,并通过实现一个简单的递归下降分析器,加深了我对编译原理中文法规则和语法分析的理解。
在实验过程中,我学会了如何根据设计的文法规则来设计递归下降分析器的结构和算法。
我使用了编程语言实现了递归下降分析器的代码,并编写了相应的测试代码进行语法分析。
通过测试,我验证了递归下降分析器的正确性。
递归向下实验报告(3篇)
![递归向下实验报告(3篇)](https://img.taocdn.com/s3/m/04f9ba10a517866fb84ae45c3b3567ec112ddc6b.png)
第1篇一、实验背景递归是一种编程技巧,通过函数调用自己的方式实现重复操作。
递归向下实验旨在通过递归函数,探究递归向下过程中的参数变化,以及递归结束条件,以加深对递归概念的理解。
二、实验目的1. 掌握递归函数的基本原理。
2. 理解递归向下过程中的参数变化。
3. 探究递归结束条件,避免出现栈溢出等问题。
三、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm四、实验内容1. 设计一个递归函数,实现阶乘计算。
2. 分析递归向下过程中参数的变化。
3. 设置递归结束条件,避免栈溢出。
五、实验步骤1. 定义递归函数,实现阶乘计算。
```pythondef factorial(n):if n == 0:return 1else:return n factorial(n - 1)```2. 分析递归向下过程中参数的变化。
以计算 5! 为例,递归向下过程如下:```factorial(5)factorial(4)factorial(3)factorial(2)factorial(1)factorial(0) -> 1return 1return 2return 6return 120```在递归向下过程中,每次调用 `factorial` 函数时,参数 `n` 逐渐减小,直到达到递归结束条件 `n == 0`。
3. 设置递归结束条件,避免栈溢出。
为了避免栈溢出,我们需要设置合适的递归结束条件。
在本例中,递归结束条件为`n == 0`。
此外,还可以设置参数 `n` 的最大值,例如:```pythondef factorial(n, max_n=10):if n == 0:return 1elif n > max_n:raise ValueError("递归深度过大,可能导致栈溢出")else:return n factorial(n - 1, max_n)```六、实验结果与分析1. 当输入 `factorial(5)` 时,程序输出结果为 120,与预期相符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《编译原理》课程
实验报告
题目用递归下降法进行表达式分析
专业
班级
学号
姓名
一. 实验题目
用递归下降法进行语法分析的方法
二. 实验日期
三. 实验环境(操作系统,开发语言)
操作系统是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)就说明两者可以相互替代。
然后,反复修改F()函数(可将printf()带入其中调试),修改“case LPAREN:”和“default:”中的部分,使这段代码即可检测出缺少‘(’又可检测出缺少‘)’以及“)(”(右括号在前)或是括号中没有数字的情况。
最后,综合理解double E();double F();void S();double T();四个函数以及运用“extern VAL yyval;”这样的语句使此代码可运用其他文件中的变量,如*yyin、*yytext。
另外为了更好理解,我将个别函数中的switch函数修改成if的选择语句。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)
这是我们第一次接触语法分析,用递归下降法来进行表达式的分析。
第一次接触的确很陌生。
在实验中,要想进行分析,需要在.l文件中写出规则,然后在.h文件中定义规则中的“+ - * / ()”,将其定义为PLUS 3 、MINUS 4、TIMES 5、 SLASH 6 LPAREN 7 、RPAREN 8,这样一来,.l文件中的规则就可运用到syn.c文件中去,而在用户输入的“+-*/()”就可传到规则中去替换成对应的字母,进行运算。
此时的‘+’就可用“PLUS”表示;‘-’就可用“MINUS”表示;‘*’就可用“TIMES”表示;‘/’就可用“SLASH”表示;‘(’就可用“LPAREN”表示;‘)’就可用“RPAREN”表示。
另外double E();double F();void S();double T()四个函数中,以S()函数为起始函数依次向后调用函数,直到函数F(),并且完成了“先算括号内,再算*/,最后算+-”的运算顺序。
另外,实验调试中是可以让用户输入的,但代码中没有一句scanf()输入函
数,而在main()函数里有“yyin=(char*)stdin;”这一句代码,这就是用来输入的,其含义就是将所输入的内容传到yyin中去。
这次实验让我初步了解了,自己编写的规则是可以运用在程序代码里并能运行的。
其实如果不用这样的方法,我们也能编写出计算表达式的代码,但是这样的方法去编写感觉代码要容易读懂很多,代码也显得简便了。
七. 实验结果(关键源代码)
#include<stdio.h>
#include "parser.h"
extern VAL yyval; //运用其他文件中的变量
extern char *yyin;
extern int yylex();
extern char *yytext;
int tokentype;
double E();
double F();
void S();
double T();
double F() // F -> (E) | int | double
{
double num;
tokentype=yylex();
switch(tokentype)
{
case INTEGER:
num = atoi(yytext);
break;
case DOUBLE:
num = atof(yytext);
break;
case LPAREN:
num = E();
if(tokentype!= RPAREN)
{
printf("表达式中缺少 ')' \n");
break;
}
if(tokentype!= LPAREN)
{
printf("表达式中缺少 '(' \n");
}
else break;
break;
default:
printf("您输入的表达式有误!\n");
break;
}
tokentype = yylex();
return num;
}
double T() // T-> F{*F | /F}
{
double t1,t2;
t1 = F();
while(tokentype == TIMES || tokentype == SLASH) {
switch(tokentype)
{
case TIMES:
t2 = F();
t1 = t1 * t2;
break;
case SLASH:
t2 = F();
t1 = t1 / t2;
break;
default:
break;
}
}
return t1;
}
double E() // E -> T{+T | -T}
{
double t1,t2;
t1 = T();
while(tokentype == PLUS || tokentype == MINUS)
{
if (tokentype == PLUS)
{
t2 = T();
t1 = t1 + t2;
break;
}
if (tokentype == MINUS)
{
t2 = T();
t1 = t1 - t2;
break;
}
if(tokentype != PLUS && tokentype != MINUS)
break;
}
return t1;
}
void S()
{
double result;
result = E();
printf("%.2f\n",result);
}
int main()
{
yyin=(char*)stdin; //输入语句,将输入的语句都传给yyin printf("请输入算术表达式: \n");
S(); //调用开始符号
system("PAUSE");
return 0;
}。