编译原理实验-递归下降分析资料报告器地设计(含源代码和运行结果)
编译原理实验报告——实验二 递归下降分析
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{
(完整)编译原理课程设计 LL(1)递归下降分析器
(完整)编译原理课程设计 LL(1)递归下降分析器编辑整理:尊敬的读者朋友们:这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望((完整)编译原理课程设计LL(1)递归下降分析器)的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为(完整)编译原理课程设计 LL(1)递归下降分析器的全部内容。
仲恺农业技术学院编译原理课程设计课程设计题目:LL(1)递归下降分析器姓名:院(系):专业班级:学号 :指导教师:设计日期:目录1、需求分析 (1)2、概要设计 (2)3、详细设计 (3)4、测试分析 (8)5、用户手册 (9)6、课程总结 (9)7、参考文献 (10)题目:LL(1)递归下降分析器1、需求分析语法分析是编译过程的核心部分。
语法分析器的任务是识别和处理比单词更大的语法单位。
如:程序设计语言中的表达式,各种说明和语句乃至全部源程序,指我们知道,语言的语法结构是用上下文无关文法描述的.按照语法分析树的建立方法,我们可以粗略地把语法分析办法分成两类,一类是自上而下分析,另一类是自下而上分析法。
而自上而下这种方法是带“回溯”的,且存在许多困难和缺点.首先,是文法的左递归性问题。
一个文法是含有左递归的,如果存在非终结符P 且,含有左递归的文法使上述的自上而下的分析过程陷入无限循环。
即,当试图用P 去匹配输入串时,我们会发现,在没有识别任何输入符号的情况下,有得重新要求P 去进行新的匹配。
因此,使用自上而下分析法必须消除文法的左递归性.其次,由于回溯,就碰到一大堆麻烦问题。
如果我们走了一大段错路,最后必须回头,那么,就应把已经做的一大堆语义工作(指中间代码产生工作和各种表格的簿记工作)推倒重来.这些事情既麻烦又费时间,所以,最好应设法消除回溯.第三,在自上而下分析过程中,当一个非终结符用某一候选匹配成功时,这种成功可能仅是暂时的。
编译原理_实验二_语法分析_递归下降分析器设计_实验报告
递归下降分析器设计一、实验/实习过程内容:利用JavaCC生成一个MiniC的语法分析器;要求:1. 用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。
2. 具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3. 如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉〈语句串〉|〈语句〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|==|!=2.消除语句中的回溯与左递归3.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)4.完成的功能包括词法分析,语法分析二、代码:options {JDK_VERSION = "1.5";}PARSER_BEGIN(eg1)public class eg1 {public static void main(String args[]) throws ParseException { eg1 parser = new eg1(System.in);parser.start();}}PARSER_END(eg1)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS: "+" >| < MINUS: "-" >| < MULTIPLY: "*" >| < DIVIDE: "/" >}TOKEN :{<BIGGER:">"> |<SMALLER:"<"> |<NOTVOLUTION:"!="> |<SMALLEREQDD:"<="> |<BIGGEREE:">=" > |<DOUBLE:"==">TOKEN: //关键字{<MAIN:"main"> |<VOID:"void"> |<IF:"if"> |<INT:"int"> | <WHILE:"while"> |<CHAR:"char"> | <VOLUTION:"="> }TOKEN : //定义整型数{< INTEGER: ["0" - "9"]( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN : //数字{<NUMBER:(<DIGIT>)+ | (<DIGIT>)+"."| (<DIGIT>)+"."(<DIGIT>)+| "."(<DIGIT>)+>}TOKEN : //标记{<COMMA:","> | <SEMICOLON:";"> | <COLON:":"> | <LEFTPARENTHESES:"("> |<RIGHTPARENTHESES:")"> | <LEFTBRACE:"{"> | <RIGHTBRACE:"}"> }TOKEN : //标识符{<IDENTIFIER:<LETTER> |<LETTER>(<LETTER> | <DIGIT> )* >|<#LETTER:["a"-"z", "A"-"Z"]>}void start():{}{<MAIN> <LEFTPARENTHESES> <RIGHTPARENTHESES> block() }void block():{}{<LEFTBRACE> string() <RIGHTBRACE>}void string():{}{yuju() (string())?}void yuju():{}{fuzhiyuju() | tiaojianyuju() | xunhuanyuju()}void fuzhiyuju():{}{<IDENTIFIER> <VOLUTION> biaodashi() <SEMICOLON>}void tiaojianyuju():{}{<IF> tiaojian() block()}void xunhuanyuju():{}<WHILE> tiaojian() block()}void tiaojian():{}{<LEFTPARENTHESES> biaodashi() guanxifu() biaodashi()<RIGHTPARENTHESES>}void biaodashi():{}{( <LEFTPARENTHESES> biaodashi() <RIGHTPARENTHESES> biaodashi2()) |(<IDENTIFIER> biaodashi2() ) | ( <NUMBER> biaodashi2() )}void biaodashi2():{}{(yunsuanfu() biaodashi() biaodashi2() )?}void yunsuanfu():{}{< PLUS > | < MINUS > |< MULTIPLY> | < DIVIDE >}void guanxifu() :{}{<BIGGER> | <SMALLER> | <NOTVOLUTION><SMALLEREQDD> | <BIGGEREE> | <DOUBLE>}三、实验/实习总结本次实习,我使用javacc完成了包括词法分析,语法分析(输出语法树),能够读文件的功能,总的来说比较满意,通过本次实习掌握了javacc基本的使用。
编译原理递归下降预测分析
《编译原理》课程实验报告课程实验题目:作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:作者学号:作者姓名:指导教师姓名:一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求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语言极其部分函数编写,易懂。
编译原理实验语法器递归下降子程序实现解析
编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机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-递归下降分析法
计算机硬件实验室实验报告一、实验目的:根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验要求:对下列文法,用递归下降分析法对任意输入的符号串进行分析:(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]='#';}。
递归下降分析器的设计
河北大学工商学院编译原理实验报告年级09级学号姓名成绩专业计算机科学与技术实验地点B3-216 指导教师李凯实验项目递归下降分析器的设计实验日期2012/5/14实验报告要求:一、实验目的1. 实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。
2.了解什么是LL(1)文法的,以及如何把一个非ll(1)的文法转化为非ll(1)型文法,深入了解如何根据ll(1)文法编写递归子程序,实现语法的检查。
3.深入了解编译程序语法分析的过程。
二、实验原理1. 基本原理递归下降法是语法分析中最易懂的一种方法。
它的主要原理是,对每个非终极符按其产生式结构构造相应语法分析子程序,其中终极符产生匹配命令,而非终极符则产生过程调用命令。
因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。
其中子程序的结构与产生式结构几乎是一致的。
2. 文法要求递归下降法要满足的条件:假设 A 的全部产生式为A α1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式Select(A-> αi)∩select(A ->αj)=Φ,当i≠j,即要求文法必需满足ll(1)文法。
3.开发工具要求本程序使用C语言写的,要求掌握C语言的基本语法和语义,特别是关于程序递归调用的要求。
4.文法的BNF式:E->EaT|T;T->TbF|FF->(E)|da:=+|-b:=*|/消除左递归之后的文法E->TE’E’->aTE’|εT->bFT’|εT’->bFT’F->(E)|da:=+|-b:=*|/三、实验要求【目的】使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。
【要求】1、使用递归下降分析算法分析表达式文法:exp ::= exp addop term | termaddop ::= + | -term ::= term mulop factor | factormulop ::= * | /factor ::= (exp) | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到number的值。
编译原理语法分析递归下降子程序实验报告
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
编译原理实验递归下降分析器的设计含源代码和运行结果
FIRST(exp)= FIRST(term)= FIRST(factor)={id, number, ( }
FIRST(texp)={ ε,+, - }
FIRST(Addop)={+, - }
FIRST(tterm)={ ε,*, / }
FIRST(mulop)={*, / }
由于分析的文件中可能出现非法字符,而一旦发现非法字符就无需再接着分析,所以在每次读取一个字符时调用islegal函数判断是否是合法字符,并返回0或1.
在main()函数中,while((lookahead=='\n'||lookahead==' ')&&lookahead!=EOF)ﻩfscanf(resource,"%c",&lookahead);
void match(chart)//写入result文件,打印输出,并读取下一个
{
fprintf(result,"%c",lookahead);//向result写入
printf("%c",lookahead);
fscanf(resource,"%c",&lookahead);//读数据
}
number()//识别数字,如果遇到数字就一直接着读直到不是数字
{
while('0'<=lookahead&&lookahead<='9')
ﻩ{
ﻩfprintf(result,"%c",lookahead);//写入
printf("%c",lookahead);
递归下降程序实验报告
一、实验目的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)
编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期: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)doc资料
《编译原理》课程实验报告课程实验题目:作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:作者学号:作者姓名:指导教师姓名:一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验内容及要求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语言极其部分函数编写,易懂。
递归下降分析器程序(c语言版,编译原理实验)1
《编译原理》实验报告实验二:语法分析程序设计班级:08计算计(3)班姓名:斯军浩学号:E08620325递归下降分析器设计[实验目的]:1.了解语法分析的主要任务。
2.熟悉编译程序的编制。
[实验内容]:根据某文法,构造一基本递归下降语法分析程序。
给出分析过程中所用的产生式序列。
[实验要求]:1.构造一个小语言的文法,例如,Pascal语言子集的文法(同实验一),考虑其中的算术表达式文法:G[<表达式>]:G[E]:<表达式>→<表达式>+<项>|<表达式>-<项>|<项> E→E+T|T<项>→<项>*<因式>|<项>/<因式>|<因式> T→T*F|F<因式>→<标识符>|<无符号整数>|(<表达式>) F→i|(E)2.设计语法树的输出形式,例如:产生式……3.编写递归下降语法分析程序dgxj.c实现基本的递归下降分析器,能够分析任给的符号串是否为该文法所定义的合法算术表达式。
实验报告中要说明分析使用的方法。
4.生成并输出分析过程中所用的产生式序列:1 产生式12 产生式2……[实验步骤]:1.写出一个小语言的文法,根据情况自由选择C语言或Pascal语言。
2.写出该小语言的算术表达式等价的LL(1)文法。
G[E]:其中E→TG G为E’G→+TG|∧∧为εT→FS S为T’S→*FS|∧F→i|(E)3.编写递归下降语法分析程序。
4.调试运行程序。
5.结果分析。
6.撰写实验报告。
实验代码#include<stdio.h>void E();void T();void E1();void T1();void F();char s[100];int i, SIGN;int main(){printf("请输入一个语句,以#号结束语句(直接输入#号推出)\n");while( 1 ){SIGN = 0;i=0;scanf("%s",&s);if( s[0] == '#')return 0;E();if(s[i]=='#')printf("正确语句!\n");printf("请输入一个语句,以#号结束语句\n");}return 1;}void E(){if(SIGN==0){T();E1();}}void E1(){if(SIGN==0){if(s[i]=='+'){++i;T();E1();}else if(s[i]!='#'&&s[i]!=')'){printf("语句有误!\n");SIGN=1;}}}void T(){if(SIGN==0){F();T1();}}void T1(){if(SIGN==0){if(s[i]=='*'){++i;F();T1();}else if(s[i]!='#'&&s[i]!=')'&&s[i]!='+'){printf("语句有误!\n");SIGN=1;}}}void F(){if(SIGN==0){if(s[i]=='('){++i;E();if(s[i]==')')++i;else if(s[i]== '#'){printf("语句有误!\n");SIGN=1;++i;}}else if(s[i]=='i')++i;else{printf("语句有误!\n");SIGN=1;}}}测试用例(1)输入i,预期显示语句正确!(2)输入iii,预期显示语句有误!(3)输入a,预期显示语句有误!(4)输入(i),预期显示语句正确!(5)输入(a),预期显示语句有误!(6)输入(i+i),预期显示语句正确!(7)输入(i+i,预期显示语句有误!(8)输入((i*i)+i)*i,预期显示语句正确!(9)输入((((i+i*i)))),预期显示语句正确!(10)输入(i+ia,预期显示语句有误!(11)输入i+i*i+i*a,预期显示语句有误!。
实验报告四递归下降语法分析程序设计
实验报告四递归下降语法分析程序设计《编译原理》实验报告实验序号: 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* 输⼊:每⾏含⼀个表达式的⽂本⽂件。
* 输出:分析成功或不成功信息。
* 创建⼈:余洪周 2006-12-8* 版本号:1.0********************************************************************* **/#include#include#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到⽂件尾。
实验二递归下降分析法实验报告
信息商务学院实验报告课程:编译原理实验名称:递归下降分析学号: *************名:***指导老师:***日期: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所示。
实验三递归下降分析器设计与实现编译原理实验报告
实验三递归下降分析器设计与实现编译原理实验报告一、引言递归下降分析器是编译原理中常用的一种语法分析方法。
它根据文法规则和输入的源代码,递归地进行语法分析,判断源代码是否符合给定的文法规则。
本实验旨在通过设计与实现一个简单的递归下降分析器,加深对编译原理中语法分析的理解。
二、实验目的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,经过递归下降分析器的分析,应该能正确判断其是否符合给定的文法规则。
六、实验总结递归下降分析器是编译原理中常用的一种语法分析方法。
通过实验三,我深入理解了递归下降分析器的原理和设计方法,并通过实现一个简单的递归下降分析器,加深了我对编译原理中文法规则和语法分析的理解。
在实验过程中,我学会了如何根据设计的文法规则来设计递归下降分析器的结构和算法。
我使用了编程语言实现了递归下降分析器的代码,并编写了相应的测试代码进行语法分析。
通过测试,我验证了递归下降分析器的正确性。
编译原理用递归下降法进行表达式分析报告实验报告材料
《编译原理》课程实验报告一. 实验题目 用递归下降法进行语法分析的方法二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是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)就说明两者可以相互替代。
最新编译原理实验(递归向下语法分析法实验)附C语言源码-成功测试
实验二递归向下分析法一、实验目和要求根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验内容(1)功能描述1、递归下降分析法的功能词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。
2、递归下降分析法的前提改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法,3、递归下降分析法实验设计思想及算法为G 的每个非终结符号U 构造一个递归过程,不妨命名为U。
U 的产生式的右边指出这个过程的代码结构:1)若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
2)若是非终结符号,则调用与此非终结符对应的过程。
当 A 的右部有多个产生式时,可用选择结构实现。
具体为:(1)对于每个非终结符号U->u1|u2|…|un处理的方法如下:U( ) { ch=当前符号;if(ch可能是u1字的开头) 处理u1的程序部分;else if(ch可能是u2字的开头)处理u2的程序部分;…else error()}(2)对于每个右部u1->x1x2…xn的处理架构如下:处理x1的程序;处理x2的程序;…处理xn的程序;(3)如果右部为空,则不处理。
(4)对于右部中的每个符号xi①如果xi为终结符号:if(xi= = 当前的符号){NextChar();return;}else出错处理②如果xi为非终结符号,直接调用相应的过程xi()说明:NextChar为前进一个字符函数。
(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输入出的格式如下:(1)E 盘建立一个文本文档" 222.txt"存储一个以#结束的符号串(包括+—*/()i#),在此位置输入符号串例如:i+i*i#(2)输出结果:i+i*i#为合法符号串备注:输入一符号串如i+i*#,要求输出为“非法的符号串” 函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《编译原理》实验报告实验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);是为了忽略分析文件中的换行或空格,之后进入分析阶段,根据返回值判断是否是合法的表达式。
在该程序中只有发现了非法字符才会返回0,否则就返回1,而对于合法的表达式,递归程序最后分析的字符就是换行符,不合法的表达式在未分析到换行符就会停止分析,所以根据最后分析的字符是否为换行符进一步确定是否为合法的表达式。
实验步骤首先将上述文法改写成LL(1)文法①消除左递归:exp →term texptexp →addop term texp | εAddop →+ | -term→factor ttermtterm →mulop factor tterm|εmulop →* | /factor →(exp) | id | number②求出每个非终结符的FIRST集合和FOLLOW集合:FIRST(exp)= FIRST(term)= FIRST(factor)={id, number, ( }FIRST(texp)={ ε,+, - }FIRST(Addop)={+, - }FIRST(tterm)={ ε,*, / }FIRST(mulop)={*, / }求出每个非终结符的FOLLOW集合:FOLLOW(exp)=FOLLOW(texp)={#, )}FOLLOW(Addop)=FOLLOW(mulop)={id, number, ( }FOLLOW(term)=FOLLOW(tterm)={+, -,#, ) }FOLLOW(factor)={ *,/,+,-,#,) }对于texp →addop term texp | ε:FIRST(Addop term texp)∩FOLLOW(texp)= φ;对于tterm →mulop factor tterm|ε:FIRST(mulop factor tterm)∩FOLLOW(tterm)= φ;而Addop →+ | - mulop →* | / factor →(exp) | id | number 显然也是符合LL(1)文法要求的,所以改写后的文法符合LL(1)文法,可以用自上而下的递归分析方法。
③为每个非终结符根据其产生式写一个分析子程序;④编写数字和字母识别程序,以便分离数字和标识符。
;⑤主函数调用递归程序进行分析,根据分析结果判断是否是合法表达式,并将所有识别到的表达式输出。
程序设计:#include <stdio.h>#include <string.h>number();id();int exp();int texp();int addop();int term();int tterm();int mulop();int factor();int islegal();void match(char t); FILE *resource;//测试文件FILE *result;//结果文件char lookahead;//全局变量void match(char t)//写入result文件,打印输出,并读取下一个{fprintf(result,"%c",lookahead);//向result写入printf("%c",lookahead);fscanf(resource,"%c",&lookahead);//读数据}number()//识别数字,如果遇到数字就一直接着读直到不是数字{while('0'<=lookahead&&lookahead<='9'){fprintf(result,"%c",lookahead);//写入printf("%c",lookahead);fscanf(resource,"%c",&lookahead);//读出}}id(){//识别标识符while((lookahead<='z'&& lookahead>='a')||(lookahead>='A'&& lookahead<='Z')||lookahead=='_'){while((lookahead<='z'&& lookahead>='a')||(lookahead>='A'&& lookahead<='Z')||lookahead=='_'||lookahead>='0'&&lookahead<='9'){fprintf(result,"%c",lookahead);//写入printf("%c",lookahead);fscanf(resource,"%c",&lookahead);//读}}}int addop()//Addop →+ | -{//分析+,-int i;if(lookahead=='+')//+{match('+');i=islegal();//判断下一个是否是合法字符,如果不是则返回0if(i)return 1;elsereturn 0;}else if(lookahead=='-')//-{match('-');i=islegal();if(i)return 1;elsereturn 0;}elsereturn 0;}int mulop()//mulop →* | / {//分析*,/int i;if(lookahead=='*'){match('*');i=islegal();if(i)return 1;elsereturn 0;}else if(lookahead=='/'){match('/');i=islegal();if(i)return 1;elsereturn 0;}elsereturn 0;}int exp()//exp →term texp{int i,j;while(!feof(resource)){if(lookahead=='('||'0'<=lookahead&&lookahead<='9'||(lookahead<='z'&& lookahead>='a')||(lookahead>='A'&& lookahead<='Z')||lookahead=='_')//FIRST(term)={id, number, ( }{i=term();if(i){j=texp();if(j){return 1;//当且仅当term和texp都返回1时才返回1 }else{return 0;}}else{return 0;}}else{return 0;;}}}int factor()//factor →(exp) | id | number{int i,m,n;if(lookahead=='('){match('(');i=exp();//返回1则继续分析if(lookahead==')'&&i){match(')');return 1;}elsereturn 0;}else if((lookahead<='z'&& lookahead>='a')||(lookahead>='A'&& lookahead<='Z')||lookahead=='_'){id();n=islegal();//判断读出的是否合法,不合法则不必接着分析if(n)return 1;elsereturn 0;}//id分析中自会匹配else if('0'<=lookahead&&lookahead<='9'){number();m=islegal();//判断读出的是否合法,不合法则不必接着分析if(m)return 1;elsereturn 0;}elsereturn 0;}int tterm()//tterm →mulop factor tterm|ε{//mulop,factor都为空或mulop,factor都为真则返回1int i,j,k;i=mulop();j=factor();if(i&&j){k=tterm();//调用自己继续分析直至mulop,factor都为空或仅其中之一返回真值,此时推出该函数return 1;}else if(!i&&!j) //mulop,factor都为空{return 1;}elsereturn 0;}int term()//term→factor tterm {//factor,tterm都为真则返回1 int i,j;i=factor();if(i){j=tterm();if(j)return 1;elsereturn 0;}elsereturn 0;}int texp()//texp →addop term texp | ε{//addop,term为空或addop,term为真int i,j,k;i=addop();j=term();if(i&&j){k=texp();//调用自己继续分析直至addop,term都为空或仅其中之一返回真值,此时推出该函数return 1;}else if(!i&&!j){return 1;//没必要继续向下分析,否则死循环}elsereturn 0;}int islegal()//当为'(',')','+','-','*','/',换行,字母,数字,下划线才合法{if(lookahead=='('||(lookahead<='9'&&lookahead>='0')||lookahead==')'||looka head=='/'||lookahead=='*'||lookahead=='+'||lookahead=='-'||(lookahead<='z'&& lookahead>='a')||(lookahead>='A'&& lookahead<='Z')||lookahead=='_'||lookahead=='\n'){return 1;}elsereturn 0;}void main(){int i;resource=fopen("work.cpp","r");if(resource==NULL){printf("fail to open!");}result=fopen("结果.txt","w");fscanf(resource,"%c",&lookahead);//读一个字符while(lookahead!=EOF){while((lookahead=='\n'||lookahead==' ')&&lookahead!=EOF)//空格或换行则接着读fscanf(resource,"%c",&lookahead);if(lookahead!=EOF){i=exp();//判断}if(i) //返回1{if(lookahead!='\n') //若没有分析到换行,则说明表达式不正确{while(lookahead!='\n')//打印该行{fprintf(result,"%c",lookahead);printf("%c",lookahead);fscanf(resource,"%c",&lookahead);}fprintf(result," error!\n");printf(" error!\n");}else //表达式分析到换行符正确{fprintf(result," right!\n");printf(" right!\n");}}else //返回0{while(lookahead!='\n')//打印该行{fprintf(result,"%c",lookahead);printf("%c",lookahead);fscanf(resource,"%c",&lookahead);}fprintf(result," error!\n");printf(" error!\n");}fscanf(resource,"%c",&lookahead); //读取下一个字符}fclose( result);fclose( resource);}实验结果及其分析:结果:被分析的文件work.cpp#include "stdio.h"#include "string.h"#include<stdio.h>main(){int i;3+466/9e/i&&;(666+op)*y;(p+8+9+i)*lprintf("%c",&i)((y+i)+p)*8i=1fgetc(fp)6+re==1y-6_a1}输出到“结果.txt”中的容:#include "stdio.h" error! #include "string.h" error! #include<stdio.h> error! main() error!{ error!int i; error!3+4 right!66/9 right!e/i right!&&; error!(666+op)*y; error!(p+8+9+i)*l right!printf("%c",&i) error! ((y+i)+p)*8 right!i=1 error!fgetc(fp) error!. .6+re==1 error!y-6 right!_a1 right!} error!分析:这个实验是每行一个表达式,且每行以换行符终结,故需要按行分析并打印输出,且对于每个非终结符的子程序要有返回值以便确定是否继续向下分析。