编译原理与技术_第1页
编译原理与技术_第2页
编译原理与技术_第3页
编译原理与技术_第4页
编译原理与技术_第5页
已阅读5页,还剩25页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

编译原理实验报告课程名称:编译原理与技术学院名称:计算机科学与技术学院专业班级:计算机学生姓名:学号:指导教师:实验一:PL/0语言建立一个词法分程序GETSYM(函数)实验目的:加深对课堂教学的理解;提高词法分析方法的实践能力。实验要求:把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM。SYM:存放每个单词的类别,为内部编码的表示形式。ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。NUM:存放用户定义的数。GETSYM要完成的任务:滤掉单词间的空格。识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。识别标识符,标识符的类别为IDENT,IDRNT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。打印源程序,边读入字符边打印。由于一个单词是由一个或多个字符组成的,所以在词法分析程序GETSYM中定义一个读字符过程GETCH。3.程序设计:首先将标识符,变量,常量,运算符,关键字,标点符号分别放入数组中。构造实验所需要的方法:如下源代码中所示(包括文本的搜索和读入等)。根据要编译的程序中的空格将其中的单词等分辨出来,并将其保存在相应的数组中。将结果写入文件。实验二:PL/0语言建立一个语法分析程序BLOCK(函数)实验内容:PL/0编译程序采用一遍扫描的方法,所以语法分析和代码生成都有在BLOCK中完成。BLOCK的工作分为两步:说明部分的处理说明部分的处理任务就是对每个过程(包括主程序,可以看成是一个主过程)的说明对象造名字表。填写所在层次(主程序是0层,在主程序中定义的过程是1层,随着嵌套的深度增加而层次数增大。PL/0最多允许3层),标识符的属性和分配的相对地址等。标识符的属性不同则填写的信息不同。所造的表放在全程量一维数组TABLE中,TX为指针,数组元素为结构体类型数据。LEV给出层次,DX给出每层的局部量的相对地址,每说明完一个变量后DX加1。例如:一个过程的说明部分为:consta=35,b=49;varc,d,e;procedurep;varg;对它的常量、变量和过程说明处理后,TABLE表中的信息如下:TX0→TX0→TX1→NAME:aNAME:bNAME:cNAME:dNAME:eNAME:pKIND:CONSTANTKIND:CONSTANTKIND:VARIABLEKIND:VARIABLEKIND:VAEIABLEKIND:PROCEDUREVAL:35VAL:49LEVEL:LEVLEVEL:LEVLEVEL:LEVLEVEL:LEVADR:DXADR:DX+1ADR:DX+2ADR:NAME:g。。。KIND:VARIABLE。。。LEVEL:LEV+1。。。ADR:DX。。。对于过程名的ADR域,是在过程体的目标代码生成后返填过程体的入口地址。TABLE表的索引TX和层次单元LEV都是以BLOCK的参数形式出现,在主程序调用BLOCK时实参的值为0。每个过程的相对起始位置在BLOCK内置初值DX=3。2.语句处理和代码生成对语句逐句分析,语法正确则生目标代码,当遇到标识符的引用则去查TABLE表,看是否有过正确的定义,若有则从表中取出相关的信息,供代码生成用。PL/0语言的代码生成是由过程GEN完成。GEN过程有三个参数,分别代表目标代码的功能码、层差、和位移量。生成的目标代码放在数组CODE中。CODE是一维数组,数组元素是结构体类型数据。PL/0语言的目标指令是一种假想的栈式计算机的汇编语言,其格式如下:flfla其中f代表功能码,l代表层次差,a代表位移量。目标指令有8条:①LIT:将常数放到运栈顶,a域为常数。②LOD:将变量放到栈顶。a域为变量在所说明层中的相对位置,l为调用层与说明层的层差值。③STO:将栈顶的内容送到某变量单元中。a,l域的含义与LOD的相同。④CAL:调用过程的指令。a为被调用过程的目标程序的入中地址,l为层差。⑤INT:为被调用的过程(或主程序)在运行栈中开辟数据区。a域为开辟的个数。⑥JMP:无条件转移指令,a为转向地址。⑦JPC:条件转移指令,当栈顶的布尔值为非真时,转向a域的地址,否则顺序执行。⑧OPR:关系和算术运算。具体操作由a域给出。运算对象为栈顶和次顶的内容进行运算,结果存放在次顶。a域为0时是退出数据区。实验主要步骤:1.首先运行词法分析器,逐个读取文件中的单词,2.然后识别每个单词,判定每个单词的类别3.之后根据单词的类别来选择不同的处理方式4.而且在语法分析函数的block函数中定义了两个可变数组,分别存放table表和code代码。5.另外定义了error数组,分别存放出错的类型,但是数量有限,不能完全识别所有错误。实验三:建立一个解释执行目标程序的函数实验内容:编译结束后,记录源程序中标识符的TABLE表已退出内存,内存中只剩下用于存放目标程序的CODE数组和运行时的数据区S。S是由解释程序定义的一维整型数组。解释执行时的数据空间S为栈式计算机的存储空间。遵循后进先出的规则,对每个过程(包括主程序)当被调用时,才分配数据空间,退出过程时,则所分配的数据空间被释放。为解释程序定义四个寄存器:I:指令寄存器,存放当前正在解释的一条目标指令。P:程序地址寄存器,指向下一条要执行的目标指令(相当于CODE数组的下标)。T:栈顶寄存器,每个过程运行时要为它分配数据区(或称为数据段),该数据区分为两部分。静态部分:包括变量存放区和三个联单元。动态部分:作为临时工作单元和累加器用。需要时临时分配,用完立即释放。栈顶寄存器T指出了当前栈中最新分配的单元(T也是数组S的下标)。B:基地址寄存器,指出每个过程被调用时,在数据区S中给出它分配的数据段起始地址,也称为基地址。每个过程被调用时,在栈顶分配三个联系单元。这三个单元的内容分别是:SL:静态链,它是指向定义该过程的直接外过程运行时数据段的基地址。DL:动态链,它是指向调用该过程前正在运行过程的数据段的基地址。RA:返回地址,记录调用该过程时目标程序的断点,即当时的程序地址寄存器P的值。具体的过程调用和结束,对上述寄存器及三个联系单元的填写和恢复由下列目标指令完成。INT0aa:为局部量个数加3OPR00恢复调用该过程前正在运行过程(或主程序)的数据段的基地址寄存器的值,恢复栈顶寄存器T的值,并将返回地址送到指令寄存器P中。CALlaa为被调用过程的目标程序的入口,送入指令地址寄存器P中。CAL指令还完成填写静态链,动态链,返回地址,给出被调用过程的基地址值,送入基址寄存器B中。部分源代码如下:packagepl0;importjava.util.Vector;publicclassgenerate{ publicwordanalysisCiFa; publicwordword; publicStringid=null;//用于登录名字表时的word名字 publicintlineNum;//用于错误处理时的行数记录 publicinterrorNumber=0;//用于保存语法分析中的错误数目 publicErrorerror=newError(); intcx;//VectorCode'ssize intcx0;//VectorCode'ssize,保存当前代码的地址 intdx;//给出每层的局部量的相对地址 intlev=-1;//记录层次 interrorNum=0; VectorCODE=newVector();;//生成一个vector矢量!//此矢量用作存放CodeElement的数组 VectorTABLE=newVector();//生成一个存放矢量作为名字表; publicgenerate(wordanalysisCF)//语法分析构造函数 { CiFa=CF;//从主程序传入一个词法分析对象,将其赋给CiFa word=CiFa.GetWord();//获得一个word analyse();//然后调用分析程序 } publicintgetErroNumber() { returnerrorNumber; } publicvoidprintTable()//用来查看符号表内容的 { for(intt=1;t<TABLE.size();t++) { tabname=(tab)TABLE.get(t); if(name.kind.equals("constant")) name.showConst(); elseif(name.kind.equals("variable")) name.show(); elseif(name.kind.equals("procedure")) { //???t++ t++; tabtempname=(tab)TABLE.get(t);//此时的name.adr为0 name.adr=tempname.adr;//??? name.show();//System.out.println("tempname:");// tempname.show(); } } } publicvoidprintTable(inti)//用来查看符号表内容的 { intt=i; tabname=(tab)TABLE.get(t); if(name.kind.equals("constant")) name.showConst(); elseif(name.kind.equals("variable")) name.show(); elseif(name.kind.equals("procedure")) { //???t++ t++; tabtempname=(tab)TABLE.get(t);//此时的name.adr为0 name.adr=tempname.adr;//??? name.show();//System.out.println("tempname:");// tempname.show(); } } publicvoidprintCode()//CodeElement的显示方法,如果没有错误,则打印CodeElement代码 { for(intk=1;k<CODE.size();k++) { Codecode=(Code)CODE.get(k); code.print(k);// System.out.println(n+"\t"+code.getF()+"\t"+code.getL()// +"\t"+code.getA());// Codecode=(Code)CODE.get(n);// System.out.println(n+"\t"+code.getF()+"\t"+code.getL()// +"\t"+code.getA()); } } publicvoidprintCode(inti)//CodeElement的显示方法,如果没有错误,则打印CodeElement代码 { intk=i; Codecode=(Code)CODE.get(k); code.print(k);// System.out.println(n+"\t"+code.getF()+"\t"+code.getL()// +"\t"+code.getA());// Codecode=(Code)CODE.get(n);// System.out.println(n+"\t"+code.getF()+"\t"+code.getL()// +"\t"+code.getA()); } /** *语法分析 *调用常量声明、变量声明、过程声明 *递归调用analyse */ publicvoidanalyse() { inttx0; lev++; dx=3;//初始ADR,以后每遇到一个变量,dx+1 tx0=TABLE.size();//用tx0保存当前层的符号在符号表中的起始位置 TABLE.addElement(newtab("","",0,0,0));//在这里给符号表填加一个元素,否则下一条代码会运行出界 ((tab)TABLE.get(tx0)).setAdr(CODE.size());//在上面加的那个元素里的私有字段adr里保存当前层代码的开始位置 CODE.addElement(newCode("jmp",0,0));//生成跳转指令由于跳转位置未知暂时添0System.out.println("1:"+CODE.size()); while(word.getSym().equals("constsym") ||word.getSym().equals("varsym") ||word.getSym().equals("procsym")) { if(word.getSym().equals("constsym"))//常量处理 { word=CiFa.GetWord(); constDefine();//调用常量声明,注意常量声明完毕时还要再次读取一个word //若在常量声明后读取的word为逗号,则要继续进行常量声明,这里采用while循环,直到word不是逗号 while(word.getSym().equals(",sym")) { word=CiFa.GetWord(); constDefine();//调用常量声明,注意常量声明完毕时还要再次读取一个word } if(word.getSym().equals(";sym"))//若word不是逗号,则应该是分号了,标志常量声明结束 { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),5);//如果常量声明完毕后没有遇到分号;则抛出15号错误 } } //变量处理 elseif(word.getSym().equals("varsym")) { word=CiFa.GetWord();//读取一个word,应该是一个ident标识符 varDefine();//调用变量声明 while(word.getSym().equals(",sym")) { word=CiFa.GetWord(); varDefine();//调用变量声明,注意常量声明完毕时还要再次读取一个word } if(word.getSym().equals(";sym")) { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),5);//如果变量声明完毕后没有遇到分号;则调用错误处理程序抛出5号错误 } } //循环声明各个子过程 //这里为什么要用while???改成if语句结果也正确,主要是例子里面没有嵌套的过程吧。 while(word.getSym().equals("procsym")) { word=CiFa.GetWord(); if(word.getSym().equals("ident")) { id=word.getName(); add("procedure",id); word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),4);//过程名不是标识符,抛出4号错误 } if(word.getSym().equals(";sym")) { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),5); }//过程名后没有分号 //保存当前的ADE和lev inttempdx=dx; intlevv=lev; //在这里递归调用下一层的分程序段分析,接下来如果不是常量、变量、过程声明, //那么就直接跳过analyse开始的while循环,开始进行语句的分析了 analyse(); dx=tempdx; lev=levv; if(word.getSym().equals(";sym")) { word=CiFa.GetWord(); //若end;后的符号不在ident,procsym,begin,call,if,while中,则调用6号错误 Stringsym=word.getSym(); if(!(sym.equals("ident")||sym.equals("procsym") ||sym.equals("beginsym")||sym.equals("callsym") ||sym.equals("ifsym")||sym.equals("whilesym"))) { errorNumber++; error.error(word.getLineNum(),6); } }else { errorNumber++; error.error(word.getLineNum(),5); } } }//???下面又不懂了啊!!! //把前面生成的跳转指令的跳转位置改成当前位置System.out.println(CODE.size());printCode(CODE.size()-1); ((Code)CODE.get(((tab)TABLE.get(tx0)).getAdr())).setA(CODE.size()); System.out.println("CODE"+((tab)TABLE.get(tx0)).getAdr());printCode(((tab)TABLE.get(tx0)).getAdr()); //在符号表中,对于过程名,adr应填入编译该过程所生成的CodeElement指令序列的入口地址 //目前TABLE.get(tx0))里面还没有什么内容。 ((tab)TABLE.get(tx0)).setAdr(CODE.size());System.out.println("TABLEtx0:"+tx0);printTable(tx0); cx0=CODE.size();//在cx0中保存当前代码的分配地址 CODE.addElement(newCode("int",0,dx));//生成空间分配指令,分配dx个空间(3个空间+变量的数目) //printCode(cx0-2);//printCode(cx0-1); //printCode(cx0);//??? statement();//处理当前遇到的语句; CODE.addElement(newCode("opr",0,0));//生成子程序返回指令; } /** *常量声明 * */ publicvoidconstDefine()//常量声明的方法 { if(word.getSym().equals("ident"))//在analyse调用常量声明时,上一个word为const,这一个应该是ident标识符 { id=word.getName();//调用Word类的getNam方法,获得当前word的内容,这里将其保存在id中,为的是一会进行的符号表插入工作 word=CiFa.GetWord();//然后再读取一个word,应该是等号"="了 if(word.getSym().equals(":=sym")) { errorNumber++; error.error(word.getLineNum(),1);//如果不是等号,而是赋值符号:=,抛出1号错误 }elseif(word.getSym().equals("=sym")) { word=CiFa.GetWord();//继续读取一个word,现在应该是一个数字了 if(word.getSym().equals("number")) { add("constant",id);//如果当前word是数字,则调用符号表插入方法,将常量插入符号表; word=CiFa.GetWord();//再次读取一个word,为后边做准备,应该是一个逗号或者是分号 }else //如果等号后不是数字,调用2号错误 { errorNumber++; error.error(word.getLineNum(),2); } }else //如果标识符后不是等号,调用3号错误 { errorNumber++; error.error(word.getLineNum(),3); } }else //如果常量声明过程中遇到的第一个字符不是标识符,调用4号错误 { errorNumber++; error.error(word.getLineNum(),4); } } /** *变量声明 */ publicvoidvarDefine()//变量声明的方法 { if(word.getSym().equals("ident")) { id=word.getName(); add("variable",id);//调用符号表注册方法进行变量的注册 word=CiFa.GetWord(); }else //如果变量声明过程中遇到的第一个字符不是标识符,调用4号错误 { errorNumber++; error.error(word.getLineNum(),4); } } /** *向Table表中增加变量 *@paramk *@paramname */ publicvoidadd(Stringk,Stringname)//Table表中添加变量 {//k中保存的是传过来的string if(k.equals("constant")) {//如果是常量,则要判断此常量的赋值是否大于整数的最大允许值2047 intnum=Integer.parseInt(word.getName()); if(num>2047) {// TABLE.addElement(newtab(id,k,0,0,0)); TABLE.addElement(newtab(name,k,0,0,0)); error.error(word.getLineNum(),31);//若整数越界,抛出31号错误,并将其赋为0,继续进行分析 System.out.println("整数越界"); }else{ //若整数没有越界,则给TABLE增加一个TableElement对象// TABLE.addElement(newtab(id,k,num,0,0)); TABLE.addElement(newtab(name,k,num,0,0)); } }elseif(k.equals("variable")) {// TABLE.addElement(newtab(id,k,0,lev,dx)); TABLE.addElement(newtab(name,k,0,lev,dx)); dx=dx+1; }elseif(k.equals("procedure")) {// TABLE.addElement(newtab(id,k,0,lev,0)); TABLE.addElement(newtab(name,k,0,lev,0)); } }//符号表注册完成 /** *在TABLE中查找标识符名字 */ publicintsearch(Stringid)//查找名字表 { inti=0; while(i<TABLE.size() &&(!((tab)TABLE.get(i)).getName().equals(id))) { i++; } if(i>=TABLE.size()) { return-1; }//如果没有找到,则返回负值 else { returni; } } /** *处理当前遇到的语句 *赋值语句、call语句、条件语句、begin、while、read、write *赋值语句:调用expression *if语句:调用condition、statement *begin:调用statement *while:调用condition、statement *write:调用expression * */ publicvoidstatement() { inti; intcx1; intcx2; //所谓语句可能是赋值语句,以标识符开头; if(word.getSym().equals("ident")) { i=search(word.getName());//在符号表中找到该标识符所在位置; if(i==-1)//如果返回的i为负值,则表示没有找到;抛出11号错误 { errorNumber++; error.error(word.getLineNum(),11); } elseif(!((tab)TABLE.get(i)).getKind().equals("variable")) { //如果在符号表中找到了,但是该标识符不是变量名,则抛出12号错误 errorNumber++; error.error(word.getLineNum(),12); i=-1;//并将i置为-1做为错误的标志; } word=CiFa.GetWord();//继续读取下一个word,正常应该是赋值符号 if(word.getSym().equals(":=sym")) { word=CiFa.GetWord();//如果是赋值符号,则继续读取一个word,正常应该是一个表达式; }else { errorNumber++; error.error(word.getLineNum(),13);//如果不是赋值符号,则抛出13号错误 } expression();//进行表达式的处理; //如果i不是负值,则表示未曾出错,i所表示的是当前语句左边标识符在符号表中的位置; if(i!=-1) {//生成一条把表达式的值写往指定内存的代码; CODE.addElement(newCode("sto",lev-((tab)TABLE.get(i)).getLev(), ((tab)TABLE.get(i)).getAdr())); } } //如果遇到了call语句 elseif(word.getSym().equals("callsym")) { word=CiFa.GetWord();//读取一个word,正常应该是一个过程名型的标识符 if(!word.getSym().equals("ident"))//如果不是标识符,抛出14号错误 { errorNumber++; error.error(word.getLineNum(),14); }else { i=search(word.getName());//查找符号表 //如果没有找到,抛出11号错误 if(i==-1) { errorNumber++; error.error(word.getLineNum(),11); } elseif(((tab)TABLE.get(i)).getKind().equals( "procedure")) {//生成call指令,call这个过程 CODE.addElement(newCode("cal",lev-((tab)TABLE.get(i)).getLev(), ((tab)TABLE.get(i+1)).getAdr())); //为什么是get(i+1).getAdr()??? }else { errorNumber++; error.error(word.getLineNum(),15); }//如果找到的不是过程名,抛出15号错误 word=CiFa.GetWord(); } } //如果是if语句 elseif(word.getSym().equals("ifsym")) { word=CiFa.GetWord();//if后正常是条件,所以执行condition函数 condition(); if(word.getSym().equals("thensym")) { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),16); }//如果if后不是then则抛出16号错误! cx=CODE.size(); cx1=cx; CODE.addElement(newCode("jpc",0,0)); //if后需要继续判断后边的语句,即Then后面的语句 statement(); ((Code)CODE.get(cx1)).setA(CODE.size()); } elseif(word.getSym().equals("beginsym")) { word=CiFa.GetWord(); statement(); //begin后需要继续判断后边的语句 while(word.getSym().equals(";sym") ||word.getSym().equals("beginsym") ||word.getSym().equals("callsym") ||word.getSym().equals("ifsym") ||word.getSym().equals("whilesym")) { if(word.getSym().equals(";sym")) { word=CiFa.GetWord(); }//为什么其它的就是出错??? else { errorNumber++; error.error(word.getLineNum(),10); } statement(); } if(word.getSym().equals("endsym")) { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),17); } } elseif(word.getSym().equals("whilesym")) { cx=CODE.size(); cx1=cx;//记录当前代码分配位置,这是while循环的开始位置 word=CiFa.GetWord();//读取word,应该是一个条件表达式 condition(); //while后边肯定有条件语句 cx=CODE.size(); cx2=cx;//记录当前代码位置,这是while循环的do中的语句的开始位置 CODE.addElement(newCode("jpc",0,0));//生成条件跳转指令,跳转位置暂时填0 if(word.getSym().equals("dosym"))//判断是否是do,否则抛出18号错误 { word=CiFa.GetWord(); }else { errorNumber++; error.error(word.getLineNum(),18); } statement();//开始分析do后的语句块 //跳转到cx1处,即再次进行判断是否进行循环 CODE.addElement(newCode("jmp",0,cx1)); //把刚才跳转暂时填0的位置改成当前位置,完成对循环的处理 //即do之前的跳转到while语句的结尾 ((Code)CODE.get(cx2)).setA(CODE.size()); } elseif(word.getSym().equals("readsym")) { word=CiFa.GetWord();//如果遇到了“读”语句块,则继续读取word,应该是左括号 if(word.getSym().equals("(sym")) { word=CiFa.GetWord(); if(word.getSym().equals("ident")) { i=search(word.getName()); if(i==-1) { errorNumber++; error.error(word.getLineNum(),11); }else { CODE.addElement(newCode("opr",0,16));//生成16号读指令,从键盘读取数字 CODE.addElement(newCode("sto",lev-((tab)TABLE.get(i)).getLev(), ((tab)TABLE.get(i)).getAdr()));//生成sto指令,存入指定变量 } } word=CiFa.GetWord(); //循环得到read语句的参数,直到该参数后不是逗号为止 while(word.getSym().equals(",sym")) { word=CiFa.GetWord(); if(word.getSym().equals("ident")) { i=search(word.getName()); if(i==-1) { errorNumber++; error.error(word.getLineNum(),11); }else { CODE.addElement(newCode("opr",0,16)); //sto将栈顶的内容送到某变量中,即将读入的数据送到对应的变量上去。 CODE.addElement(newCode("sto",lev-((tab)TABLE.get(i)).getLev(), ((tab)TABLE.get(i)).getAdr())); } } word=CiFa.GetWord(); } if(!word.getSym().equals(")sym")) { errorNumber++; error.error(word.getLineNum(),9); }//如果不是预想的右括号,抛出9号错误 } //如果不是左括号,抛出0号错误 else { errorNumber++; error.error(word.getLineNum(),0); } word=CiFa.GetWord(); } elseif(word.getSym().equals("writesym")) { word=CiFa.GetWord(); if(word.getSym().equals("(sym")) { word=CiFa.GetWord(); expression(); CODE.addElement(newCode("opr",0,14)); while(word.getSym().equals(",sym")) { word=CiFa.GetWord(); expression(); CODE.addElement(newCode("opr",0,14)); } if(!word.getSym().equals(")sym")) { errorNumber++; error.error(word.getLineNum(),9); }else { word=CiFa.GetWord(); } }//??? CODE.addElement(newCode("opr",0,15)); } } /** *处理条件语句 *调用expression */ publicvoidcondition()//条件语句的处理 { //存储运算符 Stringrelop=null; if(word.getSym().equals("oddsym"))//如果是一元运算符 { word=CiFa.GetWord(); expression();//对一元运算的表达式进行分析 CODE.addElement(newCode("opr",0,6));//生成奇偶判断指令 }else //不是一元运算符则是二元运算符 { expression();//对左边的表达式进行分析 relop=word.getSym();//把二元运算符保存起来 word=CiFa.GetWord(); expression();//对右边的表达式进行分析然后根据刚才保存的运算符,生成相应判断指令 if(relop.equals("=sym")) { CODE.addElement(newCode("opr",0,8)); }elseif(relop.equals("#sym")) { CODE.addElement(newCode("opr",0,9)); }elseif(relop.equals("<sym")) { CODE.addElement(newCode("opr",0,10)); }elseif(relop.equals(">=sym")) { CODE.addElement(newCode("opr",0,11)); }elseif(relop.equals(">sym")) { CODE.addElement(newCode("opr",0,12)); }elseif(relop.equals("<=sym")) { CODE.addElement(newCode("opr",0,13)); }else { System.out.println(word.getName()+""+relop); errorNumber++; error.error(word.getLineNum(),20); }//如果刚才保存的不是逻辑运算符,则抛出20号错误 } }//条件分析完毕 /** *处理表达式 *调用term */ publicvoidexpression()//表达式的处理 { Stringaddop=null;//保存表达式开头的符号用于表示正负 if(word.getSym().equals("+sym")||word.getSym().equals("-sym")) { //把正负号保存在string类型的addop中,继续读取一个word,正常应该为表达式的一个项 addop=word.getSym(); word=CiFa.GetWord(); term();//进行项的分析 if(addop.equals("-sym"))//如果保存下来的是个负号,则生成一条1号指令,取反运算 { CODE.addElement(newCode("opr",0,1)); } }else //如果不是正负号开头,就应该是一个表达式的项开头,直接进行项的分析 { term(); } //项后应该应该是加运算或者减法运算 while(word.getSym().equals("+sym")||word.getSym().equals("-sym")) { addop=word.getSym();//把运算符保存在addop中 word=CiFa.GetWord(); term();//分析项 if(addop.equals("+sym"))//项分析完毕后,如果刚才保存的是加号,则生成加法指令 { CODE.addElement(newCode("opr",0,2)); }else //否则生成减法指令 { CODE.addElement(newCode("opr",0,3)); } } }//表达式分析完毕 /** *项的处理(乘法和除法也属于项) *调用element */ publicvoidterm() { Stringmulop=null; element();//每个项都是由一个因子开头,所以直接调用因子分析方法 while(word.getSym().equals("*sym")||word.getSym().equals("/sym"))//因子后应该遇到乘号或是除号 { mulop=word.getSym();//把运算符保存在mulop中(乘法或是除法) word=CiFa.GetWord(); element(); //运算符后应该是一个因子,进行因子分析 if(mulop.equals("*sym"))//如果刚才保存的运算符为乘号则生成opr4号乘法指令, { CODE.addElement(newCode("opr",0,4)); }else //如果刚才保存的不是乘号,则生成除法运算指令 { CODE.addElement(newCode("opr",0,5)); } } }//项分析完毕 /** *因子的分析处理 */ publicvoidelement()//因子的分析处理; { inti; while(word.getSym().equals("ident")||word.getSym().equals("number") ||word.getSym().equals("(sym"))//循环处理因子 { if(word.getSym().equals("ident"))//如果遇到的是标识符,则查符号表 { i=search(word.getName()); if(i==-1)//如果查符号表后返回负值,则表示没有找到,抛出11号错误 { errorNumber++; error.error(word.getLineNum(),11); } //如果返回的不是负值,则表示在符号表中的找到了该标识符,getKind返回该标识符的类型 elseif(((tab)TABLE.get(i)).getKind().equals( "constant")) //如果该标识符为常量,则生成lit指令,把val放到栈顶 { //4lit010是在这里产生的。为什么??? CODE.addElement(newCode("lit",0, ((tab)TABLE.get(i)).getVal()));System.out.println("aaa"+

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论