实验二递归下降分析法实验报告

合集下载

编译原理实验报告——实验二 递归下降分析

编译原理实验报告——实验二  递归下降分析
if(sym=='*') {
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基本的使用。

实验2 递归下降分析器设计与实现

实验2 递归下降分析器设计与实现
实验二 递归下降语法分析器设 计与实现
一、实验目的
• 掌握自上而下语法分析的思想 • 掌握递归下降分析法的原理和方法
二、实验内容ቤተ መጻሕፍቲ ባይዱ
• 在实验一已经实现的词法分析器的基础上 设计递归下降语法分析子程序 • 可以自选语法分析的语句,比如赋值语句, 算术表达式,条件语句等 • 实现某一种语句的分析即可
三、实验要求
• • • • • • • • • 先确定要进行语法分析的语句 给出语句的文法 确定文法是否为LL(1)文法,不是请先改造 计算各条产生式的select集合 设计详细的流程图 构造递归下降子程序 要求思路清晰,源码有必要的注释 给出各种不同测试数据和测试结果 给出详细的使用说明

编译原理-实验报告2-递归下降分析法

编译原理-实验报告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输出的格式如下:(1)递归下降分析程序,编制人:姓名,学号,班级(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串例如:i+i*i#(3)输出结果:i+i*i#为合法符号串备注:输入一符号串如i+i*#,要求输出为“非法的符号串”。

注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);三、实验过程:程序设计:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。

2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。

程序编写:1.定义部分:定义常量、变量、数据结构。

2.初始化:从文件将输入符号串输入到字符缓冲区中。

3.利用递归下降分析法,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。

四、实验结果(1)程序流程图(2)运行结果示例程序:#include <>#include<>#include<>#include<>char a[50] ,b[50],d[500],e[10];char ch;int n1,i1=0,flag=1,n=5;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();void main() /*递归分析*/{int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';printf("递归下降分析程序,编制人:武普泉,20号,1020562班\n");printf("输入一以#结束的符号串(包括+ - * / ( ) i #,且长度小于50):");do{scanf("%c",&ch);a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];printf("文法\t分析串\t\t\t分析字符\t\t剩余串\n");f=E1();if(f==0) return ;if (ch=='#'){ printf("accept\n");p=0;x=d[p];// {// printf("%c",x);p=p+1;x=d[p]; /*输出推导式*/ // }while(a[p]!='#')printf("%c",a[p++]);printf("为合法字符!\n");}else {// printf("error\n");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");printf("回车返回\n");getchar();getchar();return;}printf("\n");printf("回车返回\n");getchar();getchar();}int E1(){ int f,t;printf("E-->TG\t");flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int E(){ int f,t;printf("E-->TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#';output();flag=1;input();input1();f=T();if (f==0)return(0);t=G();if (t==0) return(0);else return(1);}int T(){ int f,t;printf("T-->FS\t");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);}int G(){int f;if(ch=='+'){b[i1]=ch;printf("G-->+TG\t");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);f=G();if(f==0)return 0;else return 1;}else if(ch=='-'){b[i1]=ch;printf("G-->-TG\t");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){// printf("G=%d\n",f);return(0);}f=G();if(f==0)return 0;else return 1;}else{printf("G-->^\t");e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;input();input1();return(1);}}int S(){int f,t;if(ch=='*'){b[i1]=ch;printf("S-->*FS\t");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);}else if(ch=='/'){b[i1]=ch;printf("S-->/FS\t");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);}else{printf("S-->^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}}int F(){ int f;int j;if(ch=='('){b[i1]=ch;printf("F-->(E)\t");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;printf("F-->(E)\t");flag=0;input();input1();ch=a[++i1];}else{printf("error\n");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");return(0);}}else if(ch=='i'){b[i1]=ch;printf("F-->i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {printf("error\n");j=0;while(a[j]!='#')printf("%c",a[j++]);printf("非法字符!\n");return(0);}return(1);}void input(){int j=0;for (;j<=i1-flag;j++)printf("%c",b[j]); /*输出分析串*/printf("\t\t\t");printf("%c\t\t\t",ch); /*输出分析字符*/ }void input1(){int j;for (j=i1+1-flag;j<n1;j++)printf("%c",a[j]); /*输出剩余字符*/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]='#';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]='#';}。

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

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

编译原理-实验⼆-递归下降分析程序构造集美⼤学计算机⼯程学院实验报告课程名称:编译原理指导教师:付永钢实验成绩:实验编号:实验⼆实验名称:递归下降分析程序构造班级:计算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,其对应的字的⾸终结符号两两不相交。

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

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

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

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

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

输入:源符号串。

输出:语法是否合法。

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

递归下降程序实验报告

递归下降程序实验报告

一、实验目的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)

编译原理实验报告二递归下降语法分析程序 (1)

编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期:201 年 5 月 25 日一、实验目的通过设计、调试递归下降语法分析程序,实现用词法分析从源程序中分出各种单词并对词法分析程序提供的单词序列进行语法检查和结构分析,熟悉并掌握常用的语法分析方法。

明确语法分析器的功能,在词法分析的基础上进一步分析程序;加深对课堂教学的理解;提高语法分析方法的实践能力;通过本实验,应达到以下目标:1、掌握递归下降的结构模型。

2、掌握语法分析的实现方法。

3、上机调试编出的语法分析程序。

二、实验过程有了第一次的经验,这次还是先画出流程图。

流程图如下:三、实验结果语法分析实验成功。

赋值时少写数字:缺少括号时:附(txt文档内容):程序运行后写入的:四、讨论与分析这个程序是在实验一的基础上写的,用的递归下降的方法。

不止能识别,还能判断一些语法的正误。

刚看书上附录的代码时,头都大了,觉得自己完成不了。

但是真正一步一步看下去,画出了流程图,就很清晰明白了。

一个函数嵌套一个函数,一步一步往细处走,刚开始是大体轮廓,然后就深入,直到最低层的判断。

书上的程序还是有一些漏洞,比如要写多个语句时,if,for,while在语句内不能加括号,不然只能分析至第一个,遇到“}”就结束了,所以在txt文件里写程序代码的时候要注意不能加{},这样才可以全部printf出来。

五、附录:关键代码(给出适当注释,可读性高)全部代码附vc++,这里粘贴主程序,以及各类函数。

int TESTparse();int TESTscan();int program();int compound_stat();int statement();int expression_stat();int expression();int bool_expr();int additive_expr();int term();int factor();int if_stat();int while_stat();int for_stat();int write_stat();int read_stat();int declaration_stat();int declaration_list();int statement_list();int compound_stat();#include<stdio.h>#include<ctype.h>int TESTscan();int TESTparse();FILE *fin,*fout;void main(){int es=0;es=TESTscan();if(es>0)printf("词法分析有错!编译停止!\n");else{printf("词法分析成功!\n");}if(es==0){es=TESTparse();if(es==0)printf("语法分析成功!\n");elseprintf("语法分析错误!\n");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。

递归下降分析实验报告

递归下降分析实验报告

一、实验目的通过本次实验,加深对递归下降分析法的理解,掌握递归下降分析法的原理和应用,并能够根据给定的文法编写相应的递归下降分析程序。

二、实验原理递归下降分析法是一种自顶向下的语法分析方法,它将文法中的每个非终结符对应一个递归过程(函数),分析过程就是从文法开始符触发执行一组递归过程(函数),向下推到直到推出句子。

递归下降分析法的前提是文法应满足以下条件: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. 实验分析通过本次实验,我们深入了解了递归下降分析法的原理和应用。

在编写递归下降分析程序的过程中,我们学会了如何根据文法设计程序结构,以及如何实现分析过程。

同时,我们还掌握了如何对输入的符号串进行分析,并输出分析结果。

实验过程中,我们遇到了一些问题,如消除二义性、消除左递归、提取左因子等。

通过查阅资料和不断尝试,我们成功解决了这些问题。

实验二_递归下降分析器设计报告

实验二_递归下降分析器设计报告

递归下降分析器设计1、实验目的:(1)掌握自上而下语法分析的要求与特点。

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

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

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

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

4、设计分析这个题目属于比较典型的递归下降语法分析。

需要先将原算术表达式方法改写为LL(1)文法为:E-->TE'E'-->+TE'|εT-->FT'T'-->*FT'|εF-->(E)|i然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。

具体方法为:(1)当遇到终结符a时,则编写语句If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到非终结符A时,则编写语句调用A()。

(3)当遇到A-->ε规则时,则编写语句If(当前读到的输入符号不属于Follow(A))error()(4)当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能唯一地选择一个候选式进行推导.//源程序代码#include<iostream>#include<string>using namespace std;void E();void E1();void T();void T1();void F();string s;int i;int ERR;int SwitchNum;int main(){do{s="";i=0;ERR=0;cout<<"Please enter your sentence:"<<endl; cin>>s;s.resize(s.size()+1);s[s.size()-1]='#';E();if(s[i]=='#')cout<<"success"<<endl;elsecout<<endl;cout<<"输入一个整数继续,其它类型退出:";}while(cin>>SwitchNum);return 0;}void E(){if(ERR==0){T();E1();}}void E1(){if(ERR==0){if(s[i]=='+'){++i;T();E1();}else if(s[i]!='#'&&s[i]!=')'){cout<<"fail"<<endl;ERR=1;}}void T(){if(ERR==0){F();T1();}}void T1(){if(ERR==0){if(s[i]=='*'){++i;F();T1();}else if(s[i]!='#'&&s[i]!=')'&&s[i]!='+') {cout<<"fail"<<endl;ERR=1;}}}void F(){if(ERR==0){if(s[i]=='('){++i;E();if(s[i]==')')++i;else if(s[i]== '#'){cout<<"fail"<<endl;ERR=1;++i;}}else if(s[i]=='i')++i;{cout<<"fail"<<endl;ERR=1;}}}测试用例(1)输入i,预期显示success(2)输入iii,预期显示fail(3)输入a,预期显示fail(4)输入(i),预期显示success(5)输入(a),预期显示fail(6)输入(i+i),预期显示success (7)输入(i+i,预期显示fail(8)输入((i*i)+i)*i,预期显示success (9)输入((((i+i*i)))),预期显示success (10)输入(i+ia,预期显示fail(11)输入i+i*i+i*a,预期显示fail。

实验2 递归下降语法分析

实验2 递归下降语法分析

实验二递归下降语法分析一、实验目的构造文法的语法分析程序,要求采用递归下降语法分析方法对输入的字符串进行语法分析,进一步掌握递归下降的语法分析方法。

二、实验内容编写为一上下文无关文法(文法如下)构造其递归下降语法分析程序,并对任给的一个输入串进行语法分析检查。

程序要求能对输入串进行递归下降语法分析,能判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。

E-->E+T|TT-->T*F|FF-->(E)|i三、实验参考:算法思想为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。

由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。

在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。

语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。

也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。

出错时,可以根据读字符的位置判断出错的位置。

四、实验说明:1.时间安排:安排在“词法分析”后。

2.实验环境:WINDOWS下,工具为Visual C++ 6.0五、上交:程序源代码;已经测试通过的3组数据(全部存在一个文本文件test1.txt中,以“第一组输入/输出;第二组输入/输出;第三组输入/输出”的顺序存放);实验报告:实验结果和分析中应包括:(1)功能描述:该程序具有什么功能?(2)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;另外可以附加函数之间的调用关系图、程序总体执行流程图(参考课本第二章)。

(3)实验总结:你在编程过程中花时多少?多少时间在纸上设计?多少时间上机编程和调试?多少时间在思考问题?遇到了哪些难题?你是怎么克服的?你对你的程序的评价?你的收获有哪些?。

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

语法分析-递归下降分析法
char *rwtab[6]={"begin","if","then","while","do","end"};//关键字
void scaner();//扫描函数
void factor();//因子
void term();//项
void expression();//表达式
void statement();//语句
else
{
cout<<"错误,表达式缺乏')'"<<endl;
kk=1;
}
}
else
{
cout<<"表达式错误,表达式开头不是'('"<<endl;
kk=1;
}
return;
}
//项
void term()
{
factor();
//问题---补充判断条件
while(syn==15 || syn==16)//当开头扫描的是'*'或'/'时,继续扫描
{
scaner();
factor();
}
return;
}
//表达式
void expression()
{
//问题---补充程序代码
term();
while(syn==14 || syn==13)//当开头扫描的是'+'或'-'时,继续扫描
{
scaner();
term();
}
return;
}

递归下降分析算法

递归下降分析算法

数学与计算机学院编译原理实验报告年级09软工学号姓名成绩专业软件工程实验地点主楼指导教师湛燕实验项目递归下降分析算法实验日期2012.6.10一、实验目的和要求使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。

重点和难点:本实验的重点是理解自顶向下分析方法的原理;难点是如何把文法改写成EBNF形式。

二、实验内容1、使用递归下降分析算法分析表达式文法:exp ::= expaddop term | termaddop ::= + | -term ::= term mulop factor | factormulop ::= * | /factor ::= (exp) | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到number的值。

2、该词法分析器以子程序形式出现,当需要进行词法分析时进行调用;3、能够识别正确和错误的表达式;4、在进行语法分析的过程中,计算输入表达式的值。

三、程序设计主要变量有:boolIsDigit(char ch);//判断字符是否是数字static string s;//staticinti=0;//staticint flag=0;//staticint result;//主要函数有:staticintexp();//staticint exp1(int temp);//staticint term();//staticint term1(int temp);//staticint factor();//static intReadNum();//提取数字递归下降的主要原理是:对每个非终结符按其产生结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。

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

五、代码和截图自己写程序如下:#include<stdio.h>#include<conio.h>#include<cstdlib>#include<string>#include <iostream>#include <fstream>#include <stdlib.h>using namespace std;staticintexp();staticint exp1(int temp);staticint term();staticint term1(int temp);staticint factor();staticintReadNum();boolIsDigit(char ch);static string s;staticinti=0;staticint flag=0;staticint result;int main(){cout<<"请输入一个语句,以“#”结束,输入“#”退出"<<endl;while(1){cin>>s;s+='#';if(s[0]=='#')return 0;result = exp();if (flag == 0){cout<<"结果是"<<endl<<result<<endl;}}return 1;}staticboolIsDigit(char ch){if (ch>= 48 &&ch<= 57)return true;elsereturn false;}staticintReadNum(){int add = 0;stringstr = "";while (s[i]!= '#'){if (s[i] == '+'||s[i] =='-'||s[i]=='*'||s[i]=='/'||s[i]==')'){break;}else if (s[i]>= 48&&s[i]<=57){str +=s[i];}else{flag= 1;cout<<"输入了错误的字符!"<<endl;return -1;}i++;}str += "!";int n = 0;while (str[n] != '!'){cout<<str<<"(数字)"<<endl;n++;}int m = 0;while (str[m] != '!'){add += (int)(str[m] - 48);add *= 10;m++;}add = add / 10; cout<<add<<endl;return add;}staticintexp(){int temp;temp = term();temp = exp1(temp);return temp;}staticint exp1(int temp) {if(s[i]=='+'){++i;temp += term(); temp = exp1(temp);}else if(s[i]=='-'){++i;temp -= term(); temp = exp1(temp);}return temp;}staticint term(){int temp;temp = factor();temp = term1(temp); return temp;}staticint term1(int temp) {if(s[i]=='*'){++i;temp *= factor();temp = term1(temp);}else if(s[i]=='/'){++i;temp /= factor();temp = term1(temp);}return temp;}staticint factor(){int temp = 0;if (IsDigit(s[i])){temp = ReadNum();}else if(s[i]=='('){++i;temp=exp();if(s[i]==')')++i;else{flag = 1;cout<<"缺少右括号!"<<endl;}}else{flag = 1;cout<<"请输入正确的格式!"<<endl;}return temp;}输入的句子不正确时,提示,如下图:输入了正确的句子后,分析如下图:。

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

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

一、实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。

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

信息商务学院实验报告
课程:编译原理
实验名称:递归下降分析
学号: ************
*名:***
指导老师:***
日期: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 20
char 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();
}
else
printf("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();
}
else
printf("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所示。

测试数据二:D盘的一个名为ceshi.txt的文本文件里输入字符串:(*i)+i,运行结果如图2所示。

图1 匹配失败
图2 匹配成功
四、实验总结
本实验是为了完成字符串的分析,判断字符串能否通过一个固定的文法推导出来,正好是对课程里学到的理论进行实践的一个机会。

本程序的实现代码在书本里以及给出了一部分,他的原理也不难理解,老师在实验要求里也给出了一部分代码,所以,此程序做起来还是很容易的,下面就来说说现实方法。

本程序的关键在于函数的递归调用,所以,在程序前面需要对文法中所涉及到的非终结符对应的函数进行声明,以免在用到的时候提示函数无声明的错误提示,程序从开始符E开始,根据文法,E可以推出T和G,就在函数E()中调用T()和G(),其他的也是类似。

这属于文法中只涉及到非终结符,遇到有终结符的情况则不同,想函数G(),因为G可以推出+TG或者-TG,所以在函数G()中,要分两种情况,先判断当前的字符是否是+,是则调用T()和G(),如果当前字符为-,就调用T()和G(),否则就是ε字符。

除了这两种情况,还有一种情况,像语法F→(E),他不仅在非终结符前有终结符,在非终结符后面也有终结符,所以F()写起来就比较复杂,在判断“(”之后条用E(),再写判断如果当前字符不是“)”就输出提示信息说明字符串不合法。

按照这种方法,把文法所涉及到的非终结符都写成对应的函数,并正确调用其他函数。

等所有的函数都描述之后就在mian()里判断当前字符是否分析到结束符#,是则说明此字符串是合法字符,否则说明此字符串为不合法字符。

Mian()函数里除了这些还要有文件的打开和关
闭以及对开始符E的函数E()的调用,以及对文件中字符串的字符流的处理,要保证判断一个字符之后要把指针指向下一个字符,所以在每个函数调用里也需要一一重复这样功能的代码,以保证程序的正确运行。

总的来时程序比较简单,代码写完调试了几下就达到了要求,中间也没出现大的错误,所以本报告里没有写调试错误这一部分。

做完实现觉得这种程序还挺有意思的,希望在以后的学习中能有更多的这样的机会,以培养我的兴趣爱好。

相关文档
最新文档