编译原理-实验二-递归下降分析程序构造

合集下载

编译原理实验报告算术表达式递归下降分析程序设计

编译原理实验报告算术表达式递归下降分析程序设计

武汉工程大学计算机科学与工程学院《编译原理》实验报告一、实验目的(1)掌握自上而下语法分析的要求与特点。

(2)掌握递归下降语法分析的基本原理和方法。

(3)掌握相应数据结构的设计方法。

二、实验内容编程实现给定算术表达式的递归下降分析器。

算术表达式文法如下: E E+T | TT T*F | FF(E) | i设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归函数,函数的名字表示规则左部的非终结符;函数体按规则右部符号串的顺序编写。

三、设计分析(1)消去该文法左递归,得到文法:E TE1E1+TE1|εT FT1T1*FT1|εF(E)| I(2)根据LL(1)文法的判断条件,计算这个文法的每个非终结符的FIRST 集和FOLLOW集,经验证,改后的文法已经是LL(1)文法。

(3)最后构造递归下降分析程序,每个函数名是相应的非终结符,函数体则是根据右部符号串的结构编写。

a.当遇到非终结符时,如:+。

则编写语句 if(当读来的输入符号 == +) 读下一个输入符号b.当遇到非终结符时,例如:T。

则编写语句调用T()。

c.当遇到非终结符ε规则时,例如:Tε。

则编写语句 if(当前读来的输入字符不属于FOLLOW(T)) error()d.当某个非终结符的规则有很多个候选式时。

按LL(1)文法的条件能唯一的选择一个候选式进行推导。

(4)递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。

因此需要分别构造E,E1,T,T1,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。

Scaner函数用于字符串的推进,input函数用于字符串的输入。

四、程序代码#include <>#include <>#include <iostream>using namespace std;char a[80];char sym;int i=0;void E();void E1();void T();elseError();}else if (sym =='i')Scaner();elseError();}五、测试用例1.输入的字符串只含有一个字符时:输入 i#a#2.输入的字符串含有 + 时:输入 ++#输入 i++#输入 i+i#3.输入的字符串含有 * 时:输入 **#输入 **i#输入 *i*#输入 i*i#i*i*#3.输入的字符串含有()时:输入()#(i)#4.输入的字符串含有多种字符:输入i+i*i#(i+i)*i#(i+i)*(i+i)#(i+*#。

编译原理 递归下降词法分析

编译原理 递归下降词法分析

编译原理实验报告—递归下降分析法程序实验2.1 递归下降分析法一、实验目的1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。

2. 本次实验的目的是加深对递归下降分析法的理解。

二、实验平台Windows + VC++6.0范例程序: “递归下降分析法.cpp ”三、实验内容对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E→TG(2)G→+TG|-TG(3)G→ε(4)T→FS(5)S→*FS|/FS(6)S→ε(7)F→(E)(8)F→i1.程序功能:输入: 一个以# 结束的符号串(包括+ - * / ()i # ):例如:i+i*i-i/i#输出:(1) 详细的分析步骤,每一步使用的产生式、已分析过的串、当前分析字符、剩余串,第一步, 产生式E->TG的第一个为非终结字符,所以不输出分析串,此时分析字符为i,剩余字符i+i*i-i/i#;第二步,由第一步的E->TG的第一个为非终结字符T,可进行对产生式T->FS 分析,此时第一个仍为非终结字符F,所以不输出分析串,分析字符仍为i, 剩余字符i+i*i-i/i#;第三步,使用产生式F->i,此时的分析串为i,,分析字符为i,匹配成功,剩余字符串+i*i-i/i#;第四步,因为使用了产生式T->FS,F->i,第一个字符i匹配成功,接着分析字符+,使用产生式S->ε,进行下步;第五步,使用产生式G->+TG,此时的分析串包含i+,分析字符为+,剩余字符串+i*i-i/i#;第六步,重复对产生式T->FS,F->i的使用,对第二个i进行匹配,此时分析串i+i,分析字符为i,剩余串*i-i/i#;第七步,分析字符*,使用产生式S->*FS, 分析串i+i*,剩余串i-i/i#;第八步,字符*匹配成功后,使用产生式F->i,匹配第三个字符i,,此时剩余串-i/i#;第九步,分析字符-,只有产生式G->-TG可以产生字符-。

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

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

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

二、实验主要内容1、文法如下:E→TE`E’→+TE’|-TE’|εT→FT`T’→*FT’|/FT’|εF→(E)|i2、求取各非终结符的First及Follow集合3、编程实现下降递归分析法,识别从键盘输入的关于整数或浮点数的算术表达式(在此,上述文法中的i代表整数或浮点数)4、对于语法错误,要指出错误具体信息。

5、运行实例如下:三、提示1、纸质实验报告内容:实验内容、非终结符的First及Follow集合、正确表达式与错误表达式各举一例进行测试并给出结果、核心源代码。

2、将本次实验代码(.c、.cpp、.java等代码文件,删除编译产生的所有其他文件,不要打包)在规定时间内以作业附件(不可在线编辑、粘贴代码)的形式提交至网站,自己保存以备课程设计(本部有毕业设计要求的学生)参考。

3、纸质实验报告提交时间:临时要求。

实验指导(参考)一、实验步骤1、求取各非终结符的First及Follow集合;2、设计几个函数E(); Ep(); T(); Tp(); F();运用First集合进行递归函数选择,运用Follow集合进行出错情况判断;3、设计主函数:从键盘接受一个算术表达式串;在串尾添加尾部标志’#’;调用函数E()进行递归下降分析。

二、如何识别整数与浮点数在函数F()中要涉及到如何识别整数与浮点数。

识别的方法是:只要碰到‘0’~‘9’之间的字符就一直循环,循环到不是数字字符与小数点字符’.’为止,其间要运用一个标志变量来保证最多只能出现一个小数点,否则应该报错。

上述循环结束即表示识别了一个数,也即表达式文法中的i。

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

递归下降分析器设计一、实验/实习过程内容:利用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基本的使用。

编译原理递归下降

编译原理递归下降

《编译原理》课程实验实验二:自顶向下的语法分析:递归下降法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("缺少值或变量。

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

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

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

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

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

步骤:1.看书,找资料,了解语法分析器的工作过程与原理2.分析题目,列出基本的设计思路1定义栈,进栈,出栈函数○2栈为空时的处理○3构造函数判断文法是否是算符文法,算符优先文法○4构造FirstVT和LastVT函数对文法的非终结符进行分析○5是算符优先文法时,构造函数对其可以进行输入待规约○串,输出规约结果○6构造主函数,对过程进行分析3.上机实践编码,将设计的思路转换成C++语言编码,编译运行4.测试,输入不同的文法,观察运行结果详细的算法描述详细设计伪代码如下:首先要声明变量,然后定义各个函数1.void Initstack(charstack &amp;s){//定义栈s.base=new charLode[20];s.top=-1; }2. void push(charstack&amp;s,charLode w){//字符进栈s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}3. void pop(charstack&amp;s,charLode &amp;w){//字符出栈w.E=s.base[s.top].E; 三、w.e=s.base[s.top].e;s.top--;}4. int IsEmpty(charstack s){//判断栈是否为空if(s.top==-1)return 1;else return 0;}5.int IsLetter(char ch){//判断是否为非终结符if(ch=&#39;A&#39;&amp;&amp;ch= &#39;Z&#39;)return 1;else return 0;}6.int judge1(int n){ //judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法}7. void judge2(int n){//judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法8.int search1(char r[],int kk,char a){ //search1是查看存放终结符的数组r中是否含有重复的终结符}9.void createF(int n){ //createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体}10.void search(charLode w){ //search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1 }分情况讨论://产生式的后选式的第一个字符就是终结符的情况//产生式的后选式的第一个字符是非终结符的情况11.void LastVT(int n){//求LastVT}12.void FirstVT(int n){//求FirstVT}13.void createYXB(int n){//构造优先表分情况讨论://优先级等于的情况,用1值表示等于}//优先级小于的情况,用2值表示小于//优先级大于的情况,用3值表示大于}14.int judge3(char s,char a){//judge3是用来返回在归约过程中两个非终结符相比较的值}15.void print(char s[],charSTR[][20],int q,int u,int ii,int k){//打印归约的过程}16. void process(char STR[][20],int ii){//对输入的字符串进行归约的过程}四、设计结果分两大类,四种不同的情况第一类情况:产生式的候选式以终结符开始候选式以终结符开始经过存在递归式的非终结符后再以终结符结束篇二:编译原理递归下降子程序北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx_作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。

编译原理实验二递归下降子程序

编译原理实验二递归下降子程序

根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。

#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]。

编译原理实验(二)

编译原理实验(二)

实验编号:语法分析(2)一、实验目的及要求编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

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

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

例如:输入begin a:=9; x:=2*3; b:=a+x end # 输出success!输入x:=a+b*c end # 输出error二、实验环境Microsoft Visual Studio VC6.0三、算法描述(1)主程序示意图如图2-1所示。

”-1 •: 结束图2-1语法分析主程序示意图(2) 递归下降分析程序示意图如图 2-2所示。

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

调用expression 函数否是 否 是否是否调用语句串分析程序是 否出错处理否syn=O&&kk=O ?是打印分析成功出错处理否否否是2调用term 函数调用statement 函数调用statement 函数调用scaner调用scaner调用scaner 调用scaner图2-2 (4)statement 语 图2-3语句串分析示意图是否:=?是否+ , -?递归下降分析程序示意图J 分析程序流程如图 2-4、2-5、2-6、2-7所示。

1是调用scaner是否end?调用s caner是否标识符?#i nclude"stdio.h"#in elude "stri ng.h" char prog[100],toke n[ 8],ch; char *rwtab [6]={"begi n","if',"the n" ,"while","do","e nd"};int syn ,p,m, n,sum;调用term函数出错处理图2-4 statement语句分析函数示意图出错处理图2-5 expression表达式分析函数示意图四、源程序清单-3 •-4 •int kk;factor();〃 因子 expressio n();〃 表达式judgue();〃 判断语句、下一条语句 term();〃 项stateme nt();〃 赋值语句 lrparser();〃 判断、输出函数 scan er();〃 读下一个字符 yucu();void mai n(){ p=0;printf(- 请输入源程序:\n"); do {scan f("%c",&ch); prog[p++]=ch; }while(ch!='#'); p=0; sca ner(); lrparser(); prin tf(" 语法分析结束! \n");lrparser() {printf(" *********************语法分析程序 ************* **\n");if (syn==1) //begi n{sca ner();yucu();if (syn==6) //end{sca ner();if (sy n==O && kk==O)prin tf("success \n");}else{if(kk!=1)prin tf("error,lose 'end' !\n"); kk=1;}}else{prin tf("error,lose 'beg in' ! \n");kk=1;return 0;}yucu()• 5 •{stateme nt();while(sy n==26) //;{sca ner();stateme nt();}return 0;}stateme nt(){if (sy n==10){sca ner();if (syn==18){sca ner();expressi on();}else{prin tf("error!"); -6 •kk=1;}}else{prin tf("error!");kk=1;}return 0;}expressi on(){term();while(s yn==13 || syn==14){sca ner();term();}return 0;}term(){factor();while(s yn==15 || syn==16)sea ner();factor();-7 •}return 0;}factor(){if(syn==10 || syn==11)scan er(); // 为标识符或整常数时,读下一个单词符号else if(syn==27){sca ner();expressi on();if(sy n==28)sca ner();else{printf("')' 错误\n"); kk=1;}}else{printf(" 表达式错误\n"); kk=1;}return 0;sea ner(){ sum=O;• 8 •for(m=0;m<8;m++)toke n[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'))){toke n[ m++]=ch;ch=prog[p++];}p--;sy n=10;toke n[m++]='\0';for(n=0;n<6;n++)if(strcmp(toke n,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;-9 •}else switch(ch){ case 'v':m=O; ch=prog[p++]; if(ch=='>'){ syn=21;}else if(ch=='='){ sy n=22;}else{ sy n=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;-10 •}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;}return 0;-11 •五、运行结果及分析输入begin a:=9;x:=2*3;b:二a+x end # 输出successerror输入x:=a+b*c end # 输出-12 •。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

集美大学计算机工程学院实验报告
课程名称:编译原理
指导教师:付永钢 实验成绩: 实验编号: 实验二
实验名称:递归下降分析程序构造
班级:计算12
姓名: 学号: 上机实践日期:2014.11
上机实践时间: 4学时
一、实验目的
通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。

通过本实验,应达到以下目标:
(1) 掌握从源程序文件中读取有效字符的方法和产生源程序内部表示文件的方法;
(2)掌握语法分析的实现方法;
(3)上机调试编出的语法分析程序。

二、实验环境
Windows7 x64、VC6.0
三、实验原理
递归下降法是语法分析中最易懂的一种方法。

它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。

因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。

其中子程序的结构与产生式结构几乎是一致的。

递归下降分析程序的实现思想是:识别程序由一组子程序组成。

每个子程序对应于一个非终结符号。

每一个子程序的功能是:选择正确的右部,扫描完相应的字。

在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。

自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。

分析速度慢。

而无回溯的自上向下分析技术,可根据输入串的当前符号以及各产生式右部首符,选择某非终结符的产生式,效率高,且不易出错。

无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。

即:假设A 的全部产生式为A →α1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式
First(A →αi )∩First (A →αj )=Φ,当i≠j.
无左递归:既没有直接左递归,也没有间接左递归。

无回溯:对于人以非中介符号U 的产生式右部n x x x |...||21,其对应的字的首终结符号两两不相交。

如果一个文法不含回路(形如P P +⇒的推导),也不含以ε为右部的产生式,那么可以通过执行消除左递归的算法消除文法的一切左递归。

四、实验内容
完成以下描述算术表达式的LL(1)文法的递归下降分析程序构造
G[E]:
E →TE ′
E ′→+TE ′|ε
T →FT ′
T′→*FT′|ε
F→(E)|i
说明:终结符号i为用户定义的简单变量,即标识符的定义。

要求具有如下功能:
1)从文件读入算术表达式/或者从终端输入
2)总控函数分析算术表达式;
3)根据分析结果正误,分别给出不同信息
五、实验步骤
1、分析文法,该文法无左递归,无回溯。

2、设计程序,采用递归下降分析法形象描述递归子程序。

程序中将要用到的几个重要数据如下:全局变量ch,存放由文件输入得到的字符。

五个子函数:E( )、
E1( )、T( )、T1( )、F( );
3、在VC6.0环境下编写程序(程序见附录)
六、实验结果
(1)输入文本:
测试结果:
(2)输入文本:
测试结果:
(3)输入文本:
测试结果:
六、实验小结
1、在本次实验中,通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握了常用的语法分析方法;
2、通过本次实验,对递归下降分析程序的构造和设计有了更为全面的认识,对LL(1)文法分析程序的实现有了进一步了解;
3、实验开始,由于没有读懂题意,把主要精力放在词法错误的分析上,对语法错误的分析不够全面,通过调试和改进,最终实现了LL(1)文法语法错误的判别;
4、通过本次实验发现,本次实验中LL(1)文法分析程序还是不够完善的,比如识别到‘(’时,必须找到‘)’,无法判别多输入‘(’产生的错误,将所有输入的‘(’认为是合法的。

附录:程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE *fp;
char ch;
#define N 20
char string[N];
char *p;
int re;
int n=1;
void E();
void T();
void E1();
void F();
void T1();
void F(){
if(ch=='i'){
printf("F--->i %c\n",ch);
*p=ch;
p++;
n++;
ch=fgetc(fp);
}
else if (ch=='('){
printf("F--->(E) %c\n",ch);
*p=ch;
p++;
ch=fgetc(fp);
n++;
E();
while(ch==EOF||ch!=')'){
printf("(%d)error:never find ')'\n",n);
if(ch==EOF)
break;
ch=fgetc(fp);
n++;
re=0;
}
if(ch==')'){
printf("F--->(E) %c\n",ch);
*p=ch;
p++;
ch=fgetc(fp);
n++;
}
}
else{
printf("(%d)error:never find 'i' or '('\n",n);
ch=fgetc(fp);
n++;
F();
}
}
void E1()
{
if (ch=='+'){
printf("E1--->+TE1 %c\n",ch);
*p=ch;
p++;
ch=fgetc(fp);
n++;
T();
E1();
}
else
printf("E1--->ε %c\n",ch);
}
void T()
{
printf("T--->FT1 %c\n",ch);
F();
T1();
}
void T1()
{
if(ch=='*'){
printf("T1--->*FT1 %c\n",ch);
*p=ch;
p++;
ch=fgetc(fp);
n++;
F();
T1();
}
else
printf("T1--->ε %c\n",ch);
}
void E(){
printf("E--->TE1 %c\n",ch);
T();
E1();
}
void main(){
if((fp=fopen("D:\\学习相关\\编译原理\\第二部分实验内容\\test.txt","r"))==NULL){
fprintf(stderr,"error opening.\n");
exit(0);
}
ch=fgetc(fp);
p=string;
printf("递归下降分析所用产生式:\n");
E();
if(re==1){
*p=ch;
printf("算式匹配成功!\n 算式结果:%s\n",string);
}
else
printf("算式匹配不成功!\n");
fclose(fp);
}。

相关文档
最新文档