递归下降语法分析程序设计样本

合集下载

实验三-递归下降法的语法分析器

实验三-递归下降法的语法分析器

魏陈强 204168实验3 递归下降法的语法分析器一、实验目的学习用递归下降法构造语法分析器的原理,掌握递归下降法的编程方法。

二、实验内容用递归下降法编写一个语法分析程序,使之与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。

这里只要求实现部分产生式,文法的开始符号为program。

(完整的源语言的文法定义见教材附录,p394)program→ blockblock→{stmts }stmts→stmt stmts |。

stmt→id=expr;| if(bool)stmt| if( bool)stmt else stmt| while(bool)stmt| do stmt while(bool ) ;| break ;| blockbool →expr < expr| expr <= expr| expr > expr| expr >= expr&| exprexpr→ expr + term| expr - term| termterm→ term * factor| term / factor| factorfactor→ ( e xpr ) | id| num三、实验要求1.个人完成,提交实验报告。

(2.实验报告中给出采用测试源代码片断,及其对应的最左推导过程(形式可以自行考虑)。

测试程序片断:{i = 2;while (i <=100){sum = sum + i;i = i + 2;}}对应的推导过程为:#program block{stmts }{stmt stmts}{id=expr;stmts }{id=num;stmts }{id=num;stmt stmts }{id=num;while(bool)stmt stmts }{id=num;while(e xpr<= expr)stmt stmts }{id=num;while(id<= expr)stmt stmts }{id=num;while(id<= num)stmt stmts }{id=num;while(id<= num)block stmts },{id=num;while(id<= num){stmts }stmts }.......四、实验思路之前编写的词法分析器,能够将语句中的每一个词素都识别出来,因此,在此基础上,定义一个二维字符串数组finaltable[100][20],用于存放由词法分析器提取出来的每个词素,比如,i=2,则finaltable[0]=”id”,finaltable[1]=”=”,finaltable[2]=”num”。

实验二 递归下降分析法的实现

实验二  递归下降分析法的实现

实验二递归下降分析法的实现一、实验目的实现一个递归下降语法分析程序,识别用户输入的算术表达式。

二、实验主要内容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。

语法分析程序(递归下降法)

语法分析程序(递归下降法)

语法分析程序(递归下降法)班级学号姓名:指导老师:一. 实验目的:1、学习语法分析的主要方法;2、熟悉复习词法分析的方法;3、判断表达式的正确性;4、熟悉C语言并提高动手能力;二. 实验内容:用递归下降分析法编写一个用于判断数学表达式是否正确的语法分析三.实验硬件和软件平台:INTEL C433MHz Cpu128Mb SDRAMTurbo C 2.0Microsoft Windows XP SP1四.步骤和算法描述:1.调用词法分析程序,转换表达式成为内号;2.调用语法分析程序,判断表达式正确与否;五.源程序:#include <stdio.h>#include <string.h>#include <io.h>#define yy swy=adv()FILE *fp1;char ch;int swy;main(){void CS();int chz(char str[15]);int adv();void CT();void E(); void EB();void ERROR();void ET();void F();void IT();void T();void sentence();clrscr();ch=' ';fp1=fopen("pas.txt","r");if(!fp1){printf("Can not open ljx.txt!!\n”); exit(0);}/* while(!feof(fp1)) */{yy;sentence();fclose(fp1);}}void ERROR(){printf("%d ERROR!\n ",swy); }void E(){T();while(swy==34||swy==35){yy;T();}}void T(){F();while(swy==36||swy==37){yy;F();}}void F(){if(swy==21||swy==22) yy;else if(swy==27){yy;E();if(swy==28) yy;else ERROR();}else ERROR();}void sentence(){ switch(swy){case 21 :{yy;if(swy==44){yy;E();}else ERROR();break;}case 1:CS();break;case 8:{yy;EB();if(swy!=4)ERROR();yy;sentence();break;}case 19:{yy;EB();if(swy!=4)ERROR();yy;sentence();}break;case 14:{yy;if(swy!=27) ERROR();yy;IT();if(swy!=28)ERROR();yy;break;}case 20:{yy;if(swy!=27) ERROR();yy;ET();if(swy!=28)ERROR();yy;break;}}}void CS(){yy;sentence();while(swy==24){yy;sentence();}if(swy==6)yy;else ERROR();}void CT(){if(swy==5){yy;sentence();}}void EB(){E();if(swy<=43&&swy>=38){yy;E();}else ERROR();}void IT(){if(swy!=21)ERROR();yy;while(swy==23){yy;if(swy!=21)ERROR();else ERROR();} }void ET(){E();while(swy==23){yy;E();}}int chz(char str1[15]){charstr[21][15]={"and","begin","const","div","do", "else","end","function","if","integer","not","or","pro cdure","program","read","real","then","type","var","while","write"};int i,max,min,mid;for(i=0;i<=14;i++)if(str1[i]<='Z'&&str1[i]>='A')str1[i]=str1[i]+'a'-'A';max=20;min=0;mid=10;while(min<=max){i=strcmp(str1,str[mid]);if(i==0) return mid;elseif(i>0){min=mid+1;mid=(max+min)/2;}else{max=mid-1;mid=(max+min)/2;}}return 0;}int adv(){char str1[15];int t,i=0,sk=0;float num,xs;if(ch==''||swy==24){fscanf(fp1,"%c",&(ch));printf("% c",ch);}while(!feof(fp1)&&i<100){if(((ch)>='a'&&(ch)<='z')||((ch)>='A'&&( ch)<='Z')){i=0;while((((ch)>='a'&&(ch)<='z')||((ch)>='A '&&(ch)<='Z')||((ch)>='0'&&(ch)<='9'))){str1[i]=(ch);i++;{fscanf(fp1,"%c",&(ch));printf("%c",ch);}}str1[i]='\0';t=chz(str1);if(!t)return 21;else return t;}else if(ch>='0'&&ch<='9'){num=0;while(ch>='0'&&ch<='9'){num=num*10+(ch)-'0';{fscanf(fp1,"%c",&(ch));printf("%c",ch); }}if(ch=='.'){xs=0.1;{fscanf(fp1,"%c",&(ch));printf("%c",ch); }while(ch>='0'&&ch<='9'){num+=(ch-'0')*xs;xs*=0.1;{fscanf(fp1,"%c",&(ch));printf("%c",ch); }}}return 22;}switch(ch){case '+' :{ch=' ';return 34;}case '*' :{ch=' ';return 36;}case ',' :{ch=' ';return 23;}case ';' :{ch=' ';return 24;}case '.' :{ch=' ';return 26;}case '(' :{ch=' ';return 27;}case ')' :{ch=' ';return 28;}case '[' :{ch=' ';return 29;}case ']' :{ch=' ';return 30;}case '{' :{ch=' ';return 45;}case '}' :{ch=' ';return 46;}case '-' :{ch=' ';return 35;}case '..' :{ch=' ';return 31;}case '/' :{ch=' ';return 37;}case '#' :{ch=' ';return 47;}case '<' : { {fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 42;}else {return 39;}}case ':' :{{fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 44;}else {return 25;}}case '>' :{{fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 44;}else {return 40;}}default:break;}if(sk==0){fscanf(fp1,"%c",&(ch));printf( "%c",ch);}else sk=0;}}。

编译原理语法分析递归下降子程序实验报告

编译原理语法分析递归下降子程序实验报告

编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行FirstVT集及LastVT集的分析,并对输入的字符串进行规约输出规约结果成功或失败。

二、设计内容及步骤内容:在C++ 6.0中编写程序代码实现语法分析功能,调试得到相应文法的判断结果:是算符优先或不是。

若是,则输出各非终结符的FirstVT与LastVT集的结果,还可进行字符串的规约,输出详细的规约步骤,程序自动判别规约成功与失败。

步骤:1.看书,找资料,了解语法分析器的工作过程与原理2.分析题目,列出基本的设计思路1定义栈,进栈,出栈函数○2栈为空时的处理○3构造函数判断文法是否是算符文法,算符优先文法○4构造FirstVT和LastVT函数对文法的非终结符进行分析○5是算符优先文法时,构造函数对其可以进行输入待规约○串,输出规约结果○6构造主函数,对过程进行分析3.上机实践编码,将设计的思路转换成C++语言编码,编译运行4.测试,输入不同的文法,观察运行结果详细的算法描述详细设计伪代码如下:首先要声明变量,然后定义各个函数1.void Initstack(charstack &amp;s){//定义栈s.base=new charLode[20];s.top=-1; }2. void push(charstack&amp;s,charLode w){//字符进栈s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}3. void pop(charstack&amp;s,charLode &amp;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=&#39;A&#39;&amp;&amp;ch= &#39;Z&#39;)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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。

设计3语法分析之递归下降分析法剖析

设计3语法分析之递归下降分析法剖析

词法分析程序一、设计目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二、设计要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>::=begin<语句串>end⑵<语句串>::=<语句>{;<语句>}⑶<语句>::=<赋值语句>⑷<赋值语句>::=ID:=<表达式>⑸<表达式>::=<项>{+<项> | -<项>}⑹<项>::=<因子>{*<因子> | /<因子>⑺<因子>::=ID | NUM | (<表达式>)2.2 实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。

例如:输入 begin a:=9; x:=2*3; b:=a+x end # 输出 success!输入 x:=a+b*c end #输出 error三、设计说明(含主要算法的流程图)1、主程序示意图如图2-1所示。

图2-1 语法分析主程序示意图2、递归下降分析程序示意图如图2-2所示。

3、语句串分析过程示意图如图2-3所示。

否是否是否是否图2-3 语句串分析示意图是图2-2 递归下降分析程序示意图4、statement语句分析程序流程如图2-4、2-5、2-6、2-7所示。

否否否是图2-4 statement语句分析函数示意图图2-5 expression表达式分析函数示意图是否否是是否否是图 2-6 term分析函数示意图否是图2-7 factor分析过程示意图5、实验源代码#include "stdio.h"#include "string.h"char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"}; int syn,p,m,n,sum;int kk;factor();expression();yucu();term();statement();lrparser();scaner();main(){p=kk=0;printf("\nplease input a string (end with '#'): \n");do{ scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}lrparser(){if(syn==1){scaner(); /*读下一个单词符号*/yucu(); /*调用yucu()函数;*/if (syn==6){ scaner();if ((syn==0)&&(kk==0))printf("success!\n");}else { if(kk!=1) printf("the string haven't got a 'end'!\n"); kk=1;}}else { printf("haven't got a 'begin'!\n");kk=1;}return;}yucu(){statement(); /*调用函数statement();*/ while(syn==26){scaner(); /*读下一个单词符号*/if(syn!=6)statement(); /*调用函数statement();*/ }return;}statement(){ if(syn==10){scaner(); /*读下一个单词符号*/if(syn==18){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/}else { printf("the sing ':=' is wrong!\n");kk=1;}}else { printf("wrong sentence!\n");kk=1;}return;}expression(){ term();while((syn==13)||(syn==14)){ scaner(); /*读下一个单词符号*/ term(); /*调用函数term();*/}return;}term(){ factor();while((syn==15)||(syn==16)){ scaner(); /*读下一个单词符号*/ factor(); /*调用函数factor(); */ }return;}factor(){ if((syn==10)||(syn==11)) scaner();else if(syn==27){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/if(syn==28)scaner(); /*读下一个单词符号*/else { printf("the error on '('\n");kk=1;}}else { printf("the expression error!\n");kk=1;}return;}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch< ='9'))){token[m++]=ch;ch=prog[p++];}p--;syn=10;token[m++]='\0';for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0) { syn=n+1;break;}}else if((ch>='0')&&(ch<='9')) { while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':m=0;ch=prog[p++];if(ch=='>'){ syn=21;}else if(ch=='='){ syn=22;}else{ syn=20;p--;}break;case '>':m=0;ch=prog[p++];if(ch=='='){ syn=24;}else{ syn=23;p--;}break;case ':':m=0;ch=prog[p++];if(ch=='='){ syn=18;}else{ syn=17;p--;}break;case '+': syn=13; break; case '-': syn=14; break; case '*': syn=15;break; case '/': syn=16;break; case '(': syn=27;break; case ')': syn=28;break; case '=': syn=25;break; case ';': syn=26;break;case '#': syn=0;break;default: syn=-1;break;}}4、运行结果及分析输入 begin a:=9; x:=2*3; b:=a+x end # 后输出success!如图4-1所示:图4-1输入 x:=a+b*c end # 后输出 error 如图4-2所示:图4-2五、总结通过本次试验,了解了语法分析的运行过程,主程序大致流程为:“置初值”调用scaner函数读下一个单词符号调用IrParse结束。

实验二:语法分析(递归下降法)

实验二:语法分析(递归下降法)

实验二:语法分析(递归下降法)一、实验目的1、掌握语法分析的基本原理;2、掌握递归下降的分析法;3、熟悉C语言程序设计。

二、实验准备微机CPU主频1.3G以上,128M内存,安装好C语言,PASCAL语言,或C++。

三、实验时间2学时四、实验内容已给语言文法,写出该文法的递归下降法语法分析器。

输入:源符号串。

输出:语法是否合法。

:文法:(1) <程序> ::= begin<语句串>end(2) <语句串> ::= <语句>{;<语句>}(3) <语句> ::= <赋值语句>(4) <赋值语句> ::= ID:=<表达式>(5) <表达式> ::= <项>{+<项>|-<项>}(6) <项> ::= <因子>{*<因子>|/<因子>}(7) <因子> ::= ID|NUM|(<表达式>)五:源程序:lrparser()对应 <程序>yucu() 对应 <语句串>statement() 对应 <语句>expression()对应 <表达式>term() 对应 <项>factor() 对应 <因子>关键字,数字,字母,符号对应码如下"begin", "if", "then", "while", "do", "end" 1——6字母 10 数字11+,-,*,/,:,:=,<,<>,<=,>,>=,=,;,(,),# 13——28,0factor()#include "stdio.h"#include "string.h"char prog[80], token[8];char ch;int syn, p, m, n, sum, kk=0;char *rwtab[6]={"begin", "if", "then", "while", "do", "end"};void scaner();void lrparser();void yucu();void statement();void expression();void term();void factor();void main(){p=0;printf("Please input string:\n");do{scanf("%c", &ch);prog[p++]=ch;}while(ch!='#'); //当遇到‘#’,结束输入p=0;scaner();lrparser();}void scaner(){for(n=0; n<8; n++) token[n]=NULL;ch=prog[p++];while(ch==' '||ch=='\n') ch=prog[p++];m=0;if((ch>='A'&&ch<='Z') || (ch>='a'&&ch<='z')){while((ch>='A'&&ch<='Z') || (ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')){token[m++]=ch;ch=prog[p++];//将prog数组的字母复制到ch数组中}token[m++]='\0';//把token的末尾设置结束符\0p--;//标记到当前token数组中不是字母的当前位置syn=10; //标记字母的对应码for(n=0; n<6; n++){if(strcmp(token, rwtab[n])==0)//判断token对应rwtab中的哪一个,并进行对应赋对应码{syn=n+1;break;}}}else if(ch>='0'&&ch<='9'){sum=0;while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';//number用来记录所对应的数字ch=prog[p++];}p--;syn=11;//标记数字的对应码}else{switch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21; //标记”<>”的对应码token[m++]=ch;}else if(ch=='='){syn=22; //标记”<=”的对应码token[m++]=ch;}else{syn=20; //标记”<”的对应码p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24; //标记”>=”的对应码token[m++]=ch;}else{syn=23; //标记”>”的对应码p--;}break;case ':':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18; //标记”:=”的对应码token[m++]=ch;}else{syn=17; //标记”:”的对应码p--;}break;case '+':syn=13; //标记”+”的对应码token[m++]=ch;break;case '-':syn=14; //标记”-”的对应码token[m++]=ch;break;case '*':syn=15; //标记”*”的对应码token[m++]=ch;break;case '/':syn=16; //标记”/”的对应码token[m++]=ch;break;case '=':syn=25; //标记”=”的对应码token[m++]=ch;break;case ';':syn=26; //标记”;”的对应码token[m++]=ch;break;case '(':syn=27; //标记”(”的对应码token[m++]=ch;break;case ')':syn=28; //标记”)”的对应码token[m++]=ch;break;case '#':syn=0; //标记”#”的对应码token[m++]=ch;break;default:syn=-1; //当不是上述字母,数字,符号时,设置syn=-1 }token[m++]='\0';}}void factor()//因子{if(syn==10 || syn==11) //当扫描的是数字或字母时,继续扫描{scaner();}else if(syn==27) //当扫描的‘(’时,继续扫描{scaner();expression();if(syn==28) //当扫描的是‘)’时,继续扫描scaner();else{kk=1;printf("ERROR: )错误\n");//表达式缺乏‘)‘,出错}}else{kk=1;printf("ERROR: 表达式错误\n");//扫描表达式,表达式开头不是‘(‘,出错}}void term()//项{factor();while(syn==15 || syn==16) //当开头扫描的是’*’或’/’时,继续扫描{scaner();factor();}}void expression()//表达式{term();while(syn==13 || syn==14) //当开头扫描的是’+’或’-’时,继续扫描{scaner();term();}}void statement()//语句{if(syn==10) //当开头扫描的是字母时,继续扫描{scaner();if(syn==18) //扫描的是’:=’时,继续扫描{scaner();expression();}else{kk=1;printf("ERROR: 赋值号错误\n");//当扫描的是’:=’,出错}}else{kk=1;printf("ERROR: 语句错误\n");}}void yucu()//语句串{statement();while(syn==26) //当开始扫描到的是’;’,继续扫描{scaner();statement();}}void lrparser()//程序{if(syn==1) //当开头扫描的是‘begin‘时,继续扫描{scaner();yucu();if(syn==6){scaner();if(syn==0 && kk==0) //当数字串的最后扫描的是‘#‘,而且并无出错,分析成功printf("success!\n");else if(syn!=0 && kk==0){kk=1;printf("ERROR: END后未正常结束\n");//数字串的最后并没有扫描到符号‘#‘,出// 错}}else{if(kk!=1){kk=1;printf("ERROR: 缺少end\n");//程序分析结束并没有扫描到’end’,出错}}}else{kk=1;printf("ERROR: begin错误\n");//开始时并没有扫描到’begin’,出错}}。

编译原理之递归下降语法分析程序(实验)

编译原理之递归下降语法分析程序(实验)

编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤C语⾔编制递归下降分析程序,并对简单语⾔进⾏语法分析。

编制⼀个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

⼆、实验原理每个⾮终结符都对应⼀个⼦程序。

该⼦程序根据下⼀个输⼊符号(SELECT集)来确定按照哪⼀个产⽣式进⾏处理,再根据该产⽣式的右端:每遇到⼀个终结符,则判断当前读⼊的单词是否与该终结符相匹配,若匹配,再读取下⼀个单词继续分析;不匹配,则进⾏出错处理每遇到⼀个⾮终结符,则调⽤相应的⼦程序三、实验要求说明输⼊单词串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

例如:输⼊begin a:=9;b:=2;c:=a+b;b:=a+c end #输出success输⼊a:=9;b:=2;c:=a+b;b:=a+c end #输出‘end' error四、实验步骤1.待分析的语⾔的语法(参考P90)2.将其改为⽂法表⽰,⾄少包含–语句–条件–表达式E -> E+T | TT -> T*F | FF -> (E) | i3. 消除其左递归E -> TE'E' -> +TE' | εT -> FT'T' -> *FT' | εF -> (E) | i4. 提取公共左因⼦5. SELECT集计算SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *}SELECT(E'->+TE')=FIRST(+TE')={+}SELECT(E'->ε)=follow(E')=follow(E)={#, )}SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i}SELECT(T'->*FT')=FRIST(*FT')={*}SELECT(T'->ε)=follow(T')=follow(T)={#, ), +}SELECT(F->(E))=FRIST((E)) ={(}SELECT(F->i)=FRIST(i) ={i}6. LL(1)⽂法判断 其中SELECT(E'->+TE')与SELECT(E'->ε)互不相交,SELECT(T'->*FT')与SELECT(T'->ε)互不相交,SELECT(F->(E))与SELECT(F->i)互不相交,故原⽂法为LL(1)⽂法。

语法分析——递归下降分析法

语法分析——递归下降分析法

实验2 语法分析——递归下降分析法一、实验目的1、通过该课程设计要学会用消除左递归的方法来使文法满足进行确定自顶向下分析的条件。

2、学会用C/C++高级程序设计语言来设计一个递归下降分析法的语法分析器;3、通过该课程设计,加深对语法分析理论的理解,培养动手实践的能力。

二、设计内容参考算数运算的递归子程序构造方法及代码,完成以下任务:构造布尔表达式的文法,并编写其递归子程序。

程序设计语言中的布尔表达式有两个作用,一是计算逻辑值,更多的情况是二,用作改变控制流语句中条件表达式,如在if-then,if-then-else或是while-do 语句中使用。

布尔表达式是由布尔算符(and,or,not)施予布尔变量或关系运算表达式而成。

为简单起见,以如下文法生成的布尔表达式作为设计对象:E→E and E | E or E | not E | i rop i | true | falsei→标识符|数字rop→>= | > | <= | < | == | <>以上文法带有二义性,并且未消除左递归,请对之处理后,再构造递归下降程序。

可适当减少工作量,暂时忽略id的定义,输入时直接用数字或字母表示。

三、语法分析器的功能该语法分析器能够分析词法分析器的结果,即单词二元式。

在输入单词二元式后,能输出分析的结果。

四、算法分析1、语法分析的相关知识;2、递归子程序法的相关理论知识;3、根据递归子程序法相关理论,具体针对文法的每一条规则编写相应得递归子程序以及分析过程等。

//在递归子程序的编写过程中,当要识别一个非终结符时,需时刻留意该非终结符的FIRST集与FOLLOW集。

程序示例一:G:P→begin d;X end G’:P→begin d;X endX→d;X|Y X→d;X|YY→Y;s|s Y→sZ Z→;sZ|ε相应的递归子程序设计如下:P(){ if(token==“begin“){ Read(token);If(token==’d’)Read(token);ElseERROR;If (token==’;’)Read(token);ElseERROR;If (token==’d’ || ‘s’)X();Else ERROR;If(token==’end’) OK;}Else ERROR;}X() //X→d;X|Y{if(token==’d’){read(token);if(token==’;’)read(token);elseERROR;If(token==’d’)X();Else if (token==’s’) //注意:对Y的识别也可以是在X的过程中一开始就进行,所以在最外层分支中,加上一个token==s的分支Y();Else ERROR;}Else ERROR;}Y() //Y→sZ{if(token==’s’){read(token);If(token==’;’ || ‘end’)Z();Else ERROR;Else ERROR;}Z() //Z→;s Z|ε{if(token==’;’){read(token);If(token==’s’)Read(token);Else ERROR;If(token==’;’)Z();Else if (token==’end’) // 类似的,这里对于读到end,也要最外层添加一个分支Return;Else ERROR;}Else ERROR;}程序示例二(参考代码):构造文法G[E]:E→E + T | T T→T * F | F F→(E)| d的递归子程序(即语法分析器)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void F();// F -> V|(E)
void V();// V -> a|b|c|d|e...|z
char s[50],n='1';//s[50]用于存储输入赋值表达式
char Table[50][3];//产生中间代码所需符号表
int SIGN,sym;//sym为s[50]中当前读入符号下标
#include<string.h>
#include <ctype.h>
void A();// A -> V:=E
void E();// E -> TE'
void T();// T -> FT'
void E1();// E'-> +TE'|-TE'|null
void T1();// T'-> *FT'|/FT'|null
1.
1.1
无回溯自上向下分析技术可用先决条件是:无左递归和无回溯。
无左递归:既没有直接左递归,也没有间接左递归。
无回溯:对于任一非终结符号U产生式右部x1|x2|…|xn,其相应字首终结符号两两不相交。
如果一种文法不含回路,也不含以ε为右部产生式,那么可以通过执行消除文法左递归算法消除文法一切左递归(改写后文法也许具有以ε为右部产生式)。
{
F();
T1();
}
2.5
函数void E1()//E'-> +TE'|-TE'|null,重要用来实现加减法语义分析。流程图如图2所示。
图2E1 ( )函数流程图
2.6
函数void T1()//T'-> *FT'|/FT'|null,重要用来实现乘除法语义分析。流程图如图3所示。
图3T1 ( )函数流程图
V -> a|b|c|d|e...|z
2
依照消除左递归后文法,可以编写相应函数。
2.1
void V()// V -> a|b|c|d|e...|z函数设计重要用来辨认小写字母,如果是小写字母话,放入字符表,不是话,输出语法错误。函数比较简朴,代码如下:
if(islower(s[sym]))
{
Table[list_n][0] = s[sym];//把读取小写字母存入符号表,便于分析是生成中间代码
编译办法 实 验 报 告
实验名称:简朴语法分析程序设计
实验规定
1.功能:对简朴赋值语句进行语法分析
随机输入赋值语句,输出所输入赋值语句与相应四元式
2.采用递归下降分析程序完毕(自上而下分析)
3.拟定各个子程序功能并画出流程图
4.文法如下:
5.编码、调试通过
采用原则输入输出方式。输入输出样例如下:
【样例输入】
x:=a+b*c/d-(e+f)
【样例输出】(阐明,语句和四元式之间用5个空格隔开)
T1:=b*c (*,b,c,T1)
T2:=T1/d (/,T1,d,T2)
T3:=a+T2 (+,a,T2,T3)
T4:=e+f (+,e,f,T4)
T5:=T3-T4 (-,T3,T4,T5)
x:=T5 (:=,T5,-,x)
文法直接左递归消除公式:
直接左递归形式:
U→Ux|y;
其中:x,y∈(VN∪VT)*,y不以U打头。
直接左递归消除:
U→yU‟
U‟→xU‟|ε
直接左递归普通形式:
U→Ux1|Ux2|…|Uxm|y1|y2|…|yn;
其中:xi≠ε ,yi都不以U打头。
普通形式直接左递归消除:
U→y1U‟| y2U‟|…| ynU‟
【样例阐明】程序除可以对的输出四元式外,当输入表达式错误时,还应能检测出语法错误,给出相应错误提示。
6.设计3-5个赋值语句测试实例,检查程序能否输出对的四元式;当输入错误句子时,检查程序可以给出语法错误相应提示信息。
7.报告内容涉及:
递归程序调用过程,各子程序流程图和总控流程图,详细设计,3-5个测试用例程序运营截图及有关阐明,有详细注释程序代码清单等。
sym=0;
scanf("%s",&s);
if( s[0] == '\0') //没有输入状况直接退出
return 0;
A();
if(s[sym]!='\0'&&SIGN==0)
Table[list_n][1] = '\0';
list_n++;
sym++;
}
else
{
printf("Operand Errors!\n");//运算对象错误
SIGN=1;
exit(0);
}
2.2
void A() // A -> V:=E函数重要用来实现赋值操作,流程图如图1所示。
图1A( )函数流程图
int list_n=0;//符号表下标
/*消除左递归及回溯
A -> V:=E
E -> TE'
E'-> +TE'|-TE'|null
T -> FT'
T'-> *FT'|/FT'|null
F -> V|(E)
V -> a|b|c|d|e...|z
*/
int main()
{
SIGN = 0;//SIGN用于批示赋值表达式与源自浮现错误3.3.1
用例1为实验规定上用例。测试成果图4所示。
图4测试用例1及成果截图
3.2
用例2为浮现大写字母,浮现报错。测试成果图5所示。
图5测试用例2及成果截图
3.3
用例3为随意编写用例。测试成果图6所示。
图6测试用例3及成果截图
代码清单
#include<stdio.h>
#include<stdlib.h>
U‟→x1U‟| x2U‟| …| xmU‟|ε
回溯消除前提是文法不得具有左递归,可提左因子来消除回溯。
1.2
依照实验中给出文法,进行消除左递归及回溯,得到下列式子
A -> V:=E
E -> TE'
E'-> +TE'|-TE'|null
T -> FT'
T'-> *FT'|/FT'|null
F -> V|(E)
2.3
函数E()里面重要递归调用函数T( )和E'( )。当没有浮现语法错误时就可正常运营。函数比较简朴,代码如下:
{
if(SIGN==0)
{
T();
E1();
}
}
2.4
函数T()里面重要递归调用函数F( )和T''( )。当没有浮现语法错误时就可正常运营。函数比较简朴,代码如下:
if(SIGN==0)
文法左递归消除算法:
1、将文法G所有非终结符排序为U1 ,U2 ,… ,Un;
2、For(i=1;i++;i≥n)
{
for j→1 to i-1
把产生式Ui→Ujα替代成Ui→β1α| β2α|…|βmα;
其中:Uj→ β1| β2 |… |βm消除Ui产生式中直接左递归;
}
3.化简改写之后文法,删除多余产生式。
相关文档
最新文档