递归下降子程序的编写
计算器程序 递归下降分析实现
![计算器程序 递归下降分析实现](https://img.taocdn.com/s3/m/1513fbf5f90f76c661371ac9.png)
递归下降分析实现计算器程序1.计算器程序文法<exp> -> <term> { <addop> <term> }<addop> -> + | -<term> -> <factor> { <mulop> <factor> }<mulop> -> * | /<factor> -> ( <exp> ) | Number2.实现功能:+ , - , * , / 和带括号的四则运算.3.实现方式:vc+递归下降分析4.代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>/* Simple integer arithmetic calculatoraccording to the EBNF:<exp> -> <term> { <addop> <term> }<addop> -> + | -<term> -> <factor> { <mulop> <factor> }<mulop> -> * | /<factor> -> ( <exp> ) | Number*/char token , str[1024] ;int pos ;int exp();int term();int factor();void error(){fprintf(stderr,"Error\n");exit(1);}void match(char expectedToken){if( token == expectedToken ) token = str[pos++] ;else error();}int exp(){int temp = term();while ( ( token == '+' ) || ( token == '-' ) ) {switch(token){case '+' : match('+');temp += term();break ;case '-' : match('-');temp -= term();break ;}}return temp ;}int factor(){int temp ;if ( token == '(' ){match('(');temp = exp();match(')');}else if( isdigit(token) ){for( temp = 0 ; isdigit(token) ; token = str[pos++] ) temp = (temp<<3) + (temp<<1) + (token^48) ;}else error();return temp ;}int term(){int temp = factor();while ( token == '*' || token == '/' ){if( token == '*' ){match('*');temp *= factor() ;}else if ( token == '/' ){match('/');int sth = factor() ;if( 0 == sth ) error();temp /= sth ;}}return temp ;}int main(){int result , t ;scanf("%d",&t); getchar();while(t--){gets(str);pos = 0 ;token = str[pos++] ;result = exp();printf("%d\n",result);}}。
递归下降语法分析程序设计说明书
![递归下降语法分析程序设计说明书](https://img.taocdn.com/s3/m/5f32ae07aef8941ea66e0537.png)
编译方法实验报告实验名称:简单的语法分析程序设计实验要求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>[样例说明]程序除能够正确输出四元式外.当输入的表达式错误时.还应能检测出语法错误.给出相应错误提示。
6.设计3-5个赋值语句测试实例.检验程序能否输出正确的四元式;当输入错误的句子时.检验程序能够给出语法错误的相应提示信息。
7.报告内容包括:递归程序的调用过程.各子程序的流程图和总控流程图.详细设计.3-5个测试用例的程序运行截图及相关说明.有详细注释的程序代码清单等。
目录1.语法分析递归下降分析算法21.1背景知识21.2消除左递归32.详细设计及流程图32.1 函数void V< > // V -> a|b|c|d|e...|z32.2 函数void A< > // A -> V:=E42.3 函数void E<> //E -> TE'42.4函数void T< > // T -> FT'42.5函数void E1< > //E'-> +TE'|-TE'|null52.6函数void T1<> // T'-> *FT'|/FT'|null53.测试用例及截图53.1测试用例1及截图53.2测试用例2及截图53.3测试用例3及截图5代码清单51.语法分析递归下降分析算法1.1背景知识无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
编译原理递归下降
![编译原理递归下降](https://img.taocdn.com/s3/m/b2a0771555270722192ef7ad.png)
《编译原理》课程实验实验二:自顶向下的语法分析:递归下降法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("缺少值或变量。
递归下降子程序编写
![递归下降子程序编写](https://img.taocdn.com/s3/m/24bd9f116c175f0e7cd13735.png)
实验5-6 递归下降子程序的编写一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验准备1.预习自上而下语法分析小节的内容;2.学生自己考虑使用的开发环境,如VC++,熟悉开发环境。
三、实验内容下列文法中选做一题:1.针对算术表达式文法:E→TE’E’→ +TE’|εT→FT’T’→*FT’ |εF→(E) |i为其编写递归下降子程序,判定某个算术表达式是否正确:如j+k*m,j*k+m输入:其输入数据应该为词法分析器输出的记号形式:i+i*i,i*i+i输出:分析结果:算术表达式结构正确或结构错误。
2.给定文法(PASCAL语言标识符定义文法)type→simple|↑id|array[simple] of typeSimple→integer|char|num dotdot num其中:dotdot表示..编写递归下降子程序,判定一个句子结构是否正确:array [3..5]of integer 输入:其输入数据应该为词法分析器输出的单词序列:array[num dotdot num] of integer输出:该句子结构是正确或错误3.给定文法:S→(T)|a+S|aT→T,S|S改写文法,使其可以使用递归下降子程序方法进行分析,编写递归下降子程序,判断句子:(((a+a+a),a+a),a)是否符合该文法。
S→(T)|aS’S’→+S|εT→ST’T’→,ST’|ε输入:(((a+a+a),a+a),a)输出:结构正确或结构错误四、实验要求1.编写程序调试运行;考虑如果将你的程序改为识别其他的文法,你的递归下降子程序可否通用,考虑递归下降子程序方法的优缺点。
2.撰写实验报告:实验名称、实验目的、实验内容、实验结果、结果分析(就第1项要求做出回答)。
五、实验时间第7周周三(4.14)第2单元上机地点:计算机系机房。
编译原理实验语法器递归下降子程序实现解析
![编译原理实验语法器递归下降子程序实现解析](https://img.taocdn.com/s3/m/1bdfa0ef08a1284ac8504335.png)
编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机1306班姓名:张涛学号:20133967 实验目标:用递归下降子程序设计实现表达式语法分析器实验内容:⑴概要设计:通过对实验一的此法分析器的程序稍加改造,使其能够输出正确的表达式的token序列。
然后利用LL(1)分析法实现语法分析。
⑵数据结构:int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'}; //运算符char bound[2]={'(',')'}; //界符struct Token{int code;char ch[10];}; //Token定义struct Token tokenlist[50]; //Token数组struct Token tokentemp; //临时Token变量⑶流程图:⑷关键函数:int IsLetter(char ch) //判断ch是否为字母int IsDigit(char ch) //判断ch是否为数字int Iskey(char *string) //判断是否为关键字int Isbound(char ch) //判断是否为界符int Isboundnum(char ch) //给出界符所在token值void T(); //分析子程序void F(); //分析子程序void E1(); //分析子程序void E(); //分析子程序void T1(); //分析子程序源程序代码:(加入注释)#include<stdio.h>#include<string.h>#include<ctype.h>#include<windows.h>int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'};char bound[2]={'(',')'};struct Token{int code;char ch[10];};struct Token tokenlist[50];struct Token tokentemp;void T();void F();void E1();void E();void T1();int IsLetter(char ch) //判断ch是否为字母{int i;for(i=0;i<=45;i++)if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))return 1;return 0;}int IsDigit(char ch) //判断ch是否为数字{int i;for(i=0;i<=10;i++)if (ch>='0'&&ch<='9')return 1;return 0;}int Isbound(char ch){int i;for(i=0;i<2;i++){if(ch==bound[i]){return i+1;}}return 0;}int Isoperate(char ch){int i;for(i=0;i<4;i++){if(ch==operate[i]){return i+3;}}return 0;}int main(){FILE *fp;int q=0,m=0;char sour[200]=" ";printf("请将源文件置于以下位置并按以下方式命名:F:\\2.txt\n");if((fp=fopen("F:\\2.txt","r"))==NULL){printf("文件未找到!\n");}else{while(!feof(fp)){if(isspace(ch=fgetc(fp)));else{sour[q]=ch;q++;}}}int p=0;printf("输入句子为:\n");for(p;p<=q;p++){printf("%c",sour[p]);}printf("\n");int state=0,nowlen=0;BOOLEAN OK=TRUE,ERR=FALSE;int i,flagpoint=0;for(i=0;i<q;i++){switch(state){case 0:ch=sour[i];if(Isbound(ch)){if(ERR){printf("无法识别\n");ERR=FALSE;OK=TRUE;}else if(!OK){printf("<10,%s>标识符\n",nowword);tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}state=4;}else if(IsDigit(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;state=3;OK=FALSE;break;}else{nowword[nowlen]=ch;nowlen++;}}else if(IsLetter(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;OK=FALSE;if(sour[i+1]=='#'){printf("<10,%s>标识符\n",nowword);struct Token tokentemp;tokentemp.code=10;int i=0;for(i;i<=nowlen;i++)tokentemp.ch[i]=nowword[i];tokenlist[m]=tokentemp;}}else{nowword[nowlen]=ch;nowlen++;}}else if(Isoperate(ch)){if(!OK){printf("<10,%s>标识符\n",nowword);tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}printf("<%d,%c>运算符\n",Isoperate(ch),ch);tokentemp.code=Isoperate(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;}break;case 3:if(IsLetter(ch)){printf("错误\n");nowword[nowlen]=ch;nowlen++;ERR=FALSE;state=0;break;}if(IsDigit(ch=sour[i])){nowword[nowlen]=ch;nowlen++;}else if(sour[i]=='.'&&flagpoint==0){flagpoint=1;nowword[nowlen]=ch;nowlen++;}else{printf("<20,%s>数字\n",nowword);i--;state=0;OK=TRUE;tokentemp.code=20;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;}break;case 4:i--;printf("<%d,%c>界符\n",Isbound(ch),ch);tokentemp.code=Isbound(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;state=0;OK=TRUE;break;}}int io=0;for(io;io<=m;io++){printf("tokenlist%d.code值为%d\n",io,tokenlist[io].code);}E();if(op==m)printf("OK!!!");elseprintf("WRONG!!!");return 0;}void E(){T();E1();}void E1(){if(tokenlist[op].code==3||tokenlist[op].code==4){tokenlist[op++];T();E1();}}void T1(){if(tokenlist[op].code==5||tokenlist[op].code==6){tokenlist[op++];F();T1();}}void T(){F();T1();}void F(){if(tokenlist[op].code==10||tokenlist[op].code==20) {tokenlist[op++];}else{if(tokenlist[op].code==1){tokenlist[op++];E();if(tokenlist[op].code==2){tokenlist[op++];}else{printf("WRONG!!!!!!");//exit(1);}}else{printf("WRONG!!!!!!");//exit(1);}}}程序运行结果:(截屏)输入:((Aa+Bb)*(88.2/3))#注:如需运行请将文件放置F盘,并命名为:2.txt 输出:思考问题回答:在递归下降子程序中要注意对于错误情况的处理,以防程序无限循环,无法结束。
编译原理实验报告:实验二编写递归下降语法分析程序
![编译原理实验报告:实验二编写递归下降语法分析程序](https://img.taocdn.com/s3/m/049acd45f242336c1eb95eed.png)
编译原理实验报告实验名称:实验二编写递归下降语法分析器实验类型:验证型实验指导教师:何中胜专业班级:13软件四姓名:丁越学号:13030504电子邮箱:862245792@实验地点:秋白楼B720实验成绩:日期:2016年4 月1 日一、实验目的通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。
通过本实验,应达到以下目标:1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
2、掌握词法分析的实现方法。
3、上机调试编出的语法分析程序。
二、实验过程1、分析对象分析算术表达式的 BNF 定义如下:〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉〈项〉→〈因式〉|〈项〉*〈因式〉|〈项〉/〈因式〉〈因式〉→〈变量〉│(〈算术表达式〉)〈变量〉→i用符号表示如下:E→T|E+T|E-TT→F|T*F|T/FF→i│(E)递归下降分析程序实现思想简单易懂。
程序结构和语法产生式有直接的对应关系。
因为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。
递归下降分析程序的实现思想是:识别程序由一组子程序组成。
每个子程序对应于一个非终结符号。
每一个子程序的功能是:选择正确的右部,扫描完相应的字。
在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。
自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。
分析速度慢。
而无回溯的自上向下分析技术,当选择某非终结符的产生时,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。
无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
无左递归:既没有直接左递归,也没有间接左递归。
无回溯:对于任一非终结符号 U 的产生式右部x1|x2|…|xn,其对应的字的首终结符号两两不相交。
2. 递归下降语法分析流程图实验分为五个模块,分别是:E( )函数,E1( )函数,T( )函数,T1( )函数,F( )函数。
编译原理语法分析递归下降子程序实验报告
![编译原理语法分析递归下降子程序实验报告](https://img.taocdn.com/s3/m/bf1050ceac51f01dc281e53a580216fc700a53dc.png)
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
编译原理实验二递归下降子程序
![编译原理实验二递归下降子程序](https://img.taocdn.com/s3/m/54a48ec3aa00b52acfc7ca6a.png)
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
#include<stdio.h>#include<stdlib.h>#define N 20char Str[N]; /* 用于存放输入的字符串 */int i=0;int max=0; /* 输入字符串的长度下标 */int curr=0; /* 当前字符的下标 */int flag=0; /* 用于标记判断过程中是否出现错误 */void inputString(); /* 输入要分析的字符串 */void nextChar(); /* 分析下一个字符 */void E();void G();void T();void S();void F();void outputResult(); /* 输出分析结果 */void inputString(){printf("\n实验名:递归下降分析程序\n\n");printf("姓名:汪茁\t学号:0904011035\t班级:09计本(4)班\n\n");printf("文法如下:\n");printf("(1) E->TG\n(2) G->+TG|-TG\n(3) G->ε\n(4) T->FS\n");printf("(5) S->*FS|/FS\n(6) S->ε\n(7) F->(E)\n(8) F->i\n\n");printf("请输入要分析的字符串(以'#'号结束):\n");for(i=0;i<N;i++){scanf_s("%c",&Str[i]);if(Str[i]=='#'){max=i;break;}}printf("\n");}void nextChar(){if(curr==max){exit(0);}else{curr++;}}void E(){T();}void G(){if(Str[curr]=='+'){nextChar();T();G();}else if(Str[curr]=='-'){nextChar();T();G();}}void T(){F();S();}void S(){if(Str[curr]=='*'){nextChar();F();S();}else if(Str[curr]=='/'){nextChar();F();S();}}void F(){if(Str[curr]=='('){nextChar();E();if(Str[curr]==')'){nextChar();}else{flag=1;}}else if(Str[curr]=='i'){nextChar();}{flag=1;}}void outputResult(){printf("分析结果:符号串");for(i=0;i<max;i++){printf("%c",Str[i]);}if(flag==0){printf("是合法的符号串!\n\n");}else{printf("是非法的符号串!\n\n");}}void main(){inputString();E();outputResult();}图 1 合法符号串[i*i+i-i/i]图 2 非法符号串[i*i+i-i/i-]图 3 带括号的合法符号串[i*(i+i)-i]图 4 带括号的非法符号串[i*(i+i-i]。
【编译原理实验】递归下降子程序设计
![【编译原理实验】递归下降子程序设计](https://img.taocdn.com/s3/m/22540153a9956bec0975f46527d3240c8447a1ef.png)
【编译原理实验】递归下降⼦程序设计实验内容给定CP语⾔中简单算术表达式⽂法G[E]:E→TE’E’→ATE’|εT→FT’T’→MFT’ |εF→(E) | iA → + | -M → * | /根据该⽂法,编写递归下降分析⼦程序。
【说明】:终结符号i为⽤户定义的简单变量,即专题1中标识符的定义。
实验要求(1)为每个⾮终结符号写⼀个函数,选择合适的数据结构来存储产⽣式规则。
(2)输⼊:是词法分析输出的⼆元组序列,即任意简单算术表达式经过专题1程序输出后得到的结果。
(3)输出:判定输⼊串是否为该⽂法定义的合法算术表达式。
(4)测试数据⾄少包含3组正确输⼊和2组错误输⼊。
设计思路先将上篇词法分析器的⼆元组输出作为输⼊读⼊到⼆维字符数组中,再将每个⼆元组的单词和编号提取出来存⼊结构体中(这⾥记录编号是为了能实现将题意中的i识别为任意的标识符)。
根据题⽬给出的产⽣式规则为每个⾮终结符号编写递归下降分析函数,使⽤变量p标记当前的单词并开始逐步分析,若分析过程中出错则直接停⽌。
若执⾏完所有的函数后p指向了结构体的末尾,则该输⼊串是该⽂法的合法算数表达式。
程序结构(1)主要数据结构:⼆维字符数组ch:⽤于读⼊输⼊的⼆元组。
结构体struct node{string str;string code;}:记录⼆元组中的单词及其编号。
(2)函数定义:void E():⾮终结符E的函数,输出E的产⽣式规则,并向下进⾏T()和E1()。
void E1():⾮终结符E’的函数,若此时的单词为“+”或“-”,则输出E’->ATE’这条产⽣式,并依次向下进⾏A()、T()和E1(),否则直接输出E’->ε。
void T():⾮终结符T的函数,输出T的产⽣式规则,并向下进⾏F()和T1()。
void T1():⾮终结符T’的函数,若此时的单词为“*”或“/”,则输出T’->MFT’这条产⽣式,并依次向下进⾏M()、F()和T1(),否则直接输出T’->ε。
自顶向下分析——递归下降法
![自顶向下分析——递归下降法](https://img.taocdn.com/s3/m/48626b46102de2bd97058804.png)
假设有文法
Z→aBa
B→bB |c
则相应的递归子程序可如下:
ReadToken
procedure Z( )
procedure B ( )
begin
begin
if token=a then Match(a);
B;
ReadToken
Match(a)
else err( )
end;
if token = b then Match(b); B;
else if token = c then Match(c); else err( )
end;
主程序:Begin ReadToken; Z end
产生式A→被选择的条件是: 当前的输入符属于predict(A→)。
至多一个产生式被选择的条件是: predict(A→k) predict(A→j )=,当k j
if tokenPredict(A2) then (2) else …… if tokenPredict(An) then (n) else err( )
end 其中对i=X1X2…Xn,(i) = ’(X1);’(X2);…;’(Xn); 如果XVN,’(X)= X 如果XVT,’(X)= Match(X) 如果X= , () = skip(空语句)
自顶向下分析——递归下降法
递归下降法(Recursive-Descent Parsing) 对每个非终极符按其产生式结构产生相应 语法分析子程序. 终极符产生匹配命令 非终极符则产生调用命令 文法递归相应子程序也递归,所以称这种 方法为递归子程序方法或递归下降法。
例:Stm→ while Exp do Stm 则对应产生式右部的语法分析程序部 分如下: begin Match($while); Exp; Match($do); Stm end
编译原理之递归下降语法分析程序(实验)
![编译原理之递归下降语法分析程序(实验)](https://img.taocdn.com/s3/m/aed6ff1b78563c1ec5da50e2524de518964bd32f.png)
编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤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)⽂法。
编译原理---递归下降分析法
![编译原理---递归下降分析法](https://img.taocdn.com/s3/m/d148d3d509a1284ac850ad02de80d4d8d15a01e0.png)
编译原理---递归下降分析法所谓递归下降法 (recursive descent method),是指对⽂法的每⼀⾮终结符号,都根据相应产⽣式各候选式的结构,为其编写⼀个⼦程序 (或函数),⽤来识别该⾮终结符号所表⽰的语法范畴。
例如,对于产⽣式E′→+TE′,可写出相应的⼦程序如下:exprprime( ){if (match (PLUS)){advance( );term( );exprprime( );}}其中:函数match()的功能是,以其实参与当前正扫视的符号 (单词)进⾏匹配,若成功则回送true,否则回送false;函数advance()是⼀个读单词⼦程序,其功能是从输⼊单词串中读取下⼀个单词,并将它赋给变量Lookahead;term则是与⾮终结符号T相对应的⼦程序。
诸如上述这类⼦程序的全体,便组成了所需的⾃顶向下的语法分析程序。
应当指出,由于⼀个语⾔的各个语法范畴 (⾮终结符号)常常是按某种递归⽅式来定义的,此种特点也就决定了这组⼦程序必然以相互递归的⽅式进⾏调⽤,因此,在实现递归下降分析法时,应使⽤⽀持递归调⽤的语⾔来编写程序。
所以,通常也将上述⽅法称为递归⼦程序法。
例4 2对于如下的⽂法G[statements]:statements→expression; statements |εexpression→term expression′expression′→+term expression′ |εterm→factor term′term′→*factor term′ |εfactor→numorid | (expression)通过对其中各⾮终结符号求出相应的FIRST集和FOLLOW集 (计算FIRST集和FOLLOW集的⽅法后⾯再做介绍),可以验证,此⽂法为⼀LL(1)⽂法,故可写出递归下降语法分析程序如程序41所⽰(其中,在⽂件lex.h⾥,将分号、加号、乘号、左括号、右括号、输⼊结束符及运算对象分别命名为SEMI,PLUS,TIMES,LP,RP,EOI及NUMORID,并指定了它们的内部码;此外,还对外部变量yytext,yyleng及yylineno进⾏了说明)。
递归下降程序实验报告
![递归下降程序实验报告](https://img.taocdn.com/s3/m/bbd60d75876fb84ae45c3b3567ec102de3bddf57.png)
一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
递归下降分析程序(语法分析)
![递归下降分析程序(语法分析)](https://img.taocdn.com/s3/m/0974c590e43a580216fc700abb68a98271feac2a.png)
递归下降分析程序(语法分析)1. ⽂法 G(S):(1)S -> AB(2)A ->Da|ε(3)B -> cC(4)C -> aADC |ε(5)D -> b|ε验证⽂法 G(S)是不是 LL(1)⽂法?FIRST集FIRST(Da)={b,a}FIRST(ε)={ε}FIRST(cC)={c}FIRST(aADC)={a}FIRST(b)={b}FOLLOW集FOLLOW(A)={c,b,a,#}其中#是FOLLOW(A)=FOLLOW(C)=FOLLOW(B)=FOLLOW(S)FOLLOW(B)={#}FOLLOW(C)={#}FOLLOW(D={a,#}SELECT集SELECT(A->Da)=FIRST(Da)={b,a}SELECT(A->ε)=FOLLOW(A)={c,b,a,#}SELECT(C->aADC)=FIRST(aADC)={a}SELECT(C->ε)=FOLLOW(C)={#}SELECT(D->b)=FIRST(b)={b}SELECT(D->ε)=FOLLOW(D)={a,#}因为SELECT(A->Da)∩SELECT(A->ε)≠∅SElECT(C->aADC)∩SELECT(C->ε)=∅SELECT(D->b)∩SELECT(D->ε)=∅所以G(S)不是LL(1)⽂法。
2.(上次作业)消除左递归之后的表达式⽂法是否是LL(1)⽂法?消除左递归得:E->TE’E’->+TE’|εT->FT’T’->*FT’|εF->(E)|iFIRST集:FIRST(TE’)={ (, i }FIRST(+TE')={+,ε}FIRST(FT’)={(,i}FIRST(*FT')={ *,ε}FIRST((E))={ (}FIRST(i)={ i }FOLLOW集:FOLLOW(E)={ ),# }FOLLOW(E')={ ),# }FOLLOW(T)={+,),#}FOLLOW(T')={+,),#}FOLLOW(F)={*,+,),#}SELECT集:SELECT (E -> TE’) = FIRST(TE’) = { ( , i }SELECT(E’ -> +TE’) = FIRST(+TE’) = { + }SELECT(E’ -> ε) = FIRST(ε) - {ε} U FOLLOW(E’) = FOLLOW(E’) = { ) , # } SELECT(T -> FT’) = FIRST(FT’) = { ( , i }SELECT(T’ -> *FT’) = FIRST(*FT’) = { * }SELECT(T’ -> ε) = FIRST(ε) - {ε} U FOLLOW(T’) = FOLLOW(T’) = { + , ) ,# } SELECT(F -> (E)) = FIRST((E)) = { ( }SELECT(F -> i) = FIRST(i) = { i }SELECT(E’ -> +TE’) = FIRST(+TE’) = { + } ∩ SELECT(E’ -> ε) = FOLLOW(E’) = { ) , # }=∅SELECT(T’ -> *FT’) = FIRST(*FT’) = { * } ∩ SELECT(T’ -> ε) =FOLLOW(T’) = { + , ) ,# }=∅SELECT(F -> (E)) = FIRST((E)) = { ( } ∩ SELECT(F -> i) = FIRST(i) = { i }=∅所以该⽂法为LL(1)⽂法。
编译原理:算术表达式递归下降分析程序设计
![编译原理:算术表达式递归下降分析程序设计](https://img.taocdn.com/s3/m/c0bf91360508763230121204.png)
实验二:算术表达式递归下降分析程序设计LD1、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
2、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:E→E+T | TT→T*F | FF→(E) | i3、设计分析题目所给的文法不为LL(1)文法,应改写成如下文法:E →TE2E2→+TE2 |∑T →FT2T2→*FT2 | ∑F →(E) | i采用递归下降分析法时,需要求出E2和T2 的FOLLOW集:FOLLOW(E2)={),#}FOLLOW(T2)={+,),#}递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。
因此需要分别构造E,E2,T,T2,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。
advance函数用于字符串的推进,input函数用于字符串的输入。
4、程序代码#include <iostream>using namespace std;char a[80]; // 字符串的存入char sym; // 单个的判断字符int i=0; // 字符串下标void E(); // 功能识别函数void E2(); // 功能识别函数void T(); // 功能识别函数void T2(); // 功能识别函数void F(); // 功能识别函数void input(); // 输入函数void advance(); // 字符串小标进一函数void main(){while(1){input();advance();E(); // 从首个推导式E开始if (sym=='#')cout<<"success"<<endl;elsecout<<"fail"<<endl;i=0; // 重新输入时,下标置0 }}void E(){T();E2();}void E2(){if(sym=='+'){advance();T();E2();}else if (sym != ')' && sym != '#'){cout<<"error!"<<endl;exit(0);}}void T(){F();T2();}void T2(){if(sym=='*'){advance();F();T2();}else if(sym!='+'&&sym!=')'&&sym!='#'){cout<<"error!"<<endl;exit(0);}}void F(){if(sym=='('){advance();E();if(sym==')')advance();else{cout<<"error!"<<endl;exit(0);}}else if(sym=='i'){advance();}else{cout<<"error!"<<endl;exit(0);}}void input(){cout<<"请输入需识别的句子:";cin>>a;}void advance(){sym=a[i];i++;}5、测试用例(1)只含有一个字符的形式:iaA(2) 含有‘+’的形式:i+ii+i+ii++++(3) 含有‘*’的形式:i*ii*i*ii***(4) 含有‘(’‘)’的形式:(i)()((i))(5) 综合形式:(i+i)*i(i+i)*(i+i)i+i*ii++i*(*i+(i+iii6、实验总结通过本次试验实践掌握了自上而下语法分析法的特点。
递归下降程序
![递归下降程序](https://img.taocdn.com/s3/m/071c080f7cd184254b353509.png)
递归下降分析程序实验报告1.实验内容编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:E→E+T | TT→T*F | FF→(E) | i2.实验分析(1 ) 对所给表达式进行分析,如果是左递归则对算术表达式进行改写消除其左递归。
改写的算术表达式如下:E→TE’E’→+TE’| εT→FT’T’→*FT’ | εF→(E) | i( 2) 写出上面表达式的FIRST集和FOLLOW集,然后对有多个规则的FIRST集求并集,看是否等于空集;对规则右部出现空串的FIRST集与FOLLOW集求并集,看是否等于空集。
对E’:FIRST(+TE′) ∩FOLLOW(E′)={+,ε} ∩{#, )}=Φ对T’:FIRST(*FT′) ∩FOLLOW(T′)={*,ε} ∩{+,#, )}=Φ对F:FIRST(i) ∩FIRST( (E) )={i} ∩{ ( }=Φ故由上面可知此改写后的文法是LL(1)文法。
(3)对上述LL(1)文法编程。
编程规则如下:①当遇到终结符a时,则编写语句If(当前读来的输入符号==a)读下一个输入符号②当前遇到非终结符A时,则编写语句调用A()。
③当前遇到A→ε规则时,则编写语句If(当前读来的输入符号不属于FOLLOW(A))error()④当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能惟一地选择一个侯选式进行推导。
3.源程序代码#include<iostream>using namespace std;#include<string>#define n 100char ch[n];int k=0;void scaner(); void E();void E1();void T();void T1();void F();void Error();void scaner(){k++;}void E(){T();E1();}void E1(){if (ch[k]=='+'){scaner();T();E1();}else if(ch[k]!=')'&&ch[k]!='#') Error();}void T(){F();T1();}void T1(){if(ch[k]=='*'){ scaner();F();T1();}else if(ch[k]=='+'&&ch[k]!=')'&&ch[k]=='#')Error();}void F(){if(ch[k]=='('){scaner();E();if(ch[k]==')')scaner();else Error();}else if(ch[k]=='i'){scaner();}else Error();}void Error(){cout<<"语法错误 !!!"<<endl;cout<<"分析失败"<<endl;exit(0);}void main(){ k=0;cout<<"请输入表达式:";cin>>ch;E();if (ch[k]=='#'){cout<<"分析成功!"<<endl;}else{cout<<"分析失败"<<endl;}}4.测试用例1.图1:输入i时成功图1 输入i匹配成功2.图2:输入i+i*i时成功图2 输入i+i*i匹配成功3.图3:输入(i)时成功图 3 输入(i)匹配成功4.图4:输入(i+(i*i))时成功图 4 输入(i+(i*I))匹配成功5.图5:输入i+i时成功图 5 输入i+i匹配成功6.图6:输入i*i时成功图6 输入i*i匹配成功7.图7:输入(i*i)时成功图7 输入(i*i)时匹配成功8.图8:输入(i+i)时成功图8 输入(i+i)时匹配成功9.图9:输入i+i+i+i+i+i时成功图9 输入i+i+i+i+i+i时匹配成功10.图10:输入i*i*i*i*i*i*i*i时成功图10 输入i*i*i*i*i*i*i时匹配成功11.图11:输入+i时失败图11 输入+i时匹配失败12.图12:输入ii时失败图12 输入ii时匹配失败13.图13:输入()时失败图13 输入()匹配失败5.实验总结本次实验主要是根据一个算术表达式文法构造一个识别该文法句子的递归下降分析程序。
c语言_递归下降分析程序实验(推荐文档)
![c语言_递归下降分析程序实验(推荐文档)](https://img.taocdn.com/s3/m/f90872377cd184254b35355d.png)
实验二递归下降语法分析程序的设计与实现一、实验目的:加深对语法分析器工作过程的理解;加强对递归下降法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容:在实验1的基础上,用递归下降分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程工具。
三、实验要求:1. 对语法规则有明确的定义;2. 编写的分析程序能够进行正确的语法分析;3. *对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;4. 实验报告要求用文法的形式对语法定义做出详细说明,说明语法分析程序的工作过程,说明错误处理的实现*。
四、实验学时:4学时五、实验步骤:1. 定义目标语言的语法规则;2. 根据语法规则输入语句段,用递归下降分析的方法进行语法分析,直到结束;3. *对遇到的语法错误做出错误处理。
六、实验内容:1.编程实现给定文法的递归下降分析程序。
E→T|E+TT→F|T*FF→(E)|i2.(参考课本P74)对文法先进行消除左递归。
3.分析程序由一组递归过程组成,文法中每个非终结符对应一个过程几个全局过程和变量:ADVANCE,把输入串指示器IP指向下一个输入符号,即读入一个单字符号SYM,IP当前所指的输入符号ERROR,出错处理子程序每个非终结符有对应的子程序的定义,首先在分析过程中,当需要从某个非终结符出发进行展开(推导)时,就调用这个非终结符对应的子程序。
4. 具体实现时:(1)当遇到终结符,编写: if(当前读到的输入符号=i)读入下一个输入符号(2)当遇到非终结符E时,编写语句:调用E()(3)当遇到E--> 编写语句 if(当前读到的输入符号不属于Follow(E))Error();(4)当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能唯一的选择一个候选式进行推导。
#include <iostream>using namespace std;char a[80]; // 字符串的存入char sym; // 单个的判断字符int i=0; // 字符串下标void E(); // 功能识别函数void E2(); // 功能识别函数void T(); // 功能识别函数void T2(); // 功能识别函数void F(); // 功能识别函数void input(); // 输入函数void advance(); // 字符串小标进一函数。
实验报告四递归下降语法分析程序设计
![实验报告四递归下降语法分析程序设计](https://img.taocdn.com/s3/m/49b0166f26284b73f242336c1eb91a37f11132fa.png)
实验报告四递归下降语法分析程序设计《编译原理》实验报告实验序号: 4 实验项⽬名称:递归下降语法分析程序设计SELECT(E’ →ε)={ε,),#}对T SELECT(T→FT’)={(,i}对T’ SELECT(T’ →*FT’)={ * }SELECT(T’ →⁄FT’)={ ⁄ }SELECT(T’ →ε)={ε,+,?,),#}对F SELECT(F→(E) )={ ( }SELECT(F→i)={ i }∴SELECT(E’ →+TE’)∩SELECT(E’ →?TE’)∩SELECT(E’ →ε)=ΦSELECT(T’ →*FT’)∩SELECT(T’→⁄FT’)∩SELECT(T’ →ε)=ΦSELECT(F→(E) )∩SELECT(F→i)= Φ由上可知,有相同左部产⽣式的SELECT集合的交集为空,所以⽂法是LL (1)⽂法。
因此,转化后的⽂法可以⽤递归下降分析法作语法分析。
(2)设计这⾥采⽤递归下降分析法形象描述递归⼦程序。
程序中将要⽤到的⼏个重要数据如下:⼀个全局变量ch,存放由⽂件输⼊得到的字符。
⼀个函数宏READ(ch),实现读取⽂件中的字符。
五个⼦函数:P(E)、P(E’)、P(T)、P(T’)、P(F)。
(3)程序代码如下/******************************************************************** ***** ⽂件名:ana.c* ⽂件描述:递归下降语法分析器。
分析如下⽅法:* E->E+T | E-T | T* T->T*F | T/F |F* F->(E) | i* 输⼊:每⾏含⼀个表达式的⽂本⽂件。
* 输出:分析成功或不成功信息。
* 创建⼈:余洪周 2006-12-8* 版本号:1.0********************************************************************* **/#include#include#define READ(ch) ch=getc(fp) /*宏:READ(ch)*/char ch; /*声明为全局变量*/int right=0;FILE *fp;struct struCH{char ch;struct struCH *next;}struCH,*temp,*head,*shift;/*head指向字符线性链表的头结点*//*shift指向动态建成的结点(游标)*/void main(int argc,char *argv[]){void E (); /* P(E) */void E1(); /* P(E')*/void T (); /* P(T) */void T1(); /* P(T')*/void F (); /* P(F) */int errnum=0,k=0,m=0,countchar=0,rownum;int charerr=0; /*开关控制量*//************************以只读⽅式打开⽂件*********************/ if((fp=fopen(argv[1],"r"))==NULL){printf("\n\tCan not open file %s,or not exist it!\n",argv[1]);exit(0); /*⽂件不存在or打不开时,正常退出程序*/}else printf("\n\tSuccess open file: %s\n",argv[1]); /*成功打开⽂件*//******************遍历整个⽂件检测是否有⾮法字符********************//*如果⽤while(!feof(fp))语⾔,将会多出⼀个字符*所以这⾥采⽤以下⽅法遍历整个⽂件检测其否有⾮法字符*//*[1]计算⽂件中字符数量*/while(!feof(fp)){READ(ch); /*这⾥读取字符只是让⽂件指针往前移*/countchar++; /*统计⽂件中的字符数(包括换⾏符及⽂件结束符)*/}rewind(fp); /*将fp⽂件指针重新指向⽂件头处,以备后⾯对⽂件的操作*/if(countchar==0){ /*空⽂件*/printf("\t%s is a blank file!\n",argv[1]);exit(0); /*正常退出本程序*/}/*[2]开始遍历⽂件*/while(k<(countchar-1)){ /*加换⾏符后countchar仍多了⼀个,不知为何*/ ch=getc(fp);if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='\n')){ charerr=1;errnum++; /*charerror出错标记,errnum统计出错个数*/}k++;}rewind(fp); /*将fp⽂件指针重新指向⽂件头处,以备后⾯的建链表操作*/if(charerr==1){ /*⽂件中有⾮法字符*/printf("\n\t%d Unindentify characters in file %s \n",errnum,argv[1]);exit(0); /*正常退出本程序*/}/*******************⾮空且⽆⾮法字符,则进⾏识别操作*****************/for(rownum=1;m<(countchar-1);rownum++){ /*识别所有⾏,rownum记录⾏号*/ /*初始变量及堆栈和*/right=1;/*初始存放待识别的表达式的线性链表头*/shift=malloc(sizeof(struCH));/**/shift->next=NULL;head=shift;/*读取⼀⾏形成线性链表*/READ(ch);putchar(ch);m++;while(ch!='\n'&&m<(countchar)){ /*⾏末or到⽂件尾。
编译原理-递归下降子程序-课程设计报告
![编译原理-递归下降子程序-课程设计报告](https://img.taocdn.com/s3/m/08576d28c8d376eeafaa3132.png)
编译原理课程设计报告2011 年 12 月 2 日设计题目 递归下降分析程序的实现 学号专业班级 计算机科学与技术学生姓名指导教师一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:递归下降分析程序的实现设计内容及要求:对文法 G: E→E+T|T构造出G的递归下降分析程序。
程序显示输出T→T*F|F匹配过程(即自上而下生成语法分析树的步骤,F→(E)|i 输出各匹配产生式序号即可)。
三、设计思路:(1)语法分析:语法分析是编译程序的核心部分,任务是分析一个文法的句子结构。
递归下降分析程序的实现的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。
(2)自上而下分析:从文法的开始符号出发,向下推导,推出句子。
可分为带“回溯”的和不带回溯的递归子程序(递归下降)分析方法。
它的主旨是对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下地为输入串建立一棵语法树。
或者说,为输入串寻找一个最左推导。
也即从文法的开始符号出发,反复使用各种产生式,寻找"匹配"的推导。
(3)递归下降分析法:对每一语法变量(非终结符)构造一个相应的子程序,每个子程序识别一定的语法单位,通过子程序间的信息反馈和联合作用实现对输入串的识别。
(4)分析过程中遇到的问题:a. 分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。
出错时,不得不“回溯”。
b.文法左递归问题。
含有左递归的文法将使自上而下的分析陷入无限循环。
(5)构造不带回溯的自上而下分析算法:a.要消除文法的左递归性:一个文法可以消除左递归的条件是①不含以 为右部的产生式②不含回路。
b.克服回溯,构造不带回溯的自上而下分析的文法条件(6)满足LL(1)文法的三个条件:①. 文法不含左递归,②. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。
计算器程序 递归下降分析实现
![计算器程序 递归下降分析实现](https://img.taocdn.com/s3/m/1513fbf5f90f76c661371ac9.png)
递归下降分析实现计算器程序1.计算器程序文法<exp> -> <term> { <addop> <term> }<addop> -> + | -<term> -> <factor> { <mulop> <factor> }<mulop> -> * | /<factor> -> ( <exp> ) | Number2.实现功能:+ , - , * , / 和带括号的四则运算.3.实现方式:vc+递归下降分析4.代码:#include <stdio.h>#include <stdlib.h>#include <ctype.h>/* Simple integer arithmetic calculatoraccording to the EBNF:<exp> -> <term> { <addop> <term> }<addop> -> + | -<term> -> <factor> { <mulop> <factor> }<mulop> -> * | /<factor> -> ( <exp> ) | Number*/char token , str[1024] ;int pos ;int exp();int term();int factor();void error(){fprintf(stderr,"Error\n");exit(1);}void match(char expectedToken){if( token == expectedToken ) token = str[pos++] ;else error();}int exp(){int temp = term();while ( ( token == '+' ) || ( token == '-' ) ) {switch(token){case '+' : match('+');temp += term();break ;case '-' : match('-');temp -= term();break ;}}return temp ;}int factor(){int temp ;if ( token == '(' ){match('(');temp = exp();match(')');}else if( isdigit(token) ){for( temp = 0 ; isdigit(token) ; token = str[pos++] ) temp = (temp<<3) + (temp<<1) + (token^48) ;}else error();return temp ;}int term(){int temp = factor();while ( token == '*' || token == '/' ){if( token == '*' ){match('*');temp *= factor() ;}else if ( token == '/' ){match('/');int sth = factor() ;if( 0 == sth ) error();temp /= sth ;}}return temp ;}int main(){int result , t ;scanf("%d",&t); getchar();while(t--){gets(str);pos = 0 ;token = str[pos++] ;result = exp();printf("%d\n",result);}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验4 递归下降子程序的编写
一、实验目的
通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
分析递归下降子程序的优缺点。
二、实验准备
1.预习自上而下语法分析小节的内容;
2.学生自己考虑使用的开发环境,如VC++,熟悉开发环境。
三、实验内容
下列文法中选做一题:
1.针对算术表达式文法:E→TE’
E’→ +TE’|ε
T→FT’
T’→*FT’ |ε
F→(E) |i
为其编写递归下降子程序,判定某个算术表达式是否正确:如j+k*m,j*k+m
输入:其输入数据应该为词法分析器输出的记号形式:i+i*i,i*i+i
输出:分析结果:算术表达式结构正确或结构错误。
2.给定文法(PASCAL语言标识符定义文法)(选做)
type→simple|↑id|array[simple] of type
Simple→integer|char|num dotdot num
其中:dotdot表示.
编写递归下降子程序,判定一个句子结构是否正确:array [3..5]of integer 输入:其输入数据应该为词法分析器输出的单词序列:array[num dotdot num] of integer
输出:分析结果
四、实验要求
1.编写程序调试运行;考虑如果将你的程序改为识别其他的文法,你的递归下降子程序可否通用,考虑递归下降子程序方法的优缺点。
2.撰写实验报告:实验名称、实验目的、实验内容、实验结果、结果分析
五、实验结果
1、程序:
#include<stdio.h> #include<iostream> #include<fstream> #include<string> char EL[20];
int word=0; void E1(); void T(); void T1(); void F();
//编写E函数//E->TE
void E()
{
//因为是第一步,所以直接输出E->TE'
printf("E->TE'\n");
T();
E1();
}
//就是那个E'函数
//E'->+TE'|ε
void E1()
{ //如果匹配为+号的话输出E'->+TE if(EL[word]=='+')
{
printf("E'->+TE'\n");
word++;
T();
E1();
}
else
//如果不是加号、则输出空
printf("T'->ε\n");
}
//T->FT
void T()
{
printf("T->FT'\n");
F();
T1();
}
//如果匹配*则输出T'->*FT,否则输出空
//T'->*FT|ε
void T1()
{
if(EL[word]=='*')
{
printf("T'->*FT'\n");
word++;
F();
T1();
}
else
printf("T'->ε\n");
} //如果为i、则输出F->i\n,如果为(则指针下移、调用E函数、如果为)则输出F->(E),否则说明括号不匹配。
//F->(E)|i
void F()
{
if(EL[word]=='i')
{
printf("F->i\n");
word++;
}
else if (EL[word]=='(')
{
word++;
E();
if(EL[word]==')'){
printf("F->(E)\n");
word++;
}
else{
printf("\n错误、括号不匹配(缺少右括号)\n");
exit (0);
} }
else{
printf("错误、请输入正确的算术表达式!\n");
exit(0);
}
}
//主函数
//输入算数表达式、为其编写递归下降子程序,判定算术表达式是否正确
int main()
{
while(1)
{
printf("请输入算数表达式:");
scanf("%s",EL);
E();
}
return 0;
}
2、截图:
(1)输入正确的算数表达式:
i+i*i
(2)输入有括号的算数表达式
: i+(i*i)
(3)输入缺少一半括号的算数表达式
: i+(i*i
(4) 输入缺少操作数的算数表达式
: i+i*。