编译原理课程设计-LR分析器总控程序的实现

合集下载

编译原理教案-lr分析

编译原理教案-lr分析

编译原理教案LR 分析一、教学目标1. 理解LR 分析法的概念和原理。

2. 学会使用LR 分析法进行语法分析。

3. 掌握LR 分析器的构造和应用。

二、教学内容1. LR 分析法的基本概念1.1 LR 分析法的定义1.2 LR 分析法的分类1.3 LR 分析法的特点2. LR 分析器的构造2.1 LR 分析器的组成2.2 LR 分析器的构建步骤2.3 LR 分析器的优化方法3. LR 分析法的应用3.1 LR 分析法在编译器设计中的应用3.2 LR 分析法在其他领域的应用三、教学方法1. 讲授法:讲解LR 分析法的基本概念、原理和构造方法。

2. 案例分析法:分析实际应用中的LR 分析法。

3. 实践操作法:引导学生动手构建LR 分析器。

四、教学准备1. 教案、PPT 及相关资料。

2. 编程环境(如Lex、Yacc 等)。

五、教学过程1. 引入:介绍LR 分析法在编译器设计中的重要性。

2. 讲解:讲解LR 分析法的基本概念、原理和构造方法。

3. 案例分析:分析实际应用中的LR 分析法。

4. 实践操作:引导学生动手构建LR 分析器。

教学评价:通过课后作业、课堂讨论和实践操作等方式评估学生对LR 分析法的理解和应用能力。

六、教学案例:LR 分析法的应用实例6.1 实例介绍:分析一个简单的算术表达式语法。

6.2 构建LR 分析器:使用编程工具(如Lex、Yacc)构建LR 分析器。

6.3 分析过程:演示LR 分析器如何分析输入的算术表达式。

七、LR 分析器的优化7.1 优化概念:介绍LR 分析器优化的目的和方法。

7.2 减少动作表的大小:通过合并相同或相似的产生式来简化动作表。

7.3 优化算法:介绍常用的LR 分析器优化算法,如LALR(1)、SLR(1) 等。

八、高级LR 分析技术8.1 LALR(1) 分析器:介绍LALR(1) 分析器的构建方法和特点。

8.2 LR(1) 与LR(0) 的比较:分析两种LR 分析器的优缺点。

编译原理-实验5-LR分析法

编译原理-实验5-LR分析法

编译原理-实验5-L R(1)分析法(总6页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--实验5《LR(1)分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

二、实验内容程序输入/输出示例(以下仅供参考):对下列文法,用LR(1)分析法对任意输入的符号串进行分析:(1)E-E+T(2)E-E—T(3)T-T*F(4)T-T/F(5)F-(E)(6)F-i输出的格式如下:(1)LR(1)分析程序,编制人:姓名,学号,班级(2)输入一个以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:步骤状态栈符号栈剩余输入串动作10#i+i*i#移进(4)输入符号串为非法符号串(或者为合法符号串)备注:1.在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。

2.在此位置输入符号串为用户自行输入的符号串。

注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。

同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照。

三、实验方法用C语言,通过对LR(1)文法的正确理解编写代码。

四、实验步骤1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3.对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程。

五、实验结果六、实验结论#include<>#include<>char*action[10][3]={"S3#","S4#",NULL,/*ACTION*/NULL,NULL,"acc","S6#","S7#",NULL,"S3#","S4#",NULL,"r3#","r3#",NULL,NULL,NULL,"r1#","S6#","S7#",NULL,NULL,NULL,"r3#","r2#","r2#",NULL,NULL,NULL,"r2#"};int goto1[10][2]={1,2,/*QOTO*/0,0,0,5,0,8,0,0,0,0,0,9,0,0,0,0,0,0};char vt[3]={'a','b','#'};/*存放非终结符*/char vn[2]={'S','B'};/*存放终结符*/char *LR[4]={"E->S#","S->BB#","B->aB#","B->b#"};/*存放产生式*/ int a[10];char b[10],c[10],c1;int top1,top2,top3,top,m,n;void main(){int g,h,i,j,k,l,p,y,z,count;char x,copy[10],copy1[10];top1=0;top2=0;top3=0;top=0;a[0]=0;y=a[0];b[0]='#';count=0;z=0;printf("----------------请输入表达式(以#结尾)--------------\n"); do{scanf("%c",&c1);c[top3]=c1;top3=top3+1; }while(c1!='#');printf("步骤\t状态栈\t\t符号栈\t\t输入串\t\tACTION\tGOTO\n"); do{ y=z;m=0;n=0; /*y,z指向状态栈栈顶*/g=top;j=0;k=0;x=c[top];count++;printf("%d\t",count);while(m<=top1){/*输出状态栈*/printf("%d",a[m]);m=m+1;}printf("\t\t");while(n<=top2){/*输出符号栈*/printf("%c",b[n]);n=n+1;}printf("\t\t");while(g<=top3){/*输出输入串*/printf("%c",c[g]);g=g+1;}printf("\t\t");while(x!=vt[j]&&j<=2)j++;if(j==2&&x!=vt[j]){printf("error\n");return;}if(action[y][j]==NULL){printf("error\n");return;}elsestrcpy(copy,action[y][j]);if(copy[0]=='S'){/*处理移进*/z=copy[1]-'0';top1=top1+1;top2=top2+1;a[top1]=z;b[top2]=x;top=top+1;i=0; while(copy[i]!='#'){printf("%c",copy[i]);i++;}printf("\n");}if(copy[0]=='r'){/*处理归约*/i=0;while(copy[i]!='#'){printf("%c",copy[i]);i++;}h=copy[1]-'0';strcpy(copy1,LR[h]);while(copy1[0]!=vn[k])k++;l=strlen(LR[h])-4;top1=top1-l+1;top2=top2-l+1;y=a[top1-1];p=goto1[y][k];a[top1]=p;b[top2]=copy1[0];z=p;printf("\t");printf("%d\n",p);}}while(action[y][j]!="acc");printf("acc\n");getchar();}七、实验小结经过这个实验的练习,通过对程序的分析,让我进一步了解LR(1)算法的思想以及它的进一步程序实现,让我对它的了解从简单的理论上升到程序实现的级别,有理论上升到实际,让我更清楚它的用途。

《编译原理》课程设计报告_LALR(1)分析器

《编译原理》课程设计报告_LALR(1)分析器

《编译原理》课程设计报告题目:LALR(1)分析器2011年6月一.设计目的1.巩固对语法分析的基本功能和原理的认识。

2.通过对语法分析表的自动生成加深语法分析表的认识。

3.理解并处理语法分析中的异常和错误。

4.熟练掌握LALR(1)语法分析过程。

二.设计内容本次课程设计是设计一个LALR(1)语法分析器。

LALR(1)是LR(1)的一种改进。

为了克服LR(1)中分析表的构造对某些同心集的分裂可能对状态数目引起剧烈的增长,从而导致存储容量的急剧增加,采用对LR(1)项目集规范族合并同心集的方法,若合并同心集后不产生新的冲突,则为LALR(1)项目集。

本次课程设计的主要内容有首先生成LR(1)项目族;再合并同心集;然后生成LALR(1)项目族,求出LALR(1)的分析表;最后能判断一个字符串是否是该文法的串,若是则生成该字符串的树。

具体实现过程及相关主要实现类如下:类:LR0功能:LR0核心项目集构造输入:产生式的数字化表示输出:LR0核心项目集实现思想:LR0核心项目集构造算法程序如下:public class LR0{ArrayList<ArrayList<int[]>> core;ArrayList<ArrayList<int[]>> Ary_c;ArrayList <int []> producer;private int [] copy(int []a ){int val[]=new int[a.length];for(int i=0;i<a.length;i++)val[i]=a[i];return val;}private ArrayList<int []> copy(ArrayList<int []>a){ArrayList <int []>val=new ArrayList <int []>();for(int i=0;i<a.size();i++){val.add(copy(a.get(i)));}return val;}public boolean isEqual(int []a,int b[]){if(a.length!=b.length)return false;for(int i=0;i<a.length;i++)if(a[i]!=b[i])return false;return true;}public boolean isEqual(ArrayList <int[]>a,ArrayList<int[]>b) {if(a.size()!=b.size())return false;for(int i=0;i<a.size();i++)if(!isEqual(a.get(i),b.get(i)))return false;return true;}public int indexof(ArrayList <int[]>a,int []b){int index;int s1[];for(index=0;index<a.size();index++){s1=a.get(index);if(isEqual(s1,b)==true)return index;}return -1;}public int indexof(ArrayList <ArrayList <int[]>>a,ArrayList <int[]>b){int index;ArrayList <int[]>s1;for(index=0;index<a.size();index++){s1=a.get(index);if(isEqual(s1,b)==true)return index;}return -1;}public int []getStartWith(int i){int count=i;ArrayList<Integer> temp=new ArrayList<Integer>(3);while(count<producer.size()){if(producer.get(count)[0]==i)temp.add(count);elseif(producer.get(count)[0]>i)break;count++;}int val[]=new int[temp.size()];for(count=0;count<temp.size();count++)val[count]=temp.get(count);return val;}public void closuer_innal(int item[],ArrayList <Integer>pos) {if(item.length==2)return ;int i;int p[];for(i=0;i<item.length&&item[i]!=-1;i++);if(item.length-1==i)return ;if(item[i+1]<1000){p=getStartWith(item[i+1]);for(i=0;i<p.length;i++)if(pos.indexOf(p[i])==-1){pos.add(p[i]);closuer_innal(producer.get(p[i]),pos);}}return ;}public ArrayList<int []> closure(int []a) //求闭包{ArrayList <int []>val=new ArrayList<int []>();ArrayList <Integer>pos=new ArrayList<Integer>();closuer_innal(a,pos);for(int i=0;i<pos.size();i++){val.add(copy(producer.get(pos.get(i))));}return val;}public ArrayList <int []>Goto(ArrayList<int[]>a,int x){int index1=0,index2=0,index3,bl,index=0;int s1[],s2[];ArrayList<int []> temp1 = new ArrayList <int[]>(); //临时ArrayList<int []> temp2 = new ArrayList <int[]>();temp1=copy(a);s1=temp1.get(index1);if(s1==null)return null;while(s1[index2]!=-1){index2++;}if(s1.length==index2)return null;index2++;for(index3=0;index3<temp1.size();index3++){s1=copy(temp1.get(index3));if(s1.length<index2+1) ///防止Array溢出continue;if(s1[index2]==x&&indexof(temp2,s1)<0){bl=s1[index2-1];s1[index2-1]=s1[index2];s1[index2]=bl; //-1往后移位temp2.add(copy(s1));}}bl=temp2.size();for(index=0;index<bl;index++) ///求goto函数中的返回值的closure集{s1=copy(temp2.get(index));temp1=closure(s1);for(index1=0;index1<temp1.size();index1++){s2=temp1.get(index1);if(indexof(temp2,s2)<0){temp2.add(s2);}}}return temp2;}public LR0(ArrayList <int []>p){core =new ArrayList<ArrayList<int[]>>();Ary_c=new ArrayList<ArrayList<int[]>>();producer=p;}public void total(){ArrayList <int []>cur=new ArrayList<int []>();cur.add(producer.get(0));core.add(cur);int i=0;while(i<core.size()){cur=core.get(i);LR0Split(cur);i++;}update();}public void LR0Split(ArrayList<int[]>cur){ArrayList <int []>handle=copy(cur);ArrayList <int []>tempal;int []temp;int []prod;int start;ArrayList <int[]>result=new ArrayList<int[]>();ArrayList <int []>val=new ArrayList<int[]>();int j;for(int i=0;i<cur.size();i++){tempal=closure(cur.get(i));for(j=0;j<tempal.size();j++)if(indexof(handle,tempal.get(j))==-1)handle.add(tempal.get(j));}while(!handle.isEmpty()){prod=(int[]) handle.get(0);start=getStart(prod); //返回-1之后的数,没有返回-1if(start==-1){handle.remove(0);continue;}result=getStartWith(start,handle); //返回handle 中所有-1之后是start的产生式,并删除repair(result); //将result中产生式-1以后的数与-1调换/*returnval=new ArrayList<int []>();for(int i=0;i<result.size();i++){temp=(int[]) result.get(i);val=closure(temp);if(indexof(returnval,temp)<0);returnval.add(temp);for(int j=0;j<val.size();j++){if(indexof(returnval,val.get(j))<0);returnval.add(val.get(j));}}*/if(indexof(core,result)<0)core.add(result);}}public int getStart(int[] prod) //返回-1之后的数,没有返回-1{int i=0;while(prod[i]!=-1&&i<prod.length)i++;if(prod.length-1<=i)return -1;elsereturn prod[i+1];}public ArrayList<int []> getStartWith(int start, ArrayList<int []>handle){ArrayList <int []> val=new ArrayList<int []>() ;int i;for(i=0;i<handle.size();i++){if(isStartWith(start,handle.get(i))){val.add(handle.get(i));handle.remove(i);i--;}}return val;} //返回handle中所有-1之后是start的产生式,并删除public boolean isStartWith(int start,int [] prod) //产生式-1之后是否为start,是返回1,否则返回0;{boolean state=false;if(getStart(prod)==start)state=true;return state;}public void repair(ArrayList <int[]>prod) //将result 中产生式-1以后的数与-1调换{int num;int i,j=0;for(i=0;i<prod.size();i++){j=0;while(prod.get(i)[++j]!=-1);if(prod.get(i).length==j+1) //遇到空字符的动作continue;num=prod.get(i)[j];prod.get(i)[j]=prod.get(i)[j+1];prod.get(i)[j+1]=num;}}public void update(){ArrayList <int[]> Ary_n=new ArrayList<int[]>();ArrayList <int[]> Ary_r;int index;int prod[];for(int i=0;i<core.size();i++){Ary_n=core.get(i);Ary_r=new ArrayList<int[]>();for(index=0;index<Ary_n.size();index++){prod=(int[]) Ary_n.get(index);if(prod[0]==0||prod[1]!=-1)Ary_r.add(prod);}if(indexof(Ary_c,Ary_r)<0)Ary_c.add(Ary_r);}System.out.println();}}类:Phrase功能:为每个项目配备向前搜索符输入:LR0核心项目集输出:LALR(1)核心项目集实现思想:LALR(1)的造核算法public void sponsor(){Queue hq;int i,j;// 核心项目lnodeLinkNode lnode;QNode qnode;// 核心项目的产生式int p[];// -2是一个特殊的标志符,也就是传播符串的标志;int s[]={-2};calFirst =new CalFirst(producer);hq=new Queue();// 开始符号的特殊处理VT.add("#");I[0].search=new int[1];I[0].search[0]=VT.indexOf("#")+1000;qnode=new QNode(0,0);hq.enq(qnode);for(i=0;i<I.length;i++){lnode=I[i];while(lnode!=null){//if(lnode.search[0]==nu)item.clear();sstr.clear();// 有自生搜索符closuer_self(lnode.prod,s);if(item.size()>0){for(j=0;j<item.size();j++){qnode=update(item.get(j),sstr.get(j),hq);//修改自生搜索符,并入队// if(qnode!=null)//hq.enq(qnode);}}lnode=lnode.next;}}while(!hq.isEmpty()){qnode=hq.deq();lnode=getLinkNode(I[qnode.state],qnode.item);//qnode.i状态中的第j个项目p=lnode.prod;item.clear();sstr.clear();// 传播传播搜索符closuer_spread(p,lnode.search);if(item.size()>0){for(j=0;j<item.size();j++){qnode=update(item.get(j),lnode.search,hq);//修改传播搜索符\并入队//if(qnode!=null)// hq.enq(qnode);}}// 对每一个状态集都进行如此处理}}// 求出项目p的闭包中所有核心项目的自生搜索符private int [] copy(int []a ){int val[]=new int[a.length];for(int i=0;i<a.length;i++)val[i]=a[i];return val;}public boolean closuer_self(int p[],int []s){int i;int left=-1;//产生式左部int temp;int []genrate;int []pos;int []new_s;//ArrayList <Integer>pos=new ArrayList<Integer>();// 找到-1(.)之后的第一个符号for(i=1;i<p.length&&p[i]!=-1;i++);i++;// p为移进项目if(i<p.length)left=p[i];// p为归约项目elsereturn false;// p的闭包为其本身if(left>=1000)return false;// example:// 0 1 -1 1 1003 2// left = 1// s' = first(1003,2,s);i++;// 项目p中left之后的符号串加上s的first集就是left -1 XXX的搜索符集new_S new_s=first(p,i,s);pos=getStartWith(left);// closuer(p,pos);for(i=0;i<pos.length;i++){genrate=producer.get(pos[i]);// 递归向下求解,暂时定为自生一次即截止,向下传播通过genarate的自生求解if(genrate.length==2)continue;if(!(left==p[0]))closuer_self(genrate,s);elseif(!isEqual(genrate,p))closuer_self(genrate,s);// 搜索符集是自生的if(new_s[0]!=-2){genrate=copy(genrate);temp=genrate[1];genrate[1]=genrate[2];genrate[2]=temp;item.add(genrate);sstr.add(new_s);}}return true;}public void closuer(int item[],ArrayList <Integer>pos) {if(item.length==2)return ;int i;int p[];for(i=0;i<item.length&&item[i]!=-1;i++);if(item[i+1]<1000){p=getStartWith(item[i+1]);for(i=0;i<p.length;i++)if(pos.indexOf(p[i])==-1){pos.add(p[i]);closuer(producer.get(p[i]),pos);}}return ;}// 返回项目p所能传播到的所有项目public boolean closuer_spread(int p[],int s[]){int i;int left=-1;//产生式左部符号int []genrate;// int []pos;int []new_s;int temp;ArrayList <Integer>pos=new ArrayList<Integer>();// 找到-1(.)之后的第一个符号for(i=1;i<p.length&&p[i]!=-1;i++);i++;// p为移进项目if(i<p.length)left=p[i];// p为归约项目elsereturn false;//以下是重点genrate=copy(p);genrate[i]=-1;genrate[i-1]=left;item.add(genrate);sstr.add(s);// p的闭包为其本身(-1之后的第一个符号为终结符)if(left>=1000)return false;// example:// 0 1 -1 1 1003 2// left = 1// s' = first(1003,2,s);i++;// 项目p中left之后的符号串加上s的first集就是left -1 XXX的搜索符集new_S int []tempArr=new int[1];tempArr[0]=-2;new_s=first(p,i,tempArr);tempArr=null;// 获得所有以left退出的项目//pos=getStartWith(left);this.closuer(p, pos);for(i=0;i<pos.size();i++){genrate=producer.get(pos.get(i));// 搜索符集是传播的if(new_s[0]==-2&&genrate.length!=2){// 递归向下求解,暂时定为传播一次即截止,向下传播通过genarate的传播/* if(!(left==p[0]))closuer_spread(genrate,s);elseif(!isEqual(genrate,p))closuer_spread(genrate,s);*/genrate=copy(genrate);temp=genrate[1];genrate[1]=genrate[2];genrate[2]=temp;item.add(genrate);sstr.add(s);}}return true;}// 返回所有以i产生的产生式的位置(>=1个),并在第一个位置之后添加-1// 本函数是建立在producer中的产生式的左部按升序基础上的,不可随意使用public int []getStartWith(int i){int count=i;ArrayList<Integer> temp=new ArrayList<Integer>(3);while(count<producer.size()){if(producer.get(count)[0]==i)temp.add(count);elseif(producer.get(count)[0]>i)break;count++;}int val[]=new int[temp.size()];for(count=0;count<temp.size();count++)val[count]=temp.get(count);return val;}public int[] first(int []prod,int i,int search[]){if(i==prod.length)return search;//calFirst.a.clear();//calFirst.firstv(prod, i, search);return calFirst.first(prod, i, search);}private int[]arrCon(int[]a,int b[]){boolean isChange=false;ArrayList <Integer>temp=new ArrayList<Integer>();int i;if(a!=null){for(i=0;i<a.length;i++)temp.add(a[i]);}for(i=0;i<b.length;i++)//有所更新{if(temp.indexOf(b[i])==-1){temp.add(b[i]);isChange=true;}}a=new int[temp.size()];for(i=0;i<a.length;i++){a[i]=temp.get(i);}if(isChange)return a;elsereturn null;}public QNode update(int []prod,int []search,Queue hq) {//返回修改的项目是第几个状态集合中的(QNode.state)的第几个项目(QNode.item)(从0记数)LinkNode p;int a[];int item;int i=0;while(i<I.length){item=0;p=I[i];while(p!=null){if(isEqual(p.prod,prod)){a =arrCon(p.search,search);//null表示没有做任何修改if(a!=null){p.search =a;hq.enq( new QNode(i,item));return null;//此处是一个危险点,必须保证不能有一个项目在多个状态中出现,否则,会出现严重的错误}}item++;p=p.next;}i++;}return null;}public boolean isEqual(int []a,int []b){if(a.length !=b.length)return false;for(int i=0;i<a.length ;i++)if(a[i]!=b[i])return false;return true;}}类:Analyze功能:整个分析程序的总控程序输入:编译目标文件、输出文件路径输出:语法分析树、三地址代码、错误信息实现思想:LR分析器工作原理class Analyze{private ArrayList<int [] > producer =new ArrayList<int []>();private ArrayList<String > VT=new ArrayList<String>();private ArrayList<String > VN=new ArrayList<String>();// private LinkNode []I;// 移进均为小于1000的,归约为大于1000的,并且接受状态的内容为-1,空状态用-2表示private int[][]Action;private int[][]Goto;//Gotoprivate String []prods;private ArrayList<String>lalr;DefaultMutableTreeNode root=null;public ArrayList <String >errorInfo=new ArrayList<String>();public ArrayList <Integer>errorLine=new ArrayList<Integer>();public void analyze(String filePath,File outFile){FileInputStream f = null;try {f = new FileInputStream(filePath);} catch (FileNotFoundException e) {e.printStackTrace();}//打开词法分析流:DataInputStream input = new DataInputStream(f);//lex为词法分析器TinyCLexer lex=new TinyCLexer(input);try {Stack<Integer> stateStack =new Stack<Integer>();//状态栈Stack<Integer> tokenStack = new Stack<Integer>();//符号栈的内容为:非终结符与VN中相对应,终结符-1000后与VT中相对应int state;int temp;int []prod;int i;int action;TokenNode data;Token token=null;Token oldtoken=null;int tokentype;int end=VT.indexOf("#")+1000;//#入栈Tree tree=new Tree();Syntax syn=new Syntax(tree,new FileWriter(outFile));stateStack.push(0);//状态0保证是开始状态tokenStack.push(end);errorInfo.clear();errorLine.clear();token=lex.nextToken();//获得下一个面临的词法符while(true){state=stateStack.peek();//获得栈顶状态if(token.getType()>=100)//无意义的跳过continue;if(token.getText()==null){token.setType(VT.indexOf("#"));}//token.getType()就是面临的输入符号(一定是终结符),它与VT中相对应action=Action[state][token.getType()];if(action==-1){prod=producer.get(0);stateStack.pop();if(prod[2]!=tokenStack.pop()){JOptionPane.showMessageDialog(null, "编译程序遇到不能处理的错误!\n分析被中止", "提示",RMATION_MESSAGE,new ImageIcon("images\\error.png"));return ;}tree.Reduce(prod.length-2, VN.get(prod[0]));syn.SyntaxAnalyze(0);root= tree.getRoot();JOptionPane.showMessageDialog(null, "编译程序完成编译!", "提示",RMATION_MESSAGE,new ImageIcon("images\\right.png"));return ;}if(Action[state][token.getType()]<1000)//移进,转移到其中内容的状态{tokentype=token.getType();if(Action[state][tokentype]==-2){errorLine.add(oldtoken.getLine());tokentype=getShift(state,tokentype);errorInfo.add("错误:行("+token.getLine()+"\t)列("+token.getColumn()+")未知语法错误[shift]!");if(tokentype==-2){JOptionPane.showMessageDialog(null, "编译程序遇到不能处理的错误!\n分析被中止", "提示",RMATION_MESSAGE,new ImageIcon("images\\error.png"));return ;}}//出错处理;stateStack.push(Action[state][tokentype]);tokenStack.push(1000+tokentype);data=new TokenNode(token.getText(),tokentype);//把token信息保存起来,备用tree.Shift(data);//移进相关信息进栈}else{//归约,用Action[state][token.getType()]的产生式归约,用第Action[state][token.getType()]条产生式//DefaultTreeModeltemp=Action[state][token.getType()]-1000;prod=producer.get(temp);for(i=prod.length-1;i>1;i--)//产生式的右部的逆序为出栈顺序{stateStack.pop();if(prod[i]!=tokenStack.pop()){JOptionPane.showMessageDialog(null, "编译程序遇到不能处理的错误!\n分析被中止", "提示",RMATION_MESSAGE,new ImageIcon("images\\error.png"));return ;}}tree.Reduce(prod.length-2, VN.get(prod[0]));if(!syn.SyntaxAnalyze(temp)){errorInfo.add("错误:行("+oldtoken.getLine()+")列("+oldtoken.getColumn()+")"+ErrorTable.getErrorMsg(syn.getErrorTy pe()));errorLine.add(oldtoken.getLine());}//出栈完毕tokenStack.push(prod[0]);//产生式左部入符号栈if(Goto[stateStack.peek()][prod[0]]==-2){errorInfo.add("错误:行("+oldtoken.getLine()+")列("+oldtoken.getColumn()+")未知语法错误[reduce]!");errorLine.add(oldtoken.getLine());continue;}stateStack.push(Goto[stateStack.peek()][prod[0]]);//根据Goto表判断状态栈的内容continue;}//只有规约的时候不需要读入,其与都要oldtoken=token;token=lex.nextToken();//获得下一个面临的词法符}} catch (Exception e) {//此处有可能是出错的状态异常,如Action[temp][-2]会出现ArrayIndexOutBounds异常//,则说明语法检查中出错了,需要有相应的出错处理JOptionPane.showMessageDialog(null, "编译程序遇到不能处理的错误!\n分析被中止", "提示",RMATION_MESSAGE,new ImageIcon("images\\error.png"));return ;}}private int getShift(int state,int type){int i,j;i=j=type;while(i>=0&&j<VT.size()){if(Action[state][i]>-2&&Action[state][i]<1000)return i;if(Action[state][j]>-2&&Action[state][j]<1000)return j;i--;j++;}return -2;}public void setAction(int a[][]){Action=a;}public int[][] getAction(){return Action;}public void setGoto(int g[][]){Goto=g;}public int[][]getGoto(){return Goto;}public void setVT(ArrayList <String >vt) {VT=vt;}public ArrayList <String>getVT(){return VT;}public void setVN(ArrayList<String >vn){VN=vn;}public ArrayList <String> getVN(){return VN;}public void setProd(ArrayList<int[]>p){producer=p;}public void setLalr(ArrayList <String >l) {lalr=l;}public ArrayList<String> getLalr(){return lalr;}public ArrayList<int []> getProd(){return producer;}public void conProds(){prods=new String[producer.size()];int []prod;int temp;int j;for(int i=0;i<producer.size();i++){prod=producer.get(i);prods[i]="";for(j=0;j<prod.length;j++){temp=prod[j];if(temp==-1)prods[i]+="->";else{if(temp<1000)prods[i]+=VN.get(temp);elseprods[i]+=VT.get(temp-1000);}}}}public String[]getProds(){return prods;}}class LinkNode{int [] prod;int [] search;LinkNode next;public LinkNode(){prod=null;search=null;next=null;}}class Tree{DefaultMutableTreeNode root;Stack <TreeNode> stack;public Tree(){stack=new Stack<TreeNode>();}// 规约,建立一个跟接点并添家响应的孩子public void Reduce(int i,String name){TreeNode temp=new TreeNode(name);Stack <TreeNode> ts=new Stack<TreeNode>();for(;i>0;i--){ts.push(stack.pop());}while(!ts.isEmpty())temp.add(ts.pop());// 当前语法树的跟接点,名字是产生式的左部的名字,接点信息暂时为空,在语义分析的时候添加数据接点root=temp;stack.push(temp);}//移进,一定是遇到了终结符,所以数据接点直接为词法分析产生的结果public void Shift(TokenNode data){TreeNode temp=new TreeNode();temp.setNode(data);stack.push(temp);}public TreeNode getRoot(){return (TreeNode)root;}}/**************************************************************** *********************************///符号表的结构class TokenTable{TokenTable head=null;//父表ArrayList <TokenTable> child=new ArrayList<TokenTable>(1);//子表String tableName;int params=-1;//参数个数,参数在child 0到params-1位置ArrayList <String>name=new ArrayList<String>();ArrayList <Integer>type=new ArrayList<Integer>();ArrayList <Integer>offset=new ArrayList<Integer>();ArrayList <Integer>length=new ArrayList<Integer>();//保存变量长度,仅对数组变量有效,其他变量为1int returnType;public TokenTable(TokenTable head){this.head=head;}}/*************************************************************************************************///保存三地址代码的四元式数据结构class Code{String op;String arg1;String arg2;String result;public Code(){}public Code(String o,String a1,String a2,String res){op=o;arg1=a1;arg2=a2;result=res;}public String print(){returnop+"\t"+arg1+"\t"+arg2+"\t"+result+(char)(13)+( char)(10);}}class Label//label 是一段代码的标签{private int beginIndex=0;private ArrayList <Code>codes=new ArrayList<Code>();private ArrayList <Integer>next=new ArrayList<Integer>();//label 的出口public Label(){}public int getBeginIndex(){return beginIndex;}public void setBeginIndex(int newIndex){if(newIndex==beginIndex)return ;int i=0;char ch;for(i=0;i<codes.size();i++){ch=codes.get(i).result.charAt(0);if(ch>='0'&&ch<='9'){codes.get(i).result=Integer.toString(Integer.parseInt(codes.ge t(i).result)+newIndex-beginIndex);}}}public void setNext(int index){int i;for(i=0;i<next.size();i++){codes.get(next.get(i)).result=Integer.toString(index);}}/*** 增加一条三地址代码* @param code*/public void addCode(Code code){codes.add(code);}/*** 增加一个出口* @param i*/public void addNext(int i){next.add(i);}/*** 将label用最小空间存储**/public void trimtoSize(){codes.trimToSize();next.trimToSize();}/*** 将label中的codes加入当前的中* @param label*/public void addLabel(Label label){if(label==null)return ;label.setBeginIndex(codes.size());//label中的beginIndex整体后移for(int i=0;i<label.codes.size();i++)codes.add(label.codes.get(i));label.setNext(codes.size());//label中的出口为codes的下一句}/*** 获得此标签中一共有多少行代码* @return*/public int getCodesSize(){return codes.size();}/*** 输出*/public void print(FileWriter cout,String fun){setNext(codes.size());// Code code =new Code("HALT","_","_","_");// addCode(code);try {String str;str=""+(char)(13)+( char)(10)+(char)(13)+( char)(10)+"\t"+fun+ (char)(13)+( char)(10);cout.write(str.toCharArray());for(int i=0;i<codes.size();i++){str=("\t"+i+":\t");cout.write(str.toCharArray());str=codes.get(i).print();cout.write(str.toCharArray());}cout.flush();} catch (Exception e){JOptionPane.showMessageDialog(null, "输出文件遇到写入的错误!\n请重新编译", "提示",RMATION_MESSAGE,new ImageIcon("images\\error.png"));return ;}}public Code getCode(int index0){return codes.get(index0);}}三.测试结果与分析本次设计采用的例文法如下:S’→SS →EE →E+TE →TT →(E)T →a分析得到它的状态图如下:由于界面实在不会做,因此运行程序得到的实际结果如下:项目族:状态转换表:分析表如下:输入字符串a+(a+a)得到语法树如下:四.心得与体会本次课程设计并非像老师所说的那么简单容易完成。

编译原理报告二 LR分析器

编译原理报告二 LR分析器

LR分析器一、目的和要求通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。

1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR 分析分析程序,并至少完成两个题目。

2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。

⑴实验前的准备按实验的目的和要求,编写语法分析程序,同时考虑相应的数据结构。

⑵调试调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。

⑶输出对于所输入的算术表达式,不论对错,都应有明确的信息告诉外界。

⑷扩充有余力的同学,可适当扩大分析对象。

譬如:①算术表达式中变量名可以是一般标识符,还可含一般常数、数组元素、函数调用等等。

②除算术表达式外,还可扩充分析布尔、字符、位等不同类型的各种表达式。

③加强语法检查,尽量多和确切地指出各种错误。

⑸编写上机实习报告。

二、背景知识※自下而上分析技术-LR(K)方法LR(K)方法是一种自下而上的语法分析方法,是当前最广义的无回溯的“移进- 归约”方法。

它根据栈中的符号串和向前查看的k(k 0)个输入符号,就能唯一确定分析器的动作是移进还是归约,以及用哪个产生式进行归约。

优点:文法适用范围广;识别效率高;查错能力强;可自动构造。

逻辑组成:总控程序+LR分析表LR分析器的结构:一个LR分析器实际是一个带先进后出存储器(栈)的确定下推自动机,它由一个输入串、一个下推栈和一个带有分析表的总控程序组成。

栈中存放着由“历史”和“展望”材料抽象而来的各种“状态”。

任何时候,栈顶的状态都代表了整个的历史和已推测出的展望。

为了有助于明确归约手续,我们把已归约出的文法符号串也同时放进栈里。

LR分析器的每一动作都由栈顶状态和当前输入符号所唯一确定。

LR分析器模型图分析器的任何一次移动都是根据栈顶状态S m和当前输入符号a i,去查看ACTION表并执行ACTION(S m,a i)规定的动作,直至分析成功或失败。

(完整word版)编译原理报告二LR分析器

(完整word版)编译原理报告二LR分析器

LR分析器一、目的和要求通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。

1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,并至少完成两个题目。

2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。

⑴实验前的准备按实验的目的和要求,编写语法分析程序,同时考虑相应的数据结构。

⑵调试调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。

⑶输出对于所输入的算术表达式,不论对错,都应有明确的信息告诉外界。

⑷扩充有余力的同学,可适当扩大分析对象。

譬如:①算术表达式中变量名可以是一般标识符,还可含一般常数、数组元素、函数调用等等。

②除算术表达式外,还可扩充分析布尔、字符、位等不同类型的各种表达式。

③加强语法检查,尽量多和确切地指出各种错误。

⑸编写上机实习报告。

二、背景知识※自下而上分析技术-LR(K)方法LR(K)方法是一种自下而上的语法分析方法,是当前最广义的无回溯的“移进- 归约”方法。

它根据栈中的符号串和向前查看的k(k³0)个输入符号,就能唯一确定分析器的动作是移进还是归约,以及用哪个产生式进行归约。

优点:文法适用范围广;识别效率高;查错能力强;可自动构造。

逻辑组成:总控程序+LR分析表LR分析器的结构:一个LR分析器实际是一个带先进后出存储器(栈)的确定下推自动机,它由一个输入串、一个下推栈和一个带有分析表的总控程序组成。

栈中存放着由“历史”和“展望”材料抽象而来的各种“状态”。

任何时候,栈顶的状态都代表了整个的历史和已推测出的展望。

为了有助于明确归约手续,我们把已归约出的文法符号串也同时放进栈里。

LR分析器的每一动作都由栈顶状态和当前输入符号所唯一确定。

LR分析器模型图分析器的任何一次移动都是根据栈顶状态S m和当前输入符号a i,去查看ACTION表并执行ACTION (S m,a i)规定的动作,直至分析成功或失败。

编译原理LR(0)分析器(C语言)

编译原理LR(0)分析器(C语言)
表2 步骤 1 2 3 4 5 6 7 8 状态栈 0 05 03 02 01 016 0165 0163 i+i*i 的 LR 分析过程表 符号栈 # #i #F #T #E #E+ #E+i #E+F 输入串 i+i*i# +i*i# +i*i# +i*i# +i*i# i*i# *i# *i# 说明 ACTION[0,i],移进 ACTION[5,+],归约且 GOTO[0,F] ACTION[3,+],归约且 GOTO[0,T] ACTION[2,+],归约且 GOTO[0,] ACTION[1,+],移进 ACTION[6,i],移进 ACTION[5,*],归约且 GOTO[6,F] ACTION[3, {0,6,0,0,11,0}, {0,1,7,0,1,1}, {0,3,3,0,3,3}, {0,5,5,0,5,5}};/*create action table's state number*/ int go[12][3]={{1,2,3}, {0,0,0}, {0,0,0}, {0,0,0}, {8,2,3}, {0,0,0}, {0,9,3}, {0,0,10}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}};/*create goto table's state*/ void main() { int step=1;/*number of analysis step*/ int length=0;/*length of string*/ int i,j,m,n; int l=0;/*length of state & ch*/ int k=0; int num; int state[6]={0};/*initial state stack*/ char ch[6]={'#'}; /*initial character stack*/ char str[10];/*define array of string*/ char cha; char how;/*how include 's','r','a' and null*/ char A; clrscr(); printf("Please input a string:"); do { scanf("%c",&cha); str[length]=cha; length++; }while(cha!='#');/*input a string and calculate it's length*/ printf("\n-------------------------------------------------------------------------------\n"); printf("Step\tState\t\tCharacter\tString\t\tAction\n");

编译原理课程设计lr

编译原理课程设计lr

编译原理课程设计lr一、教学目标本课程的教学目标是使学生掌握编译原理的基本概念、理论和方法,培养学生对编译器设计和实现的理解和能力。

具体目标如下:1.理解编译原理的基本概念,如文法、语法、词法、抽象语法树等。

2.掌握编译器的主要组成部分和工作原理,如词法分析器、语法分析器、中间代码生成器、代码优化器和目标代码生成器等。

3.熟悉编译器的实现技术,如有限自动机、递归下降分析和动态规划等。

4.能够使用编译原理的相关工具和技术,如LEX、YACC等。

5.具备简单的编译器设计和实现能力,能够编写词法分析器、语法分析器和目标代码生成器等。

情感态度价值观目标:1.培养学生的抽象思维能力和逻辑推理能力。

2.激发学生对编译原理的兴趣和好奇心,培养学生的学术探索精神。

二、教学内容本课程的教学内容主要包括编译原理的基本概念、理论和方法。

具体内容包括以下几个方面:1.编译原理概述:介绍编译器的作用、分类和基本组成部分。

2.词法和语法分析:讲解词法的定义、有限自动机、正则表达式等概念,以及语法分析的基本方法、分析树和抽象语法树等。

3.中间代码生成和优化:介绍中间代码的概念、生成方法和技术,以及代码优化的方法和策略。

4.目标代码生成:讲解目标代码的概念、生成方法和目标代码优化等。

5.编译器实现技术:介绍有限自动机、递归下降分析和动态规划等技术在编译器实现中的应用。

三、教学方法本课程采用多种教学方法相结合的方式,以激发学生的学习兴趣和主动性。

具体方法如下:1.讲授法:教师讲解编译原理的基本概念、理论和方法。

2.案例分析法:分析典型的编译器设计和实现案例,使学生更好地理解编译原理的应用。

3.实验法:安排实验课程,让学生亲自动手实现简单的编译器组件,提高学生的实践能力。

4.讨论法:课堂讨论,鼓励学生提问、发表见解,培养学生的思维能力和沟通能力。

四、教学资源本课程的教学资源包括教材、参考书、多媒体资料和实验设备等。

具体如下:1.教材:《编译原理》(作者: Alfred V. Aho, Monica S. Lam, RaviSethi, Jeffrey D. Ullman)。

编译原理课程设计--LR(0)分析器自动构造程序的实现

编译原理课程设计--LR(0)分析器自动构造程序的实现

衡阳师范学院工科课程设计 -《编译原理》课程设计报告题目:LR(0)分析器自动构造程序的实现学号:13190207姓名:谭金星班级:1302指导教师:陈琼老师日期:2016年6月20日目录第一章概述 (3)第二章设计的基本原理 (4)2.1 识别文法的LR(0)项目集规范族的构造 (4)2.2 LR(0)分析表的构造 (4)2.3 LR(0)分析器总控程序构造 (5)第三章程序设计 (6)3.1 程序总体构架 (6)3.2 程序存储结构 (7)3.2.1 符号表存储结构 (7)3.2.2 产生式表存储结构 (7)3.2.3 项目集规范族表存储结构 (8)3.2.4 LR(0)分析表存储结构 (9)3.3 程序算法 (9)3.3.1 项目集规范族的构造 (9)3.3.2 LR(0)分析表构造 (10)第四章程序测试 (11)4.1 符号表测试 (11)4.2 产生式表测试 (12)4.3 项目集规范族表测试 (12)4.4 LR(0)分析表测试 (13)4.5 LR(0)分析器测试 (13)第五章总结和展望 (14)附录 (16)参考文献 (17)一概述本课程设计完成了以下内容:1. 实现了对任意给定的文法G,识别文法活前缀的DFA、DFA的状态转化矩阵及(0)LR项目集规范族的构造;2. 判断该文法是否为(0)LR分析表的构造,并输出到指定文LR文法,实现了(0)件中;3. 实现了(0)LR分析器总控程序,对输入的表达式进行文法分析。

4.在VC++6.0程序上运行二 设计的基本原理本课程设计的核心算法错误!未找到引用源。

主要有三点:1. 识别文法活前缀的DFA 、DFA 的状态转化矩阵及(0)LR 项目集规范族的构造;2. (0)LR 分析表的构造;3.(0)LR 分析器总控程序的构造。

2.1 识别文法的LR(0)项目集规范族的构造采用CLOSURE ε-(闭包)的构造一个文法G 的(0)LR 项目规范簇。

编译原理教案lr分析

编译原理教案lr分析

编译原理教案-LR分析一、教学目标1. 理解LR分析的基本概念和原理2. 掌握LR分析的构造方法和使用技巧3. 能够应用LR分析解决编译过程中的词法分析和语法分析问题二、教学内容1. LR分析的基本概念LR分析的定义和作用LR分析的状态和动作2. LR分析的构造方法LR分析表的构造步骤LR分析表的优化方法3. LR分析的使用技巧LR分析的输入处理LR分析的错误处理和恢复三、教学过程1. 引入LR分析的概念,解释其在编译过程中的重要性2. 讲解LR分析的基本原理和状态动作的定义3. 演示LR分析表的构造过程和优化方法4. 通过实例讲解LR分析的使用技巧和应用场景5. 进行课堂练习,让学生巩固所学知识和技能四、教学评估1. 课堂讲解和演示的效果评估2. 学生课堂练习的表现评估3. 学生对LR分析的理解程度和应用能力的评估五、教学资源1. 教案、PPT和教学资料2. LR分析的相关教材和参考书3. 编程环境和编译工具六、教学案例分析1. 分析具体编译程序的LR分析过程。

2. 通过案例,理解LR分析在实际编译过程中的应用。

3. 讨论如何优化LR分析表以提高分析效率。

七、LR分析练习1. 让学生通过练习题加深对LR分析的理解。

2. 练习题包括LR分析表的构造、状态动作的确定等。

3. 教师提供解答和解析,帮助学生巩固知识点。

八、LR分析在实际中的应用1. 讲解LR分析在其他编译环节中的应用,如词法分析、语义分析等。

2. 探讨如何将LR分析与其他编译技术相结合,提高编译效率。

3. 分析实际项目中LR分析的成功应用案例。

九、课堂讨论与研究1. 组织学生进行课堂讨论,分享对LR分析的理解和心得。

2. 讨论LR分析在实际编程和编译过程中的优势和局限。

3. 引导学生进行研究性学习,探索LR分析的新技术和方法。

十、教学总结与展望1. 总结本章节所学内容,强调LR分析在编译原理中的重要性。

2. 鼓励学生在后续学习中继续探索和研究LR分析相关技术。

LR 分析方法程序设计原理与实现技术实验报告及源代码 北京交通大学

LR 分析方法程序设计原理与实现技术实验报告及源代码 北京交通大学
lr分析方法程序设计原理与实现技术实验报告及源代码北京交通大学lr分析方法程序设计原理与实现技术xxx1028xxx计科1xxx通过设计编写和构造lr0项目集规范簇和lr分析表对给定的符号串进行lr析的程序了解构造lr0分析表的步骤对文法的要求能够从文法出发生成lr0分析表并对给定的符号串进行分析
LR 分析方法程序设计原理与实现技术
分析失败:aAcAd
分析成功:acd
7. 实验总结:
本次实验按照书上的相应步骤,一步一步按照要求来完成实现,最终文成了给定文 法的分析程序。首先是获取文法,文法的获取是采用直接输入的方法,保存成预先设定 的结构体,然后根据文法,对文法编号,求出项目集规范族,然后再构造 LR(0)分析 表,最后根据分析表来判断输入符号串是否为此文法产生的语言。
sign = 0;
for(int i = 0;i < pro[0].data.size();i ++){
for(int j = 0;j < pro[0].data[i].right.size();j ++){
char ch = pro[0].data[i].right[j][1];
if(ch <= 'Z' && ch >= 'A' && pro[0].data[i].sign == 0){ //
cout << " 文法获取完成"
<< endl;
cout << "****************************************" << endl;
cout << endl;

LR(0)分析法的实现编译原理课程设计

LR(0)分析法的实现编译原理课程设计

LR(0)分析法的实现编译原理课程设计《编译原理》课程设计报告LR(0)分析法的实现学院(系):班级:学生姓名:学号指导教师:时间:从2007 年12月17日到2007年 12月29日目录1.课程设计的目的 (2)2.课程设计的内容及要求 (2)3.实现原理 (3)3.1 LR分析器结构 (3)3.2 LR分析法寻找可归约句柄的依据 (3)3.3 LR分析器的核心 (4)3.4 LR分析器的总控程序 (4)3.5 具体过程分析如下: (5)3.6 LR(0)分析表构造基本思想 (5)3.7 构造LR(0)分析表的方法 (6)3.7.1生成文法G的LR(0)项目 (6)3.7.2 由项目构成识别文法活前缀的DFA (6)3.7.3将所得DFA确定化 (6)3.7.4 LR(0)项目集规范簇的自动构造 (7)3.7.5 LR(0)分析表的构造算法 (7)4.算法实现流程图 (8)5.测试数据 (9)6.结果输出及分析 (10)7.软件运行环境及限制 (14)8.心得体会 (15)9.参考文献 (15)1.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。

同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。

2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。

2.文法采用常用的方式进行描述,例如:S→aA。

3.以文件方式读取文法。

4.求出项目集规范族(即所有的状态)。

5.给出状态间的关系。

6.给出LR(0)分析表。

7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。

3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。

对所有的LR分析器总控程序都是相同的。

(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。

编译原理课程设计LR(1)分析法

编译原理课程设计LR(1)分析法

课程设计说明书课程名称:_编译原理课程设计_题目: LR(1)分析法院系:_专业班级:学号:__学生姓名:___指导教师:___2012年 6 月 22 日安徽理工大学课程设计(论文)任务书2012年6 月22 日安徽理工大学课程设计(论文)成绩LR(1)分析法一、系统简介及需求分析1.1 设计目的及要求(1)掌握LR(1)分析法的基本原理;(2)掌握LR(1)分析表的构造方法;(3)掌握LR(1)驱动程序的构造方法。

(4)构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子.1.2实验内容根据某一文法编制调试LR(1)分析程序,以便对任意输入的符号串进行分析。

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

对下列文法,用LR(1)分析法对任意输入的符号串进行分析:(0)E->S(1)S->BB(2)B->aB(3)B->b程序输入一以#结束的符号串(包括a、b、#),如:abb#。

输出过程如下:步骤状态栈符号栈输入串ACTION GOTO1 0 # abb# S3... ... ... ... ... ...图1-1二、设备与环境2.1硬件设备内存容量 2 GB硬盘容量 320 GB硬盘描述 7200转,SATA流处理器个数 322.2软件环境操作系统:WINDOWS XP开发平台:C语言开发软件: VC++ 6.0三、系统分析3.1 LR(1)分析法定义LR分析法是一种有效的自底向上的语法分析技术,它能适用于大部分上下文无关文法的分析,一般叫LR(k)分析方法,其中L是指自左(Left)向右扫描输入单词串,R是指分析过程都是构造最右(Right)推导的逆过程(规范归约),括号中的k是指在决定当前分析动作时向前看的符号个数。

3.2 LR(1)分析方法的主要思想(1)严格地进行最左归约(识别句柄并归约它)。

(2)将识别句柄的过程划分为由若干状态控制,每个状态控制识别出句柄的一个符号。

编译原理教案lr分析

编译原理教案lr分析

编译原理教案LR 分析第一章:LR 分析简介1.1 课程目标理解LR 分析的基本概念和原理掌握LR 分析的基本算法和实现方法1.2 教学内容LR 分析的定义和作用LR 分析的基本原理和算法LR 分析器的构造和优化1.3 教学方法讲解和演示相结合的方式进行教学通过实例和练习帮助学生理解和掌握LR 分析的原理和方法1.4 教学工具投影仪和计算机LR 分析相关的教学软件和工具第二章:LR 分析的基本原理2.1 课程目标理解LR 分析的基本原理和算法掌握LR 分析器的构造和优化方法2.2 教学内容LR 分析的分类和特点LR 分析的基本原理和算法LR 分析器的构造和优化方法2.3 教学方法讲解和演示相结合的方式进行教学通过实例和练习帮助学生理解和掌握LR 分析的原理和方法2.4 教学工具投影仪和计算机LR 分析相关的教学软件和工具第三章:LR 分析的算法实现3.1 课程目标理解LR 分析的基本算法和实现方法掌握LR 分析器的构造和优化方法3.2 教学内容LR 分析的基本算法和实现方法LR 分析器的构造和优化方法LR 分析的应用和示例3.3 教学方法讲解和演示相结合的方式进行教学通过实例和练习帮助学生理解和掌握LR 分析的原理和方法3.4 教学工具投影仪和计算机LR 分析相关的教学软件和工具第四章:LR 分析器的构造和优化4.1 课程目标掌握LR 分析器的构造和优化方法能够设计和实现一个简单的LR 分析器4.2 教学内容LR 分析器的构造和优化方法LR 分析器的实现和测试LR 分析器的优化技巧和策略4.3 教学方法讲解和演示相结合的方式进行教学通过实例和练习帮助学生理解和掌握LR 分析器的构造和优化方法4.4 教学工具投影仪和计算机LR 分析相关的教学软件和工具第五章:LR 分析的应用和示例5.1 课程目标了解LR 分析在编译器设计中的应用和示例能够使用LR 分析方法分析和解决编译器设计中的问题5.2 教学内容LR 分析在编译器设计中的应用和示例LR 分析方法的优缺点和适用场景LR 分析与其他分析方法的比较和选择5.3 教学方法讲解和演示相结合的方式进行教学通过实例和练习帮助学生理解和掌握LR 分析的应用和示例5.4 教学工具投影仪和计算机LR 分析相关的教学软件和工具第六章:LR 分析器的实现细节6.1 课程目标理解LR 分析器实现过程中的关键细节。

编译原理LR0分析过程的实现

编译原理LR0分析过程的实现

淮北师范大学编译原理课程设计课题名称:LR(0)分析过程的实现班级:2014级非师2班学号:20141202109姓名: 夏涛目录1.课程设计的目的22.课程设计的内容及要求23.实现原理23.1 LR分析器结构23.2 LR分析法寻找可归约句柄的依据33.3 LR分析器的核心33.4 LR分析器的总控程序43.5 具体过程分析如下:43.6 LR(0)分析表构造基本思想43.7 构造LR(0)分析表的方法53.7.1生成文法G的LR(0)项目53.7.2 由项目构成识别文法活前缀的DFA53.7.3将所得DFA确定化53.7.4 LR(0)项目集规范簇的自动构造63.7.5 LR(0)分析表的构造算法74.算法实现流程图75.测试数据86.结果输出及分析97.软件运行环境及限制128.心得体会139.参考文献131.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。

同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。

2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。

2.文法采用常用的方式进行描述,例如:S→aA。

3.以文件方式读取文法。

4.求出项目集规范族(即所有的状态)。

5.给出状态间的关系。

6.给出LR(0)分析表。

7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。

3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。

对所有的LR分析器总控程序都是相同的。

(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。

(3) 分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。

编译原理-LR语法分析器的控制程序实验报告

编译原理-LR语法分析器的控制程序实验报告

编译原理实验报告学号姓名时间专业班级实验题目:LR语法分析器的控制程序实验目的:手工模拟控制程序计算,对源程序进行LR 语法分析主要是分析表的构造实验内容与步骤:1.将要进行LR 语法分析的源程序和LR 语法分析器控制程序放在同一文件夹中。

2.用 C 语言编写 LR 语法分析器控制程序,程序代码如下:#include <fstream.h>#include <iostream.h>#include <stdlib.h>#include <string.h>struct code_val{char code;char val[20];};const char *p[]={//产生式"S→ E","E → E+T","E → T","T → T*F","T → F","F → (E)","F → i"};const char TNT[ ]="+*()i#ETF";//LR 分析表列的字符const int M[][9]={//LR 分析表数字化,列字符 +*()i#ETF用数字 012345678 标识。

{ 0, 0, 4, 0, 5,0, 1, 2, 3},//0 表示出错, s4 用 4 表示。

{ 6, 0, 0, 0, 0,99},//Acc 用 99 表示{-2, 7, 0,-2, 0,-2},//r2 用 -2 表示{-4,-4, 0,-4, 0,-4},{ 0, 0, 4, 0, 5, 0, 8, 2, 3},{-6,-6, 0,-6, 0,-6}, { 0, 0,4, 0, 5, 0, 0, 9, 3},{ 0, 0, 4, 0, 5, 0, 0, 0,10},{ 6, 0, 0,11},{-1, 7, 0,-1, 0,-1},{-3,-3, 0,-3, 0,-3},{-5,-5, 0,-5, 0,-5}};int col(char);void main(){//列定位函数原型int state[50]={0};//状态栈初值char symbol[50]={'#'};//符号栈初值int top=0;//栈顶指针初值ofstream cout("par_r.txt");//语法分析结果输出至文件par_r.txtifstream cin("lex_r.txt");// lex_r.txt 存放词法分析结果,语法分析器从该文件输入数据。

编译原理-LR语法分析器的控制程序实验报告

编译原理-LR语法分析器的控制程序实验报告

编译原理实验报告实验目的:手工模拟控制程序计算,对源程序进行LR 语法分析 主要是分析表的构造实验内容与步骤:1•将要进行LR 语法分析的源程序和LR 语法分析器控制程序放在同一文件夹 中。

2.用C 语言编写LR 语法分析器控制程序,程序代码如下:#in elude <fstream.h> #in clude <iostream.h> #i nclude <stdlib.h> #in clude <stri ng.h> struct code_val{char code;char val[20]; };con st char *p[]={// 产生式"S T E","E T E+T","E T T","T T T*F","T T F","F T (E)","F T i };const char TNT[ ]="+*()i#ETF"; con st int M[][9]={{ 0, 0, 4, 0, 5,0, 1,2, 3}, { 6, 0, 0, 0, 0,99}, {-2, 7, 0,-2, 0,-2}, {-4,-4, 0,-4, 0,-4}, { 0, 0, 4, 0, 5, 0, 8, 2, 3}, {-6,-6, 0,-6, 0,-6},{ 0, 0, 4, 0, 5, 0, 0, 9, 3}, { 0, 0, 4, 0, 5, 0, 0, 0,10}, { 6, 0, 0,11}, {-1,7, 0,-1,0,-1}, {-3,-3, 0,-3, 0,-3}, {-5,-5, 0,-5, 0,-5} };//LR 分析表列的字符//LR 分析表数字化,列字符 +*()i#ETF 用数字012345678标识。

编译原理教案LR分析

编译原理教案LR分析

S aAcBe[1] aAcd[4]e[1] aAb[3]cd[4]e[1] ab[2]b[3]cd[4]e[1]
每次归约句型的 前部分依次为:
ab[2] aAb[3] aAcd[4] aAcBe[1]
规范句型的这种前部分符号串称为可归前缀
我们把形成可归前缀之前包括可归前缀在内 的所有规范句型的前缀都称为活前缀
动作
移进 移进 归约(A→b) 移进 归约(A→Ab)
状态栈
0 02 024 023 0236
ACTION
S2 S4 r2 S6 r3
GOTO
3 3
对输入串abbcde#的LR分析过程
S
1*
b
4
0 a 2 A 3 b 6
c
5 B7e9
d
8
步骤 符号栈 输入符号串
1) # 2) #a 3) #ab 4) #aA 5) #aAb 6) #aA
# #a #ab #aA #aAb #aA #aAc # aAcd #aAcB #aAcBe
abbcde# bbcde# bcde# bcde# cde# cde# de# e# e# #
动作
移进 移进 归约(A→b) 移进 归约(A→Ab) 移进 移进 归约(B→d) 移进 归约(S→aAcBe)
a c e b d#SA B
0 S2 1
1 acc
2
S4
3
3
S5
S6
4 r2 r2 r2 r2 r2 r2
Si:移进,并将状态i进栈 ri:用第i个产生式归约,同时状
5 6 r3 r3 r3 r3 r3 r3 7
7
态栈与符号栈退出相应个符号, 根据GOTO表将相应状态入栈

LR 分析方法程序设计原理与实现技术

LR 分析方法程序设计原理与实现技术

LR 分析方法程序设计原理与实现技术1郑杰09274053本实验程序中的一些约定:在工程文件main.h中定义所有函数,和数据结构。

在符号方面,$S定义为拓广文法的新引入的起始符号,$START不能和$S一样,并且,为了方便,在原来的产生式上强行加上这么一条产生式$S $START,这一点在main.c中定义文法可以看出来,并且该产生式加在产生式集的首要位置。

状态栈的设计引用以前程序中的数据结构,但是栈操作在本程序中有所扩展。

下面按照程序编写过程顺序介绍各个模块:一.文法产生式扩展由原来的产生式拓展成为加’.’的文法,并且在这个过程中要引入新的起始符号,但是在程序中并没有在这个过程中这么做,原因是因为在原来的产生式集中已经引入新的符号以及产生式,根据原始产生式集计算所需要存储新的拓展产生式集的所需要的产生式个数,然后动态开辟内存空间,再对每个原始产生式的各个位置加'.'。

在本次程序中用来产生拓展文法产生式集的函数定义如下:PPRO ParseProArray(PPRO lpPriProArr,int iProLen,int *iParsedLen)//参数说明:lpPriProArr:PPRO原始产生式集iProLen:int原始产生式个数iParsedLen:int*;拓展产生式集的个数返回值//返回值:拓展产生式集的首地址二.CLOSURE闭包求取在介绍求一个项目集的闭包前,先介绍程序中存储项目集(状态)的数据结构:typedef struct _ITEM_COLLOECTION{int iCount;//项目集合中的产生式个数int iSeqNumber;//项目集合(状态)的状态号PPRO ProCollection[MAX_ITEM_COUNT];//产生式集合的引用数组struct _ITEM_COLLOECTION * nextCollection;//由于程序中项目集合之间存储组织是单向链表,因此有这个域struct _GO{//GOTO映射数组,byte Symbol;//经历当前符号struct _ITEM_COLLOECTION * DestStatus;//跳转的下一个状态(项目集合)的引用}GO_MAP[SYMBOL_COUNT];//由符号个数来定义这个数组的长度}ITEM_COLL,*PITEM_COLL;1编译原理第五次实验报告.求解一个项目集合的CLOSURE闭包的具体方法是1.对于给定的项目集I,对于I中的的每一个产生式属于2.对于现有的闭包集合中的产生式A-->a.Xb,其中X是非终结符,那么对于文法拓展的产生式X-->.Y均属于CLOSURE(I)。

LR(0)分析法的实现编译原理课程设计

LR(0)分析法的实现编译原理课程设计

LR(0)分析法的实现编译原理课程设计《编译原理》课程设计报告LR(0)分析法的实现学院(系):班级:学生姓名:学号指导教师:时间:从2007 年12月17日到2007年 12月29日目录1.课程设计的目的 (2)2.课程设计的内容及要求 (2)3.实现原理 (3)3.1 LR分析器结构 (3)3.2 LR分析法寻找可归约句柄的依据 (3)3.3 LR分析器的核心 (4)3.4 LR分析器的总控程序 (4)3.5 具体过程分析如下: (5)3.6 LR(0)分析表构造基本思想 (5)3.7 构造LR(0)分析表的方法 (6)3.7.1生成文法G的LR(0)项目 (6)3.7.2 由项目构成识别文法活前缀的DFA (6)3.7.3将所得DFA确定化 (6)3.7.4 LR(0)项目集规范簇的自动构造 (7)3.7.5 LR(0)分析表的构造算法 (7)4.算法实现流程图 (8)5.测试数据 (9)6.结果输出及分析 (10)7.软件运行环境及限制 (14)8.心得体会 (15)9.参考文献 (15)1.课程设计的目的通过课程设计进一步理解高级语言在计算机中的执行过程,加深对编译原理中重点算法和编译技术的理解,提高自己的编程能力,培养好的程序设计风格。

同时通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。

2.课程设计的内容及要求1.可以使用任何语言来完成,例如:Java、C、C++。

2.文法采用常用的方式进行描述,例如:S→aA。

3.以文件方式读取文法。

4.求出项目集规范族(即所有的状态)。

5.给出状态间的关系。

6.给出LR(0)分析表。

7.给定的任意符号串判定是否是文法中的句子,将分析过程用计算机打印出来。

3.实现原理3.1 LR分析器结构LR分析器由三个部分组成:(1) 总控程序,也可称驱动程序。

对所有的LR分析器总控程序都是相同的。

(2) 分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。

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

合肥工业大学计算机与信息学院课程设计课程:编译原理专业班级:计算机科学与技术09-2班学号:姓名:一:设计题目题目: LR分析器总控程序的实现设计内容及要求:对P.101中的文法,按图5.5LR分析表构造LR分析器。

要求程序按P.102例5.7那样,对于输入串i*i+i,输出LR分析器的工作过程。

改进:可以自行输入输入串,能按重新按钮重新开始,外加了一个计时器。

二:设计目的进一步了解了LR分析器的整个工作过程,将LR分析器以图形界面的形式展现了出来,有利加深了对LR分析过程的掌握。

三:实验原理本程序是用windows编的,大体的思想是这样的:通过建立一个符号栈,状态栈,输入栈(结构体类型定义的)分别用来存放符号,状态,输入串,将LR 分析表构造成为一个二维数组table[13][9],其中0--11表示状态结点,21--26表示规约标号,-1表示error(出错),12表示acc(接受),在acation函数里面通过i等于多少来判断到底是规约还是移进。

在Main_OnCommand()函数中通过switch....case..来判断每次及下一步所要执行的操作。

运行的时候,首先要输入一个以#结尾的输入串,然后单击开始——>下一步.....,如果规约成功,则弹出一个规约成功的对话框,否则弹出一个规约失败的对话框。

当然在运行的过程中如果出现什么差错,都可以单击重新开始按钮重新输入输入串重新开始。

四:实验代码#include "stdAfx.h"#include <windows.h>#include <windowsx.h>#include "resource.h"#include "MainDlg.h"char *str2[6]={"E->E+T","E->T","T->T*F","T->F","F->(E)","F->i"};int flag=0;#define MAX 20typedef struct{int stack1[MAX];int top1;}status;typedef struct{char stack2[MAX];int top2;}symbol_instr;char index_char[9]={'i','+','*','(',')','#','E','T','F'};//为二维数数组的纵坐标//LR分析表//0--11表示状态结点,21--26表示规约标号,//-1表示error(出错),12表示acc(接受)int table[13][9] = {{ 5,-1,-1, 4,-1,-1, 1, 2, 3},\{-1, 6,-1,-1,-1,12,-1,-1,-1},\{-1,22, 7,-1,22,22,-1,-1,-1},\{-1,24,24,-1,24,24,-1,-1,-1},\{ 5,-1,-1, 4,-1,-1, 8, 2, 3},\{-1,26,26,-1,26,26,-1,-1,-1},\{ 5,-1,-1, 4,-1,-1,-1, 9, 3},\{ 5,-1,-1, 4,-1,-1,-1,-1,10},\{-1, 6,-1,-1,11,-1,-1,-1,-1},\{-1,21, 7,-1,21,21,-1,-1,-1},\{-1,23,23,-1,23,23,-1,-1,-1},\{-1,25,25,-1,25,25,-1,-1,-1}};//规约规则struct rule{char x;int y;}r[6]={{'E',3},{'E',1},{'T',3},{'T',1},{'F',3},{'F',1}}; //后面的代表A—>@中@的长度BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch(uMsg){HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose);}return FALSE;}void init_stack1(HWND hwnd,status *p){if( !p)MessageBox(hwnd,TEXT("出错"),TEXT("警告"),MB_OK|MB_ICONHAND);p->top1 = -1;}void push1(HWND hwnd,status *&p,int x){if(p->top1 < MAX-1){p->top1++;p->stack1[p->top1] = x;}else MessageBox(hwnd,TEXT("出错"),TEXT("警告"),MB_OK|MB_ICONHAND);}int pop1(HWND hwnd,status *p){int x;if(p->top1 != 0){x = p->stack1[p->top1];p->top1--;return x;}else{MessageBox(hwnd,TEXT("状态栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n状态栈1空!\n");return 0;}}void out_stack(HWND hwnd,status *p){if(p->top1 <0)MessageBox(NULL,TEXT("状态栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n状态栈3空!\n");int i;TCHAR str[256];for(i=0;i<=p->top1;i++)wsprintf(&str[i],"%d",p->stack1[i]);SetDlgItemText(hwnd,IDC_EDIT1,str);}int get_top1(HWND hwnd,status *p){int x;if(p->top1 != -1){x = p->stack1[p->top1];return x;}else{MessageBox(hwnd,TEXT("状态栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n状态栈2空!\n");return 0;}}void init_stack2(HWND hwnd,symbol_instr *p){if( !p)MessageBox(hwnd,TEXT("出错"),TEXT("警告"),MB_OK|MB_ICONHAND);p->top2= -1;}void push2(HWND hwnd,symbol_instr *p,char x){if(p->top2 < MAX-1){p->top2++;p->stack2[p->top2] = x;p->stack2[p->top2+1]='\0';}else MessageBox(hwnd,TEXT("出错"),TEXT("警告"),MB_OK|MB_ICONHAND);}char pop2(HWND hwnd,symbol_instr *p){char x;if(p->top2 != -1){x = p->stack2[p->top2];p->top2--;p->stack2[p->top2+1]='\0';return x;}else{MessageBox(hwnd,TEXT("符号栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n符号栈1空!\n");return 0;}}void out_stack1(HWND hwnd,symbol_instr *p){if(p->top2 <0)MessageBox(hwnd,TEXT("符号栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n状态栈3空!\n");SetDlgItemText(hwnd,IDC_EDIT2,p->stack2);}void out_stack2(HWND hwnd,symbol_instr *p){if(p->top2 <0)MessageBox(hwnd,TEXT("符号栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n状态栈3空!\n");SetDlgItemText(hwnd,IDC_EDIT3,p->stack2);}char get_top2(HWND hwnd,symbol_instr *p){char x;if(p->top2 != -1){x = p->stack2[p->top2];return x;}else{MessageBox(hwnd,TEXT("符号栈为空"),TEXT("警告"),MB_OK|MB_ICONHAND);//printf("\n符号栈2空!\n");return 0;}}void print(HWND hwnd,status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p){out_stack(hwnd,status_p); //输出状态栈的内容out_stack1(hwnd,symbol_p); //输出符号栈的内容out_stack2(hwnd,instr_p); //输出输入串}int get_index_char(char i){for(int j=0;j<9;j++){if(index_char[j] == i)return j;}return -1;}int goto_char(HWND hwnd,status *status_p,symbol_instr *instr_p){char x;int y,z;x = get_top2(hwnd,instr_p); //输入栈的内容y = get_top1(hwnd,status_p); //状态栈栈顶内容z = get_index_char(x); //得到i,*等相当于二维数组return table[y][z];}void action(HWND hwnd,status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p){int i,j,x;char a;i = goto_char(hwnd,status_p,instr_p);//规约出错if(i == -1)MessageBox(hwnd,TEXT("规约出错!"),TEXT("结束"),MB_OK|MB_ICONEXCLAMATION);//规约成功if(i == 12){MessageBox(hwnd,TEXT("规约成功!"),TEXT("结束"),MB_OK|MB_ICONEXCLAMATION);flag=1;}//移进动作if(i>=0 && i<=11){push1(hwnd,status_p,i);a = pop2(hwnd,instr_p);push2(hwnd,symbol_p,a);print(hwnd,status_p,symbol_p,instr_p);}//规约动作if(i>=21 && i<=26){x = r[i-21].y;for(j=0;j<x;j++){pop1(hwnd,status_p);pop2(hwnd,symbol_p);}push2(hwnd,instr_p,r[i-21].x);SetDlgItemText(hwnd,IDC_EDIT4,str2[i-21]);}}void CALLBACK TimerProc(HWND hwnd,UINT message,UINT iTimerID,DWORD dwTime) {SYSTEMTIME stLocal;TCHAR buf[256];GetLocalTime(&stLocal);wsprintf(buf,"%d年%d月%d 日%d:%d:%d",stLocal.wYear,stLocal.wMonth,stLocal.wDay,stLocal.wHour,stLocal.wM inute,stLocal.wSecond);SetDlgItemText(hwnd,IDC_EDIT5,buf);}BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){SetTimer(hwnd,0,1000,TimerProc);return TRUE;}status *status_p=new status;symbol_instr *symbol_p=new symbol_instr;symbol_instr *instr_p=new symbol_instr ;void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){switch(id){case IDC_BUTTON1:{init_stack1(hwnd,status_p); //初始化各栈init_stack2(hwnd,symbol_p);init_stack2(hwnd,instr_p);//压进栈初始元素push1(hwnd,status_p,0);push2(hwnd,symbol_p,'#');char x;TCHAR msg[256];GetDlgItemText(hwnd,IDC_EDIT3,msg,sizeof(msg));unsigned int i;for(i=0;i < strlen(msg);i++)push2(hwnd,symbol_p,msg[i]);//然后由符号栈弹出,压进输入栈while( symbol_p->top2 != 0){x = pop2(hwnd,symbol_p);push2(hwnd,instr_p,x);}print(hwnd,status_p,symbol_p,instr_p);//打印初始分析表*/ }break;case IDC_BUTTON2:{action(hwnd,status_p,symbol_p,instr_p);}break;case IDC_BUTTON3:{SetDlgItemText(hwnd,IDC_EDIT1,TEXT(""));SetDlgItemText(hwnd,IDC_EDIT2,TEXT(""));SetDlgItemText(hwnd,IDC_EDIT3,TEXT(""));SetDlgItemText(hwnd,IDC_EDIT4,TEXT(""));}break;default:break;}}void Main_OnClose(HWND hwnd){EndDialog(hwnd, 0);}四:实验结果(1)当输入i*i+i#时最终弹出规约成功的对话框:(2)当输入ii*i#时,最终会弹出规约出错的对话框如下:。

相关文档
最新文档