递归下降语法分析设计原理与实现技术实验报告
编译原理实验报告——实验二 递归下降分析
printf("T'->*FT'\t"); printf("#E'T'F*\t\t"); print(); } else { printf("T'->/FT'\t"); printf("#E'T'F/\t\t"); print(); }
7
myAdvance(); printf("\t\t"); printf("#E'T'F\t\t"); print(); myF(); } if( sym!='*'||sym!='/') { printf("T'->^\t\t"); printf("#E'\t\t"); print(); } return(1); } else return(0); } /*判断是否是表达式或者括号*/ int myF() { int p; if (sym >= 'A' && sym <= 'Z' || sym >= 'a' && sym <= 'z' ) { printf("F->i\t\t"); printf("#E'T'i\t\t"); print(); myAdvance(); printf("\t\t"); printf("#E'T'\t\t"); print(); return(1); } else{
编译原理_实验二_语法分析_递归下降分析器设计_实验报告
递归下降分析器设计一、实验/实习过程内容:利用JavaCC生成一个MiniC的语法分析器;要求:1. 用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。
2. 具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3. 如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉〈语句串〉|〈语句〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|==|!=2.消除语句中的回溯与左递归3.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)4.完成的功能包括词法分析,语法分析二、代码:options {JDK_VERSION = "1.5";}PARSER_BEGIN(eg1)public class eg1 {public static void main(String args[]) throws ParseException { eg1 parser = new eg1(System.in);parser.start();}}PARSER_END(eg1)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS: "+" >| < MINUS: "-" >| < MULTIPLY: "*" >| < DIVIDE: "/" >}TOKEN :{<BIGGER:">"> |<SMALLER:"<"> |<NOTVOLUTION:"!="> |<SMALLEREQDD:"<="> |<BIGGEREE:">=" > |<DOUBLE:"==">TOKEN: //关键字{<MAIN:"main"> |<VOID:"void"> |<IF:"if"> |<INT:"int"> | <WHILE:"while"> |<CHAR:"char"> | <VOLUTION:"="> }TOKEN : //定义整型数{< INTEGER: ["0" - "9"]( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN : //数字{<NUMBER:(<DIGIT>)+ | (<DIGIT>)+"."| (<DIGIT>)+"."(<DIGIT>)+| "."(<DIGIT>)+>}TOKEN : //标记{<COMMA:","> | <SEMICOLON:";"> | <COLON:":"> | <LEFTPARENTHESES:"("> |<RIGHTPARENTHESES:")"> | <LEFTBRACE:"{"> | <RIGHTBRACE:"}"> }TOKEN : //标识符{<IDENTIFIER:<LETTER> |<LETTER>(<LETTER> | <DIGIT> )* >|<#LETTER:["a"-"z", "A"-"Z"]>}void start():{}{<MAIN> <LEFTPARENTHESES> <RIGHTPARENTHESES> block() }void block():{}{<LEFTBRACE> string() <RIGHTBRACE>}void string():{}{yuju() (string())?}void yuju():{}{fuzhiyuju() | tiaojianyuju() | xunhuanyuju()}void fuzhiyuju():{}{<IDENTIFIER> <VOLUTION> biaodashi() <SEMICOLON>}void tiaojianyuju():{}{<IF> tiaojian() block()}void xunhuanyuju():{}<WHILE> tiaojian() block()}void tiaojian():{}{<LEFTPARENTHESES> biaodashi() guanxifu() biaodashi()<RIGHTPARENTHESES>}void biaodashi():{}{( <LEFTPARENTHESES> biaodashi() <RIGHTPARENTHESES> biaodashi2()) |(<IDENTIFIER> biaodashi2() ) | ( <NUMBER> biaodashi2() )}void biaodashi2():{}{(yunsuanfu() biaodashi() biaodashi2() )?}void yunsuanfu():{}{< PLUS > | < MINUS > |< MULTIPLY> | < DIVIDE >}void guanxifu() :{}{<BIGGER> | <SMALLER> | <NOTVOLUTION><SMALLEREQDD> | <BIGGEREE> | <DOUBLE>}三、实验/实习总结本次实习,我使用javacc完成了包括词法分析,语法分析(输出语法树),能够读文件的功能,总的来说比较满意,通过本次实习掌握了javacc基本的使用。
递归下降语法分析器实验报告
编译原理实验报告题目: 递归下降语法分析器学 院 计算机科学与技术 专 业 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 语言的运算符。
编译原理-实验4递归下降分析法
实验4《递归下降分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验内容程序输入/输出示例(以下仅供参考):对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E-TG(2)G-+TG|—TG(3)G-ε(4)T-FS(5)S-*FS|/FS(6)S-ε(7)F-(E)(8)F-i输出的格式如下:(3)备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符I,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好)。
三、实验方法用C语言,根据递归下降分析法的规则编写代码,并测试。
四、实验步骤1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3.对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;五、实验结果六、实验结论#include<stdio.h>#include<dos.h>#include<stdlib.h>#include<string.h>char a[50],b[50],d[200],e[10];char ch;int numOfEq,i1=0,flag=1,n=6;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();//================================================ void main()/*递归分析*/{ int foe1,i=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='?';d[4]='T';d[5]='G';d[6]='#';printf("请输入字符串(以#号结束)\n");do{ scanf("%c",&ch);a[i]=ch;i++;}while(ch!='#');numOfEq=i;ch=b[0]=a[0];printf("文法\t分析串\t\t分析字符\t剩余串\n");if (foe1==0) return;if (ch=='#'){ printf("accept\n");i=0;x=d[i];while(x!='#'){ printf("%c",x);i=i+1;x=d[i];/*输出推导式*/}printf("\n");}else{ printf("error\n");printf("回车返回\n");getchar();getchar();return;}}//================================================ int E1(){ int fot,fog;printf("E->TG\t");flag=1;input();input1();fot=T();if (fot==0) return(0);fog=G();if (fog==0) return(0);else return(1); }//================================================ int E(){ int fot,fog;printf("E->TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='?';e[4]='T';e[6]='#';output();flag=1;input();input1();fot=T();if (fot==0) return(0);fog=G();if (fog==0) return(0);else return(1); }//================================================ int T(){ int fof,fos;printf("T->FS\t");e[0]='T';e[1]='=';e[2]='>';e[3]='?';e[4]='F';e[5]='S';e[6]='#';output();flag=1;input();input1();fof=F();if (fof==0) return(0);fos=S();if (fos==0) return(0);else return(1); }//================================================ int G(){ int fot;if(ch=='+'){ b[i1]=ch;printf("G->+TG\t");e[0]='G';e[2]='>';e[3]='?';e[4]='+';e[5]='T';e[6]='G';e[7]='#';output();flag=0;input();input1();ch=a[++i1];fot=T();if (fot==0) return(0); G();return(1);}else if(ch=='-'){ b[i1]=ch;printf("G->-TG\t"); e[0]='G';e[1]='=';e[2]='>';e[3]='?';e[4]='-';e[5]='T';e[6]='G';e[7]='#';output();flag=0;input();input1();ch=a[++i1];fot=T();if (fot==0) return(0); G();return(1); }printf("G->^\t");e[1]='=';e[2]='>';e[3]='?';e[4]='^';e[5]='#';output();flag=1;input();input1();return(1);}//================================================ int S(){ int fof,fos;if(ch=='*'){ b[i1]=ch;printf("S->*FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='*';e[5]='F';e[6]='S';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];fof=F();if (fof==0)return(0);fos=S();if (fos==0) return(0);else return(1); }else if(ch=='/'){ b[i1]=ch;printf("S->/FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='/';e[5]='F';e[6]='S';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];fof=F();if (fof==0) return(0);fos=S();if (fos==0) return(0);else return(1); }printf("S->^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='?';e[4]='^';e[5]='#';output();flag=1;a[i1]=ch;input();input1();return(1); }//================================================ int F(){int f;if(ch=='('){ b[i1]=ch;printf("F->(E)\t");e[0]='F';e[1]='=';e[2]='>';e[3]='?';e[3]='(';e[4]='E';e[5]=')';e[7]='#'; output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0); if(ch==')'){ b[i1]=ch;printf("F--(E)\t");flag=0;input();input1();ch=a[++i1]; }else{ printf("error\n");return(0);}}else if(ch=='i'){b[i1]=ch;printf("F->i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='?';e[4]='i';e[5]='#';output();flag=0;input();input1();ch=a[++i1];}else{printf("error\n");return(0);}return(1);}//================================================ void input(){ int i=0;for (;i<=i1-flag;i++)printf("%c",b[i]);/*输出分析串*/printf("\t\t");printf("%c\t\t",ch);/*输出分析字符*/}//================================================ void input1(){ int i;for (i=i1+1-flag;i<numOfEq;i++)printf("%c",a[i]);/*输出剩余字符*/printf("\n");}//================================================ void output(){/*推导式计算*/int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='?';d[n+3]='#';n=n+3;i=n;i=i-2;while(d[i]!='?'&&i!=0)i--;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]='#';}七、实验小结通过本次试验实践掌握了自上而下语法分析法的特点。
编译原理实验报告:实验二编写递归下降语法分析程序
编译原理实验报告实验名称:实验二编写递归下降语法分析器实验类型:验证型实验指导教师:何中胜专业班级: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( )函数。
编译原理语法分析递归下降子程序实验报告
编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行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日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
递归下降语法分析设计原理与实现技术实验报告
递归下降语法分析设计原理与实现技术实验报告变更说明、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
、实验容:[实验项目]完成以下描述算术表达式的LL(1)文法的递归下降分析程序G[E]: E —TEE'—ATE | £T—FTT'—MFT | &F—(E)|iA—+|-M—*|/[设计说明]终结符号i为用户定义的简单变量,即标识符的定义。
[设计要求](1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(2)递归下降分析程序应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
三、实验环境:操作系统:Windows 7软件:VC++6.0四、程序功能描述:提供了两种输入方式:键盘和文件,有文件输入时需为二元式序列;能够对输入的字符串做出正确的递归下降分析判断,并给出判断结果;能发现输入串中的错误,包含非法字符,输入不匹配等;能够处理一些可预见性的错误,如文件不存在,用户输入非法等。
五、数据结构设计:全局:局部(main()中):六、程序结构描述:设计方法:本程序采用从键盘输入或文件读取两种输入方式,其中文件的容需为二元式序列,然后按照递归下降分析的方法对输入的字符串进行分析判断,并输出判断结果,程序通过对输入串的检查能够发现输入串中的错误。
程序规定的单词符号及其种别码见下表:单词符号及其种别码表主要函数说明:- 肆1 dqxj classes白”血Globals4 AQ0 advance[|1铤。
卜・E l (JQ errorQ・errorlf)卜.FD$ initO・Justlfy[char ch int i|卜“.MO| 4 mainO卜・TOj ©T1Dadvance():将下一个字符送入current ;error():输出错误,表示不是该文法的句子;error1();输出错误,输入容不合法;ini t():初始化函数;justify。
编译原理之递归下降语法分析程序(实验)
编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤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.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
语法分析——递归下降分析法
实验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的递归子程序(即语法分析器)。
实验2 递归下降分析器设计与实现
实验二 递归下降语法分析器设 计与实现
一、实验目的
• 掌握自上而下语法分析的思想 • 掌握递归下降分析法的原理和方法
二、实验内容
• 在实验一已经实现的词法分析器的基础上 设计递归下降语法分析子程序 • 可以自选语法分析的语句,比如赋值语句, 算术表达式,条件语句等 • 实现某一种语句的分析即可
三、实验要求
• • • • • • • • • 先确定要进行语法分析的语句 给出语句的文法 确定文法是否为LL(1)文法,不是请先改造 计算各条产生式的select集合 设计详细的流程图 构造递归下降子程序 要求思路清晰,源码有必要的注释 给出各种不同测试数据和测试结果 给出详细
递归下降分析实验报告
一、实验目的通过本次实验,加深对递归下降分析法的理解,掌握递归下降分析法的原理和应用,并能够根据给定的文法编写相应的递归下降分析程序。
二、实验原理递归下降分析法是一种自顶向下的语法分析方法,它将文法中的每个非终结符对应一个递归过程(函数),分析过程就是从文法开始符触发执行一组递归过程(函数),向下推到直到推出句子。
递归下降分析法的前提是文法应满足以下条件:1. 消除二义性:确保文法中每个产生式都只有一个确定的意义。
2. 消除左递归:避免产生式出现如A -> A...A的形式。
3. 提取左因子:将产生式中的左因子提取出来,避免出现左递归。
4. 判断是否为LL(1)文法:LL(1)文法是指文法满足左递归和右递归的文法。
三、实验内容1. 根据给定的文法编写递归下降分析程序。
2. 对输入的符号串进行分析,判断其是否属于该文法。
3. 输出分析过程和结果。
四、实验步骤1. 阅读相关资料,了解递归下降分析法的原理和应用。
2. 根据给定的文法,设计递归下降分析程序的结构。
3. 编写递归下降分析程序,实现分析过程。
4. 编写测试用例,验证递归下降分析程序的正确性。
5. 分析实验结果,总结实验经验。
五、实验结果与分析1. 实验结果根据给定的文法,编写了递归下降分析程序,并进行了测试。
以下为部分测试用例及结果:(1)输入:eBaA输出:分析成功,属于该文法。
(2)输入:abAcB输出:分析成功,属于该文法。
(3)输入:dEdaC输出:分析成功,属于该文法。
(4)输入:edc输出:分析成功,属于该文法。
2. 实验分析通过本次实验,我们深入了解了递归下降分析法的原理和应用。
在编写递归下降分析程序的过程中,我们学会了如何根据文法设计程序结构,以及如何实现分析过程。
同时,我们还掌握了如何对输入的符号串进行分析,并输出分析结果。
实验过程中,我们遇到了一些问题,如消除二义性、消除左递归、提取左因子等。
通过查阅资料和不断尝试,我们成功解决了这些问题。
实验2 递归下降语法分析
实验二递归下降语法分析一、实验目的构造文法的语法分析程序,要求采用递归下降语法分析方法对输入的字符串进行语法分析,进一步掌握递归下降的语法分析方法。
二、实验内容编写为一上下文无关文法(文法如下)构造其递归下降语法分析程序,并对任给的一个输入串进行语法分析检查。
程序要求能对输入串进行递归下降语法分析,能判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。
E-->E+T|TT-->T*F|FF-->(E)|i三、实验参考:算法思想为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。
由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。
在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。
语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。
也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。
出错时,可以根据读字符的位置判断出错的位置。
四、实验说明:1.时间安排:安排在“词法分析”后。
2.实验环境:WINDOWS下,工具为Visual C++ 6.0五、上交:程序源代码;已经测试通过的3组数据(全部存在一个文本文件test1.txt中,以“第一组输入/输出;第二组输入/输出;第三组输入/输出”的顺序存放);实验报告:实验结果和分析中应包括:(1)功能描述:该程序具有什么功能?(2)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;另外可以附加函数之间的调用关系图、程序总体执行流程图(参考课本第二章)。
(3)实验总结:你在编程过程中花时多少?多少时间在纸上设计?多少时间上机编程和调试?多少时间在思考问题?遇到了哪些难题?你是怎么克服的?你对你的程序的评价?你的收获有哪些?。
递归下降语法分析实验报告
编译原理实验报告一、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
二、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:S→a|∧|(T)T→T,S|S三、设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。
四、设计分析这个题目属于比较典型的递归下降语法分析。
需要先将原算术表达式方法改写为LL(1)文法为:S→a|∧|(T)T→ST’T’→,ST’|ε然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。
具体方法为:(1)当遇到终结符a时,则编写语句If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到终结符∧时,则编写语句If(当前读到的输入符号==∧)读入下一个输入符号(3)当遇到终结符﹙时,则编写语句If(当前读到的输入符号==﹙)读入下一个输入符号(4)当遇到非终结符T时,则编写scaner()函数读取下一个单词符号并将它放在全程变量sym中(5)当遇到非终结符S时,则编写S()函数(6)当遇到非终结符T’时,则编写T’()(7)当遇到终结符,时,则编写语句If(当前读到的输入符号==,)读入下一个输入符号(8)当遇到非终结符T时,则编写T()五、实验代码#include"stdio.h"void S();void T();void scaner();void error();char sym;char s[100];int i=0;int main(){printf("请输入一个语句,以#号结束语句(直接输入#号推出)\n");scanf("%s",&s);scaner();S();if (sym=='#'){printf("success");return 1;}else{printf("fail");return 0;}}void scaner(){sym=s[i];i++;}void T'(){if(sym==','){scaner();S();T'();}else if(sym!=')')error();}void error(){printf("语句有误!\n");}void T(){S();T'();}void S(){if (sym=='a'||sym=='^')scaner();else if(sym=='('){scaner();T();if(sym==')')scaner();elseerror();}elseerror();}六、测试用例和实验结果(1)输入a,预期显示语句正确!(2)输入∧,预期显示语句正确!(3)输入(a,b),预期显示语句有误!(4)输入(a ,a),预期显示语句正确!(5)输入(a,(a,a)),预期显示语句正确!七、测试结果截图(1)输入a的测试结果(2)输入^的测试结果(3)输入(a,b)的测试结果(4)输入(a ,a)的测试结果(5)输入(a,(a,a))测试结果八、实验总结通过该实验,我深入的学习了递归下降分析法的内容和原理,它是确定的自上而下的分析法,这种分析法是要求文法是LL(1)的,它的基本思想是对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该终结符所表示的语法成分,由于描述语言的文法常常是递归定义的,因此相应的这组函数必然是相互递归的方式进行调用的,所以将此种分析法称为递归下降分析法。
实验报告四递归下降语法分析程序设计
实验报告四递归下降语法分析程序设计《编译原理》实验报告实验序号: 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到⽂件尾。
实验二递归下降分析法实验报告
信息商务学院实验报告课程:编译原理实验名称:递归下降分析学号: *************名:***指导老师:***日期:2014年5月13日实验二递归下降分析法一、实验目的和要求1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。
2. 本次实验的目的是加深对递归下降分析法的理解。
二、实验内容(1)功能描述对下列文法,用递归下降分析法对任意输入的符号串进行分析,看是否能匹配成功:(1)E→TG(2)G→+TG|-TG(3)G→ε(4)T→FS(5)S→*FS|/FS(6)S→ε(7)F→(E)(8)F→i(2)程序结构描述本程序的实现方法主要就是函数的递归调用,在程序前面先对文法中所涉及到的非终结符对应的函数进行声明,以免在用到的时候提示函数无声明的错误提示,程序从开始符E开始,根据文法,E可以推出T和G,就在函数E()中调用T()和G(),其他的也是类似,这属于文法中只涉及到非终结符;遇到有终结符的情况则不同,想函数G(),因为G可以推出+TG或者-TG,所以在函数G()中,要分两种情况,先判断当前的字符是否是+,是则调用T()和G(),如果当前字符为-,就调用T()和G(),否则就是ε字符;按照这种方法,把文法所涉及到的非终结符都写成对应的函数,并正确调用其他函数。
等所有的函数都描述之后就在mian()里判断当前字符是否分析到结束符#,是则说明此字符串是合法字符,否则说明此字符串为不合法字符。
(3)程序部分代码#include<string.h>#include<stdio.h>#include<stdlib.h>FILE *fp;char ch;#define N 20char string[N];char *p;void E();void T();void G();void F();void S();void E(){printf("E-->TG...%c\n",ch);T();G();}void F(){if(ch=='i'){printf("F-->i...%c\n",ch);*p=ch;p++;ch=fgetc(fp);}else if(ch=='('){printf("F-->(E)...%c\n",ch);*p=ch;p++;ch=fgetc(fp);E();if(ch==')'){*p=ch;p++;ch=fgetc(fp);}else{printf("没有右括号“)”匹配不成功!\n");exit(0);}}else{printf("算式匹配不成功!\n");exit(0);}}void G(){if(ch=='+'){printf("G-->+TG...%c\n",ch);*p=ch;p++;ch=fgetc(fp);T();G();}else if(ch=='-'){printf("G-->+TG...%c\n",ch);*p=ch;p++;ch=fgetc(fp);T();G();}elseprintf("G-->空...%c\n",ch); }void T(){printf("T-->FS...%c\n",ch);F();S();}void S(){if(ch=='*'){printf("S-->*FS...%c\n",ch);*p=ch;p++;ch=fgetc(fp);F();S();}else if(ch=='/'){printf("S-->/FS...%c\n",ch);*p=ch;p++;ch=fgetc(fp);F();S();}elseprintf("S-->空...%c\n",ch);}void main(){if((fp=fopen("D:\\3.txt","r"))==NULL){ //读取文件内容,并返回文件指针,该指针指向文件的第一个字符fprintf(stderr,"error opening.\n");exit(1);}ch=fgetc(fp);p=string;printf("调用分析程序所用产生式:\n");E();if(ch=='#'){*p=ch;printf("算法匹配成功!\n算法结果:%s\n",string);}else{printf("算法匹配不成功!\n");}fclose(fp);}三、实验结果测试数据一:D盘的一个名为ceshi.txt的文本文件里文件里输入字符串:(*i)+i#,运行结果如图1所示。
递归下降分析实验报告
实习二递归下降分析一、实验目的:根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、实验预习提示1、递归下降分析法的功能词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。
2、递归下降分析法的前提改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法,3、递归下降分析法实验设计思想及算法为G的每个非终结符号U构造一个递归过程,不妨命名为U。
U的产生式的右边指出这个过程的代码结构:(1)若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
(2)若是非终结符号,则调用与此非终结符对应的过程。
当A的右部有多个产生式时,可用选择结构实现。
具体为:(1)对于每个非终结符号U->u1|u2|…|un处理的方法如下:U( ){ch=当前符号;if(ch可能是u1字的开头) 处理u1的程序部分;else if(ch可能是u2字的开头)处理u2的程序部分;…else error()}(2)对于每个右部u1->x1x2…xn的处理架构如下:处理x1的程序;处理x2的程序;…处理xn的程序;(3)如果右部为空,则不处理。
(4)对于右部中的每个符号xi①如果xi为终结符号:if(xi= = 当前的符号){NextChar(); /% NextChar为前进一个字符函数。
%/ return;}else 出错处理②如果xi为非终结符号,直接调用相应的过程xi()三、实验要求程序输入/输出示例:对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|-TG|ε(3)T->FS(4)S->*FS|/FS|ε(5)F->(E)|i输出的格式如下:(1)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i#(2)输出结果:i+i*i#为合法符号串? 备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。
实验三递归下降分析器设计与实现编译原理实验报告
实验三递归下降分析器设计与实现编译原理实验报告一、引言递归下降分析器是编译原理中常用的一种语法分析方法。
它根据文法规则和输入的源代码,递归地进行语法分析,判断源代码是否符合给定的文法规则。
本实验旨在通过设计与实现一个简单的递归下降分析器,加深对编译原理中语法分析的理解。
二、实验目的1.学习递归下降分析器的原理和设计方法;2.掌握使用递归下降分析器进行简单语法分析的过程;3.加深对编译原理中文法规则和语法分析的理解。
三、实验过程1.设计文法规则:根据实验要求,设计一个简单的算术表达式文法规则。
例如,我们可以采用以下文法规则:```E->E+T,E-T,TT->T*F,T/F,FF -> ( E ) , num```2.设计分析器:根据设计的文法规则,设计递归下降分析器的结构和算法。
我们可以使用编程语言实现一个类,其中包含递归下降分析器所需要的方法和数据结构。
3. 实现分析器:根据设计的分析器结构和算法,使用编程语言实现递归下降分析器的代码。
可以选择常用的编程语言,如C++、Java、Python等。
4.进行语法分析:编写测试代码,使用实现的递归下降分析器对输入的算术表达式进行语法分析。
根据分析结果,判断输入的算术表达式是否符合给定的文法规则。
五、实验结果实验结果根据设计的分析器的实现和测试代码的编写而定。
例如,对于以下输入的算术表达式:(3+4)*5-2,经过递归下降分析器的分析,应该能正确判断其是否符合给定的文法规则。
六、实验总结递归下降分析器是编译原理中常用的一种语法分析方法。
通过实验三,我深入理解了递归下降分析器的原理和设计方法,并通过实现一个简单的递归下降分析器,加深了我对编译原理中文法规则和语法分析的理解。
在实验过程中,我学会了如何根据设计的文法规则来设计递归下降分析器的结构和算法。
我使用了编程语言实现了递归下降分析器的代码,并编写了相应的测试代码进行语法分析。
通过测试,我验证了递归下降分析器的正确性。
递归下降语法分析器实验报告
一、实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。
二、实验原理1. 基本原理递归下降法是语法分析中最易懂的一种方法。
它的主要原理是,对每个非终极符按其产生式结构构造相应语法分析子程序,其中终极符产生匹配命令,而非终极符则产生过程调用命令。
因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。
其中子程序的结构与产生式结构几乎是一致的。
2. 文法要求递归下降法要满足的条件:假设A的全部产生式为Aα1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式predict(Aαi)∩predict(Aαj)=Φ,当i≠j.3. 实现原理假设文法中有如下的产生式A1 | 2 | … | n,则应按如下方法编写语法分析子程序procedure A()begin if tokenPredict(A1) then θ(1) elseif tokenPredict(A2) then θ(2) else……if tokenPredict(An) then θ(n) elseerror()end其中对i =X1X2…Xn,θ(i) =θ’(X1); θ’(X2);…; θ’(Xn);● 如果XiVN,θ’(Xi)= Xi● 如果XiVT,θ’(Xi)= Match(Xi)● 如果Xi= , θ’(λ) = skip(空语句)三、实验要求1、使用递归下降分析算法分析表达式文法:exp ::= exp addop term | termaddop ::= + | -term ::= term mulop factor | factormulop ::= * | /factor ::= (exp) | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到number的值。
2、该词法分析器以子程序形式出现,当需要进行词法分析时进行调用;3、能够识别正确和错误的表达式;4、在进行语法分析的过程中,计算输入表达式的值。
实验二(递归下降分析)
实验二递归下降语法分析一.实验目的1、按照语言的语法要求编写文法的规则2、转化文法的规则,使之具有EBCF,消除左递归和左因子3、掌握编程形式的语法分析器的实现二.实验内容在TINY计算机语言的编译程序的词法分析部分实现的基础上,采用递归下降的方法实现语法分析,形成语法树。
语法分析的输入是记号串,按照从左到右扫描,按照文法规则的要求,判断语句是否符合文法要求,如果符合要求则形成语法数,不符合则指出原因。
为了简化程序的编写,对语法有具体如下的要求:(1)只有5中语句if、repeat、read、write、assignment。
(2)read只作用一个变量,实现输入。
(3)write只作用一个表达式,实现输出。
(4)表达式只有两类:布尔表达式,只用于if和repeat语句的测试,算术表达式采用左结合和优先级的方式组成。
(5)没有变量的声明,仅仅在赋值时采用隐性的方式说明,只有整型变量;(6)每个语句序列采用‘;’的形式分开,最后一个语句没有分号(7)没有函数或过程三.实验要求要求实现语法分析程序的以下功能:(1)在实现之前首先实现EBNF,消除左递归和左因子,为递归下降程序做好准备(2)对于语句和表达式采用枚举的形式定义,形成一个统一的树结点结构(3)把正确源程序的首先经过词法分析形成二元式记号提供给语法分析程序(4)如果出现错误,指出错误的位置和类型(5)把语法树按照树的前序遍历的形式把所有的结点按照某种形式输出语法分析进行具体的要求:(1)语法分析的具体功能实现是一个函数TreeNode* parse(),分析记号串,形成一个语法数。
(2)编写一个单独的函数parseTree(TreeNode*)遍历整个语法树,把每个结点信息输出程序:头文件:#include<string>using namespace std;enum WordType {WRONG, NUMBER, IDENTIFIER, IF, THEN, ELSE, END, //7REPEAT, UNTIL, READ, WRITE, FALSE, PLUS, SUBTRACT, MULTIPLY, //16DIVIDEY, EQUAL, LESSTHAN, SEMICOLON, FINAL, ASSIGNMENT, S_BRACKET_L, S_BRACKET_R,//24LINE_FEED, SPACE, TAB, BIG_BRACKET_L, BIG_BRACKET_R}; //29void CiFa ();void Yufa2 ();string IntToStr(int n);//将数字转换成字符串int EqulStr (string s1, string s2);//比较两个字符串是否相等,相等返回1,否则返回0源文件:头文件中函数:#include<iostream>#include<string>#include<sstream>#include<stdexcept>#include"head.h"using namespace std;string IntToStr(int n){ostringstream result;result << n;return result.str();}int EqulStr (string s1, string s2){if (s1 == s2)return 1;elsereturn 0;}词法分析:#include<iostream>#include<iomanip>#include<ctype.h>#include<fstream>#include<string>#include"head.h"using namespace std;enum CharType {ALPHABET, OTHER};enum WrongType1 {ZERO, ALP_NUM, NUM_ALP, UNLEAGL_S, NO_MATCH, UNKNOW};char *Words [] = {"wrong", "number", "identifier", "if", "then", "else", "end",//7 "repeat", "until","read", "write", "false", "+", "-", "*", //16"/", "=", "<", ";", "$",":=", "(", ")",//24"\n", " ", " ", "{", "}"}; //29typedef struct{char *str;int wordtype;}Two;char ArrayChar[100], cbuffer;int i=-1, numline = 1, wordtype;string LineChar;Two T;ifstream fp("source.txt",ios::in);ofstream outfile ("cifa.txt", ios::out);void CiFa (){Two GetToken();if (!fp)cout<<"文件打开错误!!"<<endl;else{cout << setiosflags (ios::left) << setw (6) << "行数" << "(";cout << setiosflags (ios::left) << setw (10)<< "类别编码" << ", ";cout << setiosflags (ios::left) << setw (20) << "字符" << ")" << endl;fp.get (cbuffer);while (!fp.eof ()){GetToken();}outfile << numline << "," << FINAL << ",";}cout << "第" << numline << " 行所有字符:" << LineChar << endl;fp.close ();outfile.close ();}int Match(char str[], int chartype)//查找匹配的字符{int i;switch (chartype){case ALPHABET:for (i = IF; i <= FALSE; i++){if (strcmp(Words[i],str) == 0)return i;}case OTHER:for (i = PLUS; i <= S_BRACKET_R; i++){if (strcmp(Words[i],str) == 0)return i;}}return WRONG;}void TypeWrong (int wrongtype, int line){switch (wrongtype){case ZERO:break;case ALP_NUM:cout << "字母后面不能紧跟数字!";break;case NUM_ALP:cout << "数字后面不能紧跟字母!";break;case UNLEAGL_S:cout << "非法特殊符号!";break;case NO_MATCH:cout << "没有与第" << line << " 行“{”匹配的“}”!";break;default :cout << "其它类型错误!";break;}}Two ConvertTwo (char str[], int wordtype, int wrongtype, int numline, int line)//进行二元转换{Two T;T.wordtype = wordtype;T.str = str;cout << setiosflags (ios::left) << setw (6) << numline << "(";cout << setiosflags (ios::left) << setw (10) << T.wordtype << ", ";cout << setiosflags (ios::left) << setw (20) << T.str << ")";if (T.wordtype == WRONG)TypeWrong (wrongtype, line);cout << endl;outfile << numline << "," << T.wordtype << "," ;return T;}void HandleAlphabet ()//首字符为字母时的处理{bool mark = true;while(!fp.eof() && isalpha(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isdigit (cbuffer)){mark = false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark){wordtype = Match(ArrayChar, ALPHABET);T = ConvertTwo(ArrayChar,(IDENTIFIER > wordtype ? IDENTIFIER : wordtype), ZERO, numline, numline);}elseT = ConvertTwo(ArrayChar,WRONG, ALP_NUM, numline, numline);}void HandleNumber ()//首字符为数字时的处理{bool mark = true;while (!fp.eof() && isdigit(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isalpha(cbuffer)){mark = false;while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark)T = ConvertTwo(ArrayChar, NUMBER, ZERO, numline, numline);elseT = ConvertTwo(ArrayChar,WRONG, NUM_ALP, numline, numline);}void DeleteNote ()//删除注释{int record = numline;while (!fp.eof() && cbuffer != '}'){fp.get(cbuffer);while (!fp.eof() && cbuffer != '}'){if (cbuffer == '\n'){ArrayChar [i + 1] = '\0';LineChar += ArrayChar;cout << "第" << numline << " 行所有字符:" << LineChar << endl;LineChar = "";numline++;i = -1;fp.get(cbuffer);}ArrayChar[++i]=cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';if (cbuffer == '}'){ArrayChar [++i] = '}';ArrayChar[i + 1]='\0';}else{T = ConvertTwo("", WRONG, NO_MATCH, numline, record);}}LineChar += ArrayChar;fp.get(cbuffer);}void HandleOther ()//字符为特殊字符时的处理{ArrayChar [++i] = cbuffer;if (ArrayChar [i] == '{')//删除注释{DeleteNote ();}else//其他字符{fp.get(cbuffer);ArrayChar [++i] = cbuffer;ArrayChar[i + 1] = '\0';char Temp1 [2];Temp1 [0] = ArrayChar [0];Temp1 [1] = '\0';if (!(wordtype = Match(ArrayChar, OTHER)))//当双字符没有匹配的时候,看单字符是否有匹配的{ArrayChar [i] = '\0';if (!wordtype)wordtype = Match(Temp1, OTHER);}else{fp.get(cbuffer);while (!fp.eof() && cbuffer != '\n' && cbuffer != ' ' && cbuffer != ' '&& !isalpha(cbuffer) && !isdigit(cbuffer)){ArrayChar [++i] = cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';wordtype = Match(ArrayChar, OTHER);}LineChar += ArrayChar;T = ConvertTwo(ArrayChar, wordtype, (wordtype > 0 ? 0: UNLEAGL_S), numline, numline);}}Two GetToken(){if(cbuffer == '\n')//忽略换行符{cout << "第" << numline << " 行所有字符:" << LineChar << endl;numline++;LineChar = "";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略空字符{LineChar += " ";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略制表符{LineChar += " ";fp.get(cbuffer);}else if (isalpha(cbuffer))//判断是否是字母{HandleAlphabet ();}else if (isdigit(cbuffer))//判断是否是数字{HandleNumber ();}else//其他字符HandleOther ();i = -1;return T;}语法分析:#include <iostream>#include <iomanip>#include <ctype.h>#include <fstream>#include <string>#include <sstream>#include <stdexcept>#include "head.h"using namespace std;ifstream fp2("cifa.txt",ios::in);int SPro ();//1int SStm ();//2int SStms ();//3int SSta ();//4int SIf ();//5int SRep ();//6int SAss ();// 7int SRea ();//8int SWri ();//9int SExp ();//10int SCom ();//11int SSim ();//12int SSims ();//13int SAdd ();//14int STer ();//15int STers ();//16int SMul ();//17int SFac ();//18char lastline [4], line [4], ch2[4];bool OK = true;void GetWord (char *line, char *ch2){strcpy_s (lastline, line);fp2.getline (line, 3, ',');fp2.getline (ch2, 3, ',');}void Yufa2 (){CiFa ();if (!fp2)cout<<"文件打开错误!!"<<endl;else{cout << "文件打开成功!" << endl;GetWord (line, ch2);while (!EqulStr (ch2, IntToStr (FINAL)))SPro ();if (OK)cout << "OK 源文件符合该文法!" << endl;elsecout << "Wrong 源文件不符合该文法!" << endl;}fp2.close ();}int SPro ()//1{if (SStm ())return 1;//如果此次读入的第一个字符不是开始符号,则继续读取下一个cout << "第" << lastline << "行错误!" << endl;GetWord (line, ch2);OK = false;return 0;}int SStm ()//2{if (SSta ()){if (SStms ())return 1;elsecout << "第 " << lastline << " 行缺少语句的结束符;!" << endl;OK = false;return 1;}return 0;}int SStms ()//3{if (EqulStr (ch2, IntToStr (SEMICOLON))){GetWord (line, ch2);if (SSta ()){if (SStms ())return 1;elsecout << "第 " << lastline << " 行缺少有效的语句!" << endl;}elsecout << "第 " << lastline << " 行 ; 后面没有有效的语句!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE)) || EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (FINAL)))return 1;return 0;}int SSta ()//4{if (SIf () || SRep () || SAss () || SRea () || SWri ())return 1;return 0;}int SIf ()//5{if (EqulStr (ch2, IntToStr (IF))){GetWord (line, ch2);if (SExp ()){if (EqulStr (ch2, IntToStr (THEN))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (END))){GetWord (line, ch2);return 1;}else if (EqulStr (ch2, IntToStr (ELSE))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (END))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行缺少语句的结束符 end!" << endl;}}else{cout << "第 " << lastline << " 行 else 后面没有有效的语句!" << endl;}}else{cout << "第 " << lastline << " 行缺少语句的结束符 end!" << endl;}}else{cout << "第 " << lastline << " 行缺少关键字 else!" << endl;}}else{cout << "第 " << lastline << " 行 then 后面没有有效的语句!" << endl;}}elsecout << "第 " << lastline << " 行 if 后面没有有效的表达式!" << endl;OK = false;return 1;}return 0;}int SRep ()//6{if (EqulStr (ch2, IntToStr (REPEAT))){GetWord (line, ch2);if (SStm ()){if (EqulStr (ch2, IntToStr (UNTIL))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 until 后面没有有效的表达式!" << endl;}else{cout << "第 " << lastline << " 行缺少关键字 until!" << endl;}}elsecout << "第 " << lastline << " 行 repeat 后面没有有效的语句!" << endl;OK = false;return 1;}return 0;}int SAss ()//7{if (EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);if (EqulStr (ch2, IntToStr (ASSIGNMENT))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 := 后面没有有效的表达式!" << endl;}else{cout << "第 " << lastline << " 行缺少关键字 :=!" << endl;}OK = false;return 1;}return 0;}int SRea ()//8{if (EqulStr (ch2, IntToStr (READ))){GetWord (line, ch2);if (EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行 read 后面没有有效的标识符!" << endl;}OK = false;return 1;}return 0;}int SWri ()//9{if (EqulStr (ch2, IntToStr (WRITE))){GetWord (line, ch2);if (SExp ())return 1;elsecout << "第 " << lastline << " 行 write 后面没有有效的表达式!" << endl;OK = false;return 1;}return 0;}int SExp ()//10{if (SSim ()){if (SCom ()){if (SSim ())return 1;elsecout << "第 " << lastline << " 行缺少(或者数字或者标识符!" << endl;OK = false;}return 1;}return 0;}int SCom ()//11{if (EqulStr (ch2, IntToStr (LESSTHAN)) || EqulStr (ch2, IntToStr (EQUAL))){GetWord (line, ch2);return 1;}return 0;}int SSim ()//12{if (STer ()){if (SSims ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;OK = false;return 1;}return 0;}int SSims ()//13{if (SAdd ()){if (STer ()){if (SSims ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;}elsecout << "第 " << lastline << " 行缺少(或者数字或者标识符!" << endl;OK = false;return 1;}elseif (EqulStr (ch2, IntToStr (THEN)) || EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE))|| EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (S_BRACKET_R)) || EqulStr (ch2, IntToStr (LESSTHAN))|| EqulStr (ch2, IntToStr (EQUAL)) || EqulStr (ch2, IntToStr (FINAL)) || EqulStr (ch2, IntToStr (SEMICOLON)))return 1;return 0;}int SAdd ()//14{if (EqulStr (ch2, IntToStr (PLUS)) || EqulStr (ch2, IntToStr (SUBTRACT))){GetWord (line, ch2);return 1;}return 0;}int STer ()//15{if (SFac ()){if (STers ())return 1;elsecout << "第 " << lastline << " 行缺少有效的关键字!" << endl;OK = false;return 1;}return 0;}int STers ()//16{if (SMul ()){if (SFac ()){if (STers ())return 1;elsecout << "第 " << lastline << " 行缺少有效的表达式!" << endl;}elsecout << "第 " << lastline << " 行缺少有效的表达式!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (THEN)) || EqulStr (ch2, IntToStr (END)) || EqulStr (ch2, IntToStr (ELSE))|| EqulStr (ch2, IntToStr (UNTIL)) || EqulStr (ch2, IntToStr (S_BRACKET_R)) || EqulStr(ch2, IntToStr (LESSTHAN))|| EqulStr (ch2, IntToStr (EQUAL)) || EqulStr (ch2, IntToStr (FINAL)) || EqulStr (ch2, IntToStr (SEMICOLON))|| EqulStr (ch2, IntToStr (PLUS)) || EqulStr (ch2, IntToStr (SUBTRACT)))return 1;return 0;}int SMul ()//17{if (EqulStr (ch2, IntToStr (MULTIPLY)) || EqulStr (ch2, IntToStr (DIVIDEY))){GetWord (line, ch2);return 1;}return 0;}int SFac ()//18{if (EqulStr (ch2, IntToStr (S_BRACKET_L))){GetWord (line, ch2);if (SExp ()){if (EqulStr (ch2, IntToStr (S_BRACKET_R))){GetWord (line, ch2);return 1;}else{cout << "第 " << lastline << " 行表达式后面缺少符号)!" << endl;}}elsecout << "第 " << lastline << " 行(后面缺少有效的表达式!" << endl;OK = false;return 1;}else if (EqulStr (ch2, IntToStr (NUMBER)) || EqulStr (ch2, IntToStr (IDENTIFIER))){GetWord (line, ch2);return 1;}return 0;}主函数:#include<iostream>#include<iomanip>#include<ctype.h>#include<fstream>#include<string>#include"head.h" using namespace std; int main (){Yufa2 ();system ("pause");return 0;}实验。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/****************************************************
课题名称:递归下降语法分析设计原理与实现技术
作者:房皓进修生13410801
最后修改时间:2014、4、16 13:52
***************************************************/
error1();
break;
case '5':
if(token[i]!='*')
{
switch(ch)
{
case '1':
if(token[i]!='(')
error1();
break;
case '2':
if(token[i]!=')')
error1();
break;
case '3':
if(token[i]!='+')
error1();
break;
case '4':
if(token[i]!='-')
实验中遇到的问题:
问题主要有在调用某个函数时没有在之前声明或定义过此函数;还有在当用户输入的选择方式非法时,提示错误并要求重新输入,这用一个while循环实现。
程序的自我评价:
此程序实现了要求中的所有功能,并增加了对用户操作错误、输入串错误检测的功能,但因编程能力的欠缺,其中有的地方不免有些繁杂,还有一些潜藏的问题,需要进一步测试来时程序变得更加具有健壮性。
(2)递归下降分析程序应能发现输入串出错;
(3)设计两个测试用例(尽可能完备,正确与出错),并给出测试结果。
3、
操作系统:Windows 7
软件:VC++6、0
4、
提供了两种输入方式:键盘与文件,有文件输入时需为二元式序列;
能够对输入的字符串做出正确的递归下降分析判断,并给出判断结果;
能发现输入串中的错误,包含非法字符,输入不匹配等;
单词符号及其种别码表
单词符号
种别码
单词符号
种别码
(
1
*
5
)
2
/
6
+
3
i
7
-
4
#
8
主要函数说明:
advance():将下一个字符送入current;
error():输出错误,表示不就是该文法的句子;
error1();输出错误,输入内容不合法;
init():初始化函数;
justify():判断文件读取内容就是否合法,包括检查非法字符与不匹配现象
递归下降语法分析设计原理与实现技术
实验报告
变更说明
日期
版本
变更位置
变更说明
作者
2014/4/16
1、0
初稿生成
房皓
一、
本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计与构造的基本原理与实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神与专业素养,从而提高学生发现问题、分析问题与解决问题的能力。
void E();
void E1();
void T();
void A();
void F();
void T1();
void M();
void error();
void error1();
void init()//初始化
{
current=token[i];
}
void justify(char ch,int i)//判断文件读取内容就是否合法,包括检查非法字符与不匹配现象
执行框图:
1)总体结构图:
2)递归下降分析构框图:
E():
E1():
T():
T()1:
M():
A():
F():
七、
测试用例一:i+i*i/i#
键盘:
文件:
测试用例二:i+i*i/#
键盘:
文件:
八、
实验心得:
通过本次实验我锻炼了自己的上机操作能力及编程能力,并对理论知识有了进一步的了解。老师提供的相对应于非终结符号的函数的流程图给了我很大的帮助,使得本实验基本思路变得很清晰,用较为简单的算法就能实现;解决实验中遇到的问题也花费了一部分时间,我增长了处理关于文件错误的能力;
T→FT′
T′→MFT′|ε
F→(E)|i
A→+|-
M→*|/
/***************************************************/
#include<iostream>
#include<conio、h>
using namespace std;
#define MAX 50
2、
[实验项目]
完成以下描述算术表达式的LL(1)文法的递归下降分析程序
G[E]: E→TE′
E′→ATE′|ε
T→FT′
T′→MFT′|ε
F→(E)|i
A→+|-
M→*|/
[设计说明]
终结符号i为用户定义的简单变量,即标识符的定义。
[设计要求]
(1)输入串应就是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串就是否为该文法定义的算术表达式的判断结果;
/**************************************************单词符号及其分类编码
单词符号种别码
(1
)2
+3
-4
*5
/6
i7
#8
//////////////////////////////////////////////////文法
G[E]:
E→TE′
E′→ATE′|ε
能够处理一些可预见性的错误,如文件不存在,用户输入非法等。
五、数据结构设计
全局:
局部(main()中):
六、程序结构描述
设计方法:
本程序采用从键盘输入或文件读取两种输入方式,其中文件的内容需为二元式序列,然后按照递归下降分析的方法对输入的字符串进行分析判断,并输出判断结果,程序通过对输入串的检查能够发现输入串中的错误。程序规定的单词符号及其种别码见下表:
main():主函数
函数调用关系说明:
main()调用justify()、init()、E()、e、E()、E1()、F()、M()、F()、T()、T1()根据输入串可互相调用或递归调用,这些函数均可调用error()函数;
A()、F()、M()调用advance()函数。
char token[MAX];
char token2[MAX];
char current;
int i=0;
/****************************************************
函数声明
****************************************************/