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

合集下载

递归下降语法分析

递归下降语法分析

实验项目名称:递归下降语法分析实验学时: 6 同组学生姓名:实验地点:实验日期:实验成绩:批改教师:批改时间:一、实验目的和要求通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。

分析递归下降子程序的优缺点。

二、实验仪器和设备硬件系统:586以上计算机、服务器要求内存256以上、Cpu 2.0GHz以上、Clinet内存128以上、CPU奔腾III以上,硬盘,光驱等软件系统:Visual Studio 2005中文版软件三、实验过程1、设计框架图1-1 递归下降程序框架图2、设计步骤1)给定文法:E→E+T|TT→T*F|FF→(E)|i2)构造FIRST()集和FOLLOW()集表2-1 FIRST()集和FOLLOW()集3、程序源代码using System;using System.Collections.Generic;using System.Text;namespace递归下降语法分析{public class Program{public static char []a=new char[50];public static char []b=new char[50];public static char []d=new char[200];public static char []e=new char[10];public static char ch;public static int n1,i1=0,flag=1,n=5;public static int total=0;/*步骤计数器*/public static int E1(){int f,t;Console.Write(total);Console.Write("\tE-->TG\t");total++;flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}public static int E(){int f,t;Console.Write(total);Console.Write("\tE-->TG\t");total++;e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#'; output();flag=1;input();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}public static int T(){int f,t;Console.Write(total);Console.Write("\tT-->FS\t");total++;e[0]='T';e[1]='=';e[2]='>';e[3]='F';e[4]='S';e[5]='#';output();flag=1;input();input1();f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}public static int G(){int f;if(ch=='+') {b[i1]=ch;Console.Write(total);Console.Write("\tG-->+TG\t");total++;e[0]='G';e[1]='=';e[2]='>';e[3]='+';e[4]='T';e[5]='G';e[6]='#'; output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0) return(0);G();return(1);}Console.Write(total);Console.Write("\tG-->^\t");total++;e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();input();input1();return(1);}public static int S(){int f,t;if(ch=='*') {b[i1]=ch;Console.Write(total);Console.Write("\tS-->*FS\t");total++;e[0]='S';e[1]='=';e[2]='>';e[3]='*';e[4]='F';e[5]='S';e[6]='#'; output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}Console.Write(total);Console.Write("\tS-->^\t");total++;e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}public static int F(){int f;if(ch=='(') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->(E)\t");total++;e[0]='F';e[1]='=';e[2]='>';e[3]='(';e[4]='E';e[5]=')';e[6]='#'; output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0);if(ch==')') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->(E)\t");total++;flag=0;input();input1();ch=a[++i1];}else {Console.Write("error\n");return(0);}}else if(ch=='i') {b[i1]=ch;Console.Write(total);Console.Write("\tF-->i\t");total++;e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {Console.Write("error\n");return(0);}return(1);}public static void input(){int j=0;for (;j<=i1-flag;j++)Console.Write(b[j]); /*输出分析串*/Console.Write("\t\t");Console.Write("\t\t",ch); /*输出分析字符*/ }public static void input1(){int j;for (j=i1+1-flag;j<n1;j++)Console.Write(a[j]); /*输出剩余字符*/ Console.Write("\n");}public static void output(){ /*推导式计算*/int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='#';n=n+2;i=n;i=i-2;while(d[i]!='>'&&i!=0) i=i-1;i=i+1;while(d[i]!=e[0]) i=i+1;q=i;m=q;k=q;while(d[m]!='>') m=m-1;m=m+1;while(m!=q) {d[n]=d[m];m=m+1;n=n+1;}d[n]='#';for(j=3;e[j]!='#';j++){d[n]=e[j];n=n+1;}k=k+1;while(d[k]!='=') {d[n]=d[k];n=n+1;k=k+1;}d[n]='#';//system("pause");}static void Main(string[] args){ /*递归分析*/int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';Console.Write("请输入字符串(长度<50,以#号结束)\n");do{ch=(char)Console.Read();a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];Console.Write("步骤\t文法\t分析串\t\t分析字符\t剩余串\n");f=E1();if (f==0) return;if (ch=='#'){Console.Write("accept\n");p=0;x=d[p];while(x!='#') {Console.Write(x);p=p+1;x=d[p]; /*输出推导式*/ }}else {Console.Write("error\n");Console.Write("回车返回\n");Console.ReadLine();Console.ReadLine();return;}Console.Write("\n");Console.Write("回车返回\n");Console.ReadLine();Console.ReadLine();}}}程序输入输出举例:1、输入“(i+i)*i”,分析如下图所示:2、输入“i#”,分析如下图所示:3、输入“i+i#”,分析如下图所示:四、实验结果与分析通过本次实验基本掌握了语法分析的原理和递归下降子程序分析方法,并且能将学到的知识学以致用,提高了对代码的分析能力,掌握了递归下降语法的构造,对自上再而下的语法分析模式有了更好的认识和理解。

编译原理实验语法器递归下降子程序实现解析

编译原理实验语法器递归下降子程序实现解析

编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机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 输出:思考问题回答:在递归下降子程序中要注意对于错误情况的处理,以防程序无限循环,无法结束。

递归下降语法分析器实验报告

递归下降语法分析器实验报告

编译原理实验报告题目: 递归下降语法分析器学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx 姓 名 宁剑 指导教师 xxxx20xx 年xx 月xx 日递归下降语法分析器装 订 线一、实验目的了解语法分析器的内部工作原理,通过在本次实验中运用一定的编程技巧,掌握对表达式进行处理的一种方法。

二、实验原理算术表达式的文法可以是(可以根据需要适当改变):E→E+E|E-E|E*E|E/E|(E)|i根据递归下降分析法或预测分析法,对表达式进行语法分析,判断一个表达式是否正确。

三、实验步骤(1) 准备:1. 阅读课本有关章节,确定算术表达式的文法;(设计出预测分析表);2. 考虑好设计方案;3. 设计出模块结构、测试数据,初步编制好程序。

(2) 上机调试,发现错误,分析错误,再修改完善。

教师根据学生的设计方案与学生进行探讨,以修改方案和代码。

(3)改造后的文法:E→E+T|E-T|TT→T*F|T/F|FF→F^|PP→c |id| (E)四、实验环境计算机VC++软件五、实验程序#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>#include<conio.h>void error();void terror();void Scanner();char sym=' ';int i=0;char strToken[30]={""};FILE *in;void E();void E1();void F();void Retract(char str[30]){for(int j=0;j<30;j++){str[j]=0;}}void Scanner(){sym=fgetc(in);if (isspace(sym)){while(1){if(isspace(sym)){sym=fgetc(in);}else break;}}if(isdigit(sym)){while(1){if (isdigit(sym)){strToken[i]=sym;i++;sym=fgetc(in);}else{printf("%s",strToken);i=0;Retract(strToken);fseek(in,-2,1);sym=fgetc(in);break;}}}else{if(sym=='+'){printf("+");}else if(sym=='-'){printf("-");}else if(sym=='*'){printf("*");}else if(sym=='/'){printf("/");}else if(sym=='^'){printf("^");}else if(sym=='('){printf("(");}else if(sym==')'){printf(")");}}}void F(){if(isdigit(sym)){Scanner();}else if (sym=='('){Scanner();E();if(sym==')'){Scanner();}else error();}else terror();}void T1(){if(sym=='*'||sym=='/'||sym=='^'){Scanner();F();T1();}}void T(){F();T1();}void E1(){if (sym=='+'||sym=='-'){Scanner();T();E1();}}void E(){T();E1();}void error(){printf("\nThis is a wrong phrase!\n");exit(0);}void terror(){printf("\nthis is a wrong parase2!\n");exit(0);}int main(){if((in=fopen("input.txt","r"))==NULL){printf("File can't open.");exit(0);}Scanner();E();if (sym!='#'){printf("\nSuccess.");}else{printf("\nFail.");}fclose(in);return 0;}六、实验结果及分析程序输入/输出示例:如参考C 语言的运算符。

设计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结束。

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

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

编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤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)⽂法。

递归下降程序实验报告

递归下降程序实验报告

一、实验目的1. 理解递归下降分析法的原理和实现方法。

2. 掌握递归下降分析程序的设计和调试。

3. 加深对编译原理中语法分析部分的理解。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。

当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。

2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。

语法分析递归下降分析法

语法分析递归下降分析法

语法分析递归下降分析法递归下降分析法是一种常用的语法分析方法,它通过构建递归子程序来解析输入的语法串。

该方法可以分为两个步骤:构建语法树和构建语法分析器。

首先,我们需要构建语法树。

语法树是一个表示语言结构的树形结构,它由各类语法片段(非终结符)和终结符组成。

构建语法树的过程就是根据文法规则从根节点开始递归地扩展子节点,直到达到文法推导出的终结符。

具体来说,我们可以通过以下步骤来构建语法树:1.设计满足语言结构的文法规则。

文法规则定义了语法片段之间的关系和转换规则。

2.将文法规则转换为程序中的递归子程序。

每个递归子程序对应一个语法片段,并按照文法规则递归地扩展子节点。

3.设计词法分析器将输入的语法串分词为单个有效的词法单元。

4.从语法树的根节点开始,根据递归子程序逐步扩展子节点,直到达到终结符。

同时,将每一步的扩展结果记录在语法树中。

接下来,我们需要构建语法分析器。

语法分析器是一个根据语法规则判断输入语法串是否符合语法规则的程序。

它可以通过递归下降分析法来实现。

具体来说,我们可以通过以下步骤来构建语法分析器:1.定义一个语法分析器的函数,作为程序的入口。

2.在语法分析器函数中,根据文法规则调用递归子程序,分析输入的语法串。

3.每个递归子程序对应一个语法片段,它会对输入的语法串进行识别和匹配,并根据文法规则进行扩展。

4.如果递归子程序无法匹配当前的输入,那么意味着输入的语法串不符合文法规则。

5.如果递归子程序成功扩展,并继续匹配下一个输入,则语法分析器会一直进行下去,直到分析完整个语法串。

总结起来,递归下降分析法是一种简单而有效的语法分析方法。

它通过构建递归子程序来解析输入的语法串,并构造出对应的语法树。

虽然递归下降分析法在处理左递归和回溯等问题上存在一定的困难,但它仍然是一种重要的语法分析方法,被广泛应用于编译器和自然语言处理等领域。

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

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

实验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)。

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

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

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

(完整的源语言的文法定义见教材附录 A.1,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”。

并且,为了以后能够方便使用switch() case 语句,另外再定义一个一维整型数组finaltableint[100],用于存放一个数字和finaltable[100][20]中的字符串对应。

这里,我们定义if=100,for=200,else=300,while=400,do=500,float=600,int=700,break=800,< = 17,<= = 16,> = 15,>= = 14,+ = 13,&&=12,||=11,}=10,{=9,;=8;)=7,(=6,= = 5,== = 4,!= =3,/=2,id =1,keyword=0,num=99,*=18,- = 19。

然后依据语法分析的正则表达式,参照实验一类似中缀改后缀的写法以及课本40页的伪代码编写。

相比词法分析器,词法分析的时候,是以单个字符为一个单位,而语法分析,我们以字符串为单位,这些字符串即finaltable[100][20]中的字符串。

编写的过程中涉及几个问题,1、如何把每一步的迭代都显示出来?对于这个问题,可以在每个非终结符函数的开头输出对应的迭代即可。

2、在应用文法的时候,应该首先消除左递归,这是至关重要的,该实验我们只要消除expr()和term()的左递归即可。

3、if语句二义性处理。

对于这个问题,我们只要再往后看一个字符串,看其是否是else,如果是,则匹配if( bool)stmt else stmt,否则匹配if(bool )stmt。

4、对于空选择,如何处理?一开始的时候,我选择暂时忽略。

五、实验代码#include<stdio.h>#include<string.h>#include <ctype.h>/*if=100,for=200,else=300,while=400,do=500,float=600,int=700,break=800,< = 17,<= = 16,> = 15,>= = 14,+ = 13,&&=12,||=11,}=10,{=9,;=8;)=7,(=6,= = 5,== = 4,!= =3,/=2,id =1,keyword=0,num=99,*=18,- = 19 */char*keyword[8]={"if","for","else","while","do","float","int","break"}; char keywordtable[20][20],re_keywordtable[20][20];char digittable[20][20],re_digittable[20][20];char otherchartable[20][20],re_otherchartable[20][20];char idtable[20][20],re_idtable[20][20];char notetable[20][20];char finaltable[100][20];int finaltableint[100];char word[20];void initialize();void alpha();void digit();void error();void otherchar();void note();void print();void prin();void check();void program();void block();void stmts();void stmt();void Bool();void expr();void expr1();void term();void term1();void factor();void match(char *t);int digit_num=0,keyword_num=0,otherchar_num=0,id_num=0,note_num=0; int redigit_num=1,rekeyword_num=1,reotherchar_num=1,reid_num=1;int final_num=0,finalnum=0;int flag_error=0;int flagerror=0;char lookahead;void main(){printf("请输入要分析的语句:\n");initialize();lookahead=getchar();while(1){if(isalpha(lookahead)){alpha();initialize();}else if(isdigit(lookahead)){digit();initialize();}else if(lookahead=='\t'||lookahead==' '){;}else if(lookahead=='\n')break;else if(lookahead=='/'){lookahead=getchar();if(lookahead=='*'){note();initialize();}else{ungetc(lookahead,stdin);strcpy(finaltable[final_num],"/");strcpy(otherchartable[otherchar_num++],"/");finaltableint[final_num++]=2;initialize();}}else{otherchar();initialize();}lookahead=getchar();}check();if(flag_error==0){printf("词法分析结果如下:\n");print();prin();program();if(finalnum==final_num)printf("语法分析完成!\n");}}void alpha(){int i=1,flag;char ch;ch=lookahead;word[0]=ch;ch=getchar();while(isalpha(ch)||isdigit(ch)){word[i++]=ch;ch=getchar();}ungetc(ch,stdin);flag=0;for(i=0;i<8;i++){if(strcmp(word,keyword[i])==0)flag=1;}if(flag==1){strcpy(keywordtable[keyword_num++],word);strcpy(finaltable[final_num],word);if(strcmp(word,"if")==0)finaltableint[final_num++]=100;if(strcmp(word,"for")==0)finaltableint[final_num++]=200;if(strcmp(word,"else")==0)finaltableint[final_num++]=300;if(strcmp(word,"while")==0)finaltableint[final_num++]=400;if(strcmp(word,"do")==0)finaltableint[final_num++]=500;if(strcmp(word,"float")==0)finaltableint[final_num++]=600;if(strcmp(word,"int")==0)finaltableint[final_num++]=700;if(strcmp(word,"break")==0)finaltableint[final_num++]=800;}else{strcpy(idtable[id_num++],word);strcpy(finaltable[final_num],"id");finaltableint[final_num++]=1;}}void digit(){int i=1,flag;char ch;ch=lookahead;word[0]=ch;ch=getchar();while(isalpha(ch)||isdigit(ch)){word[i++]=ch;ch=getchar();}ungetc(ch,stdin);flag=0;for(i=0;word[i]!='\0';i++){if(word[i]<'0'||word[i]>'9')flag=1;}if(flag==1){strcpy(idtable[id_num++],word);strcpy(finaltable[final_num],"id");finaltableint[final_num++]=1;}else{strcpy(digittable[digit_num++],word);strcpy(finaltable[final_num],"num");finaltableint[final_num++]=99;}}void otherchar(){char ch;ch=lookahead;switch(ch){case '!':{ch=getchar();if(ch=='='){strcpy(otherchartable[otherchar_num++],"!=");strcpy(finaltable[final_num],"!=");finaltableint[final_num++]=3;}else{ungetc(ch,stdin);error();}}break;case '=':{ch=getchar();if(ch=='='){strcpy(otherchartable[otherchar_num++],"==");strcpy(finaltable[final_num],"==");finaltableint[final_num++]=4;}else{strcpy(otherchartable[otherchar_num++],"=");strcpy(finaltable[final_num],"=");finaltableint[final_num++]=5;ungetc(ch,stdin);}}break;case '(':strcpy(otherchartable[otherchar_num++],"(");strcpy(finaltable[final_num],"(");finaltableint[final_num++]=6; // ( 6 break;case ')':strcpy(otherchartable[otherchar_num++],")");strcpy(finaltable[final_num],")");finaltableint[final_num++]=7; // ) 7 break;case ';':strcpy(otherchartable[otherchar_num++],";");strcpy(finaltable[final_num],";");finaltableint[final_num++]=8; // ; 8 break;case '{':strcpy(otherchartable[otherchar_num++],"{");strcpy(finaltable[final_num],"{");finaltableint[final_num++]=9; // { 9 break;case '}':strcpy(otherchartable[otherchar_num++],"}");strcpy(finaltable[final_num],"}");finaltableint[final_num++]=10; // } 10 break;case '||':strcpy(otherchartable[otherchar_num++],"||");strcpy(finaltable[final_num],"||");finaltableint[final_num++]=11; // || 11 break;case '&&':strcpy(otherchartable[otherchar_num++],"&&");strcpy(finaltable[final_num],"&&");finaltableint[final_num++]=12; //&& 12 break;case '+':strcpy(otherchartable[otherchar_num++],"+");strcpy(finaltable[final_num],"+");finaltableint[final_num++]=13; // + 13 break;case '-':strcpy(otherchartable[otherchar_num++],"-");strcpy(finaltable[final_num],"-");finaltableint[final_num++]=19; // - 19 break;case '>':{ch=getchar();if(ch=='='){strcpy(otherchartable[otherchar_num++],">=");strcpy(finaltable[final_num],">=");finaltableint[final_num++]=14;} // >= 14else{strcpy(otherchartable[otherchar_num++],">");strcpy(finaltable[final_num],">");finaltableint[final_num++]=15; // > 15ungetc(ch,stdin);}}break;case '<':{ch=getchar();if(ch=='='){strcpy(otherchartable[otherchar_num++],"<=");strcpy(finaltable[final_num],"<=");finaltableint[final_num++]=16;} // <= 16else{strcpy(otherchartable[otherchar_num++],"<");strcpy(finaltable[final_num++],"<");finaltableint[final_num++]=17; //< 17ungetc(ch,stdin);}}break;case '*':strcpy(finaltable[final_num],"*");finaltableint[final_num++]=18; // * 18break;default:error();break;}}void error(){flag_error=1;printf("出现错误,中止分析!\n");}void initialize(){int i;for(i=0;i<20;i++){word[i]='\0';}}void check(){int i,j,flag;strcpy(re_keywordtable[0],keywordtable[0]);for(i=1;i<keyword_num;i++){flag=0;for(j=0;j<rekeyword_num;j++){if(strcmp(keywordtable[i],re_keywordtable[j])==0){flag=1;break;}}if(flag==0)strcpy(re_keywordtable[rekeyword_num++],keywordtable[i]); }strcpy(re_digittable[0],digittable[0]);for(i=1;i<digit_num;i++){flag=0;for(j=0;j<redigit_num;j++){if(strcmp(digittable[i],re_digittable[j])==0){flag=1;break;}}if(flag==0)strcpy(re_digittable[redigit_num++],digittable[i]);}strcpy(re_otherchartable[0],otherchartable[0]);for(i=1;i<otherchar_num;i++){flag=0;for(j=0;j<reotherchar_num;j++){if(strcmp(otherchartable[i],re_otherchartable[j])==0){flag=1;break;}if(flag==0)strcpy(re_otherchartable[reotherchar_num++],otherchartable[i]);}strcpy(re_idtable[0],idtable[0]);for(i=1;i<id_num;i++){flag=0;for(j=0;j<reid_num;j++){if(strcmp(idtable[i],re_idtable[j])==0){flag=1;break;}}if(flag==0)strcpy(re_idtable[reid_num++],idtable[i]);}}void note(){char ch;int i=0;ch=getchar();while(1){if(ch=='*'){ch=getchar();if(ch=='/')break;else{ungetc(ch,stdin);word[i++]=ch;}}else{word[i++]=ch;ch=getchar();}strcpy(notetable[note_num++],word);}void print(){int i;//printf("Keywords:\n");if(keyword_num!=0)for(i=0;i<rekeyword_num;i++)printf("< %s, >\n",re_keywordtable[i]);//printf("\nDigits:\n");if(digit_num!=0)for(i=0;i<redigit_num;i++)printf("< number,%s >\n",re_digittable[i]);//printf("\nOtherchars:\n");if(otherchar_num!=0)for(i=0;i<reotherchar_num;i++)printf("< comparison,%s >\n",re_otherchartable[i]);//printf("\nId:\n");if(id_num!=0)for(i=0;i<reid_num;i++)printf("< id,%s >\n",re_idtable[i]);if(note_num!=0){printf("注释:\n");for(i=0;i<note_num;i++)printf("%s\n",notetable[i]);}printf("词法分析完成!\n");}void prin(){int i;finaltableint[final_num]='\0';printf("语法分析结果如下:\n");for(i=0;i<final_num;i++)printf("%s",finaltable[i]);printf("\n语法分析过程如下:\n");}void program(){printf("program-->block\n");block();if(flagerror==1){error();return;}}void block(){if(flagerror==1){return;}printf("block-->{stmts}\n");match("{");stmts();match("}");}void stmts(){if(flagerror==1){return;}if(finaltableint[finalnum]==10){printf("stmts-->null\n");return;}printf("stmts-->{stmt stmts}\n");stmt();stmts();}void stmt(){if(flagerror==1){return;}switch(finaltableint[finalnum]){case 1:printf("stmt-->id=expr\n");match("id");match("=");expr();match(";");break;case 100:match("if");match("(");Bool();match(")");stmt();if(strcmp(finaltable[finalnum],"else")==0){printf("stmt-->if(bool) stmt else stmt\n");match("else");stmt();break;}else{printf("stmt-->{if(bool) stmt\n");break;}case 400:printf("stmt-->while(bool) stmt\n");match("while");match("(");Bool();match(")");stmt();break;case 500:printf("stmt-->do stmt while(bool)\n");match("do");stmt();match("while");match("(");Bool();match(")");match(";");case 800:printf("stmt-->break;\n");match("break");match(";");break;default:printf("stmt-->block\n");block();break;}}void Bool(){if(flagerror==1){return;}expr();switch(finaltableint[finalnum]){case 17:printf("bool-->expr<expr\n");match("<");expr();break;case 16:printf("bool-->expr<=expr\n");match("<=");expr();break;case 15:printf("bool-->expr>expr\n");match(">");expr();break;case 14:printf("bool-->expr>=expr\n");match(">=");expr();break;default:printf("bool-->expr\n");expr();}}void expr(){if(flagerror==1){return;}printf("expr-->term expr1\n");term();expr1();}void expr1(){if(flagerror==1){return;}switch(finaltableint[finalnum]){case 13:printf("expr1-->+term expr1\n");match("+");term();expr1();break;case 19:printf("expr1-->-term expr1\n");match("-");term();expr1();break;default:printf("expr1-->null\n");return;}}void term(){if(flagerror==1){}printf("term-->factor term1\n");factor();term1();}void term1(){if(flagerror==1){return;}switch(finaltableint[finalnum]){case 18:printf("term1-->*factor term1\n");match("*");factor();term1();break;case 2:printf("term1-->/factor term1\n");match("/");factor();term1();break;default:printf("term1-->null\n");return;}}void factor(){if(flagerror==1){return;}switch(finaltableint[finalnum]){case 6:printf("fatcor-->(expr)\n");match("(");expr();match(")");case 1:printf("factor-->id\n");match("id");break;case 99:printf("factor-->num\n");match("num");break;default:flagerror=1;break;}}void match(char *t){if(strcmp(finaltable[finalnum],t)==0) ;else{flagerror=1;return;}finalnum++;}六、实验结果对于正确的语句:{i = 2;while (i <=100){sum = sum + i;i = i + 2;}}结果:对于不正确的语句:(while之后多了一个;){i = 2;while (i <=100);i = i + 2;}结果:七、实验总结遇到的问题1:定义字符串的时候出错,写成char t;解决办法:正确的定义:Char *t;遇到的问题2:我使用词法分析所得的每一个词素作为语法分析的单位,但是这些都是字符串,而switch()case 语句只能用int型的。

相关文档
最新文档