实验二 语法分析程序设计与实现

实验二语法分析程序设计与实现一、实验目的任选一种有代表性的语法分析方法,如算符优先法、递归下降法、LL(1)、SLR(1)、LR(1)等,通过设计、编制、调试实现一个典型的语法分析程序,对实验一所得扫描器提供的单词序列进行语法检查和结构分析,实现并进一步掌握常用的语法分析方法。

二、基本实验内容与要求选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。

G2[<算术表达式>]:<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表达式>)若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F 和i代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。

要求:1、确定语法分析程序的流程图,同时考虑相应的数据结构,编写一个语法分析源程序。

2、将词法、语法分析合在一起构成一个完整的程序,并调试成功。

3、供测试的例子应包括符合语法规则的语句,及分析程序能判别的若干错例。

对于所输入的字符串,不论对错,都应有明确的信息输出。

三、问题分析及源程序LL1文法:改写文法为:E->TG eG>+TG gT->FS tF->-TG g1G->^ g2S->*FS sT->/FS s1S->^ s2F->(E) fG->i f1分析表:LL1源程序#include<iostream.h>#include<stdio.h>#include<stdlib.h>#include<string.h>char A[30]; /*分析栈*/char B[30]; /*剩余串*/char v1[20]={'i','+','-','*','/','(',')','#'}; /*终结符*/char v2[20]={'E','G','T','S','F'}; /*非终结符*/int j=0,b=0,top=0,l; /*L为输入串长度*/class type /*产生式类型定义*/{public:char origin; /*大写字符*/char array[5]; /*产生式右边字符*/int length; /*字符个数*/};type e,t,g,g1,g2,s,s1,s2,f,f1; /*类对象*/type C[10][10]; /*预测分析表*/void print() /*输出分析栈*/{int a;for(a=0;a<=top+1;a++)cout<<A[a];cout<<"\t\t";}void print1() /*输出剩余串*/{int j;for(j=0;j<b;j++) /*输出对齐符*/cout<<" ";for(j=b;j<=l;j++)cout<<B[j];cout<<"\t\t\t";}void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha; /*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';strcpy(g1.array,"-TG");g1.length=3;g2.origin='G';g2.array[0]='^';g2.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';strcpy(s1.array,"/FS");s1.length=3;s2.origin='S';s2.array[0]='^';s2.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++) /*初始化分析表*/ for(n=0;n<=7;n++)C[m][n].origin='N'; /*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][5]=e;C[1][1]=g;C[1][2]=g1;C[1][6]=g2;C[1][7]=g2;C[2][0]=t;C[2][5]=t;C[3][1]=s2;C[3][2]=s2;C[3][3]=s;C[3][4]=s1;C[3][6]=s2;C[3][7]=s2;C[4][0]=f1;C[4][5]=f;cout<<"提示:本程序只能对由'i','+','-','*','/','(',')'构成的以'#'结束的字符串进行分析,\n";cout<<"请输入要分析的字符串:";do/*读入分析串*/{cin>>ch;if ((ch!='i') &&(ch!='+')&&(ch!='-')&&(ch!='*')&&(ch!='/')&&(ch!='(')&&(ch!=')')&&(ch !='#')){cout<<"输入串中有非法字符\n";exit(1); //强制退出程序}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/cout<<"步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n";do{x=A[top--];/*x为当前栈顶字符*/cout<<k++;cout<<"\t\t";for(j=0;j<=7;j++)/*判断是否为终结符*/ if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/cout<<"acc!"<<endl;/*接受 */getchar();exit(1); //退出程序}/*if*/if(x==ch){print();print1();cout<<"匹配"<<endl;ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}else/*出错处理*/{print();print1();cout<<"出错"<<endl;/*输出出错终结符*/exit(1);}}else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=7;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();cout<<cha.origin<<"->"; /*输出产生式*/for(j=0;j<cha.length;j++)cout<<cha.array[j];cout<<"\n";for(j=(cha.length-1);j>=0;j--) /*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}else/*出错处理*/{print();print1();cout<<"出错"<<endl;/*输出出错非终结符*/exit(1);}}}while(finish==0);}运行结果:第一章 MCL-1型页脚内容11。

合集下载

实验二--LL分析法实验报告

实验二--LL分析法实验报告

实验二LL(1)分析法一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。

使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。

有利于提高学生的专业素质,为培养适应社会多方面需要的能力。

二、实验内容及设计原理所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。

实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。

我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。

当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。

LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。

对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘#’,则宣布分析成功,停止分析过程。

(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。

(3)若X是一个非终结符,则查看预测分析表M。

若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。

若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。

三、程序结构描述1、定义的变量初始化预测分析表:LL E[8]={"TG","TG","error","error","error","error","error","error"}; LL G[8]={"error","error","null","+TG","-TG","error","error","null"}; LL T[8]={"FS","FS","error","error","error","error","error","error"}; LL S[8]={"error","error","null","null","null","*FS","/FS","null"};LL F[8]={"i","(i)","error","error","error","error","error","error"}; const int MaxLen=10; 初始化栈的长度const int Length=10; 初始化数组长度char Vn[5]={'E','G','T','S','F'}; 非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'}; 终结符数组char ch,X; /全局变量,ch用于读当前字符,X用于获取栈顶元素char strToken[Length]; 存储规约表达式2、定义的函数class stack 栈的构造及初始化int length(char *c) 输出字符数组的长度void print(int i,char*c) 剩余输入串的输出void run() 分析程序3、LL(1)预测分析程序流程图四、程序源代码及运行结果#include<iostream>using namespace std;const int MaxLen=10; //初始化栈的长度const int Length=10;//初始化数组长度char Vn[5]={'E','G','T','S','F'};//非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'};//终结符数组char ch,X;//全局变量,ch用于读当前字符,X用于获取栈顶元素char strToken[Length];//存储规约表达式struct LL//ll(1)分析表的构造字初始化{char*c;};LL E[8]={"TG","TG","error","error","error","error","error","error"}; LL G[8]={"error","error","null","+TG","-TG","error","error","null"}; LL T[8]={"FS","FS","error","error","error","error","error","error"}; LL S[8]={"error","error","null","null","null","*FS","/FS","null"};LL F[8]={"i","(i)","error","error","error","error","error","error"}; class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();//删除栈顶元素void out();//输出栈中元素~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<" ";}int length(char *c){int l=0;for(int i=0;c[i]!='\0';i++)l++;return l;}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<" ";}void run(){bool flag=true;//循环条件int step=0,point=0;//步骤、指针int len;//长度cout<<"请输入要规约的字符串:"<<endl;cin>>strToken;ch=strToken[point++];//读取第一个字符stack s;s.push('#');//栈中数据初始化s.push('E');s.get_top(X);//取栈顶元素cout<<"步骤"<<"分析栈"<<"剩余输入串"<<"所用产生式"<<"动作"<<endl;cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<"初始化"<<endl;while(flag){if((X==Vt[0])||(X==Vt[1])||(X==Vt[2])||(X==Vt[3])||(X==Vt[4])||(X==Vt[5])||(X==V t[6])) //判断是否为终结符(不包括#){if(X==ch)//终结符,识别,进行下一字符规约{s.pop();s.get_top(X);ch=strToken[point++];cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<"GETNEXT(I)"<<endl;}else{flag=false;cout<<"error!"<<endl;}}else if(X=='#')//规约结束{if(X==ch){cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<ch<<" "<<"结束"<<endl;s.pop();flag=false;}else{flag=false;cout<<"error!"<<endl;}}else if(X==Vn[0]) //非终结符E{for(int i=0;i<8;i++)//查分析表if(ch==Vt[i]){if(strcmp(E[i].c,"error")==0)//出错{flag=false;cout<<"error"<<endl;}else{ //对形如X->X1X2的产生式进行入栈操作s.pop();len=length(E[i].c)-1;for(int j=len;j>=0;j--)s.push(E[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<E[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<E[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[1]) //同上,处理G{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(G[i].c,"null")==0){s.pop();cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<"ε"<<" "<<"POP"<<endl;s.get_top(X);}else if(strcmp(G[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(G[i].c)-1;for(int j=len;j>=0;j--)s.push(G[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<G[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<G[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[2]) //同上处理T{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(T[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(T[i].c)-1;for(int j=len;j>=0;j--)s.push(T[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<T[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<T[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[3])//同上处理S{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(S[i].c,"null")==0){s.pop();cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<"ε"<<" "<<"POP"<<endl;s.get_top(X);}else if(strcmp(S[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(S[i].c)-1;for(int j=len;j>=0;j--)s.push(S[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<S[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<S[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[4]) //同上处理F{for(int i=0;i<7;i++)if(ch==Vt[i]){if(strcmp(F[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(F[i].c)-1;for(int j=len;j>=0;j--)s.push(F[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<F[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<F[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else //出错处理{flag= false;cout<<"error"<<endl;}}}int main(){run();system("pause");return 0;}测试:输入i*i+i#结果:实验二--LL(1)分析法实验报告五、实验总结1. 本实例能利用正确的LL1文法分析表判断任意符号串是否属于该文法的句子;显示了具体分析过程;支持打开、新建、保存分析表;保存分析结果。

《c语言程序设计》实验报告(实验-2)

《c语言程序设计》实验报告(实验-2)

《c语⾔程序设计》实验报告(实验-2)《C语⾔程序设计》实验报告2013~2014学年第⼆学期班级姓名学号指导教师实验⼀实验项⽬名称:C程序的运⾏环境和运⾏C程序的⽅法所使⽤的⼯具软件及环境:Visual C++ 6.0⼀、实验⽬的:1.了解在Visual C++ 6.0环境下如何编辑、编译、连接和运⾏⼀个C程序;2.通过运⾏简单的C程序,初步了解C源程序的特点。

⼆、预习内容:教材《C语⾔程序设计教程》第1章。

三、实验内容:1. 在Visual C++ 6.0环境下输⼊并运⾏下⾯的程序:#includeint main( ){printf("This is a C program.\n");return 0;}2. 在Visual C++ 6.0环境下输⼊下⾯的程序(有语法错误),编译、连接、调试该程序,直⾄程序⽆语法错误,然后运⾏程序,并观察分析运⾏结果。

#includeint main( ){int a,b,suma=3;b=4;sun=a+b;print(“%d+%d=%d\n”,a,b,sum);return 0;}四、实验结果:1. 运⾏结果(或截图):This is a C program.Press any key to continue2. (1) 改正后的源程序:#includeint main( ){int a,b,sum;a=3;b=4;sum=a+b;printf("%d+%d=%d\n",a,b,sum);return 0;}(2) 运⾏结果(或截图):3+4=7五、思考题:1. ⼀个C程序上机的步骤有哪些?答:上级输⼊与编辑源程序—对原程序进⾏编译–与库函数链接–运⾏可执⾏的⽬标程序。

2. 组成C程序的基本单位是函数,⼀个函数包括哪⼏个部分?答:⼀个函数包括两部分:分别为函数头或函数⾸部和函数体。

成绩指导教师签名实验⼆实验项⽬名称:数据类型、运算符和表达式所使⽤的⼯具软件及环境:Visual C++ 6.0⼀、实验⽬的:1.掌握整型、实型与字符型这三种基本类型的概念;2.掌握常量及变量的使⽤⽅法;3. 掌握基本算术运算符及其表达式的使⽤⽅法;4. 掌握++、--运算符、赋值运算符及其表达式的使⽤⽅法。

程序设计实验报告(matlab)

程序设计实验报告(matlab)

程序设计实验报告(matlab)实验一: 程序设计基础实验目的:初步掌握机器人编程语言Matlab。

实验内容:运用Matlab进行简单的程序设计。

实验方法:基于Matlab环境下的简单程序设计。

实验结果:成功掌握简单的程序设计和Matlab基本编程语法。

实验二:多项式拟合与插值实验目的:学习多项式拟合和插值的方法,并能进行相关计算。

实验内容:在Matlab环境下进行多项式拟合和插值的计算。

实验方法:结合Matlab的插值工具箱,进行相关的计算。

实验结果:深入理解多项式拟合和插值的实现原理,成功掌握Matlab的插值工具箱。

实验三:最小二乘法实验目的:了解最小二乘法的基本原理和算法,并能够通过Matlab进行计算。

实验内容:利用Matlab进行最小二乘法计算。

实验方法:基于Matlab的线性代数计算库,进行最小二乘法的计算。

实验结果:成功掌握最小二乘法的计算方法,并了解其在实际应用中的作用。

实验六:常微分方程实验目的:了解ODE的基本概念和解法,并通过Matlab进行计算。

实验内容:利用Matlab求解ODE的一阶微分方程组、变系数ODE、高阶ODE等问题。

实验方法:基于Matlab的ODE工具箱,进行ODE求解。

实验结果:深入理解ODE的基本概念和解法,掌握多种ODE求解方法,熟练掌握Matlab的ODE求解工具箱的使用方法。

总结在Matlab环境下进行程序设计实验,使我对Matlab有了更深刻的认识和了解,也使我对计算机科学在实践中的应用有了更加深入的了解。

通过这些实验的学习,我能够灵活应用Matlab进行各种计算和数值分析,同时也能够深入理解相关的数学原理和算法。

这些知识和技能对我未来的学习和工作都将有着重要的帮助。

实验二C语言中的分支语句程序设计实验

实验二C语言中的分支语句程序设计实验

实验二 C语言中的分支语句程序设计一、实验目的:1.掌握C语言的基本语法;2.掌握C语言的表达式运算及标准库函数的调用方法;3.掌握C语言的基本输入输出语句;4.掌握字符类型、整型和浮点型数据的输入输出及表达式计算方法;5.掌握if语句和switch语句的用法;6.掌握分支程序结构的设计思想;二、实验内容(一)分析程序,用程序验证下面各个表达式的值1、当整型变量a,b,c的值分别为3,4,5时,以下各语句执行后a,b,c的值为多少? (1) if(a>c) {a=b; b=c; c=a;}else {a=c; c=b; b=a;}执行后a,b,c的值为,,(2) if(a<c) a=c;else a=b; c=b; b=a;执行后a,b,c的值为,,(3) if(a!=c) ;else a=c; c=b; b=a;执行后a,b,c的值为,,2、若整数x分别等于95、87、100、43、66、79,57,则以下程序段运行后屏幕显示是什么?switch(x/10){ case 6:case 7: printf("Pass\n"); break;case 8: printf("Good\n"); break;case 9:case 10: printf("V eryGood\n"); break;case 5 : printf("Between Pass and Fail\n");default: printf("Fail\n");}x等于95时,程序段运行后屏幕上显示。

x等于87时,程序段运行后屏幕上显示。

x等于100时,程序段运行后屏幕上显示。

x等于43时,程序段运行后屏幕上显示。

x等于66时,程序段运行后屏幕上显示。

x等于79时,程序段运行后屏幕上显示。

x等于57时,程序段运行后屏幕上显示。

编译原理-语法分析程序报告

编译原理-语法分析程序报告

编译原理实验实验二语法分析器实验二:语法分析实验一、实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。

本次实验的目的主要是加深对LR(1)分析法的理解。

二、实验预习提示1、LR(1)分析法的功能LR(1)分析法的功能是利用LR(1)分析表,对输入符号串自下而上的分析过程。

2、LR(1)分析表的构造及分析过程。

三、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容);实验报告必须包括设计的思路,以及测试报告(输入测试例子,输出结果)。

语法分析器一、功能描述:语法分析器,顾名思义是用来分析语法的。

程序对给定源代码先进行词法分析,再根据给定文法,判断正确性。

此次所写程序是以词法分析器为基础编写的,由于代码量的关系,我们只考虑以下输入为合法:数字自定义变量+ * ()$作为句尾结束符。

其它符号都判定为非法。

二、程序结构描述:词法分析器:class wordtree;类,内容为字典树的创建,插入和搜索。

char gettype(char ch):类型处理代入字串首字母ch,分析字串类型后完整读入字串,输出分析结果。

因读取过程会多读入一个字母,所以函数返回该字母进行下一次分析。

bool isnumber(char str[]):判断是否数字代入完整“数字串”str,判断是否合法数字,若为真返回1,否则返回0。

bool isoperator(char str[]):判断是否关键字代入完整“关键字串”str,搜索字典树判断是否存在,若为存在返回1,否则返回0。

语法分析器:int action(int a,char b):代入当前状态和待插入字符,查找转移状态或归约。

node2 go(int a):代入当前状态,返回归约结果和长度。

void printstack():打印栈。

int push(char b):将符号b插入栈中,并进行归约。

实验二--语法分析程序的设计-

实验二--语法分析程序的设计-
实验二
姓名:学号:专业班级
一、实验目的
通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中预测分析方法。
二、实验内容
设计一个文法的预测分析程序,判断特定表达式的正确性。
三、实验要求
1、给出文法如下:
G[E]
E->T|E+T;
import java.io.*;
public class test2 {
static String[] key_word = { "main", "if", "then", "while", "do", "int",
"else" };
static String[] cal_word = { "+", "-", "*", "/", "<", ">", "{", "}", "(",
static String[] firstT = { "i", "(" };
static String[] firstTB = { "*", "@" };
static String[] firstF = { "i", "(" };
static String[][] list = { { "", "i", "+", "*", "(", ")", "#" },

编译原理实验报告

《编译原理》实验报告软件131 陈万全132852一、需求分析通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。

通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。

1、词法分析程序设计与实现假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。

输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。

输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。

对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。

2、语法分析程序设计与实现选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。

G2[<算术表达式>]:<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表达式>)若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。

南邮编译原理报告实验二

实验报告(2015 / 2016 学年第二学期)课程名称编译原理实验名称语法分析器的构造实验时间2016年5月26日指导单位计算机软件教学中心指导教师黄海平学生姓名班级学号学院(系)计算机学院、软件学院专业计算机科学与技术实验报告实验名称语法分析器的构造指导教师黄海平实验类型验证实验学时4实验时间2016.5.26一、实验目的和要求实验目的:设计、编制、调试一个LL(1)语法分析器,利用语法分析器对符号串的识别,加深对语法分析原理的理解。

实验要求:1、检测左递归,如果有则进行消除;2、求解FIRST集和FOLLOW集;3、构建LL(1)分析表;4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。

以上实验要求可分两个同学完成。

例如构建分析表一个同学完成、构建分析程序并分析符号串另一个同学完成。

二、实验环境(实验设备)硬件:计算机软件:Visual C ++6.0二、实验原理及内容实验内容:设计并实现一个LL(1)语法分析器,实现对算术文法G[E]:E->E+T|TT->T*F|FF->(E)|i所定义的符号串进行识别,例如符号串abc+age+80为文法所定义的句子,符号串(abc-80(*s5)不是文法所定义的句子。

实验代码:#include<cstdio>#include<string>#include<iostream>using namespace std;void input_grammer(string *G)//输入文法G,n个非终结符{int i=0;//计数char ch='y';while(ch=='y'){cin>>G[i++];cout<<"继续输入?(y/n)\n";cin>>ch;}}void preprocess(string *G,string *P,string &U,string &u,int &n,int &t,int &k)//将文法G预处理产生式集合P,非终结符、终结符集合U、u,{int i,j,r,temp;//计数char C;//记录规则中()后的符号int flag;//检测到()n=t=k=0;for( i=0;i<50;i++) P[i]=" ";//字符串如果不初始化,在使用P[i][j]=a时将不能改变,可以用P[i].append(1,a)U=u=" ";//字符串如果不初始化,无法使用U[i]=a 赋值,可以用U.append(1,a)for(n=0;!G[n].empty();n++){ U[n]=G[n][0];}//非终结符集合,n为非终结符个数for(i=0;i<n;i++){for(j=4;j<G[i].length();j++){if(U.find(G[i][j])==string::npos&&u.find(G[i][j])==string::npos)if(G[i][j]!='|'&&G[i][j]!='^')//if(G[i][j]!='('&&G[i][j]!=')'&&G[i][j]!='|'&&G[i][j]!='^')u[t++]=G[i][j];}}//终结符集合,t为终结符个数for(i=0;i<n;i++){flag=0;r=4;for(j=4;j<G[i].length();j++){P[k][0]=U[i];P[k][1]=':';P[k][2]=':';P[k][3]='=';/* if(G[i][j]=='('){ j++;flag=1;for(temp=j;G[i][temp]!=')';temp++);C=G[i][temp+1];//C记录()后跟的字符,将C添加到()中所有字符串后面}if(G[i][j]==')') {j++;flag=0;}*/if(G[i][j]=='|'){//if(flag==1) P[k][r++]=C;k++;j++;P[k][0]=U[i];P[k][1]=':';P[k][2]=':';P[k][3]='=';r=4;P[k][r++]=G[i][j];}else{P[k][r++]=G[i][j];}}k++;}//获得产生式集合P,k为产生式个数}int eliminate_1(string *G,string *P,string U,string *GG)//消除文法G1中所有直接左递归得到文法G2,要能够消除含有多个左递归的情况){string arfa,beta;//所有形如A::=Aα|β中的α、β连接起来形成的字符串arfa、beta int i,j,temp,m=0;//计数int flag=0;//flag=1表示文法有左递归int flagg=0;//flagg=1表示某条规则有左递归char C='A';//由于消除左递归新增的非终结符,从A开始增加,只要不在原来问法的非终结符中即可加入for(i=0;i<20&&U[i]!=' ';i++){ flagg=0;arfa=beta="";for(j=0;j<100&&P[j][0]!=' ';j++){if(P[j][0]==U[i]){if(P[j][4]==U[i])//产生式j有左递归{flagg=1;for(temp=5;P[j][temp]!=' ';temp++) arfa.append(1,P[j][temp]);if(P[j+1][4]==U[i]) arfa.append("|");//不止一个产生式含有左递归}else{for(temp=4;P[j][temp]!=' ';temp++) beta.append(1,P[j][temp]);if(P[j+1][0]==U[i]&&P[j+1][4]!=U[i]) beta.append("|");}}}if(flagg==0)//对于不含左递归的文法规则不重写{GG[m]=G[i]; m++;}else{flag=1;//文法存在左递归GG[m].append(1,U[i]);GG[m].append("::=");if(beta.find('|')!=string::npos) GG[m].append("("+beta+")");else GG[m].append(beta);while(U.find(C)!=string::npos){C++;}GG[m].append(1,C);m++;GG[m].append(1,C);GG[m].append("::=");if(arfa.find('|')!=string::npos) GG[m].append("("+arfa+")");else GG[m].append(arfa);GG[m].append(1,C);GG[m].append("|^");m++;C++;}//A::=Aα|β改写成A::=βA‘,A’=αA'|β,}return flag;}int* ifempty(string* P,string U,int k,int n){int* empty=new int [n];//指示非终结符能否推导到空串int i,j,r;for(r=0;r<n;r++) empty[r]=0;//默认所有非终结符都不能推导到空int flag=1;//1表示empty数组有修改int step=100;//假设一条规则最大推导步数为步while(step--){for(i=0;i<k;i++){r=U.find(P[i][0]);if(P[i][4]=='^') empty[r]=1;//直接推导到空else{for(j=4;P[i][j]!=' ';j++){if(U.find(P[i][j])!=string::npos){if(empty[U.find(P[i][j])]==0) break;}else break;}if(P[i][j]==' ') empty[r]=1;//多步推导到空else flag=0;}}}return empty;}string* FIRST_X(string* P,string U,string u,int* empty,int k,int n){int i,j,r,s,tmp;string* first=new string[n];char a;int step=100;//最大推导步数while(step--){// cout<<"step"<<100-step<<endl;for(i=0;i<k;i++){//cout<<P[i]<<endl;r=U.find(P[i][0]);if(P[i][4]=='^'&&first[r].find('^')==string::npos) first[r].append(1,'^');//规则右部首符号为空else{for(j=4;P[i][j]!=' ';j++){a=P[i][j];if(u.find(a)!=string::npos&&first[r].find(a)==string::npos)//规则右部首符号是终结符{first[r].append(1,a);break;//添加并结束}if(U.find(P[i][j])!=string::npos)//规则右部首符号是非终结符,形如X::=Y1Y2...Yk{s=U.find(P[i][j]);//cout<<P[i][j]<<":\n";for(tmp=0;first[s][tmp]!='\0';tmp++){a=first[s][tmp];if(a!='^'&&first[r].find(a)==string::npos)//将FIRST[Y1]中的非空符加入first[r].append(1,a);}}if(!empty[s]) break;//若Y1不能推导到空,结束}if(P[i][j]==' ')if(first[r].find('^')==string::npos)first[r].append(1,'^');//若Y1、Y2...Yk都能推导到空,则加入空符号}}}return first;}string FIRST(string U,string u,string* first,string s)//求符号串s=X1X2...Xn的FIRST集{int i,j,r;char a;string fir;for(i=0;i<s.length();i++){if(s[i]=='^') fir.append(1,'^');if(u.find(s[i])!=string::npos&&fir.find(s[i])==string::npos){fir.append(1,s[i]);break;}//X1是终结符,添加并结束循环if(U.find(s[i])!=string::npos)//X1是非终结符{r=U.find(s[i]);for(j=0;first[r][j]!='\0';j++){a=first[r][j];if(a!='^'&&fir.find(a)==string::npos)//将FIRST(X1)中的非空符号加入fir.append(1,a);}if(first[r].find('^')==string::npos) break;//若X1不可推导到空,循环停止}if(i==s.length())//若X1-Xk都可推导到空if(fir.find(s[i])==string::npos) //fir中还未加入空符号fir.append(1,'^');}return fir;}string** create_table(string *P,string U,string u,int n,int t,int k,string* first)//构造分析表,P为文法G的产生式构成的集合{int i,j,p,q;string arfa;//记录规则右部string fir,follow;string FOLLOW[5]={")#",")#","+)#","+)#","+*)#"};string **table=new string*[n];for(i=0;i<n;i++) table[i]=new string[t+1];for(i=0;i<n;i++)for(j=0;j<t+1;j++)table[i][j]=" ";//table存储分析表的元素,“ ”表示errorfor(i=0;i<k;i++){arfa=P[i];arfa.erase(0,4);//删除前个字符,如:E::=E+T,则arfa="E+T"fir=FIRST(U,u,first,arfa);for(j=0;j<t;j++){p=U.find(P[i][0]);if(fir.find(u[j])!=string::npos){q=j;table[p][q]=P[i];}//对first()中的每一终结符置相应的规则}if(fir.find('^')!=string::npos){follow=FOLLOW[p];//对规则左部求follow()for(j=0;j<t;j++){if((q=follow.find(u[j]))!=string::npos){q=j;table[p][q]=P[i];}//对follow()中的每一终结符置相应的规则}table[p][t]=P[i];//对#所在元素置相应规则}}return table;}void analyse(string **table,string U,string u,int t,string s)//分析符号串s {string stack;//分析栈string ss=s;//记录原符号串char x;//栈顶符号char a;//下一个要输入的字符int flag=0;//匹配成功标志int i=0,j=0,step=1;//符号栈计数、输入串计数、步骤数int p,q,r;string temp;for(i=0;!s[i];i++){if(u.find(s[i])==string::npos)//出现非法的符号cout<<s<<"不是该文法的句子\n";return;}s.append(1,'#');stack.append(1,'#');//’#’进入分析栈stack.append(1,U[0]);i++;//文法开始符进入分析栈a=s[0];//cout<<stack<<endl;cout<<"步骤分析栈余留输入串所用产生式\n";while(!flag){// cout<<"步骤分析栈余留输入串所用产生式\n"cout<<step<<" "<<stack<<" "<<s<<" ";x=stack[i];stack.erase(i,1);i--;//取栈顶符号x,并从栈顶退出//cout<<x<<endl;if(u.find(x)!=string::npos)//x是终结符的情况{if(x==a){s.erase(0,1);a=s[0];//栈顶符号与当前输入符号匹配,则输入下一个符号cout<<" \n";//未使用产生式,输出空}else{cout<<"error\n";cout<<ss<<"不是该文法的句子\n";break;}}if(x=='#'){if(a=='#') {flag=1;cout<<"成功\n";}//栈顶和余留输入串都为#,匹配成功else{cout<<"error\n";cout<<ss<<"不是该文法的句子\n";break;}}if(U.find(x)!=string::npos)//x是非终结符的情况{p=U.find(x);q=u.find(a);if(a=='#') q=t;temp=table[p][q];cout<<temp<<endl;//输出使用的产生式if(temp[0]!=' ')//分析表中对应项不为error{r=9;while(temp[r]==' ') r--;while(r>3){if(temp[r]!='^'){stack.append(1,temp[r]);//将X::=x1x2...的规则右部各符号压栈i++;}r--;}}else{cout<<"error\n";cout<<ss<<"不是该文法的句子\n";break;}}step++;}if(flag) cout<<endl<<ss<<"是该文法的句子\n";}int main(){int i,j;string *G=new string[50];//文法Gstring *P=new string[50];//产生式集合Pstring U,u;//文法G非终结符集合U,终结符集合uint n,t,k;//非终结符、终结符个数,产生式数string *GG=new string[50];//消除左递归后的文法GGstring *PP=new string[50];//文法GG的产生式集合PPstring UU,uu;//文法GG非终结符集合U,终结符集合uint nn,tt,kk;//消除左递归后的非终结符、终结符个数,产生式数string** table;//分析表cout<<" 欢迎使用LL(1)语法分析器!\n\n\n";cout<<"请输入文法(同一左部的规则在同一行输入,例如:E::=E+T|T;用^表示空串)\n";input_grammer(G);preprocess(G,P,U,u,n,t,k);cout<<"\n该文法有"<<n<<"个非终结符:\n";for(i=0;i<n;i++) cout<<U[i];cout<<endl;cout<<"该文法有"<<t<<"个终结符:\n";for(i=0;i<t;i++) cout<<u[i];cout<<"\n\n 左递归检测与消除\n\n";if(eliminate_1(G,P,U,GG)){preprocess(GG,PP,UU,uu,nn,tt,kk);cout<<"该文法存在左递归!\n\n消除左递归后的文法:\n\n"; for(i=0;i<nn;i++) cout<<GG[i]<<endl;cout<<endl;cout<<"新文法有"<<nn<<"个非终结符:\n";for(i=0;i<nn;i++) cout<<UU[i];cout<<endl;cout<<"新文法有"<<tt<<"个终结符:\n";for(i=0;i<tt;i++) cout<<uu[i];cout<<endl;//cout<<"新文法有"<<kk<<"个产生式:\n";//for(i=0;i<kk;i++) cout<<PP[i]<<endl;}else{cout<<"该文法不存在左递归\n";GG=G;PP=P;UU=U;uu=u;nn=n;tt=t;kk=k;}cout<<" 求解FIRST集\n\n";int *empty=ifempty(PP,UU,kk,nn);string* first=FIRST_X(PP,UU,uu,empty,kk,nn);string FOLLOW[5]={")#",")#","+)#","+)#","+*)#"};for(i=0;i<nn;i++)cout<<"FIRST("<<UU[i]<<"): "<<first[i]<<endl;cout<<" 求解FOLLOW集\n\n";for(i=0;i<nn;i++)cout<<"FOLLOW("<<UU[i]<<"): "<<FOLLOW[i]<<endl; cout<<"\n\n 构造文法分析表\n\n"; table=create_table(PP,UU,uu,nn,tt,kk,first);cout<<" ";for(i=0;i<tt;i++) cout<<" "<<uu[i]<<" ";cout<<"# "<<endl;for( i=0;i<nn;i++){cout<<UU[i]<<" ";for(j=0;j<t+1;j++)cout<<table[i][j];cout<<endl;}cout<<"\n\n 分析符号串\n\n"; string s;cout<<"请输入要分析的符号串\n";cin>>s;analyse(table,UU,uu,tt,s); return 0;}实验结果:四、实验小结(包括问题和解决方法、心得体会、意见与建议等)在这次实验中,我又一次复习了,什么是LL(1)语法分析器,如何对符号串进行分析。

实验二MATLAB程序设计含实验报告

实验二 MATLAB 程序设计一、 实验目的1.掌握利用if 语句实现选择结构的方法。

2.掌握利用switch 语句实现多分支选择结构的方法。

3.掌握利用for 语句实现循环结构的方法。

4.掌握利用while 语句实现循环结构的方法。

5.掌握MATLAB 函数的编写及调试方法。

二、 实验的设备及条件计算机一台(带有MATLAB7.0以上的软件环境)。

M 文件的编写:启动MATLAB 后,点击File|New|M-File ,启动MATLAB 的程序编辑及调试器(Editor/Debugger ),编辑以下程序,点击File|Save 保存程序,注意文件名最好用英文字符。

点击Debug|Run 运行程序,在命令窗口查看运行结果,程序如有错误则改正三、 实验内容1.编写求解方程02=++c bx ax 的根的函数(这个方程不一定为一元二次方程,因c b a 、、的不同取值而定),这里应根据c b a 、、的不同取值分别处理,有输入参数提示,当0~,0,0===c b a 时应提示“为恒不等式!”。

并输入几组典型值加以检验。

(提示:提示输入使用input 函数)2.输入一个百分制成绩,要求输出成绩等级A+、A 、B 、C 、D 、E 。

其中100分为A+,90分~99分为A ,80分~89分为B ,70分~79分为C ,60分~69分为D ,60分以下为E 。

要求:(1)用switch 语句实现。

(2)输入百分制成绩后要判断该成绩的合理性,对不合理的成绩应输出出错信息。

(提示:注意单元矩阵的用法)3.数论中一个有趣的题目:任意一个正整数,若为偶数,则用2除之,若为奇数,则与3相乘再加上1。

重复此过程,最终得到的结果为1。

如:2?13?10?5?16?8?4?2?16?3?10?5?16?8?4?2?1运行下面的程序,按程序提示输入n=1,2,3,5,7等数来验证这一结论。

请为关键的Matlab 语句填写上相关注释,说明其含义或功能。

实验二 C语言中的分支语句程序设计实验

实验二 C语言中的分支语句程序设计一、实验目的:1.掌握C语言的基本语法;2.掌握C语言的表达式运算及标准库函数的调用方法;3.掌握C语言的基本输入输出语句;4.掌握字符类型、整型和浮点型数据的输入输出及表达式计算方法;5.掌握if语句和switch语句的用法;6.掌握分支程序结构的设计思想;二、实验内容(一)分析程序,用程序验证下面各个表达式的值1、当整型变量a,b,c的值分别为3,4,5时,以下各语句执行后a,b,c的值为多少? (1) if(a>c) {a=b; b=c; c=a;}else {a=c; c=b; b=a;}执行后a,b,c的值为,,(2) if(a<c) a=c;else a=b; c=b; b=a;执行后a,b,c的值为,,(3) if(a!=c) ;else a=c; c=b; b=a;执行后a,b,c的值为,,2、若整数x分别等于95、87、100、43、66、79,57,则以下程序段运行后屏幕显示是什么?switch(x/10){ case 6:case 7: printf("Pass\n"); break;case 8: printf("Good\n"); break;case 9:case 10: printf("VeryGood\n"); break;case 5 : printf("Between Pass and Fail\n");default: printf("Fail\n");}x等于95时,程序段运行后屏幕上显示。

x等于87时,程序段运行后屏幕上显示。

x等于100时,程序段运行后屏幕上显示。

x等于43时,程序段运行后屏幕上显示。

x等于66时,程序段运行后屏幕上显示。

x等于79时,程序段运行后屏幕上显示。

x等于57时,程序段运行后屏幕上显示。

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