我关于对他投诉问题的员工投诉调查报告告。该句语法对吗?

语法分析实验报告
语法分析实验报告
范文一:语法分析实验报告一、 语法分析功能与目的语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成作准备。执行语法分析任务的程序叫语法分析程序或语法分析器。语法分析程序以词法分析输出的符号串作为输入,在分析过程中检查这个符号串是否为该程序语言的句子。如是,则输出该句子的分析数,否则就表示源程序存在语法错误,需要报告错误的性质和位置。二、TEST语法规则①∶∶={}②∶∶=|ε③∶∶=int ;④::=|ε⑤::=|||||||⑥::=if()[else]⑦::=while()⑧:=for(;;)⑨::=write;⑩::=read;(11)::={}(12):=;|;(13)::==|(14):=|(>|=|(15)::={(+|-)}(16)::={(*|/)}(17)::=()||(18)::=dowhile();三、 实验四要求及改进思路实验要求:修改词法分析程序TESTscan.c和语法分析程序TESTparse.c这二个文件,使该程序能分析:(1) do语句(有关文法规则参见P77的习题8。)(2) 同一行中声明多个变量(文法规则参见P77的习题7)。例如:原先可以分析的变量声明是:现在能分析的变量声明是: int a,改进思路:对于问题(1),由于do语句的语法规则为::=dowhile();do语句的正确输入形式为:do {表达式}while (表达式);所以do语句的前半部分为一个复合语句,所以在语法分析程序中要能分析出do语句,必须在定义do语句时先要求该句子属于复合语句,然后使指针为while,再到(,然后是表达式,接着就是),最后为;,这就是完整的do语句。 ①定义do语句的代码如下:int do_stat(){int es = 0;fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);es=compound_stat(); //调用复合语句if(es>0) return (es);if (strcmp(token, "while")) return(es=8);fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp(token, "(")) return(es=5); //少左括号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);es = expression();
//调用表达式if(es>0) return (es);if (strcmp(token, ")")) return(es=6); //少右括号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp(token, ";")) return(es=4); //少分号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);}②然后在语法分析程序的开始定义的函数中必须加上int do_stat();;③然后在函数出错的情况switch (es)的函数中加上case 8: printf("do后面缺少while! \n");,这是说明do语句不完整的出错情况。对于问题(2):同一行中定义多个变量,对比前后变化的两个变量声明形式,我们可以看出同一行中定义多个变量时,在分析第一个变量时原来的变量声明能分析得出来,但是在接下来的变量中就有变化了,在同一行定义多个变量的第二个变量是接第一个变量后的,第二个变量的为第一个变量后接着一个逗号,然后就是第二个变量,如果同一行有n多个变量,那么从第三个变量开始,就先能分析出其必须先要分析出第二个变量,以此类推,分析出第n个变量就必须分析出前n-1个变量,而且要能分析出第n(n>2)个变量,其要求就如同分析出第二个变量,它就是一个反复调用的过程。我们可以定义一个函数d(),要求它的结构为逗号后接着标识符,然后就由原来的分析出单个变量的变量声明在分析到标识符的时候调用我们定义的函数d(),就能实现一行识别出多个变量了。函数d()的定义如下:int d(){if(strcmp(token,",")==0){
int es=0;fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp (token, "ID")) return (es=3); //不是标识符fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);d();}}在声明语句定义时调用d()函数实现一行识别出多个变量的情况如下: // : : = int ID;int declaration_stat(){int es=0;fscanf(fp, "%s %s\n", &token, &token1);printf ("%s %s\n",token, token1);if (strcmp (token, "ID")) return (es=3); //不是标识符fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);d();if (strcmp(token,";")) return(es=4);fscanf (fp, "%s %s\n", &token, &token1);printf ("%s %s\n",token, token1);return(es);}四、 该语法分析程序是递归下降分析的语法分析方法递归下降分析的方法思路是将文法中的每一个非终结符U的文法规则看作是识别U的一个过程定义,为每个非终结符另构造一个子程序,以完成该非终结符号所对应的语法成分的分析和识别任务。如果U的文法规则的右部只有一个候选式,按从左向右的顺序依次构造规则U的识别过程代码:①如果有终结符号,判断能否与输入的符号相等,如果想等,表示识别成功,读入指针指向下一个输入符号;如果不想等,则意味着输入串此时有语法错误; ②如果是非终结符号,则简单调用这个非终结符号的子程序,由这个子程序完成该非终结符号所对应的语法成分分析和识别任务;③当一条规则右部有多个候选式时,则根据每个候选式的第一个符号确定该候选式分支;只有被调用的分析识别某语法成分的子程序匹配输入串成功,且正确返回时,该语法成分才算真正获得识别。五、输入文件内容及屏幕输出内容(11)①输入正确的源文件如下:词法分析结果内容如下:②语法分析屏幕输出的内容如下:下面接着余下的输出部分:(12)①输入文件为错误的源文件如下:从语法分析结果中我们看到语法分析都for语句的后半句i++的时候就停止了,然后错误的缘由是缺少操作数,因为for语句后接着的是,而i++:形式没有符合TEST的语法规则里的任何一种语句规则,所以出现错误。②当输入源程序改为如下:从语法分析输出结果我们看出当分析到do语句的最后时出错,错误为缺少分号,说明我们的源文件输入do语句有错,查看do语句的标准形式,最后面应该以分号结束,而我们输入的源文件缺少了分号,所以出现了错误。③当输入源文件为如下所示时:语法分析屏幕输出如下所示:我们从语法分析结果看出,这次语法分析根本就无法开始,错误为缺少{,说明我们的输入的程序开始就有错误,查看TEST语法规则,第一个规则为∶∶={},说明输入程序以{开始并以}结束,而反观我们的输入程序,并没有以{开始,所以语法分析根本无法进行,所以出现了缺少{ 的错误提醒。六、实验体会通过本次实验,我们更加了解了语法分析的原理以及其与词法分析的关系,语法分析和词法相比其又更加复杂了一点点,虽然每次修改代码的时候我都感觉很艰难,因为C++学得不好,但是在其他两位组员的努力下就能顺利的解决了,最后我也能在他们的帮助下懂得了实验的原理与解答过程,真心感谢呀。原文地址:语法分析实验报告一、 语法分析功能与目的语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成作准备。执行语法分析任务的程序叫语法分析程序或语法分析器。语法分析程序以词法分析输出的符号串作为输入,在分析过程中检查这个符号串是否为该程序语言的句子。如是,则输出该句子的分析数,否则就表示源程序存在语法错误,需要报告错误的性质和位置。二、TEST语法规则①∶∶={}②∶∶=|ε③∶∶=int ;④::=|ε⑤::=|||||||⑥::=if()[else]⑦::=while()⑧:=for(;;)⑨::=write;⑩::=read;(11)::={}(12):=;|;(13)::==|(14):=|(>|=|(15)::={(+|-)}(16)::={(*|/)}(17)::=()||(18)::=dowhile();三、 实验四要求及改进思路实验要求:修改词法分析程序TESTscan.c和语法分析程序TESTparse.c这二个文件,使该程序能分析:(1) do语句(有关文法规则参见P77的习题8。)(2) 同一行中声明多个变量(文法规则参见P77的习题7)。例如:原先可以分析的变量声明是:现在能分析的变量声明是: int a,改进思路:对于问题(1),由于do语句的语法规则为::=dowhile();do语句的正确输入形式为:do {表达式}while (表达式);所以do语句的前半部分为一个复合语句,所以在语法分析程序中要能分析出do语句,必须在定义do语句时先要求该句子属于复合语句,然后使指针为while,再到(,然后是表达式,接着就是),最后为;,这就是完整的do语句。 ①定义do语句的代码如下:int do_stat(){int es = 0;fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);es=compound_stat(); //调用复合语句if(es>0) return (es);if (strcmp(token, "while")) return(es=8);fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp(token, "(")) return(es=5); //少左括号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);es = expression();
//调用表达式if(es>0) return (es);if (strcmp(token, ")")) return(es=6); //少右括号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp(token, ";")) return(es=4); //少分号fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);}②然后在语法分析程序的开始定义的函数中必须加上int do_stat();;③然后在函数出错的情况switch (es)的函数中加上case 8: printf("do后面缺少while! \n");,这是说明do语句不完整的出错情况。对于问题(2):同一行中定义多个变量,对比前后变化的两个变量声明形式,我们可以看出同一行中定义多个变量时,在分析第一个变量时原来的变量声明能分析得出来,但是在接下来的变量中就有变化了,在同一行定义多个变量的第二个变量是接第一个变量后的,第二个变量的为第一个变量后接着一个逗号,然后就是第二个变量,如果同一行有n多个变量,那么从第三个变量开始,就先能分析出其必须先要分析出第二个变量,以此类推,分析出第n个变量就必须分析出前n-1个变量,而且要能分析出第n(n>2)个变量,其要求就如同分析出第二个变量,它就是一个反复调用的过程。我们可以定义一个函数d(),要求它的结构为逗号后接着标识符,然后就由原来的分析出单个变量的变量声明在分析到标识符的时候调用我们定义的函数d(),就能实现一行识别出多个变量了。函数d()的定义如下:int d(){if(strcmp(token,",")==0){
int es=0;fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);if (strcmp (token, "ID")) return (es=3); //不是标识符fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);d();}}在声明语句定义时调用d()函数实现一行识别出多个变量的情况如下: // : : = int ID;int declaration_stat(){int es=0;fscanf(fp, "%s %s\n", &token, &token1);printf ("%s %s\n",token, token1);if (strcmp (token, "ID")) return (es=3); //不是标识符fscanf(fp,"%s %s\n",&token,&token1);printf("%s %s\n",token,token1);d();if (strcmp(token,";")) return(es=4);fscanf (fp, "%s %s\n", &token, &token1);printf ("%s %s\n",token, token1);return(es);}四、 该语法分析程序是递归下降分析的语法分析方法递归下降分析的方法思路是将文法中的每一个非终结符U的文法规则看作是识别U的一个过程定义,为每个非终结符另构造一个子程序,以完成该非终结符号所对应的语法成分的分析和识别任务。如果U的文法规则的右部只有一个候选式,按从左向右的顺序依次构造规则U的识别过程代码:①如果有终结符号,判断能否与输入的符号相等,如果想等,表示识别成功,读入指针指向下一个输入符号;如果不想等,则意味着输入串此时有语法错误; ②如果是非终结符号,则简单调用这个非终结符号的子程序,由这个子程序完成该非终结符号所对应的语法成分分析和识别任务;③当一条规则右部有多个候选式时,则根据每个候选式的第一个符号确定该候选式分支;只有被调用的分析识别某语法成分的子程序匹配输入串成功,且正确返回时,该语法成分才算真正获得识别。五、输入文件内容及屏幕输出内容(11)①输入正确的源文件如下:词法分析结果内容如下:②语法分析屏幕输出的内容如下:下面接着余下的输出部分:(12)①输入文件为错误的源文件如下:从语法分析结果中我们看到语法分析都for语句的后半句i++的时候就停止了,然后错误的缘由是缺少操作数,因为for语句后接着的是,而i++:形式没有符合TEST的语法规则里的任何一种语句规则,所以出现错误。②当输入源程序改为如下:从语法分析输出结果我们看出当分析到do语句的最后时出错,错误为缺少分号,说明我们的源文件输入do语句有错,查看do语句的标准形式,最后面应该以分号结束,而我们输入的源文件缺少了分号,所以出现了错误。③当输入源文件为如下所示时:语法分析屏幕输出如下所示:我们从语法分析结果看出,这次语法分析根本就无法开始,错误为缺少{,说明我们的输入的程序开始就有错误,查看TEST语法规则,第一个规则为∶∶={},说明输入程序以{开始并以}结束,而反观我们的输入程序,并没有以{开始,所以语法分析根本无法进行,所以出现了缺少{ 的错误提醒。六、实验体会通过本次实验,我们更加了解了语法分析的原理以及其与词法分析的关系,语法分析和词法相比其又更加复杂了一点点,虽然每次修改代码的时候我都感觉很艰难,因为C++学得不好,但是在其他两位组员的努力下就能顺利的解决了,最后我也能在他们的帮助下懂得了实验的原理与解答过程,真心感谢呀。
范文二:编译原理实验报告实验名称:实验类型:指导教师:专业班级:姓
号:实验地点:实验成绩:编写语法分析程序
软件1002班
______________________日期:
05 月日 20一、实验目的通过设计、编写、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握递归下降语法分析方法。语法分析是编译过程的核心部分,它的主要功能是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成作准备.语法分析程序在分析过程中检查符号串是否为该程序的句子.若是则输出该句子的分析树,否则就表示源程序存在语法错误,并报告错误的性质与位置.二、实验设计1、TEST的语法规则以及改写文法1)::={}FIRST({})={ 2)::= | ε
::=::= | ε3)::=int ID;
FIRST(int ID)=int4)::=| ε::=::=| εFIRST(| ε)= if、while、for、read、write、{ 、(、ID、NUM、;、| ε5)::= ||| ||
|FIRST(||||| |)=if、while、for、read、write、{ 、(、ID、NUM、;6)::= if ()
[else ]::= if () (ε| [else ])FIRST(if_stat)=if7)::= while ()
FIRST(while)=while8)::= for(;;)FIRST(for)=for9)::=FIRST()= 10)::=read ID;FIRST(read ID)= 11)::={}
FIRST({})={ 12)::=;|;FIRST(;|;)=;、(、ID、NUM 13)::= ID=|FIRST(ID=|)=ID、(、NUM14)::=|(>|=|
::=(ε|(>|=|)FIRST((ε|(>|=|))=(、ID、NUM15)::={(+|-)}产生式:::=(+|-)|::= ::=(+|-)|ε FIRST()=(、ID、NUM FIRST((+|-)|ε)=+、-、ε FOLLOW)=>、=、16)::={(*| /)}::=(*| /)|::=::=(*| /)|ε FIRST( )=(、ID、NUM FIRST((*| /)|ε)=*、/、ε FOLLOW()=>|=|17)::=()|ID|NUMFIRST(()|ID|NUM)=(、ID、NUM三、实验过程1、编写代码1)改写文法,消除二义性; 2)消除左递归、提取左因子; 3)求FIRST集、FOLLOW集;4)检查是不是 LL(1) 文法,若不是 LL(1),说明文法的复杂性超过自顶向下方 法的分析能力5)直接根据产生式设计相应的程序2、实验结果5、{
number=b+a;
}测试未能通过:未能通过的原因:第一条语句后边没有“;”。四、讨论与分析1、LL(1)分析的主要问题是不能处理左递归文法且要求分析表不能有多重定义。①左递归转成右递归LL(1)分析不能处理左递归文法,但也不能像递归下降分析那样将左递归改为采用扩充BNF表示,必须将左递归文法变成右递归文法。②有多重定义时,可以提取公因子,消除二义性。 2、不是所有的文法都满足递归下降分析条件的文法。如:S::=As’|bS’’ S’::=AUU|BRR S’’::=U|R A::=aAU|b B::=aBR|b U::=c R::=d3、不能够直接解决根本性的问题。五、关键代码if(es==0&&strcmp(token,";")==0)//空语句{
while(strcmp(token,";")==0)
fscanf(fp,"%s %s\n",&token,&token1);
printf("%s %s\n",token,token1);
if(es==0&&strcmp(token,"if")==0)//if语句
es=if_stat();
}if(es==0&&strcmp(token,"while")==0)//while语句
es=while_stat();
if(es==0&&strcmp(token,"for")==0)//for语句
es=for_stat();
//可在此处添加do语句调用if(es==0&&strcmp(token,"do")==0)//dowhile语句
es=dowhile_stat();
if(es==0&&strcmp(token,"read")==0)//read语句
es=read_stat();
if(es==0&&strcmp(token,"write")==0) //write语句
es=write_stat();
if(es==0&&strcmp(token,"{")==0)//复合语句
es=compound_stat();
if(es==0&&(strcmp(token,"ID")==0||strcmp(token,"NUM")==0||strcmp(token,"(")==0)){
es=expression_stat();//表达式语句
return (es);六、实验体会语法分析就是费词法分析的结果,根据语言规则,将一个个单词组成的各种语言的各种语法类,分析时如果发现不合法规则的符号,要不这些出错的符号及错误性质报告给程序员。通过语法分析程序,我了解了语法分析的一般方法有自顶向下分析方法和自底向上分析方法。两种方法都是自左向右地读入符号,先对读入的符号进行词法分析,词法分析成功后再进行语法分析。在实验中我还熟悉了FIRST和FOLLOW集的求法。更巩固了我的程序设计能力。最深的体会是:磨刀不误砍柴工。看完实验指导书,首先不应该去编写程序,而是去设计程序,理清了程序的流程,就能很快写出程序,而且比没有经过设计写出来的程序质量要好得多。编写语法分析程序首先要改写文法,这也是最重要的。在写程序时,首先要理清需求,即程序该有那些功能,然后再设计程序的各个子函数以及子函数之间的调用关系或者程序需要那些类,类与类之间的关系以及类里面的各个函数。对于程序员,最重要的是程序的设计,而不是编写代码。TEST语言无法识别连续定义的语句,形如:”int a ,”,遇到这样的语句会报缺少“;”的语法错误;改进方法:在读取表示符后如果读取到“,”,那么后边读取到的标示符就是真确的,否则为语法错误。
范文三:《编译系统设计实践》实验项目二:语法分析指导老师:组长:组员:一、 实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对LR(1)分析法的理解。二、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容)。三、程序设计与实现1.功能描述:根据给定的文法,由程序生成项集族和语法分析表,对输入的源程序进行词法分析,得到语法分析的输入串,经过语法分析后得到三个栈,它们分别是状态栈,字符栈,输入栈,从而分析出输入的源程序是否有语法错误。2.重要过程描述:1)本实验有两个输入文件:一个为源代码输入文件“in_code.txt”,一个为文法的输入文件“in_gram.txt”,三个输出文件:一个为词法的输出和语法的输入文件“out_in.txt”,一个为项目集族和分析表的输出文件“out_items.txt”一个为语法分析结果的输出即栈的输出“result.txt”。
2) 重要数据结构:typedef struct
production typedef struct collection{/状态集 {//产生式
state i[300]; char suf[25]; //搜索符 //状态个数}
rear[30]; //产生式后部
//产生式头部struct fstr
//小圆点的位置{ //first集char str[50];//first符号串 }//first符号串 字符个数typedef struct s//是否包含空符号 {//状态i }prod
p[50];//产生式short int anatab[300] //产生式数量}34. 重要函数说明find(state &unclosure,int n)函数:功能:判断是否已包含某一产生式。在求闭包closure()函数中对其进行调用;参数说明:unclosure还没有求闭包的状态;n表示第几个产生式。first(char tmp)函数:求各文法符号的first集,确定搜索符时使用到。在求闭包的函数中队其进行调用;参数说明:tmp为需要求first集的文法符号。sign()函数:功能:提取文法符号序列,将所有的文法符号+’$’都存放在一个一维数组中,该数组在输出分析表及语法分析中对栈进行处理时是需要使用。reloadtoken()函数:功能:词法分析的结果。从文件中读入字符到buff中,将得到的单词定义成相应的运算符、分隔符,关键字k,标识符i,实数f',整数n;写入到out_in.txt文件中,该文件为词法分析的输出,语法分析的输入。void items(coll &head)函数:功能:求LR(1)项目集族void closure(state &unclosure)函数:功能:求LR(1)项目集族的闭包。state mygoto(const state &cur,int k,int tmp)函数:功能:填写分析表anatab[][],使用数字,空白用0,S移入为负数,r规约为正数,-32767表示acc接受。四、关键代码/*求LR(1)项目集族*/ void items(coll &head) {int i,j,k;//建立项集memset(&head,0,LENCOLL);//初始化第一条增广文法 s->S,$;
head.i[0].p[0].front = 's';strcpy(head.i[0].p[0].rear,"S");
head.num++;
head.i[0].num++;head.i[0].p[0].suf[0]='$';
//对增广文法求闭包
closure(head.i[0]);for(i = 0;i//strnum为文法符号个数{
pnext = mygoto(head.i[i],i,j);/*求LR(1)项目集族的闭包*/ void closure(state &unclosure) {int i = 0,j = 0,k =0;for(i = 0;i//isupper()用于求tmp是否是大写字母 {for(j = 0;jif(gram[j][0] == tmp)
{memset(&firstx,0,sizeof(fstruct));
first(unclosure.p[i].rear[unclosure.p[i]if(pnext.num == 0)
//判断pnext状态是否已经存在
for(k = 0,findi = 0;kfindi = 1;
if(findi == 0)
anatab[i][j] = head.
head.i[head.num] =
head.num++;
}.point + 1]);
f(firstx.blank)
strcat(firstx.str,unclosure.p[i].suf);
k = find(unclosure,j);
if(k == -1)//该产生式未出现过,加入
strcpy(unclosure.p[unclosure.num].rear,&gram[j][1]);
unclosure.p[unclosure.num].front = gram[j][0];
unclosure.p[unclosure.num].point = 0;
unclosure.p[unclosure.num].seq = j + 1;//第几条文法strcpy(unclosure.p[unclosure.num].suf,firstx.str);unclosure.num++;
} else{strcat(unclosure.p[k].suf,firstx.str); /出现过,只加上后缀
}//语法分析,对栈进行处理int stacktop,schrtop,
stacktop = 0;
schrtop = -1;memset(stack,-1,sizeof(stack));memset(stackchar,0,sizeof(stackchar));stack[0] = 0;printf("
符号\n ");
printf("\n ");while(gets(buffatt)!=NULL)
bufftop = 0;
if(bufftop > 100){}
sp = strchr(strsign,buffatt[bufftop]);
if(sp == NULL)
printf("%c not find\n",buffatt[bufftop]);
{}}}}}row = sp -}
nextsta = anatab[stack[stacktop]][row];
if(nextsta
printf("%d,%d,%c\n",stacktop,row,buffatt[bufftop]);
printf("error\n");
if(nextsta > 0)
for(i = 0;i
printf("%-4d",stack[i]);
printf("|%-100s|%100s\n",stackchar,(buffatt+bufftop));stacktop++;
stack[stacktop] =//移进状态
schrtop++;
stackchar[schrtop] = buffatt+bufftop));
grami = nextsta * (-1) - 1;
len = strlen(gram[grami]) - 1; buffatt[bufftop]; //移进符号
bufftop++;//前移待分析串位置
}if(nextsta == -32767 && buffatt[bufftop] == '$')
for(i = 0;i
printf("%-4d",stack[i]);
}printf("|%-100s|%100s\n",stackchar,(buffatt+bufftop));
printf("\nacc\n");
if(nextstafor(i = 0;i
printf("%-4d",stack[i]);
}printf("|%-100s|%100s\n",stackchar,(for(i = 0;i五、程序测试限于程序量,文法定义如下:S→E S→A(B){S} S→A(B){S}A{S} B→EDE D→> D→= D→E→i=E-T E→T T→i=T*F T→i=T/F T→F F→(S) F→i A→k由于篇幅有限,仅截取部分项目集族和分析表测试数据1:a=b*c词法分析结果:i=i*i$语法分析结果:状态栈
| i=i*i$ 0
acc测试数据2:while(a>){if(t>=t1){ a=t+t2}else{a=t3*t4}}词法分析结果:k(i>){k(i>=i){i=i+i}k{i=i*i}}$语法分析结果:测试数据3:while(a>b){if(t>=t1){ a=t+t2}else{a=t3*t4}}词法分析结果:k(i>i){k(i>=i){i=i+i}k{i=i*i}}$语法分析结果:,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,五、小组成员分工与实验小结对于本实验,我们小组成员分工如下:陈雪如负责将原先的词法分析程序进行相应的修改使之适合于语法分析;程序设计的过程比较艰难,各个重要函数参考了书本里的代码实现,因为这是我们自上大学来设计的一个最复杂的程序,对我们来说比较有挑战。代码的编写过程中用到了一些以前从未用过的函数,都是现学现用,掌握还不是很深。在代码调试过程中结果出现许多无法解释的错误,但是我们坚持下来了,最终调试出了结果。此次实验,让我们对编译原理的基本知识有了深入的了解,加强了对语法分析的认识。也让我们组员的动手实践能力得到很大的提高。
范文四:编译原理语法分析实验报告软工082班兰洁一、 实验内容二、 实验目的三、 实验要求四、 程序流程图? 主函数;? scanner();? irparser()函数? yucu()
/*语句串分析*/? statement()/*语句分析函数*/? expression()/*表达式分析函数*/? term()/*项分析函数*/? factor()/*因子分析函数*/五、 程序代码六、 测试用例七、 输出结果八、 实验心得一、实验内容:编写为一上下文无关文法构造其递归下降语法分析程序,并对任给的一个输入串进行语法分析检查。程序要求能对输入串进行递归下降语法分析,能判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。二、实验目的:构造文法的语法分析程序,要求采用递归下降语法分析方法对输入的字符串进行语法分析,实现对词法分析程序所提供的单词序列的语法检查和结构分析,进一步掌握递归下降的语法分析方法。三、实验要求:利用C语言编制递归下降分析程序,并对Training语言进行语法分析。1. 待分析的Training语言语法。用扩充的表示如下:-->functionendfunc-->{;}??ID??{+|-}?{*|/}?ID|NUM|()备注:实验当中 我对程序进行了扩展,增加了程序识别if条件判断语句,while循环语句的功能2. 实验要求说明输入单词串以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。四、程序流程图主函数:Scanner()函数:irparser()函数yucu()
/*语句串分析*/statement()/*语句分析函数*/expression()/*表达式分析函数*/term()/*项分析函数*/factor()/*因子分析函数*/五、程序代码:递归下降分析文法:-->functionendfunc-->{ ; }? | |??{ + | - }?{*|/}?ID | NUM | ()?()| (ID) |(NUM)??()| (ID) |(NUM)?备注:红色字体部分为我对代码实现功能的主要修改与扩展部分。/*语法分析源代码*/#include#includechar prog[80],token[8];int syn,p,m=0,n,sum,kk=0;char *rwtab[6]={"function","if","then","while","do","endfunc"}; void yucu();void expression();void statement();void factor();void term();void irparser();void scaner(){ for (n=0;ntoken[n]=NULL; while(ch==' ' || ch=='\n')
ch=prog[p++]; m=0; if((ch='a') || (ch='A')) {while((ch='a') || (ch='A') || (ch='0'))
{token[m++]=
} syn=10; for(n=0;n} else { switch(ch)
{ case'='0') { sum=sum*10+ch-'0';
} syn=11; ch=prog[p++]; case'>':m=0;token[m++]=
ch=prog[p++]; if(ch=='=') { syn=24;
} else {syn=23;p--; } token[m++]= case'=' :m= 0;token[m ++ ]=
ch=prog[p++]; if(ch=='=') { syn= 25;else {syn=18; ch=prog[--p]; } case'!':m=0; token[m++]=
ch=prog[++p]; if(ch=='=') {
syn=22; token[m++]= } else
syn=-1; case'+':syn=13;
token[0]= case'-':syn=14;
token[0]= case'*':syn=15;
token[0]= case'/':syn=16;
token[0]= case';':syn=26;
token[0]= case'(':syn=27;
token[0]= case')':syn=28;
token[0]= case'#':syn=0;
token[0]= default:syn=-1;// } ch=prog[p++]; } }
void irparser(){ if(syn==1){ scaner();
yucu();/*语句串分析*/if(syn==0&&kk==0)/*程序分析识别完*/printf("success");}} elseelse{ if(kk!=1) /*没以endfunc结束*/
}{ printf("error!need 'endfunc'");
}kk=1;{ printf("error!need'function'");
}void yucu()
/*语句串分析*/{
statement();/*调用语句分析函数*/while(syn==26)/*一个语句识别结束,继续识别*/
{ scaner();
statement();} } }void statement()/*语句分析函数*/ {
if(syn==10){ scaner();if(syn==18)
//如果是赋值语句 { scaner();expression();}
//这个过程实现语法分析判断语句}}kk=1;elseif(syn==6)elseif(syn==2)
//如果是条件判断语句 就判断条件表达式的语法! { scaner();if(syn==27)
//判断括号匹配 {do{scaner();
//进入括号内部进行表达式分析
expression();
}while(syn!=28); }else { printf("error! need another')'");kk=1;}
//()内判断完成 !scaner();
//然后进行语句块分析!
statement();}
//到这里是实现判断if语句的语法分析// 类似的往里添加 循环语句 !
elseif(syn==4)
//如果是循环语句 就判断条件表达式的语法! { scaner();//ch=prog[p++];if(syn==27) { do{scaner();
expression();
}while(syn!=28);printf("error! need another')'");kk=1;
//()内判断完成 !scaner();
//然后进行语句块分析!
statement();
}void expression()/*表达式分析函数*/ {
term();while(syn==13||syn==14){
scaner();}
//这里是实现判断while语句的语法分析else{ printf("error!the statement error!");
}kk=1;term(); }
}void term()/*项分析函数*/ { factor();
}void factor()/*因子分析函数*/ {
if(syn==10||syn==11){ scaner(); } else/*看是否是表达式*/ { expression();if(syn==27) while(syn==15||syn==16) { scaner();factor();}}}} else{
printf("error! expression error!"); }if(syn==28) {
scaner();} else{
printf("error! need another')'");
}kk=1;void main() { p=0;
}printf("\n please input the string:\n"); do{ ch=getchar();prog[p++]=} while(ch!='#'); p=0;ch=prog[p++]; scaner();irparser();六、测试用例七、输出结果测试用例1测试用例2测试用例4测试用例3八、实验心得通过编译原理实验二语法分析实验,使得自己对语法分析的流程有了更深刻的了解,使得语法分析递归向下思想更加具体化,虽然源代码并非由自己设计,但是在调试程序的过程中,逐步理解程序递归下降思想,思路不断理清,不仅理解了程序分析赋值语句的算法,同时在这基础上,我对程序做了功能扩展,增加了语法分析条件判断语句和while条件循环语句,即是程序中红色字体部分。在调试与算法功能扩展的过程中,理清了语法分析程序的思路。从一开始对程序的陌生,到后来逐步了解程序的流程,当我耐心的一步一步理解程序思想,一次次的更改测试用例,一遍遍的调试,最终终于得到了预期的答案。这次实验使我对理论的语法分析递归下降的理解更加具体清晰,受益匪浅。
范文五:编译原理实验报告词法分析和语法分析专业班级
jk0701学生姓名
舒月学号 实验题目:
研究性学习专题一
词法分析程序构造原理与实现技术研究性学习专题二
递归下降语法分析设计原理与实现技术一 实验目的(1)研究性学习专题一→字母︱ 字母︱ 数字
→数字︱ 数字
→+ ︱- ︱* ︱; ︱(︱)→=︱=︱>︱=︱*
→/该语言的保留字 :begin
and or not[设计说明] (1)该语言大小写不敏感;(2)字母为a-z A-Z,数字为0-9;(3)可以对上述文法进行扩充和改造;(4) ‘/*……*/’为程序的注释部分。(2)研究性学习专题二G[E]: E→TE′E′→ATE′|ε
T′→MFT′|ε
M→*|/[设计说明] 终结符号i为用户定义的简单变量,即标识符的定义。二 实验分析过程词法分析程序功能描述:根据上述正则文法,输入一串字符串,输出一串二元式序列组成的中间文件,在实现的过程中,能发现输入串中的错误。语法分析程序功能描述:根据词法分析输出的二元式序列,对二元式序列进行判定,时候满足语法的要求,若满足,则输出结果为正确,反之,为错误。主要数据结构: 用TokenBean类存储数字,标识符,保留字 的类别,表示,和识别名public class TokenBean {
SS }用ArrayList来装TokenBean类程序结构描述:(1) 词法分析过程用到的主要函数public boolean isNumber(char ch)//判断输入字符是否为整数 public boolean isAlph(char ch) //判断输入字符是否为字母 private void isKey(String str)// 判断str是关键字还是标识符 public void excute(String s)
//对字符串s 进行分析,得出二元式(2) 语法分析过程用到的主要函数public boolean ipresent(int kind)//识别保留字,标识符,整数
以下是判断函数,入口为E() 若E为真,则二元式序列满足语法分析
private boolean E()
// E→TE′
private boolean E1()
// E′→ATE′|εprivate boolean A()
//A→+|-private boolean T()
// T→FT′
private boolean T1()
// T′→MFT′|ε
private boolean M()
private boolean F()
//F→ (E)|i流程图
(1) 词法分析程序执行图:(2 )语法分析程序流程图:三 验结果及分析 正确实例: a + b – c * d(1)词法分析过程
输入: 字符串输出: 二元式序列
并可以保存二元式序列(2)语法分析过程对二元式序列进行判定 ,给出的例题是正确的,所以结果为true错误实例分析:(a + b(1)词法分析过程输入: 字符串输出: 二元式序列
并可以保存二元式序列(2)语法分析过程对二元式序列进行判定 ,给出的例题是错误的,所以结果为false 在出错区里面报错四 实验总结编程的过程中,遇到的难点:在实现的过程中,对string类的不了解,从char 转换到string的过程中,出现错误。 对程序的整体框架在开始的时候,考虑不周详,尤其是对while循环条件设置,通过不断地反复调试,能基本上实现词法分析和语法分析的功能。 收获:能把用户图形界面和编程较好的实现在一起。
范文六:LL1实验报告08计算机3班1.设计原理所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =,,#",则宣布分析成功,停止分析过程。(2)若X = a ,,#",则把X从STACK栈顶弹出,让a指向下一个输入符号。(3)若X是一个非终结符,则查看预测分析表M。若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。事实上,LL(1)的分析是根据文法构造的,它反映了相应文法所定义的语言的固定特征,因此在LL(1)分析器中,实际上是以LL(1)分析表代替相应方法来进行分析的。2.分析LL ( 1) 分析表是一个二维表,它的表列符号是当前符号,包括文法所有的终结和自定义。的句子结束符号#,它的表行符号是可能在文法符号栈SYN中出现的所有符号,包括所有的非终结符,所有出现在产生式右侧且不在首位置的终结符, 自定义的句子结束符号#表项。为当前栈符号与当前符号匹配后,所要求的栈操作和输入操作。表项表明了文法的终结符与非终结符是否可能相遇。其中 , 栈操作包括两种,一是弹栈;二是弹栈后,将符号串ABc反转后压栈;输 入 操作 包 括 两 种 ,一 是 读 入下一符号,是保持当前符号不变。具体的造算法为171。(1 ) 设 A , B 为文法的非终结符,C为文法的终结符和非终结符组成的字符串,a为文法的终结符将所 有 产 生式分为四类:6)A->aB,则(A,a )项填写为(B调向后压栈,读入下一个字符):(ii)A->a; A->a,则将〔A, a)项填写为(弹栈,读入下一个字符):(iii)A->BC,则将(A,select(A->BC))项全部填写为(将BC调向后压栈,保持当前字符不读入):(iv)A->N,则将(A, follow(A))项全部填写为(弹栈,保持当前字符不读)。(2) 对表行和表列的所有字符进行循环;(3) 如果当前表行的字符是非终结符,它必有产生式,依据此产生式的类型,填写表项。(4) 如果当前表列的字符不在此产生式的选择集合中,该项填写为Eror。(5)对 (# ,#)项填写为OK;(6) 对当前表行字符为终结符的,只有它与表列字符相同时,才填写为(弹栈,读入下一个字符),否则填入Eror。3.流程图数据结构#include"iostream.h"#include "stdio.h"#include "malloc.h"#include "conio.h"struct Lchar{char char_struct Lchar *}Lchar,*p,*h,*temp,*top,*int table[5][8]={{1,0,0,1,0,0},{0,1,0,0,1,1},{1,0,0,1,0,0},{0,1,1,0,1,1},{1,0,0,1,0,0}};int i,j;void push(char pchar){temp=(struct Lchar*)malloc(sizeof(Lchar));temp->char_ch=temp->next=top=}void pop(void){curtocmp=top->char_if(top->char_ch!='#')top=top->}void doforpush(int t){switch(t){case 0:push('A');push('T');case 5:push('A');push('T');case 11:push('A');push('T');push('+');case 20:push('B');push('F');case 23:push('B');push('F');case 32:push('B');push('F');push('*');case 40:push('i');case 43:push(')');push('E');push('(');}}void changchartoint(){switch(curtocmp){case 'A':i=1;case 'B':i=3;case 'E':i=0;case 'T':i=2;case 'F':i=4;}switch(curchar){case 'i':j=0;case '+':j=1;case '*':j=2;case '(':j=3;case ')':j=4;case '#':j=5;}}void dosome(void){for(;;){pop();curchar=h->char_printf("\n%c\t%c",curchar,curtocmp);if(curtocmp=='#' && curchar=='#')if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F'){if(curtocmp!='#'){changchartoint();if(table[i][j]){t=10*i+j;doforpush(t);}else{right=0;}}elseif(curtocmp!=curchar){right=0;}else}elseif(curtocmp!=curchar){right=0;}else{h=h->}}}void main(void){coutcoutcoutcoutcoutcout-"coutcoutcoutcoutE+T|T"coutT*F|F"cout(E)|i"coutright=1;base=(struct Lchar*)malloc(sizeof(Lchar));base->next=NULL;base->char_ch='#';temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=temp->char_ch='E';top=h=(struct Lchar*)malloc(sizeof(Lchar));h->next=NULL;p=h;do{ch=getch();putch(ch);if(ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#'){temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=h->next=h=h->}else{temp=p->printf("\nInput a wrong char!Input again:\n"); for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsetemp=temp->}}}while(ch!='#');p=p->h=p;dosome();if(right)printf("\n成功!\n");elseprintf("\n错误!\n");getch();}截图:LL1实验报告08计算机3班1.设计原理所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =,,#",则宣布分析成功,停止分析过程。(2)若X = a ,,#",则把X从STACK栈顶弹出,让a指向下一个输入符号。(3)若X是一个非终结符,则查看预测分析表M。若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。事实上,LL(1)的分析是根据文法构造的,它反映了相应文法所定义的语言的固定特征,因此在LL(1)分析器中,实际上是以LL(1)分析表代替相应方法来进行分析的。2.分析LL ( 1) 分析表是一个二维表,它的表列符号是当前符号,包括文法所有的终结和自定义。的句子结束符号#,它的表行符号是可能在文法符号栈SYN中出现的所有符号,包括所有的非终结符,所有出现在产生式右侧且不在首位置的终结符, 自定义的句子结束符号#表项。为当前栈符号与当前符号匹配后,所要求的栈操作和输入操作。表项表明了文法的终结符与非终结符是否可能相遇。其中 , 栈操作包括两种,一是弹栈;二是弹栈后,将符号串ABc反转后压栈;输 入 操作 包 括 两 种 ,一 是 读 入下一符号,是保持当前符号不变。具体的造算法为171。(1 ) 设 A , B 为文法的非终结符,C为文法的终结符和非终结符组成的字符串,a为文法的终结符将所 有 产 生式分为四类:6)A->aB,则(A,a )项填写为(B调向后压栈,读入下一个字符):(ii)A->a; A->a,则将〔A, a)项填写为(弹栈,读入下一个字符):(iii)A->BC,则将(A,select(A->BC))项全部填写为(将BC调向后压栈,保持当前字符不读入):(iv)A->N,则将(A, follow(A))项全部填写为(弹栈,保持当前字符不读)。(2) 对表行和表列的所有字符进行循环;(3) 如果当前表行的字符是非终结符,它必有产生式,依据此产生式的类型,填写表项。(4) 如果当前表列的字符不在此产生式的选择集合中,该项填写为Eror。(5)对 (# ,#)项填写为OK;(6) 对当前表行字符为终结符的,只有它与表列字符相同时,才填写为(弹栈,读入下一个字符),否则填入Eror。3.流程图数据结构#include"iostream.h"#include "stdio.h"#include "malloc.h"#include "conio.h"struct Lchar{char char_struct Lchar *}Lchar,*p,*h,*temp,*top,*int table[5][8]={{1,0,0,1,0,0},{0,1,0,0,1,1},{1,0,0,1,0,0},{0,1,1,0,1,1},{1,0,0,1,0,0}};int i,j;void push(char pchar){temp=(struct Lchar*)malloc(sizeof(Lchar));temp->char_ch=temp->next=top=}void pop(void){curtocmp=top->char_if(top->char_ch!='#')top=top->}void doforpush(int t){switch(t){case 0:push('A');push('T');case 5:push('A');push('T');case 11:push('A');push('T');push('+');case 20:push('B');push('F');case 23:push('B');push('F');case 32:push('B');push('F');push('*');case 40:push('i');case 43:push(')');push('E');push('(');}}void changchartoint(){switch(curtocmp){case 'A':i=1;case 'B':i=3;case 'E':i=0;case 'T':i=2;case 'F':i=4;}switch(curchar){case 'i':j=0;case '+':j=1;case '*':j=2;case '(':j=3;case ')':j=4;case '#':j=5;}}void dosome(void){for(;;){pop();curchar=h->char_printf("\n%c\t%c",curchar,curtocmp);if(curtocmp=='#' && curchar=='#')if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F'){if(curtocmp!='#'){changchartoint();if(table[i][j]){t=10*i+j;doforpush(t);}else{right=0;}}elseif(curtocmp!=curchar){right=0;}else}elseif(curtocmp!=curchar){right=0;}else{h=h->}}}void main(void){coutcoutcoutcoutcoutcout-"coutcoutcoutcoutE+T|T"coutT*F|F"cout(E)|i"coutright=1;base=(struct Lchar*)malloc(sizeof(Lchar));base->next=NULL;base->char_ch='#';temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=temp->char_ch='E';top=h=(struct Lchar*)malloc(sizeof(Lchar));h->next=NULL;p=h;do{ch=getch();putch(ch);if(ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#'){temp=(struct Lchar*)malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=h->next=h=h->}else{temp=p->printf("\nInput a wrong char!Input again:\n"); for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsetemp=temp->}}}while(ch!='#');p=p->h=p;dosome();if(right)printf("\n成功!\n");elseprintf("\n错误!\n");getch();}截图:
范文七:LL(1)语法分析程序实验报告实验目的与要求:通过设计、编写和调试构造First集合、Follow集合和LL(1)预测分析表,利用LL(1) 预测分析表来分析给定的符号串的程序,了解构造LL(1)分析表的构造步骤、分析方法、对文法的要求。能够从文法G出发,自动生成对应的分析表,并分析给定的符号串,并通过表格和图形的方式实现。实验环境:开发语言:C#开发平台:VisualStudio2010运行平台:windows平台,并装有.net3.5以上输入:一个文法以及一个待分析的给定符号串输出:该文法的中所有非终结符的First和Follow集合该文法的LL(1)预测分析表根据LL(1)预测分析表分析符号串的过程和分析树实验的测试语法:E->TA A->+TA|ε T->FB B->*FB|ε F->(E)|i实验的测试符号串:合法:i*i+i非法:i*i+i-i实验设计:1.
LL(1)语法分析程序的详细数据流图设计2.
数据结构设计 a)
类设计b) 数据成员设计3.
函数子模块设计4.
算法设计a)求各个文法符号X的First集合算法1. 如果X是一个终结符号,那么First(X)=X。2. 如果X是一个非终结符号,且X->Y1Y2…..YK是一个产生式,其中k>=1,那么如果对于某个i,a在First(Yi)中且ε 在所有的First(Y1),First(Y2)…….First(Yi-1)中,就把a 加入到First(X)中。3. 如果X->ε是一个产生式,那么将ε加入到First(X)中。4. 不断应用上述规则,直到再没有新的终结符号或ε可以被加入任何First集合中为止。 算法实现:bool flag=for(inti =0;istring str=nonterminalsymbols[i]; Listfirstlist =(List)First[str]; Listlist=(List)grammerhashtable[str]; for(intj =0;jif(terminalsymbols.Contains(list[j][0].ToString())){//以终结符开头 if(!firstlist.Contains(list[j][0].ToString())){ flag=firstlist.Add(list[j][0].ToString()); } }if(((List)grammerhashtable[str]).Contains("ε")){//包含ε if(!firstlist.Contains("ε")){ flag=firstlist.Add("ε"); } }if(nonterminalsymbols.Contains(list[j][0].ToString())) {//以非终结符开头,将该非终结符中的first放入A中ListfromFirstlist = (List)First[list[j][0].ToString()]; foreach (string s infromFirstlist){if(s!="ε" &&!firstlist.Contains(s)){//将X中非ε元素加入到First集合中 flag= firstlist.Add(s); } } }for(k=0;kif(grammerhashtable.Contains(list[j][k])){ Listtemplist= (List)First[list[j][k]]; if(!templist.Contains("ε")){ foreach(string s in templist){ if(!firstlist.Contains(s)){ firstlist.Add(s);flag= } } } } }}if(i ==nonterminalsymbols.Count -1){ if(flag==false) elseflag= i =-1; }}b)计算所有非终结符A的Follow(A) 集合算法 1. 2. 3. 4.将#放入到Follow(S)中,其中S是开始符号,而#是输入右端的结束标记。 如果存在一个表达式A->XBY,那么First(Y)中除了ε之外的所有符号都在Follow(B) 中如果存在一个产生式A->XB,或存在产生式A->XBY,且First(Y)包含ε,那么Follow(A) 中的所有符号都在Follow(B)中。不断应用上述规则,直到再没有新的终结符号可以被加入任何Follow集合中为止。算法实现:((List)Follow[StartStr]).Add("#"); bool flag=for(inti =0;iListfollowlist = (List)Follow[str];Listlist =(List)grammerhashtable[str]; for(intj =0;jfor(k=0;kif(nonterminalsymbols.Contains(list[j][k].ToString())){ intpos =k+1;//非终结符A后面跟着一个终结符a的话,则把a放入Follow(A) if(posListtofollowlist= (List)Follow[list[j][k].ToString()]; if(!tofollowlist.Contains(list[j][pos].ToString())) { tofollowlist.Add(list[j][pos].ToString()); flag = } }else{//非终结符A后面跟着一串非终结符的话,获得后面的第一个First中不含有ε的while(posng())&&((List)First[list[j][pos].ToString()]).Contains("ε"))pos++; if(pos==list[j].Length)pos--;//pos>=list[j].Length-1代表A->XB或A->XBY且Y中所有的First都包含ε //这是把Follow(A)中的所有符号放入Follow(B)中 if(pos>=list[j].Length -1){Listtofollowlist= (List)Follow[list[j][k].ToString()]; foreach(strings in followlist){if(s!="ε"&&!tofollowlist.Contains(s)){ tofollowlist.Add(s); flag= } }}//如果存在A->XBY的情况话,把First(Y)中的非ε放入Follow(B) if(posk&&nonterminalsymbols.Contains(list[j][pos].ToString())){Listfromfollowlist= (List)First[list[j][pos].ToString()]; Listtofollowlist= (List)Follow[list[j][k].ToString()]; foreach(strings in fromfollowlist){if(s!="ε"&&!tofollowlist.Contains(s)){ tofollowlist.Add(s); flag= } } } } } } }if(i ==nonterminalsymbols.Count -1){ if(flag==false) elseflag= i =-1; }}c)构造LL(1)预测分析表的算法对于文法G的每个产生式A->,进行如下处理:1.对于First()中的每个终结符号a,将A->加入到M[A,a]中。如果ε在First()中,那么对于Follow(A)中的每个终结符号b,将A->加入到M[A,b] 中。如果ε在First()中,且#在Follow(A)中,也将A->加入到M[A,#]。2.3.完成上面的操作后,如果M[A,a]中没有产生式,那么将M[A,a]设置为空条目。算法实现:for(inti =0;iListgrammers =(List)grammerhashtable[str]; for(intj =0;jif(terminalsymbols.Contains(grammers[j][0].ToString())){list.Add(newNode(str,grammers[j][0].ToString(),str+"->" +grammers[j])); }else{intpos =0;while(pos&&((List)First[grammers[j][pos].ToString()]).Contains("ε")) { pos++; }bool flag =//是否包含ε if(pos ==grammers[j].Length){ pos--; flag= }if(flag==false&&nonterminalsymbols.Contains(grammers[j][pos].ToString())){ Listfromfirstlist= (List)First[grammers[j][pos].ToString()]; foreach(string s in fromfirstlist){list.Add(newNode(str,s,str+"->"+grammers[j])); } }else{Listfromfollowlist= (List)Follow[str]; foreach(string s in fromfollowlist){list.Add(newNode(str,s,str+"->"+grammers[j])); } } } }}实验结果:1.程序主体界面2.求语法的First和Follow集合3.显示预测分析表4.语法分析过程(合法的i*i+i)5.语法分析树(合法的i*i+i)6.语法分析过程(非法的i*i+i-1)说明:如下图所示,在14步时分析失败。
范文八:《编译原理》上机实验报告标题:LL(1)语法分析程序单位:计算机学院2001级13班报 告 人:龚
栋 罗晓波 指导教师:何炎详 编程环境:VC++6.0 时
间:日1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。3.流程图4.源程序/*******************************************语法分析程序作者:龚勋
罗晓波学号:
计科系 13班********************************************/#include#include#include/*******************************************/int count=0;
/*分解的产生式的个数*/
/*所有终结符和非终结符的总数*/
/*开始符号*/char termin[50];
/*终结符号*/char non_ter[50];
/*非终结符号*/char v[50];
/*所有符号*/char left[50];
/*左部*/char right[50][50];
/*右部*/char first[50][50],follow[50][50];
/*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50];
/*所有单个符号的FIRST集合*/char select[50][50];
/*各单个产生式的SELECT集合*/char f[50],F[50];
/*记录各符号的FIRST和FOLLOW是否已求过*/ char empty[20];
/*记录可直接推出^的符号*/char TEMP[50];
/*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1;
/*表示输入文法是否有效*/int ll=1;
/*表示输入文法是否为LL(1)文法*/int M[20][20];
/*分析表*/
/*用户输入时使用*/char empt[20];
/*求_emp()时使用*/char fo[20];
/*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){ if(strlen(p)==0)
{ return(0);
for(i=0;;i++)}
return(1);
/*若在,返回1*/ if(i==strlen(p))
return(0);
/*若不在,返回0*//*******************************************得到一个不是非终结符的符号********************************************/char c(){}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){
/*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20], ch=c();
/*得到一个非终结符*/ k=strlen(non_ter); non_ter[k]= non_ter[k+1]='\0'; for(j=0;j}
/*如果‘|’后的首符号和左部不同*/
left[count]= right[count][0]='^'; right[count][1]='\0'; count++; for(j=n;j/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20]; for(j=3;j} else {
left[count]=point[0];
memcpy(right[count],temp,m);
right[count][m]='\0';
} m=0; count++;left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]){char vn[50],vt[50]; char p[50][50]; int i,j,k; printf("\n请输入文法的非终结符号串:"); getchar(); m=0;
scanf("%s",vn);i=strlen(vn);memcpy(n,vn,i);n[i]='\0'; printf("请输入文法的终结符号串:"); getchar();
scanf("%s",vt);i=strlen(vt);memcpy(t,vt,i);t[i]='\0'; scanf("%c",&s); getchar(); printf("请输入文法产生式的条数:"); getchar();
printf("请输入文法的开始符号:");
scanf("%d",&i);for(j=1;j}
if(p[j][1]!='-'||p[j][2]!='>') {
printf("\ninput error!"); return('\0');
validity=0; printf("请输入文法的第%d条(共%d条)产生式:",j,i); scanf("%s",p[j-1]);
getchar();
for(j=0;j}
/*检测输入错误*/for(k=0;k{
/*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){
/*d是目标符号串,s是源串,type=1,源串中的‘ ^ ’一并并入目串;type=2,源串中的‘ ^ ’不并入目串*/ for(i=0;i} } /*******************************************求所有能直接推出^的符号********************************************/ void emp(char c){
/*即求所有由‘ ^ ’推出的符号*/}/*******************************************求某一符号能否推出‘ ^ ’********************************************/ int _emp(char c){
/*若能推出,返回1;否则,返回0*/int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; merge(empt,temp,1); if(in(c,empty)==1)
if(i==count) if(left[i]==c)
/*找一个左部为c的产生式*/ {
if(j==1&&in(right[i][0],empty)==1)
return(1); else if(j==1&&in(right[i][0],termin)==1)
return(0); return(1); for(i=0;;i++) char temp[10]; for(i=0;i{for(k=0;kif(in(right[i][k],empt)==1)}/*******************************************判断读入的文法是否正确********************************************/ int judge(){int i,j;for(i=0;i}
} return(0); return(1);/*******************************************求单个符号的FIRST********************************************/ void first2(int i){
/*i为符号在所有输入符号中的序号*/
char c,temp[20];int j,k,m; c=v[i]; char ch='^'; emp(ch); if(in(c,termin)==1)
/*若为终结符*/{first1[i][0]=c;first1[i][1]='\0'; }
else if(in(c,non_ter)==1)
/*若为非终结符*/ {
for(j=0;j}
} } merge(first1[i],first1[k],2); {
} empt[0]='\0'; if(_emp(right[j][k])==1&&k/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){ int j,k,m; char temp[20]; length=strlen(p); if(length==1)
/*如果右部为单个符号*/ {}
for(j=0;;j++)
memcpy(first[i],first1[j],strlen(first1[j]));
first[i][strlen(first1[j])]='\0'; } else {
} memcpy(TEMP,first1[j],strlen(first1[j])); TEMP[strlen(first1[j])]='\0'; if(v[j]==p[0]) if(i>=0)
first[i][0]='^';
first[i][1]='\0'; } else {
} TEMP[0]='^'; TEMP[1]='\0';
{ if(i>=0)
/*如果右部为符号串*/ {
for(j=0;;j++)
if(v[j]==p[0]) if(i>=0) else
empt[0]='\0'; if(_emp(p[k])==1&&kfor(m=0;;m++)}/*******************************************求各产生式左部的FOLLOW********************************************/void FOLLOW(int i){int j,k,m,n,result=1; char c,temp[20]; c=non_ter[i];
/*c为待求的非终结符*/ temp[0]=c; temp[1]='\0'; merge(fo,temp,1); if(c==start) {
/*若为开始符号*/
if(in(c,right[j])==1)
/*找一个右部含有c的产生式*/ { temp[0]='#'; temp[1]='\0'; merge(follow[i],temp,1);
} else if(_emp(p[k])==0) temp[0]='^'; temp[1]='\0'; if(i>=0)
merge(first[i],temp,1);
merge(TEMP,temp,1);
if(v[m]==right[i][k+1])
merge(first[i],first1[m],2); else
merge(TEMP,first1[m],2);
else if(_emp(p[k])==1&&k==length-1)
for(j=0;jif(right[j][k]==c)
/*k为c在该产生式右部的序号*/
for(m=0;;m++) if(v[m]==left[j])
/*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1) {
/*如果c在产生式右部的最后*/
/*如果c不在产生式右部的最后*/
for(n=k+1;n}}
} merge(follow[i],TEMP,2); F[i]='1';/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50]; for(j=0;j} printf("\nfirst:"); for(i=0;iselect[i][strlen(first[i])]='\0';} printf("\nselect:"); for(i=0;i}return(1);/*******************************************
构造分析表M********************************************/ void MM(){int i,j,k,m;for(i=0;ii=strlen(termin);termin[i]='#';
/*将#加入终结符数组*/
termin[i+1]='\0';}/*******************************************
总控算法********************************************/ void syntax(){int i,j,k,m,n,p,q; char S[50],str[50]; scanf("%s",str);
printf("请输入该文法的句型:"); for(i=0;ii=strlen(str); str[i]='#'; str[i+1]='\0'; S[0]='#'; S[1]= S[2]='\0'; j=0; ch=str[j]; {
if(in(S[strlen(S)-1],termin)==1) {
} else if(S[strlen(S)-1]=='#') { printf("\n该符号串不是文法的句型!");
if(S[strlen(S)-1]!=ch)
printf("\n该符号串是文法的句型.");
if(non_ter[i]==S[strlen(S)-1])
if(termin[k]==ch)
} printf("\n词法错误!"); if(k==strlen(termin)) } else {
} j++; ch=str[j];
S[strlen(S)-1]='\0';
for(i=0;;i++) for(k=0;;k++)if(M[i][k]==-1) {
} else { printf("\n语法错误!");m=M[i][k];if(right[m][0]=='^')}/*******************************************
一个用户调用函数********************************************/ void menu(){}syntax(); printf("\n是否继续?(y or n):"); scanf("%c",&choose); getchar(); while(choose=='y')
} for(p=j;p=0;n--)
S[q+strlen(right[m])]='\0'; } S[strlen(S)-1]='\0';
S[p++]=right[m][n];
printf("\nS:%s str:",S);/*******************************************
主函数********************************************/ void main(){}int i,j; start=grammer(termin,non_ter,left,right);
/*读入一个文法*/ printf("\nstart:%c",start); strcpy(v,non_ter); strcat(v,termin); printf("\nv:%s",v); printf("\nnon_ter:%s",non_ter); printf("\nright:"); for(i=0;i=0)
printf("M[%d][%d]=%d ",i,j,M[i][j]); printf("\n该文法不是一个LL1文法!");
printf("\n文法有效");
printf("\n");
printf("\n");
menu(); }5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序
范文九:编译原理实验报告实验名称:
编写语法分析程序实验类型:
指导教师:
专业班级:
实验地点:实验成绩:____________________日期:2013年 月日实验二
编写语法分析程序一、实验目的通过设计、编写、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握递归下降语法分析方法。二、实验设计1、改写文法,消除二义性,消除左递归,提取左公因子
2、求出非终结符FIRST集,有ε表达式的FOLLOW集
3、根据每条文法编写程序
4,、测试三、实验过程
1、改写文法
TEST语言语法规则:1)::={} 2)::= | ε 3)::=int ID;4)::=| ε5)::= |||
|| | 6)::= if ()
[else ] 7)::= while ()
8)::= for(;;) 9)::=10)::=read ID;11)::={} 12)::=;|;13)::= ID=| 14)::=|(>|=|
15)::={(+|-)}
16)::={(*| /)}
17)::=()|ID|NUM改写后文法:1)::={}
2)::= | ε
消除左递归:::= |ε
3)::=int ID;4)::=| ε消除左递归:::=|ε 5)::= |||
|| |6)::= if ()
[else ]7)::= while ()8)::= for(;;)
10)::=read ID;
FRIST()={(、ID、NUM、;}13)::= ID=|
14)::=|(>|=|消除左公因子:::=|AA::= >||>=||==|!=|ε15)::={(+|-)}
消除左递归:::=
::=+|-|ε16)::={(*| /)}消除左递归:::=::=*|/|ε17)::=()|ID|NUM2、FIRST集:1)FIRST({})={ { }
2)FRIST()={ int ,ε}
3)FIRST(declaration_stat)={int}4) FIRST()={if、while、for、read、write、{、(、ID、NUM、; ε}5)FIRST::={ if、while、for、read、write、command、experiession} 6)
FIRST::={ if } 7)FIRST)={while} 8)FIRST())={for} 9)FIRST()={write} 10)FIRST(read ID;)={read} 11)FRIST({})={{}12)FRIST()={(、ID、NUM、;} 13)FRIST()={ID、(、NUM}14)FRIST()={(、ID、NUM}
FRIST(>)={>}FRIST()={=)={>=}
FRIST()={)={==}
FRIST(!=)={!=}
FRIST(ε)={ ε}FRIST(A)={ >、= ,、15)
FRIST(additive_expr) = {(,ID,NUM} FRIST(R) = {ε,+,-}
16) FRIST={ (,ID,NUM }
FRIST()={* 、/、 ε} 17)FIRST::={ (,ID,NUM }3、FLLOW集2)FOLLOW()={int、if、while、for、read、write、{、(、ID、NUM、;
} 3)FOLLOW(statement_list)={ }
} 14)FRIST(A)={ >、= ,15)FOLLOW
、= 、== 、!= 、; 、) } 16) FOLLOW(term_1)={ + 、—、
、= 、== 、!= 、;4、流程图:::= |||
|| |、)}::= ID=|5、编写代码三、实验结果测试数据是词法分析结果{ {int int ID;int int NUM ;;123int int ID A ;;int int;;int int ID;int int ID b ,,ID;read read ID;for for ((ID i ==1NUM ;;ID i;ID i ==ID i ++1NUM ) {) {ID abc ==ID abc ++; }; }结果四、讨论与分析1、对于不满足无回溯的递归下降分析条件的有(2)(4)改为右递归(14)提取左公因子(15)(16)改为右递归
2、不是,如
S→AU|BRA→aAU|b
R→d其中S→aAUU|bU|aBRR|bR
即S→a(AUU|BRR)|b(U|R) S→aS1|bS2 S1→AUU|BRR S2→U|RA→aAU|b
R→d永远不能满足3、递归算法的实现效率低,处理能力相对有限,通用性差,难以自动生成五、附录:关键代码
//分析additive_expr//文法::=// ::=+|-|εvoid additive_expr()
//直接调用term(),R(); {term();
R(); } void R() {if (strcmp(str,"+")==0||strcmp(str,"-"))
}getStr(); term(); R();//判断是否在FOLLOW集里else if (strcmp(str,">")==0||strcmp(str,"=")==0||
{getStr();strcmp(str,"} }六、六、实验者自评写代码时遇到困难就去看书,做实验时通过老实讲明白改写文法作用,必须按改写后的文法写代码才能尽可能包含所有的情况,不只是能检查出代码是对的,回来后又改写了代码
范文十:LL(1)语法分析一, 实验名称:实现LL分析。二, 实验要求:? 输入任意文法? 消除左递归? 消除左因子? 测试任意输入语句是否合法? 数据结构描述? 算法说明? 输出first集合输出follow集合输出LL(1)表三. 设计原理及算法描述所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘#’,则宣布分析成功,停止分析过程。
(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。(3)若X是一个非终结符,则查看预测分析表M。若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。
事实上,LL(1)的分析是根据文法构造的,它反映了相应文法所定义的语言的固定特征,因此在LL(1)分析器中,实际上是以LL(1)分析表代替相应方法来进行分析的。2.构造LL(1)分析表考查文法G[E]:E→E+T | TT→T*F | FF→( E ) | i | x | y我们容易看出此文法没有左公因子也没有二义性,但却存在两个直接左递归,这里我们利用引入新非终结符的方法来消除它使方法满足要求,即:对形如:U→Ux|y的产生式(其中x,y V+ ,y不以U开头),引入一个新的非终结符U’后,可以等价地改写成为:U→yU’U’→x U’|ε显然改写后,U和U’都不是左递归的非终结符。因此文法G[E]按上述方法消去左递归后可等价地写成:E→TPP→+TP | εT→FQQ→*FQ | εF→( E ) | i | x | y在构造LL(1)预测分析表之前,首先要构造该文法的每个非终结符的FIRST和FOLLOW集合,按照下面描述的算法来构造这两个集合。①FIRST集合的构造算法:(1)若X∈VT,则FIRST(X)={X}。(2)若X∈VN,且有产生式X→a……,则把a加入到FIRST(X)中;若X→ε也是一条产生式,则把ε也加到FIRST(X)中。(3)若X→Y……是一个产生式且Y∈VN,则把FIRST(Y)中的所有非ε-元素都加到FIRST(X)中;若X→Y1Y2…Yk是一个产生式,Y1,…,Yi-1都是非终结符,而且,对于任何j,1≤j≤i-1,FIRST(Yj)都含有ε(即Y1…Yi-1* ε),则把FIRST(Yj)中的所有非ε-元素都加到FIRST(X)中;特别是,若所有的FIRST(Yj)均含有ε,j=1,2,…,k,则把ε加到FIRST(X)中。连续使用上面的规则,直至每个集合FIRST不再增大为止。
②FOLLOW集合的构造算法:(1)对于文法的开始符号S,置#于FOLLOW(S)中;(2)若A→αBβ是一个产生式,则把FIRST(β)| {ε}加至FOLLOW(B)中;(3)若A→αB是一个产生式,或A→αBβ是一个产生式而β ε(即ε∈FIRST(β)),则把FOLLOW(A)加至FOLLOW(B)中。
连续使用上面的规则,直至每个集合FOLLOW不再增大为止。 现在来构造G[E]的LL(1)预测分析表。预测分析表M[A, a]是如下形式的一个矩阵。A为非终结符,a是终结符或‘#’。矩阵元素 M[A, a]中存放这一条关于A的产生式,指出当A面临输入符号a是所应采用的规则。M[A, a]也可能存放一条“出错标志”,指出当A根本不该面临输入符号a。4.利用分析表进行预测分析带预测分析的PDA1)总程序的算法描述如下:BEGIN首先把‘#’然后把文法开始符号推进STACK栈;把第一个输入符号读进a;FLAG:=TRUE;WHILE FLAG DOBEGIN把栈顶符号出栈到X中;IF X?VT THENIF X =a THEN 把下一输入符号读进aELSE ERRORELSE IF X= ‘#’ THENIF X=a THEN FLAG:=FALSEELSE ERRORELSE IF M[A, a]={X(R)x1x2…xk} THEN把xk, xk–1,…, x1依次进栈/*若x1, x2 …xk=e,则不进栈*/ELSE ERROREND OF WHILE;STOP /*分析成功,过程结束*/END四.主要数据结构描述1. char termin[50];
/*终结符号*/char non_ter[50];
/*非终结符号*/char v[50];
/*所有符号*/char left[50];
/*左部*/char right[50][50];
/*右部*/char first[50][50],follow[50][50];
/*各产生式右部的FIRST和左部的FOLLOW集合*/int M[20][20];
/*二维数组存储分析表*/栈T用来存放产生式的右边Str数组存放要分析的句子串五. 运行结果:ERTWF#+*()i#测试文法G[E]:1 E -> TR2 R -> +TR|^3 T -> FW4 W -> * FW|^5 F -> (E)|i分析例句:i*(i)# , i+i#六.结果分析以上两个试验从较大呈度上说明了程序运行的正确性及稳定性,当然,对程序本身还有待进行更进一步的严格测试。

我要回帖

更多关于 投诉调查报告范文 的文章

 

随机推荐