编译原理实验报告——实验二 递归下降分析
编译原理实验报告算术表达式递归下降分析程序设计
武汉工程大学计算机科学与工程学院《编译原理》实验报告一、实验目的(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下: E E+T | TT T*F | FF(E) | i设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归函数,函数的名字表示规则左部的非终结符;函数体按规则右部符号串的顺序编写。
三、设计分析(1)消去该文法左递归,得到文法:E TE1E1+TE1|εT FT1T1*FT1|εF(E)| I(2)根据LL(1)文法的判断条件,计算这个文法的每个非终结符的FIRST 集和FOLLOW集,经验证,改后的文法已经是LL(1)文法。
(3)最后构造递归下降分析程序,每个函数名是相应的非终结符,函数体则是根据右部符号串的结构编写。
a.当遇到非终结符时,如:+。
则编写语句 if(当读来的输入符号 == +) 读下一个输入符号b.当遇到非终结符时,例如:T。
则编写语句调用T()。
c.当遇到非终结符ε规则时,例如:Tε。
则编写语句 if(当前读来的输入字符不属于FOLLOW(T)) error()d.当某个非终结符的规则有很多个候选式时。
按LL(1)文法的条件能唯一的选择一个候选式进行推导。
(4)递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。
因此需要分别构造E,E1,T,T1,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。
Scaner函数用于字符串的推进,input函数用于字符串的输入。
四、程序代码#include <>#include <>#include <iostream>using namespace std;char a[80];char sym;int i=0;void E();void E1();void T();elseError();}else if (sym =='i')Scaner();elseError();}五、测试用例1.输入的字符串只含有一个字符时:输入 i#a#2.输入的字符串含有 + 时:输入 ++#输入 i++#输入 i+i#3.输入的字符串含有 * 时:输入 **#输入 **i#输入 *i*#输入 i*i#i*i*#3.输入的字符串含有()时:输入()#(i)#4.输入的字符串含有多种字符:输入i+i*i#(i+i)*i#(i+i)*(i+i)#(i+*#。
编译原理 递归下降词法分析
编译原理实验报告—递归下降分析法程序实验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可以产生字符-。
实验二 递归下降分析法的实现
实验二递归下降分析法的实现一、实验目的实现一个递归下降语法分析程序,识别用户输入的算术表达式。
二、实验主要内容1、文法如下:E→TE`E’→+TE’|-TE’|εT→FT`T’→*FT’|/FT’|εF→(E)|i2、求取各非终结符的First及Follow集合3、编程实现下降递归分析法,识别从键盘输入的关于整数或浮点数的算术表达式(在此,上述文法中的i代表整数或浮点数)4、对于语法错误,要指出错误具体信息。
5、运行实例如下:三、提示1、纸质实验报告内容:实验内容、非终结符的First及Follow集合、正确表达式与错误表达式各举一例进行测试并给出结果、核心源代码。
2、将本次实验代码(.c、.cpp、.java等代码文件,删除编译产生的所有其他文件,不要打包)在规定时间内以作业附件(不可在线编辑、粘贴代码)的形式提交至网站,自己保存以备课程设计(本部有毕业设计要求的学生)参考。
3、纸质实验报告提交时间:临时要求。
实验指导(参考)一、实验步骤1、求取各非终结符的First及Follow集合;2、设计几个函数E(); Ep(); T(); Tp(); F();运用First集合进行递归函数选择,运用Follow集合进行出错情况判断;3、设计主函数:从键盘接受一个算术表达式串;在串尾添加尾部标志’#’;调用函数E()进行递归下降分析。
二、如何识别整数与浮点数在函数F()中要涉及到如何识别整数与浮点数。
识别的方法是:只要碰到‘0’~‘9’之间的字符就一直循环,循环到不是数字字符与小数点字符’.’为止,其间要运用一个标志变量来保证最多只能出现一个小数点,否则应该报错。
上述循环结束即表示识别了一个数,也即表达式文法中的i。
编译原理_实验二_语法分析_递归下降分析器设计_实验报告
递归下降分析器设计一、实验/实习过程内容:利用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基本的使用。
编译原理用递归下降法进行表达式分析实验报告
《编译原理》课程实验报告题目用递归下降法进行表达式分析专业班级学号姓名一.实验题目用递归下降法进行语法分析的方法二.实验日期三.实验环境(操作系统,开发语言)操作系统是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)就说明两者可以相互替代。
编译原理递归下降
《编译原理》课程实验实验二:自顶向下的语法分析:递归下降法1、实验目的:编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
2、实验要求:文法(教材199页)(1)把词法分析作为语法分析的子程序实现(5分)(2)独立的语法分析程序(4分)(3)输入串以‘#’结束,输出成功(success)或出错(error)、指出出错位置(行、列以及错误类型)#include<iostream>#include<ctype.h>#include<fstream>#include<string.h>#include<malloc.h>using namespace std;ifstream fp("in.txt",ios::in);char cbuffer;char *key[13]={"if","else","for","while","do","return","break","continue","int","void" ,"main","begin","end"}; //关键字char *border[8]={ "," , ";" , "{" , "}" , "(" , ")" ,"//","\""}; //分界符char *arithmetic[6]={"+" , "-" , "*" , "/" , "++" , "--"}; //运算符char *relation[7]={"<" , "<=" , "=" , ">" , ">=" , "==" ,"!="}; //关系运算符char *lableconst[80]; //标识符int constnum=40;int lableconstnum=0;int colnum = 1, linenum=1; //统计常数和标识符数量int type1, type2;int search(char searchchar[],int wordtype){int i=0,t=0;switch (wordtype){case 1:{ for (i=0;i<=12;i++) //关键字{if (strcmp(key[i],searchchar)==0)return(i+1);}return(0);}case 2:{for (i=0;i<=6;i++) //分界符{if (strcmp(border[i],searchchar)==0)return(i+1);}return(0);}case 3:{for (i=0;i<=5;i++) //运算符{if (strcmp(arithmetic[i],searchchar)==0)return(i+1);}return(0);}case 4:{for (i=0;i<=6;i++) //关系运算符{if (strcmp(relation[i],searchchar)==0)return(i+1);}return(0);}case 5:{for (t=40;t<=constnum;t++) //常数{if (strcmp(searchchar,lableconst[t])==0)//判断该常数是否已出现过return(t+1);}lableconst[t-1]=(char *)malloc(sizeof(searchchar));//为新的元素分配内存空间strcpy(lableconst[t-1],searchchar);//为数组赋值lableconst指针数组名constnum++; //常数个数自加return(t);}case 6:{for (i=0;i<=lableconstnum;i++){if (strcmp(searchchar,lableconst[i])==0) //判断标识符是否已出现过return(i+1);}lableconst[i-1]=(char *)malloc(sizeof(searchchar));strcpy(lableconst[i-1],searchchar);lableconstnum++; //标识符个数自加return(i);}default:cout<<"错误!";return 0;}}char alphaprocess(char buffer) //字符处理过程{int atype;int i=-1;char alphatp[20];while (((isalpha(buffer))||(isdigit(buffer))) && !fp.eof()){alphatp[++i]=buffer;fp.get(buffer);}alphatp[i+1]='\0';//在末尾添加字符串结束标志if (atype=search(alphatp,1)){cout<<alphatp<<"\t\t\t"<<"关键字"<<endl;type1 = 0;}else{atype=search(alphatp,6); //标识符cout<<alphatp<<"\t\t\t"<<"标识符"<<endl;type1 = 1;}type2 = atype;return(buffer);}char digitprocess(char buffer) //数字处理过程{int i=-1;char digittp[20];int dtype;while((isdigit(buffer)||buffer=='.'||buffer=='e'||buffer=='+'||buffer=='-')&& !fp.eof()) {digittp[++i]=buffer;fp.get(buffer);}digittp[i+1]='\0';dtype=search(digittp,5);cout<<digittp<<"\t\t\t"<<"数据"<<endl;type1 = 8;type2 = dtype;return(buffer);}char otherprocess(char buffer) //分界符、运算符、逻辑运算符、等{int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){fp.get(buffer);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,3)) //判断该运算符是否是//由连续的两个字符组成的{cout<<othertp<<"\t\t\t"<<"运算符"<<endl;fp.get(buffer);type1 = 2;goto out;}else//单字符逻辑运算符{othertp[1]='\0';cout<<othertp<<"\t\t\t"<<"逻辑运算符"<<endl;type1 = 3;goto out;}}if (otype=search(othertp,4)) //关系运算符{fp.get(buffer);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)) //判断该关系运算符是否是//由连续的两个字符组成的{cout<<othertp<<"\t\t\t"<<"关系运算符"<<endl;fp.get(buffer);type1 = 4;goto out;}else//单字符逻辑运算符{othertp[1]='\0';cout<<othertp<<"\t\t\t"<<"逻辑运算"<<endl;type1 = 5;goto out;}}if (buffer=='!') //"=="的判断{fp.get(buffer);if (buffer=='=')//cout<<"!= (2,2)\n";fp.get(buffer);type1 = 6;goto out;}else{if (otype=search(othertp,2)) //分界符{cout<<othertp<<"\t\t\t"<<"分界符"<<endl;fp.get(buffer);type1 = 7;goto out;}}if ((buffer!='\n')&&(buffer!=' '))cout<<"错误!,字符非法"<<"\t\t\t"<<buffer<<endl;fp.get(buffer);out:type2 = otypetp;return(buffer);}void getWord(){type1 = -1;while(type1 == -1){if (fp.eof()) break;colnum++;if(cbuffer=='\n'){linenum++;colnum = 1;fp.get(cbuffer);}else if (isalpha(cbuffer)){cbuffer=alphaprocess(cbuffer);}else if (isdigit(cbuffer)){cbuffer=digitprocess(cbuffer);}elsecbuffer=otherprocess(cbuffer);}}string eText;bool hasError;void setError(string text) {hasError = true;eText = text;}void checkExpression();void checkFactor() {cout << type1 << " " << type2 << endl;if (type1 == 1 || type1 == 8) getWord();else if (type1 == -1) setError("缺少值或变量。
编译原理-实验报告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]='#';}。
编译原理语法分析递归下降子程序实验报告
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
递归下降程序实验报告
一、实验目的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. 消除二义性:确保文法中每个产生式都只有一个确定的意义。
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. 实验分析通过本次实验,我们深入了解了递归下降分析法的原理和应用。
在编写递归下降分析程序的过程中,我们学会了如何根据文法设计程序结构,以及如何实现分析过程。
同时,我们还掌握了如何对输入的符号串进行分析,并输出分析结果。
实验过程中,我们遇到了一些问题,如消除二义性、消除左递归、提取左因子等。
通过查阅资料和不断尝试,我们成功解决了这些问题。
实验二_递归下降分析器设计报告
递归下降分析器设计1、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
2、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:E-->E+T|TT-->T*F|FF-->(E)|i3、设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。
4、设计分析这个题目属于比较典型的递归下降语法分析。
需要先将原算术表达式方法改写为LL(1)文法为:E-->TE'E'-->+TE'|εT-->FT'T'-->*FT'|εF-->(E)|i然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。
具体方法为:(1)当遇到终结符a时,则编写语句If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到非终结符A时,则编写语句调用A()。
(3)当遇到A-->ε规则时,则编写语句If(当前读到的输入符号不属于Follow(A))error()(4)当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能唯一地选择一个候选式进行推导.//源程序代码#include<iostream>#include<string>using namespace std;void E();void E1();void T();void T1();void F();string s;int i;int ERR;int SwitchNum;int main(){do{s="";i=0;ERR=0;cout<<"Please enter your sentence:"<<endl; cin>>s;s.resize(s.size()+1);s[s.size()-1]='#';E();if(s[i]=='#')cout<<"success"<<endl;elsecout<<endl;cout<<"输入一个整数继续,其它类型退出:";}while(cin>>SwitchNum);return 0;}void E(){if(ERR==0){T();E1();}}void E1(){if(ERR==0){if(s[i]=='+'){++i;T();E1();}else if(s[i]!='#'&&s[i]!=')'){cout<<"fail"<<endl;ERR=1;}}void T(){if(ERR==0){F();T1();}}void T1(){if(ERR==0){if(s[i]=='*'){++i;F();T1();}else if(s[i]!='#'&&s[i]!=')'&&s[i]!='+') {cout<<"fail"<<endl;ERR=1;}}}void F(){if(ERR==0){if(s[i]=='('){++i;E();if(s[i]==')')++i;else if(s[i]== '#'){cout<<"fail"<<endl;ERR=1;++i;}}else if(s[i]=='i')++i;{cout<<"fail"<<endl;ERR=1;}}}测试用例(1)输入i,预期显示success(2)输入iii,预期显示fail(3)输入a,预期显示fail(4)输入(i),预期显示success(5)输入(a),预期显示fail(6)输入(i+i),预期显示success (7)输入(i+i,预期显示fail(8)输入((i*i)+i)*i,预期显示success (9)输入((((i+i*i)))),预期显示success (10)输入(i+ia,预期显示fail(11)输入i+i*i+i*a,预期显示fail。
编译原理实验(递归向下语法分析法实验)
//定义一个数组大小常量
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>
编译原理实验报告二
深圳大学实验报告课程名称:编译原理实验项目名称:语法分析--递归下降法学院:计算机与软件专业:软件工程指导教师:张小建报告人:文成学号:2011150259 班级: 2 实验时间:2013-12-25实验报告提交时间:2013-12-26教务部制一、实验目的:掌握自顶向下的语法分析法——递归下降法。
二、实验内容:用递归下降法对如下所定义的逻辑表达式进行语法分析。
1 L→ L || A2 L→ A3 A→ A && R4 A→ R5 R→ [ L ]6 R→ ! L7 R→ E >= E8 R→ E > E9 R→ E <= E10 R→ E < E11 R→ E == E12 R→ E != E13 R→ E14 E→ E + T15 E→ T16 T→ T * F17 T→ F18 F→ ( E )19 F→ n // 数20 F→ i // 标识符三、实验设计:1、消除该文法的左递归(产生式1、3、14、16);产生式(1)L→ L || A (2)L→ A消除左递归得到:L→ A L' L'→ || A L' | з产生式(3)A→ A && R (4)A→ R消除左递归得到:A→ RA' A'→ && RA' | з产生式(14)E→ E + T (15)E→ T消除左递归得到:E→ TE' E'→ + TE' | з产生式(16)T→ T * F (17)T→ F消除左递归得到:T→ FT' T'→ *FT' | з2、通过抽取公共左因子(产生式7 ~ 12),对该文法进行LL(1)改造;产生式7~127 R→ E >= E8 R→ E > E9 R→ E <= E10 R→ E < E11 R→ E == E12 R→ E != E抽取公共左因子:R→ ER'R'→ >=E | >E | <=E | <E | ==E | !=E3、证明最终得到的文法为LL(1)文法。
实验二递归下降分析法实验报告
信息商务学院实验报告课程:编译原理实验名称:递归下降分析学号: *************名:***指导老师:***日期: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.熟悉编译程序的编制。
[实验内容]:根据某文法,构造一基本递归下降语法分析程序。
给出分析过程中所用的产生式序列。
[实验要求]:1.选择一个文法,进行实验,可选的文法包括以下三个:P190 4.8P190 4.9P190 4.102.设计语法分析程序的输出形式(输出应为语法树或推导),一个可以参考的例子,可见图1。
3.编写递归下降语法分析程序(参考P148-149 Topdown parsing byrecursive-descent),实现基本的递归下降分析器,能够分析任给的符号串是否为该文法所定义的合法句子。
实验报告中要说明分析使用的方法。
4.根据所作业题选项e所给出的input,生成并输出分析过程中所用的产生式序列(show the actions of parser):1 产生式12 产生式2……5.自已设计一个不合法的句子,作为输出进行分析,给出结果。
[实验过程]本次实验选择的文法为P190 4.8lexp->atom|listatom->number|identifierlist->(lexp-seq)lexp-seq->lexp lexp-seq1.写出实现的算法,并画流程图。
本次实验采用递归下降算法,算法流程图如下图1-1:图1-1 算法流程图2.根据你选择的文法,分析左递归或左因子是否会影响本算法的结果。
会影响本算法的结果。
递归下降分析法要求的文法是LL(1)文法,需要消除左递归和左因子的影响。
如果存在左因子,对相同的字符跳转到不同的函数,无法实现递归。
3.列举实验设计过程中出现的问题及解决的方法(至少3条,选择实验中最困扰的问题)。
1).会多次输出accept/error结果解决方案:所有的递归函数返回类型为int,若accept返回1,error返回0,在main主函数中统一判断输出语句。
编译原理递归下降分析器 C语言
数学与软件科学学院实验报告学期:2015至2016第2学期2016年3月21日课程名称:编译原理专业:信息与计算科学2013级5班实验编号:2实验名称:递归下降分析器指导教师:王开端姓名:李丹学号:2013060510实验成绩:实验二递归下降分析器实验目的:通过设计、编制、调试递归下降语法分析程序,对输入的符号串进行分析匹配,观察输入符号串是否为给定文法的句子。
实验内容:根据文法G[E]设计递归下降分析器并分析输入串)(*321i i i +是否为文法的句子。
G[E]:E→E+T|TT→T*F|F F→(E)|i实验步骤:在进行递归下降分析法之前,必须对文法进行左递归和回溯的消除。
1消除左递归直接消除见诸于产生式中的左递归比较容易,其方法是引入一个新的非终结符,把含有左递归的产生式改为右递归。
文法G[E]经过消去直接左递归后得到文法G’[E]为:G’[E]:iE F FT T FT T TE E TE E |)(|'*''|'''→→→+→→εε2消除回溯回溯发生的原因在于候选式存在公共的左因子。
一般情况下,设文法中关于A 的产生式为ji i A ββδβδβδβ|...|||...||121+→,那么,可以把这些产生式改写为⎩⎨⎧→→+ij i A A A ββββδ|...|'|...||'11经过反复提取左因子,就能把每个非终结符(包括新引进者)的所有候选首字符集变为两两不相交(既不含有公共左因子)。
3什么是递归下降分析法递归下降分析法是一种自顶向下的分析方法,文法的每个非终结符对应一个递归过程(函数)。
分析过程就是从文法开始符出发执行一组递归过程(函数),这样向下推导直到推出句子;或者说从根节点出发,自顶向下为输入串寻找一个最左匹配序列,建立一棵语法树。
在不含左递归和每个非终结符的所有候选终结首字符集都两两不相交条件下,我们就可能构造出一个不带回溯的自顶向下的分析程序,这个分析程序是由一组递归过程(或函数)组成的,每个过程(或函数)对应文法的而一个非终结符。
实验二(递归下降分析)
实验二递归下降语法分析一.实验目的1、按照语言的语法要求编写文法的规则2、转化文法的规则,使之具有EBCF,消除左递归和左因子3、掌握编程形式的语法分析器的实现二.实验内容在TINY计算机语言的编译程序的词法分析部分实现的基础上,采用递归下降的方法实现语法分析,形成语法树。
语法分析的输入是记号串,按照从左到右扫描,按照文法规则的要求,判断语句是否符合文法要求,如果符合要求则形成语法数,不符合则指出原因。
为了简化程序的编写,对语法有具体如下的要求:(1)只有5中语句if、repeat、read、write、assignment。
(2)read只作用一个变量,实现输入。
(3)write只作用一个表达式,实现输出。
(4)表达式只有两类:布尔表达式,只用于if和repeat语句的测试,算术表达式采用左结合和优先级的方式组成。
(5)没有变量的声明,仅仅在赋值时采用隐性的方式说明,只有整型变量;(6)每个语句序列采用‘;’的形式分开,最后一个语句没有分号(7)没有函数或过程三.实验要求要求实现语法分析程序的以下功能:(1)在实现之前首先实现EBNF,消除左递归和左因子,为递归下降程序做好准备(2)对于语句和表达式采用枚举的形式定义,形成一个统一的树结点结构(3)把正确源程序的首先经过词法分析形成二元式记号提供给语法分析程序(4)如果出现错误,指出错误的位置和类型(5)把语法树按照树的前序遍历的形式把所有的结点按照某种形式输出语法分析进行具体的要求:(1)语法分析的具体功能实现是一个函数TreeNode* parse(),分析记号串,形成一个语法数。
(2)编写一个单独的函数parseTree(TreeNode*)遍历整个语法树,把每个结点信息输出程序:头文件:#include<string>using namespace std;enum WordType {WRONG, NUMBER, IDENTIFIER, IF, THEN, ELSE, END, //7REPEAT, UNTIL, READ, WRITE, FALSE, PLUS, SUBTRACT, MULTIPLY, //16DIVIDEY, EQUAL, LESSTHAN, SEMICOLON, FINAL, ASSIGNMENT, S_BRACKET_L, S_BRACKET_R,//24LINE_FEED, SPACE, TAB, BIG_BRACKET_L, BIG_BRACKET_R}; //29void CiFa ();void Yufa2 ();string IntToStr(int n);//将数字转换成字符串int EqulStr (string s1, string s2);//比较两个字符串是否相等,相等返回1,否则返回0源文件:头文件中函数:#include<iostream>#include<string>#include<sstream>#include<stdexcept>#include"head.h"using namespace std;string IntToStr(int n){ostringstream result;result << n;return result.str();}int EqulStr (string s1, string s2){if (s1 == s2)return 1;elsereturn 0;}词法分析:#include<iostream>#include<iomanip>#include<ctype.h>#include<fstream>#include<string>#include"head.h"using namespace std;enum CharType {ALPHABET, OTHER};enum WrongType1 {ZERO, ALP_NUM, NUM_ALP, UNLEAGL_S, NO_MATCH, UNKNOW};char *Words [] = {"wrong", "number", "identifier", "if", "then", "else", "end",//7 "repeat", "until","read", "write", "false", "+", "-", "*", //16"/", "=", "<", ";", "$",":=", "(", ")",//24"\n", " ", " ", "{", "}"}; //29typedef struct{char *str;int wordtype;}Two;char ArrayChar[100], cbuffer;int i=-1, numline = 1, wordtype;string LineChar;Two T;ifstream fp("source.txt",ios::in);ofstream outfile ("cifa.txt", ios::out);void CiFa (){Two GetToken();if (!fp)cout<<"文件打开错误!!"<<endl;else{cout << setiosflags (ios::left) << setw (6) << "行数" << "(";cout << setiosflags (ios::left) << setw (10)<< "类别编码" << ", ";cout << setiosflags (ios::left) << setw (20) << "字符" << ")" << endl;fp.get (cbuffer);while (!fp.eof ()){GetToken();}outfile << numline << "," << FINAL << ",";}cout << "第" << numline << " 行所有字符:" << LineChar << endl;fp.close ();outfile.close ();}int Match(char str[], int chartype)//查找匹配的字符{int i;switch (chartype){case ALPHABET:for (i = IF; i <= FALSE; i++){if (strcmp(Words[i],str) == 0)return i;}case OTHER:for (i = PLUS; i <= S_BRACKET_R; i++){if (strcmp(Words[i],str) == 0)return i;}}return WRONG;}void TypeWrong (int wrongtype, int line){switch (wrongtype){case ZERO:break;case ALP_NUM:cout << "字母后面不能紧跟数字!";break;case NUM_ALP:cout << "数字后面不能紧跟字母!";break;case UNLEAGL_S:cout << "非法特殊符号!";break;case NO_MATCH:cout << "没有与第" << line << " 行“{”匹配的“}”!";break;default :cout << "其它类型错误!";break;}}Two ConvertTwo (char str[], int wordtype, int wrongtype, int numline, int line)//进行二元转换{Two T;T.wordtype = wordtype;T.str = str;cout << setiosflags (ios::left) << setw (6) << numline << "(";cout << setiosflags (ios::left) << setw (10) << T.wordtype << ", ";cout << setiosflags (ios::left) << setw (20) << T.str << ")";if (T.wordtype == WRONG)TypeWrong (wrongtype, line);cout << endl;outfile << numline << "," << T.wordtype << "," ;return T;}void HandleAlphabet ()//首字符为字母时的处理{bool mark = true;while(!fp.eof() && isalpha(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isdigit (cbuffer)){mark = false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark){wordtype = Match(ArrayChar, ALPHABET);T = ConvertTwo(ArrayChar,(IDENTIFIER > wordtype ? IDENTIFIER : wordtype), ZERO, numline, numline);}elseT = ConvertTwo(ArrayChar,WRONG, ALP_NUM, numline, numline);}void HandleNumber ()//首字符为数字时的处理{bool mark = true;while (!fp.eof() && isdigit(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isalpha(cbuffer)){mark = false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark)T = ConvertTwo(ArrayChar, NUMBER, ZERO, numline, numline);elseT = ConvertTwo(ArrayChar,WRONG, NUM_ALP, numline, numline);}void DeleteNote ()//删除注释{int record = numline;while (!fp.eof() && cbuffer != '}'){fp.get(cbuffer);while (!fp.eof() && cbuffer != '}'){if (cbuffer == '\n'){ArrayChar [i + 1] = '\0';LineChar += ArrayChar;cout << "第" << numline << " 行所有字符:" << LineChar << endl;LineChar = "";numline++;i = -1;fp.get(cbuffer);}ArrayChar[++i]=cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';if (cbuffer == '}'){ArrayChar [++i] = '}';ArrayChar[i + 1]='\0';}else{T = ConvertTwo("", WRONG, NO_MATCH, numline, record);}}LineChar += ArrayChar;fp.get(cbuffer);}void HandleOther ()//字符为特殊字符时的处理{ArrayChar [++i] = cbuffer;if (ArrayChar [i] == '{')//删除注释{DeleteNote ();}else//其他字符{fp.get(cbuffer);ArrayChar [++i] = cbuffer;ArrayChar[i + 1] = '\0';char Temp1 [2];Temp1 [0] = ArrayChar [0];Temp1 [1] = '\0';if (!(wordtype = Match(ArrayChar, OTHER)))//当双字符没有匹配的时候,看单字符是否有匹配的{ArrayChar [i] = '\0';if (!wordtype)wordtype = Match(Temp1, OTHER);}else{fp.get(cbuffer);while (!fp.eof() && cbuffer != '\n' && cbuffer != ' ' && cbuffer != ' '&& !isalpha(cbuffer) && !isdigit(cbuffer)){ArrayChar [++i] = cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';wordtype = Match(ArrayChar, OTHER);}LineChar += ArrayChar;T = ConvertTwo(ArrayChar, wordtype, (wordtype > 0 ? 0: UNLEAGL_S), numline, numline);}}Two GetToken(){if(cbuffer == '\n')//忽略换行符{cout << "第" << numline << " 行所有字符:" << LineChar << endl;numline++;LineChar = "";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略空字符{LineChar += " ";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略制表符{LineChar += " ";fp.get(cbuffer);}else if (isalpha(cbuffer))//判断是否是字母{HandleAlphabet ();}else if (isdigit(cbuffer))//判断是否是数字{HandleNumber ();}else//其他字符HandleOther ();i = -1;return T;}语法分析:#include <iostream>#include <iomanip>#include <ctype.h>#include <fstream>#include <string>#include <sstream>#include <stdexcept>#include "head.h"using namespace std;ifstream fp2("cifa.txt",ios::in);int SPro ();//1int SStm ();//2int SStms ();//3int SSta ();//4int SIf ();//5int SRep ();//6int SAss ();// 7int SRea ();//8int SWri ();//9int SExp ();//10int SCom ();//11int SSim ();//12int SSims ();//13int SAdd ();//14int STer ();//15int STers ();//16int SMul ();//17int SFac ();//18char lastline [4], line [4], ch2[4];bool OK = true;void GetWord (char *line, char *ch2){strcpy_s (lastline, line);fp2.getline (line, 3, ',');fp2.getline (ch2, 3, ',');}void Yufa2 (){CiFa ();if (!fp2)cout<<"文件打开错误!!"<<endl;else{cout << "文件打开成功!" << endl;GetWord (line, ch2);while (!EqulStr (ch2, IntToStr (FINAL)))SPro ();if (OK)cout << "OK 源文件符合该文法!" << endl;elsecout << "Wrong 源文件不符合该文法!" << endl;}fp2.close ();}int SPro ()//1{if (SStm ())return 1;//如果此次读入的第一个字符不是开始符号,则继续读取下一个cout << "第" << lastline << "行错误!" << endl;GetWord (line, ch2);OK = false;return 0;}int SStm ()//2{if (SSta ()){if (SStms ())return 1;elsecout << "第 " << lastline << " 行缺少语句的结束符;!" << endl;OK = false;return 1;}return 0;}int SStms ()//3{if (EqulStr (ch2, IntToStr (SEMICOLON))){GetWord (line, ch2);if (SSta ()){if (SStms ())return 1;elsecout << "第 " << lastline << " 行缺少有效的语句!" << endl;}elsecout << "第 " << lastline << " 行 ; 后面没有有效的语句!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE)) || EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (FINAL)))return 1;return 0;}int SSta ()//4{if (SIf () || SRep () || SAss () || SRea () || SWri ())return 1;return 0;}int SIf ()//5{if (EqulStr (ch2, IntToStr (IF))){GetWord (line, ch2);if (SExp ()){if (EqulStr (ch2, IntToStr (THEN))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (END))){GetWord (line, ch2);return 1;}else if (EqulStr (ch2, IntToStr (ELSE))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (END))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行缺少语句的结束符 end!" << endl;}}else{cout << "第 " << lastline << " 行 else 后面没有有效的语句!" << endl;}}else{cout << "第 " << lastline << " 行缺少语句的结束符 end!" << endl;}}else{cout << "第 " << lastline << " 行缺少关键字 else!" << endl;}}else{cout << "第 " << lastline << " 行 then 后面没有有效的语句!" << endl;}}elsecout << "第 " << lastline << " 行 if 后面没有有效的表达式!" << endl;OK = false;return 1;}return 0;}int SRep ()//6{if (EqulStr (ch2, IntToStr (REPEAT))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (UNTIL))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 until 后面没有有效的表达式!" << endl;}else{cout << "第 " << lastline << " 行缺少关键字 until!" << endl;}}elsecout << "第 " << lastline << " 行 repeat 后面没有有效的语句!" << endl;OK = false;return 1;}return 0;}int SAss ()//7{if (EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);if (EqulStr (ch2, IntToStr (ASSIGNMENT))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 := 后面没有有效的表达式!" << endl;}else{cout << "第 " << lastline << " 行缺少关键字 :=!" << endl;}OK = false;return 1;}return 0;}int SRea ()//8{if (EqulStr (ch2, IntToStr (READ))){GetWord (line, ch2);if (EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行 read 后面没有有效的标识符!" << endl;}OK = false;return 1;}return 0;}int SWri ()//9{if (EqulStr (ch2, IntToStr (WRITE))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 write 后面没有有效的表达式!" << endl;OK = false;return 1;}return 0;}int SExp ()//10{if (SSim ()){if (SCom ()){if (SSim ())return 1;elsecout << "第 " << lastline << " 行缺少(或者数字或者标识符!" << endl;OK = false;}return 1;}return 0;}int SCom ()//11{if (EqulStr (ch2, IntToStr (LESSTHAN)) || EqulStr (ch2, IntToStr (EQUAL))){GetWord (line, ch2);return 1;}return 0;}int SSim ()//12{if (STer ()){if (SSims ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;OK = false;return 1;}return 0;}int SSims ()//13{if (SAdd ()){if (STer ()){if (SSims ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;}elsecout << "第 " << lastline << " 行缺少(或者数字或者标识符!" << endl;OK = false;return 1;}elseif (EqulStr (ch2, IntToStr (THEN)) || EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE))|| EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (S_BRACKET_R)) || EqulStr (ch2, IntToStr (LESSTHAN))|| EqulStr (ch2, IntToStr (EQUAL)) || EqulStr (ch2, IntToStr (FINAL)) || EqulStr (ch2, IntToStr (SEMICOLON)))return 1;return 0;}int SAdd ()//14{if (EqulStr (ch2, IntToStr (PLUS)) || EqulStr (ch2, IntToStr (SUBTRACT))){GetWord (line, ch2);return 1;}return 0;}int STer ()//15{if (SFac ()){if (STers ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;OK = false;return 1;}return 0;}int STers ()//16{if (SMul ()){if (SFac ()){if (STers ())return 1;elsecout << "第 " << lastline << " 行缺少有效的表达式!" << endl;}elsecout << "第 " << lastline << " 行缺少有效的表达式!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (THEN)) || EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE))|| EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (S_BRACKET_R)) || EqulStr(ch2, IntToStr (LESSTHAN))|| EqulStr (ch2, IntToStr (EQUAL)) || EqulStr (ch2, IntToStr (FINAL)) || EqulStr (ch2, IntToStr (SEMICOLON))|| EqulStr (ch2, IntToStr (PLUS)) || EqulStr (ch2, IntToStr (SUBTRACT)))return 1;return 0;}int SMul ()//17{if (EqulStr (ch2, IntToStr (MULTIPLY)) || EqulStr (ch2, IntToStr (DIVIDEY))){GetWord (line, ch2);return 1;}return 0;}int SFac ()//18{if (EqulStr (ch2, IntToStr (S_BRACKET_L))){GetWord (line, ch2);if (SExp ()){if (EqulStr (ch2, IntToStr (S_BRACKET_R))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行表达式后面缺少符号)!" << endl;}}elsecout << "第 " << lastline << " 行(后面缺少有效的表达式!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (NUMBER)) || EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);return 1;}return 0;}主函数:#include<iostream>#include<iomanip>#include<ctype.h>#include<fstream>#include<string>#include"head.h" using namespace std; int main (){Yufa2 ();system ("pause");return 0;}实验。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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{
9
print(); return(1); } } } /*移位*/ void myAdvance() { int i; if (ip < strlen(st)) { ip = ip + 1; sym1(); } } /*main 函数*/ void main() { gets(st); init(); printf("所用产生式\t 符号栈\t\t 输入串\n"); printf("\t\t"); printf("#E\t\t"); print(); myE(); if (sym!='#' || tz==1) { printf("error\n"); tz = 0; } else printf("right\n"); } 六、实验者自评(主要从实验态度、方法、效果上给一个客观公正的自我评价) 通过这次实验知道了递归下降分析的过程,刚开始这个程序我只是按照实验指导书上 给出的流程图以及要求写了最简单的一种,但是不能把分析过程显示出来,并且还有地方 有错,并没有达到老师要求。后来经过修改才体现了分#39;->^\t\t"); printf("#\t\t"); print(); return(1);
} } else
return(0); } /*判断乘除*/ int myT() {
printf("T->FT'\t\t"); printf("#E'T'F\t\t"); print(); int p; p=myF(); if(p) { while( sym=='*'||sym=='/') {
10
通过本次试验,我能够设计、编制、调试一个递归下降语法分析程序,实现对词法分 析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法,掌握了从 源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法,理解了词法分析 的实现方法、
11
return(1); else
return(0); }
if (sym != ')' ) { printf("error\n"); tz = 1; return(0);
} else { printf("F->(E)\t\t"); printf("#E'T'(E)\t"); print(); myAdvance(); printf("\t\t"); printf("#E'T'\t\t");
2
四、讨论与分析 根据递归下降法分析法和分析对象,可以得出下面的流程图。 用递归下降法分析上述算术表达式的框图,如图 3-4 所示。 这里,ZC 过程为总控程序,主要完成: (a)通知外界键入算术表达式; (b)控制E过程分析算术表达式; (c)根据分析结果之正误,分别通知外界不同的信息。 ZC 过程被设计成可以分析无穷多个算术表达式。E、T 和 F 三个过程分别对应〈算术 表达式〉、〈项〉和〈因式〉三个产生式的处理。它们用到两个公共过程。一个是函数 过程 SYM,它负责从输入字符串 ST 中取出下一个字符,并存入 SYM 中等待分析。另一个 过程 ADVANCE 负责剔除 ST 中的首字符。
编译原理实验报告
实验名称: 实验类型: 指导教师: 专业班级: 姓 名: 学 号: 电子邮件: 实验地点: 实验成绩:
编写递归下降语法分析器 验证型实验 庄燕滨 10 软件卓越 黄子轩 10030416
15251909800@ 秋白楼 B705
日期: 2013 年 5 月 31 日
1
一、实验目的 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单 词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以 下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的语法分析程序。 二、实验过程 1、分析对象 分析算术表达式的 BNF 定义如下: 〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉 〈项〉→〈因式〉|〈项〉*〈因式〉|〈项〉/〈因式〉 〈因式〉→〈变量〉│(〈算术表达式〉) 〈变量〉→i 用符号表示如下: E→T|E+T|E-T T→F|T*F|T/F F→i│(E) 2、题目: 编写递归下降语法分析器。 3、要求: 根据递归下降法分析法,完成上述算术表达式的分析器构造。主要完成: (1) 通知外界键入算术表达式; (2) 控制过程分析算术表达式; (3) 根据分析结果正误,分别通知外界不同的信息。 三、实验结果 测试数据:i*i+i# 实验结果:
3
4
5
五、附录:关键代码(给出适当注释,可读性高) /* 判断加减*/ int myE() { printf("E->TE'\t\t"); printf("#E'T\t\t"); print(); int p ; p=myT(); if(p) { while(sym=='+'||sym=='-') {
if (sym !='(' )
8
{ printf("error\n"); return(0); tz = 1;
} else {
printf("F->(E)\t\t"); printf("#E'T'(E)\t"); print(); myAdvance(); printf("\t\t"); printf("#E'T'\t\t"); print(); p =myE(); if(p)
if(sym=='+') {
printf("E'->+TE'\t"); printf("#E'T+\t\t"); print(); } else { printf("E'->-TE'\t"); printf("#E'T-\t\t"); print(); } myAdvance(); printf("\t\t"); printf("#E'T\t\t"); print(); myT(); return(1); } if(sym!='+'||sym!='-')