编译原理实验报告二 递归下降语法分析程序
编译原理实验报告——实验二 递归下降分析
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{
编译原理 递归下降词法分析
编译原理实验报告—递归下降分析法程序实验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("缺少值或变量。
编译原理-实验报告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]='#';}。
编译原理实验二递归下降子程序
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
#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]。
编译原理语法分析实验报告
语法分析实验报告实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1 待分析的简单语言的语法用扩充的BNF表示如下:1)<程序>::=begin<语句串>end2)<语句串>::=<语句>{;<语句>}3)<语句>::=<赋值语句>4)<赋值语句>::=ID:=<表达式>5)<表达式>::=<项>{+<项> | -<项>}6)<项>::=<因子>{*<因子> | /<因子>7)<因子>::=ID | NUM | (<表达式>)2.2 实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
例如:输入 begin a:=9; x:=2*3; b:=a+x end #输出语法分析成功输入 x:=a+b*c end #输出语法分析2.3 语法分析程序的酸法思想1)主程序示意图如图2-1所示。
图2-1 语法分析主程序示意图2)递归下降分析程序示意图如图2-2所示。
3)语句串分析过程示意图如图2-3所示。
图2-2 递归下降分析程序示意图图2-3 语句串分析示意图4)statement语句分析程序流程如图2-4、2-5、2-6、2-7所示。
图2-4 statement语句分析函数示意图图2-5 expression表达式分析函数示意图图 2-6 term分析函数示意图图2-7 factor 分析过程示意图三、语法分析程序的C 语言程序源代码#include <stdio.h>#include <stdlib.h>#include <string.h>char prog[100],ch,token[8];int p=0,syn,n,i;char *keyword[6]={"begin","then","if","while","do","end"};void scaner();void Irparse();void statement();void expression_r();void term();void factor();void main(){int select=-1;p=0;printf("please input sentence, end of '#' !\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;printf("请输入1 或 2 \n 1.词法分析\n 2.语法分析\n");scanf("%d",&select);if(select==1){do{scaner();switch(syn){case -1:printf("词法分析出错\n");break;default :printf("<%d,%s>\n",syn,token);break; }}while(syn!=0);printf("词法分析成功\n");}else if(select==2){scaner();if(syn==1){Irparse();}//beginelse{printf("语法分析出错! 请检查begin关键字\n");return;} if(syn==6)//end{scaner();if(syn==0){printf("恭喜语法分析成功\n");}else{printf("语法分析出错! 请检查是否缺少'#'\n");} }else{printf("语法分析出错! 请检查是否缺少'end'\n");}}getchar();}void scaner(){for(n=0;n<8;n++){token[n]='\0';}n=0;ch=prog[p++];while(ch==' '){ch=prog[p++];}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){do{token[n++]=ch;ch=prog[p++];}while((ch>='a'&&ch<='z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch <='9'));syn=10;for(n=0;n<6;n++){if(strcmp(token,keyword[n])==0){syn=n+1;}}p--;//return;}else if(ch>='0'&&ch<='9'){p--;do{token[n++]=prog[p++];ch=prog[p];}while(ch>='0'&&ch<='9');syn=11;return;}else{//ch=prog[p++];switch(ch){case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ':':syn=17;token[0]=ch;ch=prog[p++];if(ch=='='){token[1]=ch;syn++;}else p--;break;case '<':syn=20;token[0]=ch;ch=prog[p++];if(ch=='>'){token[1]=ch;syn++;}else if(ch=='='){token[1]=ch;syn=syn+2;} else p--;break;case '>':syn=23;token[0]=ch;ch=prog[p++];if(ch=='='){token[1]=ch;syn++;}else p--;break;case '=':syn=25;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default: printf("词法分析出错! 请检查是否输入非法字符\n");syn=-1;break;}//return;}}void Irparse(){scaner();statement();while(syn==26)//;{scaner();statement();}}void statement(){if(syn==10){scaner();if(syn==18){scaner();expression_r();}else{printf("语法分析出错! 请检查表达式是否正确\n");return;}}else{printf("语法分析出错! 请检查语句是否正确\n");return; }}void expression_r(){term();while(syn==13||syn==14)//+ -{scaner();term();}}void term(){factor();while(syn==15||syn==16)//* /{scaner();factor();}}void factor(){if(syn==10||syn==11){scaner();}else if(syn==27){scaner();expression_r();if(syn==28){scaner();}else {printf("语法分析出错! 请检查是否缺少')'\n");return;}}else {printf("语法分析出错! 请检查是否输入非法字符\n");return;}}四、程序测试结果1)开始调试的界面2)对源程序begin a:=9; x:=2*3; b:=a+x end #的源文件,经过语法分析后如下图4-1所示:图 4-1 正确结果输出3)对源程序x:=a+b*c end #的源文件,经过语法分析后如下图4-2所示:图 4-2 错误结果输出五、总结通过对语法分析程序的设计和编写,使自己获得了很大的收获,并且使自己对语法分析程序的功能有了更进一步认识。
编译原理之递归下降语法分析程序(实验)
编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤C语⾔编制递归下降分析程序,并对简单语⾔进⾏语法分析。
编制⼀个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
⼆、实验原理每个⾮终结符都对应⼀个⼦程序。
该⼦程序根据下⼀个输⼊符号(SELECT集)来确定按照哪⼀个产⽣式进⾏处理,再根据该产⽣式的右端:每遇到⼀个终结符,则判断当前读⼊的单词是否与该终结符相匹配,若匹配,再读取下⼀个单词继续分析;不匹配,则进⾏出错处理每遇到⼀个⾮终结符,则调⽤相应的⼦程序三、实验要求说明输⼊单词串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:输⼊begin a:=9;b:=2;c:=a+b;b:=a+c end #输出success输⼊a:=9;b:=2;c:=a+b;b:=a+c end #输出‘end' error四、实验步骤1.待分析的语⾔的语法(参考P90)2.将其改为⽂法表⽰,⾄少包含–语句–条件–表达式E -> E+T | TT -> T*F | FF -> (E) | i3. 消除其左递归E -> TE'E' -> +TE' | εT -> FT'T' -> *FT' | εF -> (E) | i4. 提取公共左因⼦5. SELECT集计算SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *}SELECT(E'->+TE')=FIRST(+TE')={+}SELECT(E'->ε)=follow(E')=follow(E)={#, )}SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i}SELECT(T'->*FT')=FRIST(*FT')={*}SELECT(T'->ε)=follow(T')=follow(T)={#, ), +}SELECT(F->(E))=FRIST((E)) ={(}SELECT(F->i)=FRIST(i) ={i}6. LL(1)⽂法判断 其中SELECT(E'->+TE')与SELECT(E'->ε)互不相交,SELECT(T'->*FT')与SELECT(T'->ε)互不相交,SELECT(F->(E))与SELECT(F->i)互不相交,故原⽂法为LL(1)⽂法。
递归下降程序实验报告
一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
编译原理实验报告二递归下降语法分析程序 (1)
编译原理实验报告实验名称:编写递归下降语法分析程序实验类型:验证型实验指导教师:专业班级:姓名:学号:电子邮件:实验地点:实验成绩:日期: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");}}六、实验者自评这个实验比第一个有难度,是在第一个完成的基础上进行的。
编译原理实验报告:实验二编写递归下降语法分析程序
编译原理实验报告实验名称:实验二编写递归下降语法分析器实验类型:验证型实验指导教师:何中胜专业班级:13软件四姓名:丁越学号:电子邮箱:实验地点:秋白楼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( )函数。
编译原理实验(递归向下语法分析法实验)
//定义一个数组大小常量
char string[N];
//定义一个用于存储算式字符串的数组
char *p;
//定义一个全局字符指针变量
函数说明:
1) 非终结符函数 E()
函数功能描述:根据以上文法要求 E->TG,所以从主函数开始调入第一个非终结符函数
执行,显示调用产生式,依次嵌套调用非终结符函数 T()和 G(),进行递归向下分析。
void E(){printf("E--->TG..............%c\n",ch);
T();
G();}
2) 非终结符函数 T()
函数功能描述:根据以上文法要求 T->FS,首先显示算式匹配所用的显示调用的产生式,
依次嵌套调用非终结符函数 F()和 S(),进行递归向下分析。
void T(){
(3)G->ε
(4)T->FS
(5)S->*FS| / FS
(6)S->ε
(7)F->(E)
(8)F->i
输入出的格式如下:
(1)E 盘建立一个文本文档" 222.txt"存储一个以#结束的符号串(包括+—*/()i#),在此
位置输入符号串例如:i+i*i#
(2)输出结果:i+i*i#为合法符号串
备注:输入一符号串如 i+i*#,要求输出为“非法的符号串”
此法分析,通过实验我对本章的语法分析也有了深刻的认识。同时通过本次编程,让我深刻
认识编程应该注重细节,编程之前首先要做好分析准备。
五、程序源代码
#include<stdio.h>
#include<stdlib.h>
编译原理:算术表达式递归下降分析程序设计
实验二:算术表达式递归下降分析程序设计LD1、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
2、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:E→E+T | TT→T*F | FF→(E) | i3、设计分析题目所给的文法不为LL(1)文法,应改写成如下文法:E →TE2E2→+TE2 |∑T →FT2T2→*FT2 | ∑F →(E) | i采用递归下降分析法时,需要求出E2和T2 的FOLLOW集:FOLLOW(E2)={),#}FOLLOW(T2)={+,),#}递归下降分析法是确定的自上而下分析法,基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。
因此需要分别构造E,E2,T,T2,F函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能。
advance函数用于字符串的推进,input函数用于字符串的输入。
4、程序代码#include <iostream>using namespace std;char a[80]; // 字符串的存入char sym; // 单个的判断字符int i=0; // 字符串下标void E(); // 功能识别函数void E2(); // 功能识别函数void T(); // 功能识别函数void T2(); // 功能识别函数void F(); // 功能识别函数void input(); // 输入函数void advance(); // 字符串小标进一函数void main(){while(1){input();advance();E(); // 从首个推导式E开始if (sym=='#')cout<<"success"<<endl;elsecout<<"fail"<<endl;i=0; // 重新输入时,下标置0 }}void E(){T();E2();}void E2(){if(sym=='+'){advance();T();E2();}else if (sym != ')' && sym != '#'){cout<<"error!"<<endl;exit(0);}}void T(){F();T2();}void T2(){if(sym=='*'){advance();F();T2();}else if(sym!='+'&&sym!=')'&&sym!='#'){cout<<"error!"<<endl;exit(0);}}void F(){if(sym=='('){advance();E();if(sym==')')advance();else{cout<<"error!"<<endl;exit(0);}}else if(sym=='i'){advance();}else{cout<<"error!"<<endl;exit(0);}}void input(){cout<<"请输入需识别的句子:";cin>>a;}void advance(){sym=a[i];i++;}5、测试用例(1)只含有一个字符的形式:iaA(2) 含有‘+’的形式:i+ii+i+ii++++(3) 含有‘*’的形式:i*ii*i*ii***(4) 含有‘(’‘)’的形式:(i)()((i))(5) 综合形式:(i+i)*i(i+i)*(i+i)i+i*ii++i*(*i+(i+iii6、实验总结通过本次试验实践掌握了自上而下语法分析法的特点。
编译原理实验报告二
深圳大学实验报告课程名称:编译原理实验项目名称:语法分析--递归下降法学院:计算机与软件专业:软件工程指导教师:张小建报告人:文成学号:2011150259 班级: 2 实验时间:2013-12-25实验报告提交时间:2013-12-26教务部制一、实验目的:掌握自顶向下的语法分析法——递归下降法。
二、实验内容:用递归下降法对如下所定义的逻辑表达式进行语法分析。
1 L→ L || A2 L→ A3 A→ A && R4 A→ R5 R→ [ L ]6 R→ ! L7 R→ E >= E8 R→ E > E9 R→ E <= E10 R→ E < E11 R→ E == E12 R→ E != E13 R→ E14 E→ E + T15 E→ T16 T→ T * F17 T→ F18 F→ ( E )19 F→ n // 数20 F→ i // 标识符三、实验设计:1、消除该文法的左递归(产生式1、3、14、16);产生式(1)L→ L || A (2)L→ A消除左递归得到:L→ A L' L'→ || A L' | з产生式(3)A→ A && R (4)A→ R消除左递归得到:A→ RA' A'→ && RA' | з产生式(14)E→ E + T (15)E→ T消除左递归得到:E→ TE' E'→ + TE' | з产生式(16)T→ T * F (17)T→ F消除左递归得到:T→ FT' T'→ *FT' | з2、通过抽取公共左因子(产生式7 ~ 12),对该文法进行LL(1)改造;产生式7~127 R→ E >= E8 R→ E > E9 R→ E <= E10 R→ E < E11 R→ E == E12 R→ E != E抽取公共左因子:R→ ER'R'→ >=E | >E | <=E | <E | ==E | !=E3、证明最终得到的文法为LL(1)文法。
实验2 递归下降语法分析
实验二递归下降语法分析一、实验目的构造文法的语法分析程序,要求采用递归下降语法分析方法对输入的字符串进行语法分析,进一步掌握递归下降的语法分析方法。
二、实验内容编写为一上下文无关文法(文法如下)构造其递归下降语法分析程序,并对任给的一个输入串进行语法分析检查。
程序要求能对输入串进行递归下降语法分析,能判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。
E-->E+T|TT-->T*F|FF-->(E)|i三、实验参考:算法思想为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。
由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。
在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。
语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。
也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。
出错时,可以根据读字符的位置判断出错的位置。
四、实验说明:1.时间安排:安排在“词法分析”后。
2.实验环境:WINDOWS下,工具为Visual C++ 6.0五、上交:程序源代码;已经测试通过的3组数据(全部存在一个文本文件test1.txt中,以“第一组输入/输出;第二组输入/输出;第三组输入/输出”的顺序存放);实验报告:实验结果和分析中应包括:(1)功能描述:该程序具有什么功能?(2)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;另外可以附加函数之间的调用关系图、程序总体执行流程图(参考课本第二章)。
(3)实验总结:你在编程过程中花时多少?多少时间在纸上设计?多少时间上机编程和调试?多少时间在思考问题?遇到了哪些难题?你是怎么克服的?你对你的程序的评价?你的收获有哪些?。
实验二递归下降分析法实验报告
信息商务学院实验报告课程:编译原理实验名称:递归下降分析学号: *************名:***指导老师:***日期: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所示。
编译原理用递归下降法进行表达式分析报告实验报告材料
《编译原理》课程实验报告一. 实验题目 用递归下降法进行语法分析的方法二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C 语言四. 实验内容(实验要求)词法分析程序和语法分析程序已经提供。
此语法分析程序能够实现:正确的输入可以给出结果。
例:输入表达式串为:(13+4)*3则应给出结果为51。
要求:(1)读懂源代码,理解内容写入实验报告(语法分析及语法分析程序和词法分析程序的接口)(2)把语法分析中使用的yyval ,用yytext 实现。
(3)在语法分析程序用加入出错处理(尽量完整,包括出错的位置,出错的原题目 用递归下降法进行表达式分析 专业 班级学号 姓名因,错误的重定位)五. 实验步骤1.生成lex.yy.c文件:将已给的mylexer.l文件打开,先理解,然后再在DOS环境下用flex运行此文件,这时会生成一个lex.yy.c文件。
2.创建工程:打开C-Free 5.0(注:用C-Free 4.0会出错),在菜单栏中的“工程(project)”菜单下选择“新建”;在新建工程中选择“控制台程序”,添加工程名字为“myleb”和保存位置后点“确定”;第1步选择“空的程序”点“下一步”;第2步再点“下一步”;最后点击“完成”。
3.在创建的工程中添加文件:在Source files文件夹中添加之前生成的lex.yy.c文件和syn.c文件,然后找到parser.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
如图:4.理解并修改syn.c文件:首先,将num = yyval.intval修改成num = atoi(yytext);将num = yyval.fval修改成num = atof(yytext)。
可以这样修改的原因:在.l文件中所写的规则中,有{DIGIT}+ { yyval.intval = atoi(yytext);return INTEGER; }和{DIGIT}+"."{DIGIT}* {yyval.fval = atof(yytext); return DOUBLE; } 这两句代码,其中yyval.intval = atoi(yytext)和yyval.fval = atof(yytext)就说明两者可以相互替代。
实验二(递归下降分析)
实验二递归下降语法分析一.实验目的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)。
编译原理实验报告
实验名称:编写递归下降语法分析程序
实验类型:验证型实验
指导教师:
专业班级:
姓名:
学号:
电子邮件:
实验地点:
实验成绩:
日期: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");
else
printf("语法分析错误!\n");
}
}
六、实验者自评
这个实验比第一个有难度,是在第一个完成的基础上进行的。
把这里面的递归和嵌套搞明白了,整个程序就好写了。
感觉还可以加一些东西,比如这个程序识别类型只能是int整型,可以加上char,float,double等。
在语句里可以多加一些常用的,do while,scanf,printf,等。