编译原理课程设计报告 133页

  • 896.99 KB
  • 2022-04-22 11:53:04 发布

编译原理课程设计报告

  • 133页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'编译原理课程设计报告1.概述编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。 编译原理是计算机专业设置的一门重要的专业课程。虽然只有少数人从事编译方面的工作,但是这门课在理论、技术、方法上都对学生提供了系统而有效的训练,有利于提高软件人员的素质和能力。由于时间和同学们的水平有限,故本实验只涉及到了词法分析,语法分析,及中间代码的四元式生成和符号表。具体概述介如下:1.词法分析:在这个阶段编译器实际阅读源程序(通常以分析程序字符流的形式表示)。扫描程序执行词法分析注释树符号表 :它将字符序列收集到称作记号错误处的有意义单元中,记号同自然语言,如英源代码理器语中的字词相似。因此可以认为扫描程序执行与优化程序拼写相似的任务。本实验的词法分析程序用于生成Token序列。2.语法分析:该程序从扫描程序中获取记号形式的源代码,并完成定义程序结构的语法分析,这与自然语言中句子的语法分析类似。语法分析定义了程序的结构元素及其关系。其任务是识别和处理比单词更大的语法单位。本实验用于指出程序设计语言中的表达式、各种说明和语句乃至全部源程序其中的语法错误;必要时,可生成内部形式,便于下一阶段处理。3.中间代码:根据中间代码的类型和优化的类型,该代码可以是文133 本串的数组、临时文本文件或是结构的连接列表。对于进行复杂优化的编译器。由于同学们水平有限,我们只做了四元式的生成。4.语义分析:程序的语义就是它的“意思”,它与语法或结构不同。程序的语义确定程序的运行,但是大多数的程序设计语言都具有在执行之前被确定而不易由语法表示和由分析程序分析的特征。这些特征被称作静态语义,而语义分析程序的任务就是分析这样的语义。一般的程序设计语言的典型静态语义包括声明和类型检查。由于同学们水平有限,我们只做了其中的符号表部分。编译原理课程兼有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,在系统软件中占有十分重要的地位。编译原理课程设计是本课程重要的综合实践教学环节,是对平时实验的一个补充。通过编译器相关子系统的设计,使学生能够更好地掌握编译原理的基本理论和编译程序构造的基本方法和技巧,融会贯通本课程所学专业理论知识;培养学生独立分析问题、解决问题的能力,以及系统软件设计的能力;培养学生的创新能力及团队协作精神。133 2.课程设计任务及要求2.1设计任务在下列内容中任选其一:1、一个简单文法的编译器前端的设计与实现。2、一个简单文法的编译器后端的设计与实现。3、一个简单文法的编译器的设计与实现。。4、自选一个感兴趣的与编译原理有关的问题加以实现,要求难度相当。2.2设计要求1、在深入理解编译原理基本原理的基础上,对于选定的题目,以小组为单位,先确定设计方案;2、设计系统的数据结构和程序结构,设计每个模块的处理流程。要求设计合理;3、编程序实现系统,要求实现可视化的运行界面,界面应清楚地反映出系统的运行结果;4、确定测试方案,选择测试用例,对系统进行测试;5、运行系统并要通过验收,讲解运行结果,说明系统的特色和创新之处,并回答指导教师的提问;133 6、提交课程设计报告。3算法与数据结构3.1算法的总体思想我的课程设计实验基于词法扫描,采用递归下降子程序法的语法分析的方法实现编译器前端。主要部分有词法扫描、语法分析、四元生成、符号表建立等。3.2词法分析3.2.1功能词法分析程序又称扫描器,任务有二:(1)识别单词——从用户的源程序中把单词分离出来;(2)翻译单词——把单词转换成机内表示,便于后续处理。词法分析是编译的第一步,其目的是对程序进行扫描,并生成token序列,以便后面进行语法分析。3.2.2数据结构词法分析中用到的数据结构如下所示://关键字表privateMapkeyWordMap=newHashMap<>();//界符表privateMapborderMap=newHashMap<>();//标识符表privateMapidSignMap=newHashMap<>();133 //常数表privateMapconstantMap=newHashMap<>();//栈privateStackpastword=newStack<>(在程序中用哈希表存储关键字表,界符表,常数表,标识符表,其中标示符表和常数表在分析单词过程中生成,关键字表和界符表根据语法规则写成,其中用哈希表中的key来存储单词,用val存储标号,如下图:(a)(b)图3-2-2:关键字表(a)和界符表(b);133 3.2.3算法词法分析主要是通过自动机来写的,设计如下:一个简单识别器(有限自动机)的设计,如图3-2-3-2所示:图3-2-3-1<字母>àA|B|C|…|Z|a|b|c|…|z<数字>à0|1|2|3|4|5|6|7|8|9其中(1)(字母),d(数字),#(源程序结束符);(2)?(空格,回车,换行),需要过滤掉;  (3)(泛指单词的后继符);  (4)…..(表示省略了其他界符的处理)。一个简单词法分析器设计,如图3-2-3-2所示:133 图3-2-3-23.3递归下降子程序设计语法3.3.1功能语法扫描器的功能主要有三:(1)识别一般源程序——检查源程序中是否符合语法规范;(2)实现ifwhile语句的识别——对于特殊语句如ifwhile的识别。(3)程序的纠错----对于源程序中出现的语法规范错误进行纠错改正并且提示。3.3.2数据结构publicclassRecursiveWay{133 Stringcurrent;//当前词.Stringkind;//当前词属性,k关键字,i标识符,c常数,界符p.Stringword;//用于词分析所用的变量.Stringsingle="";//用于词分析所用的的单个字母所用变量staticinttures=0;//说明多少个错误。inttype2=0;//类型说明,如果是整形为1,实数型为2,字符型为3WordScannerscanner=newWordScanner();}3.3.3程序生成文法://程序定义<1程序program>->program<2ID标识符后有读取><3分程序deputyProgram><3分程序deputyProgram>-><10变量说明VD><4复合语句compoundStatement>//语句定义变量说明VD:Variabledescription<10变量说明VD>->var<5标识符表IDTable>:<6类型type>;<5标识符表IDTable>-><2标识符ID>{,<2标识符ID>}<4复合语句compoundStatement>->begin{!endwhileif<7语句表statementTable>}<8compoundStatement1>->begin<7语句表statementTable>end;|<9赋值语句assignmentStatement>;<7语句表statementTable>-><9赋值语句assignmentStatement>{;<9赋值语句assignmentStatement>}<9赋值语句assignmentStatement>-><2标识符ID>:=<18算术表达式AE>133 <11while>-><12or>do<8compoundStatement1><13if>-><12or>then<8compoundStatement1>else<8compoundStatement1><12or>-><14and>{or<14and>}<14and>-><15not>{and<15not>}<15not>->not<16booleans>|<16booleans><16booleans>-><17boolTerm>|(<12or>)前后换顺序<17boolTerm>-><18算术表达式AE>w2<18算术表达式AE>//算术表达式定义。AE:Arithmeticexpression<18算术表达式AE>-><19项term>{w0<19项term>}<19项term>-><20因子factor>{w1<20因子factor>}<20因子factor>-><21算术量quantity>|(<18算术表达式AE>)前后换顺序<21算术量quantity>-><2标识符ID>|<22常数constant>//上面的英文为程序中的函数名或标识符,汉字为注释其中w0:+,-w1:*,/w2:>|<|==|<=|>=3.3.4算法流程图:133 133 133 133 133 调用词法分析中的read().得到要分析的词和属性133 报错并给出正确答案纠错提示不符合语法语法中检查符合语法报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案一直分析到源程序的末尾:并给其他同学负责的部分提供语法是否规范信息报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案报错并给出正确答案3.4语义分析及四元式生成3.4.1功能采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。3.4.2数据结构四元式结构publicclassQuat{privateStringfirst="";privateStringsecond="";privateStringthird="";privateStringfourth="";}四元式组:用于增删查改四元式Quats={Quat1,Quat2,Quat3,Quat4....}3.4.3算法133 图3-4-3-1说明:scanner是用来读取程序代码;forfour在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句简单的条件语句if和while进行翻译。语义规则(属性文法)重点是算术表达式,赋值语句和条件语句133 产生式语义规则i:=E{Gen(:=,E.PLACE,—,entry(i))}E®E1+E2{E.PLACE=Newtemp;Gen(+,E1.PLACE,E2.PLACE,E.PLACE)}E®E1*E2{E.PLACE=Newtemp;Gen(*,E1.PLACE,E2.PLACE,E.PLACE)}E®-E1{E.PLACE=Newtemp;Gen(@,E1.PLACE,—,E.PLACE)}E®(E1){E.PLACE=E1.PLACE}E®i{E.PLACE=Entry(i)}产生式语义规则S®ifEthenMS1{backpatch(E.truelist,M.quad);S.nextlist:=merge(E.falselist,S1.nextlist)}M®ε{M.quad:=nextquad;}N®ε{N.nextlist:=makelist(nextquad);Gen(j,—,—,0)}S®ifEthenM1S1NelseM2S2{backpatch(E.truelist,M1.quad);backpatch(E.falselist,M2.quad);133 S.nextlist:=merge(S1.nextlist,N.nextlist,S2.nextlist)}S®whileM1EdoM2S1{backpatch(S1.nextlist,M1.quad);Gen(j,—,—,M1.quad);backpatch(E.truelist,M2.quad);S.nextlist:=E.falselist}S®beginLend{S.nextlist:=L.nextlist}S®A{S.nextlist:=makelist()/*空链*/}L®S{L.nextlist:=S.nextlist}L®L1;MS{backpatch(L1.nextlist,M.quad);L.nextlist:=S.nextlist}这里着重说明对算数表达式的四元分析:这里我们用到了四元式转化为逆波兰式算法:133 (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。133 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串储存并输出。(4)如果不是数字,该字符则是运算符,此时需比较优先关系。做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。其中的优先关系我们用一个数组保存charpre[][]={/*运算符之间的优先级制作成一张表格*/{">",">","<","<","<",">",">"},{">",">","<","<","<",">",">"},{">",">",">",">","<",">",">"},{">",">",">",">","<",">",">"},{"<","<","<","<","<","=","0"},{">",">",">",">","0",">",">"},{"<","<","<","<","<","0","="}};巧妙的用两个运算符作为数组的横纵坐标,输入操作符立马可得优先关系。133 然后我们将生成都是逆波兰式转化为四元式:(1)构造一个栈,存放运算对象。(2)读入一个用逆波兰式表示的简单算术表达式。(3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。133 (4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。说明:每次进行计算时(即要算两个操作数的结果时),我们将操作符作为四元式第一项,弹出的操作数依次作为四元式的第二和三项,运算结果作为四元式第四项,即Quat(运算符,操作数1,操作数2,结果),然后讲Quat放入Quats中储存起来,便于后续处理。当然,我们也可以不真正的算出结果,而是用一个函数newSuo()来产生一个有序的变量来表示。下面是对when,if和while的处理133 对要执行的语句进行规约并产生四元式,这里主要是指赋值语句和算数表达式。根据词法分析的词法三元式判断do关键字4处理要执行的语句3判断do关键字根据布尔表达式规则处理布尔表达式,由于我们文法中没专门布尔表达式,我们只处理如a>1这样的并产生四元式根据词法分析的词法三元式判断关键字,这里的关键字是指when,if和while,并产生四元式2布尔表达式规约1判断关键字这里说明下词法、语法和语义分析的衔接1、词法分析是分析输入代码产生词法三元式的程序。读入代码,并将代码中的单词分解成词法三元式。2、语法分析读入词法三元式,并根据词法三元式对句子进行语法分析。3、语义分析嵌入在语法分析中。根据语法分析中得到的句子类型和语义四元式产生规则,产生四元式。关键代码(由组长刘鑫伟与我一起书写)说明:本人写此编译器代码时对Java知之甚少,所以主要是在组长帮助下,边学边写。133 3.5符号表3.5.1功能符号表是标识符的动态语义词典,属于编译中语义分析的知识库,符号表可以存储标识符的各种信息,以便以后做处理。3.5.2数据结构1.符号表集合。//符号表总表。privateHashMapsynbTable=newHashMap<>();//数组表。privateListarrayTable=newArrayList<>();//结构表。privateListstrutsTable=newArrayList<>();//函数表。privateListfunctionTable=newArrayList<>();//活动记录表。privateStack>vallStack=newStack<>();privateArrayListglobalList=newArrayList<>();2.符号表总表元素实体类。publicclassSynb{//名字,标识符源码。133 privateStringname;//值(新增项)。privateStringvalue;/**类型,指针,指向类型表相应项。:i(整型),r(实型),c(字符型),b(布尔型),a(数组型),*d(结构型)f(函数),c(常量),t(类型),d(域名),v,vn,vf(变量,换名形参,赋值形参)。*/privateTypetype;//数据长度。privateintlength;}3.数组表实体类。publicclassArray{//数组的下界。privateStringlow;//数组的上界。privateStringup;//成分类型指针,指向该维数组成分类型(在类型表中的信息)。privateStringctp;//成分类型的长度,成分类型的数据所值单元的个数。133 privateStringclen;}4.结构体表实体类。publicclassStruts{//结构的域名。privateStringid;//区距。privateStringoff;//域成分类型指针,指向idk域成分类型(在类型表中的信息)。privateStringtp;}5.函数表。publicclassFunction{//层次号,该过函静态层次嵌套号。privateStringlevel;//区距,该过函自身数据区起始单元相对该过函值区区头位置。privateStringoff;//参数个数,该过函的形式参数的个数。privateStringfn;//参数表,指向形参表。133 privateStringentry;//入口地址,该函数目标程序首地址(运行时填写)。privateStringparam;}6.活动记录表实体类。publicclassVall{//从属于哪个活动记录块。privateStringbelongs;//局部数据区:用来存放局部变量、内情向量、临时单元。privateStringname;//形式单元:用来存放实参的值或地址。(值)privateStringvalue;//执行动作。privateStringaction;}3.5.3算法符号表的建立是在程序的声明部分,或者说是在函数的声明部分,因此我们只要对声明部分进行处理就可以了。我们发现,声明部分一般都在begin前面,我们利用这个特点,在begin前面进行符号表的建立,在begin和end之间进行四元式的生成。133 在进行符号表的建立过程中,我们又分了两种情况,一种是含有function的语句,即函数的声明语句,还有一种是普通的语句,即普通的变量和常量的声明语句。具体的实现可以参照voidestable()这个函数。4程序设计与实现4.1程序流程图图4-14.2程序说明4.2.1程序说明说明:133 a.按照功能,分不同功能,分为5个package,分别为com.compiler(编译器入口包)、com.wordScanner(词法扫描器包),com.syntaxAnalysis(语法分析包)、com.middleCode(中间代码包)、com.signTable(符号表包)。b.每个package中可能包含若干个Class,实现具体的功能,组织结构如图4-2-1所示。图4-2-1c.import包省去,仅显示package部分,以显示组织结构。4.2.2程序源代码packagecom.compiler;/**133 *编译器前端。*@author刘鑫伟**/publicclassCompiler{WordScannerwordScanner=newWordScanner();RecursiveWayrecursiveWay=newRecursiveWay();publicvoidexcute(){recursiveWay.recursive();if(recursiveWay.getTures()==0){ForFourforFour=newForFour();SignTablesignTable=newSignTable();forFour.forreadWord();signTable.display();}}}packagecom.wordScanner;/**133 *词法扫描器**@authorGao,Bayi;Liu,Xinwei*/publicclassWordScanner{//词表路径。publicstaticfinalStringTABLE_PATH="resource/table.txt";//代码路径。publicstaticfinalStringCODE_PATH="resource/code.txt";//待扫描代码。privateStringcode="";//token。privateStringtoken="";//关键字表。privateMapkeyWordMap=newHashMap<>();//界符表。privateMapborderMap=newHashMap<>();//标示符表。privateMapidSignMap=newHashMap<>();//常数表。privateMapconstantMap=newHashMap<>();133 privateStackpastword=newStack<>();{readCodeFromFile();writeToMap();scan(code);}/***从文本中读取代码。*/publicvoidreadCodeFromFile(){try{FilemyFile=newFile(CODE_PATH);FileReaderfileReader=newFileReader(myFile);BufferedReaderreader=newBufferedReader(fileReader);Stringline=null;while((line=reader.readLine())!=null){code=code+line+"";}reader.close();133 }catch(Exceptionex){ex.printStackTrace();}}/***将词表写入Map。*/publicvoidwriteToMap(){try{FilemyFile=newFile(TABLE_PATH);FileReaderfileReader=newFileReader(myFile);BufferedReaderreader=newBufferedReader(fileReader);Stringline=null;Stringkind=null;while((line=reader.readLine())!=null){if("KeyWord".equals(line)||"Border".equals(line)){kind=line;}elseif("KeyWord".equals(kind)){String[]splits=line.split("");133 keyWordMap.put(splits[0],splits[1]);}elseif("Border".equals(kind)){String[]splits=line.split("");borderMap.put(splits[0],splits[1]);}}reader.close();}catch(Exceptionex){ex.printStackTrace();}}/***扫描代码。*@paramcode*代码字符串。*/publicvoidscan(Stringcode){Stringword;//当前单词。charstart;//开始字符。charch;//当前字符。133 while(!"".equals(code)){inti=0;while(code.indexOf("")==0){code=code.substring(1);}if("".equals(code)){break;}start=code.charAt(0);if((start>="A"&&start<="Z")||(start>="a"&&start<="z")){ch=code.charAt(0);while((ch>="a"&&ch<="z")||(ch>="A"&&ch<="Z")||Character.isDigit(ch)){i=i+1;if(i>=code.length()){break;}ch=code.charAt(i);}133 word=code.substring(0,i);//截取字符串//判断当前单词在哪个表中if(keyWordMap.containsKey(word)){token=token+"<"+word+","+"Keyword"+","+keyWordMap.get(word)+">";}elseif(idSignMap.containsKey(word)){token=token+"<"+word+","+"idSign"+","+idSignMap.get(word)+">";}else{idSignMap.put(word,"0"+(idSignMap.size()+1));token=token+"<"+word+","+"idSign"+","+idSignMap.get(word)+">";}}elseif(Character.isDigit(start)){intpointerTimes=0;ch=code.charAt(0);while(Character.isDigit(ch)||((ch==".")&&pointerTimes==0)){if(ch=="."){pointerTimes++;}133 i=i+1;if(i>=code.length()){break;}ch=code.charAt(i);}word=code.substring(0,i);if(constantMap.containsKey(word)){token=token+"<"+word+","+"constant"+","+constantMap.get(word)+">";}else{constantMap.put(word,"0"+(constantMap.size()+1));token=token+"<"+word+","+"constant"+","+constantMap.get(word)+">";}}else{start=code.charAt(0);if(start=="<"||start==">"||start=="="||start==":"){ch=code.charAt(1);133 StringsignAdd=""+start+ch;if(borderMap.containsKey(signAdd)){i=i+2;token=token+"<"+signAdd+","+"border"+","+borderMap.get(signAdd)+">";}else{i=i+1;token=token+"<"+start+","+"border"+","+borderMap.get(""+start)+">";}}else{i=i+1;token=token+"<"+start+","+"border"+","+borderMap.get(""+start)+">";}}code=code.substring(i);token=token+"";}133 }/***读单词,给语法分析提供使用。**@paramcode*待识别的程序。*@return当前单词。*/publicStringreadWord(){Stringword="";//当前单词。charstart;//开始字符。charch;//当前字符。inti=0;while(code.indexOf("")==0){code=code.substring(1);}if("".equals(code)){return"";}start=code.charAt(0);133 if((start>="A"&&start<="Z")||(start>="a"&&start<="z")){ch=code.charAt(0);while((ch>="a"&&ch<="z")||(ch>="A"&&ch<="Z")||Character.isDigit(ch)){i=i+1;if(i>=code.length()){break;}ch=code.charAt(i);}word=code.substring(0,i);}elseif(Character.isDigit(start)){intpointerTimes=0;ch=code.charAt(0);while(Character.isDigit(ch)||((ch==".")&&pointerTimes==0)){if(ch=="."){pointerTimes++;}i=i+1;if(i>=code.length()){133 break;}ch=code.charAt(i);}word=code.substring(0,i);}else{if(start=="<"||start==">"||start=="="||start==":"){ch=code.charAt(1);StringsignAdd=""+start+ch;if(borderMap.containsKey(signAdd)){i=i+2;word=signAdd;}else{i=i+1;word=""+start;}}else{i=i+1;word=""+start;}}133 code=code.substring(i);returnword;}publicStringread(){Stringcurrent=readWord();Stringcurrents=null;if(borderMap.containsKey(current)){currents=current+"|"+"p";}elseif(idSignMap.containsKey(current)){currents=current+"|"+"i";}elseif(keyWordMap.containsKey(current)){currents=current+"|"+"k";}elseif(constantMap.containsKey(current)){currents=current+"|"+"c";}elsecurrents=current+"|"+"err";returncurrents;}publicArrayListreadWord(Stringcode){ArrayListresult=newArrayList<>();this.code=code;133 while(!"".equals(this.code)){result.add(readWord());}returnresult;}publicArrayListfhq(){ArrayListret=newArrayList<>();Stringnow=null,past=null;now=readWord();while(!".".equals(now)){if(":=".equals(now)){past=pastword.pop();ret.add(past);pastword.push(""+now);now=readWord();}else{pastword.push(""+now);now=readWord();}}returnret;}133 /***@returnthecode*/publicStringgetCode(){returncode;}/***@paramcode*thecodetoset*/publicvoidsetCode(Stringcode){this.code=code;}/***@returnthetoken*/publicStringgetToken(){returntoken;}}133 packagecom.syntaxAnalysis;/***递归下降语法分析。**@authorXiao,Hui;Liu,Xinwei**/publicclassRecursiveWay{Stringcurrent;Stringkind;Stringword;Stringsingle="";staticinttures=0;//说明多少个错误。inttype2=0;//类型说明,如果是整形为1,实数型为2,字符型为3WordScannerscanner=newWordScanner();//拆开词函数publicStringchar2(){charch=word.charAt(0);word=word.substring(1);return""+ch;133 }publicvoidread(){Stringcurrents;currents=scanner.read();String[]splits=currents.split("\|");current=splits[0];kind=splits[1];}//1程序入口,<1程序program>->program<2标识符ID><3分程序deputyProgram>publicvoidprogram(){read();if(!"program".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为program");tures++;}read();ID();deputyprogram();}133 //2判断是否是符合标识符定义,a型,abc型,abc123型publicvoidID(){if(!"i".equals(kind)){System.out.println("标识符错误"+":"+current);}read();}//3<3分程序deputyProgram>-><10变量说明VD><4复合语句compoundStatement>privatevoiddeputyprogram(){VD();compoundStatement();}//4复合语句的判断,主体部分**,里面是主体架构,从begin到最后的end.publicvoidcompoundStatement(){if(!"begin".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为begin");tures++;}read();133 while(!"end".equals(current)){if("while".equals(current)){whiles();}elseif("if".equals(current)){ifs();}elsestatementTable();}read();if(!".".equals(current)){System.out.println("结尾符号错误"+":"+current+""+"应该为.");tures++;read();}}//5号<5标识符表IDTable>-><2标识符ID>{,<2标识符ID>}publicvoidIDTable(){ID();while(",".equals(current)){read();ID();}133 }//6确定变量的类型,以便后面算数表达式的检查;privatevoidtype(){if("k".equals(kind)){if("integer".equals(current)||"int".equals(current)){read();type2=1;}//如果是整形的话elseif("real".equals(current)){read();type2=2;}//如果是实数型elseif("char".equals(current)){read();type2=3;}//如果是字符型}else{System.out.println("关键字类型错误"+":"+current+""+"应该为integer或real或char");tures++;read();133 }}//7号语句表的判断,主体部分*,主要的部分语句,和赋值语句联系紧密privatevoidstatementTable(){assignmentStatement();while(";".equals(current)){read();assignmentStatement();}}//8<8compoundStatement1复合语句2>->begin<7statementTable语句表>end;|<9//assignmentStatement赋值语句>;//这里是主要处理whlie,if的复合语句;privatevoidcompoundStatement1(){if("begin".equals(current)){read();statementTable();if("end".equals(current)){read();if(!";".equals(current)){133 System.out.println("符号错误"+":"+current+""+"应该为;");tures++;}}else{System.out.println("关键字错误"+":"+current+""+"应该为end");tures++;read();}}elseassignmentStatement();if(";".equals(current)){read();}else{System.out.println("符号错误"+":"+current+""+"应该为;");tures++;read();}}//9号赋值语句的判断,给语句赋值privatevoidassignmentStatement(){133 ID();if(":=".equals(current)){read();word=current+"#";AE();}else{System.out.println("符号错误"+":"+current+""+"应该为:=");tures++;read();}}//10<10变量说明VD>->var<5标识符表IDTable>:<6类型type>privatevoidVD(){if(!"var".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为var");tures++;}read();IDTable();if(":".equals(current)){133 read();type();if(";".equals(current)){read();}else{System.out.println("符号错误"+":"+current+""+"应该为;");tures++;read();}}else{System.out.println("符号错误"+":"+current+""+"应该为;");tures++;read();}}//11<11while>-><12or>do<8compoundStatement1复合语句>publicvoidwhiles(){or();if(!"do".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为do");133 tures++;}read();compoundStatement1();}//12<12or>-><14and>{or<14and>}privatevoidor(){and();while("or".equals(current)){read();and();}}//13<13if>-><12or>then<8compoundStatement1>else<8compoundStatement1>publicvoidifs(){or();if(!"then".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为then");tures++;133 }read();compoundStatement1();if(!"else".equals(current)){System.out.println("关键字错误"+":"+current+""+"应该为else");tures++;}read();compoundStatement1();}//14<14and>-><15not>{and<15not>}privatevoidand(){not();while("and".equals(current)){read();not();}}//15<15not>->not<16booleans>|<16booleans>privatevoidnot(){if("not".equals(current)){133 read();boolTerm();}elsebooleans();}//16<16booleans>-><17boolTerm>|(<12or>)publicvoidbooleans(){if("(".equals(current)){read();or();if(")".equals(current)){read();}else{System.out.println("算术表达式错误"+":"+current+""+"应该为)");tures++;read();}}else{read();boolTerm();}}133 //17<17boolTerm>-><18AE>w2<18AE>publicvoidboolTerm(){AE();if("<".equals(current)||">".equals(current)||"<=".equals(current)||">=".equals(current)||"==".equals(current)){read();AE();}else{System.out.println("语句表达错误"+":"+current+""+"应该为");tures++;read();}}//18算术表达式的判断,主要的算术表达式:如:a:=b+2;privatevoidAE(){term();while("+".equals(current)||"-".equals(current)){read();term();}133 }//19算术表达式中因子的判断,如:b*2privatevoidterm(){factor();while("*".equals(current)||"/".equals(current)){read();factor();}}//20<20因子factor>-><21算术量quantity>|(<18算术表达式AE>)privatevoidfactor(){if("(".equals(current)){read();AE();if(")".equals(current)){read();}else{System.out.println("算术表达式错误"+":"+current+""+"应该为)");tures++;}133 }elseif(")".equals(current)){System.out.println("算术表达式错误"+":"+current+""+"应该为(");tures++;read();AE();if(")".equals(current)){read();}else{System.out.println("算术表达式错误"+":"+current+""+"应该为)");tures++;}}elsequantity();}//21<21算术量quantity>-><2标识符ID>|<22常数constant>privatevoidquantity(){word=current;single=char2();if(single.matches("[A-Za-z]")){ID();133 }elseif(single.matches("[0-9]")){constant();}else{System.out.println("算术表达式中的变量或数据错误"+":"+current+""+"应该为");tures++;read();quantity();}}//22有两条路线,如果前面定义的是整形变量,那么走ints(),如果定义的是实数,走real(),privatevoidconstant(){if("c".equals(kind)){if(type2==1){ints();}elseif(type2==2){real();}elseif(type2==3){chars();}}else{System.out.println("数据错误"+":"+current);133 }read();}//23判断是否符合整形数的定义,privatevoidints(){word=current+"#";single=char2();for(;!"#".equals(single);){number();if(".".equals(single)){System.out.println("原定义为整形"+":"+current+""+"应该为整形");tures++;single=char2();}}}//24判断是否符合实数的定义,如3.4对,3.错;privatevoidreal(){word=current+"#";single=char2();while(!"#".equals(single)){133 number();if(".".equals(single)){number();}}}//25判断是否是字符;是就再取后续字符publicvoidchars(){if(single.matches("[A-Za-z]")){single=char2();}}//26判断是否是数字,是就再取后续字符publicvoidnumber(){if(single.matches("[0-9]")){single=char2();}/*elseif(".".equals(single)){single=char2();if("#".equals(single)){System.out.println("实数拼写错误"+":"+current+""+"应该为");133 tures++;}}*/}publicstaticintgetTures(){returntures;}/***入口函数。*/publicvoidrecursive(){program();if(tures==0){System.out.println("Perfect!!");System.out.println("nToken:n"+scanner.getToken());}else{System.out.println("Therehave"+tures+"errors");}System.out.println();}133 }packagecom.middleCode;publicclassForFour{privateinti=1,j=1,k=1;privateArrayListquats=newArrayList<>();WordScannerscanner=newWordScanner();SignTablesignTable=newSignTable();publicstaticvoidmain(String[]args){ForFouraForFour=newForFour();aForFour.forreadWord();//System.out.println(aForFour.quats.toString());}publicvoidforreadWord(){StringaString;Quatquat;StringpreWord=null;while(!"".equals((aString=readWord()))){133 if("program".equals(aString)){quat=newQuat();forProgram(quat);}elseif("begin".equals(aString)){quat=newQuat();forBegain(quat);}elseif("do".equals(aString)){quat=newQuat();fordo(quat);}elseif("if".equals(aString)){quat=newQuat();forif(quat);}elseif("else".equals(aString)){quat=newQuat();forElse(quat);}elseif(":=".equals(aString)){forSuanshu(preWord);}elseif(("end".equals(aString))){quat=newQuat();StringpString=readWord();if(";".equals(pString)){forEndIfWhileLast(quat);133 }elseif(".".equals(pString)){forEndLast(quat);}}preWord=aString;}displayQuats();}publicvoidforProgram(Quatquat){quat.setFirst("program");quat.setSecond(readWord());quats.add(quat);}publicvoidforBegain(Quatquat){quat.setFirst("begin");quats.add(quat);}133 publicvoidfordo(Quatquat){quat.setFirst("do");quats.add(quat);}publicvoidforif(Quatquat){StringifFirst=readWord();quat.setSecond(ifFirst);StringifSecond=readWord();quat.setFirst(ifSecond);StringifThird=readWord();quat.setThird(ifThird);Stringresult="t"+i++;quat.setFourth(result);quats.add(quat);QuatsecondQuat=newQuat();secondQuat.setFirst("if");secondQuat.setSecond(result);Stringresult1="t"+i++;secondQuat.setFourth(result1);133 quats.add(secondQuat);QuatthirdQuat=newQuat();thirdQuat.setFirst("then");quats.add(thirdQuat);}publicvoidforElse(Quatquat){quat.setFirst("else");StringD="k"+k++;quat.setSecond(D);quats.add(quat);}publicvoidforwhile(Quatquat){quat.setFirst("while");quats.add(quat);QuatfivethQuat=newQuat();StringwhileFirst=readWord();133 fivethQuat.setSecond(whileFirst);StringwhileSecond=readWord();fivethQuat.setFirst(whileSecond);StringwhileThird=readWord();fivethQuat.setThird(whileThird);Stringresult="j"+j++;fivethQuat.setFourth(result);quats.add(fivethQuat);}/***对算数表达式进行处理。**@parampreWord*/publicvoidforSuanshu(StringpreWord){Stringpre=null;Quatquat=newQuat();StringcString;StringdString="";while(!(cString=readWord()).matches(";||if||while||while||end")){133 dString=dString+signTable.replaceVariable(cString);if(":=".equals(cString)){preWord=pre;}pre=cString;}//弹出while时,说明此时已经读完一个表达式或字符或数字//if(isExpression(dString)){//此处调用计算表达式或字符或数字的函数(dstring)Prioritypriority=newPriority();priority.dealConverseExpression(dString);for(Quatq:priority.getQuats()){if(q.getFirst()==null){q.setFirst(":=");q.setSecond(q.getFourth());q.setFourth(preWord);}quats.add(q);}//System.out.println(priority.getQuats().toString());if(cString.equals(";")){forSuanshu(preWord);133 }elseif(cString.equals("if")){Quatquat1=newQuat();forif(quat1);}elseif(cString.equals("while")){Quatquat2=newQuat();forwhile(quat2);}elseif(cString.equals("end")){if(";".equals(readWord())){Quatquat3=newQuat();forEndIfWhileLast(quat);}else{Quatquat4=newQuat();forEndLast(quat);}}}publicvoidforEndLast(Quatquat){quat.setFirst("end");quat.setSecond(quats.get(0).getSecond());quats.add(quat);}133 publicvoidforEndIfWhileLast(Quatquat){quat.setFirst("end");StringdString=null;for(inti=quats.size();i>0;i--){Strings=quats.get(i-1).getFirst();if("if".equals(s)){dString=quats.get(i-1).getFourth();break;}elseif("while".equals(s)){dString=quats.get(i).getFourth();break;}}quat.setSecond(dString);quats.add(quat);}/**133 *判断是不是表达式。**@paramcode*带判断代码。*@return*/publicbooleanisExpression(Stringcode){if(code.contains("+")||code.contains("-")||code.contains("*")||code.contains("/")){returntrue;}returnfalse;}privateStringreadWord(){returnscanner.readWord();}//词法读取w/***显示四元式。*/publicvoiddisplayQuats(){133 System.out.println("四元式:共"+quats.size()+"个");for(Quatquat:quats){System.out.println(quat.toString());}System.out.println();}}packagecom.middleCode;/***四元式象实体类。**@author刘鑫伟**/publicclassQuat{privateStringfirst="";privateStringsecond="";privateStringthird="";133 privateStringfourth="";publicQuat(){}publicQuat(Stringfirst){super();this.first=first;}publicQuat(Stringfirst,Stringsecond,Stringthird,Stringfourth){super();this.first=first;this.second=second;this.third=third;this.fourth=fourth;}/***@returnthefirst*/publicStringgetFirst(){returnfirst;133 }/***@paramfirst*thefirsttoset*/publicvoidsetFirst(Stringfirst){this.first=first;}/***@returnthesecond*/publicStringgetSecond(){returnsecond;}/***@paramsecond*thesecondtoset*/publicvoidsetSecond(Stringsecond){this.second=second;}133 /***@returnthethird*/publicStringgetThird(){returnthird;}/***@paramthird*thethirdtoset*/publicvoidsetThird(Stringthird){this.third=third;}/***@returnthefourth*/publicStringgetFourth(){returnfourth;}/**133 *@paramfourth*thefourthtoset*/publicvoidsetFourth(Stringfourth){this.fourth=fourth;}/**(non-Javadoc)**@seejava.lang.Object#toString()*/@OverridepublicStringtoString(){return"("+first+","+second+","+third+","+fourth+")";}}packagecom.middleCode;/***优先级。*133 *@authorLiu,Xinwei**/publicclassPriority{privatestaticfinalStringPRIORPATH="resource/prior.txt";//优先级表。privateHashMap>priorMap=newHashMap<>();privateArrayListquats=newArrayList<>();privateStackfirstStack=newStack<>();privateStacksecondStack=newStack<>();/***初始化优先级表。*/publicvoidinitPriorMap(){try{BufferedReaderreader=newBufferedReader(newFileReader(newFile(PRIORPATH)));HashMapcolMap=newHashMap<>();Stringline;133 inti=0;while((line=reader.readLine())!=null){if(++i%5==1){colMap=newHashMap<>();}String[]splits=line.split("");colMap.put(splits[1],splits[2]);priorMap.put(splits[0],colMap);}reader.close();}catch(Exceptione){thrownewRuntimeException(e);}//System.out.println(priorMap.toString());}/**逆波兰式。*/publicvoiddealConverseExpression(Stringexpression){Stringtop;133 Quatquat;initPriorMap();//待测试表达式。//System.out.println(expression);firstStack.push("#");WordScannerscanner=newWordScanner();ArrayListwords=scanner.readWord(expression);//System.out.println(words.toString());for(Stringitem:words){if(isOperator(item)){top=firstStack.peek();if("(".equals(item)){firstStack.push(item);}elseif(")".equals(item)){while(!"(".equals(top=firstStack.pop())){if(!"(".equals(top)){secondStack.push(top);buildQuat(top);}}}elseif("(".equals(top)){firstStack.push(item);133 }elseif(">".equals(priorMap.get(item).get(top))){firstStack.push(item);}else{top=firstStack.pop();secondStack.push(top);buildQuat(top);firstStack.push(item);}}else{secondStack.push(item);}}while(!"#".equals(top=firstStack.pop())){secondStack.push(top);buildQuat(top);}if(firstStack.size()==0&&secondStack.size()!=0){Quatq=newQuat(null);q.setFourth(secondStack.pop());quats.add(q);133 }//System.out.println(secondStack.toString());for(Quatq:quats){//System.out.println(q.toString());}}/***构建四元式。*/publicvoidbuildQuat(Stringtop){Quatquat=newQuat(top);for(intj=0;j<3;j++){StringsecondTop=secondStack.pop();if(j==0){quat.setFirst(secondTop);}elseif(j==1){quat.setThird(secondTop);}else{quat.setSecond(secondTop);doubleresult=0;if("+".equals(quat.getFirst())){133 result=Double.parseDouble(quat.getSecond())+Double.parseDouble(quat.getThird());}elseif("-".equals(quat.getFirst())){result=Double.parseDouble(quat.getSecond())-Double.parseDouble(quat.getThird());}elseif("*".equals(quat.getFirst())){result=Double.parseDouble(quat.getSecond())*Double.parseDouble(quat.getThird());}elseif("/".equals(quat.getFirst())){result=Double.parseDouble(quat.getSecond())/Double.parseDouble(quat.getThird());}quat.setFourth(""+result);quats.add(quat);secondStack.push(""+result);}}}/***是否是操作符。**@paramiterm*/133 publicbooleanisOperator(Stringitem){if(item.matches("\+||\-||\*||\/||\(||\)")){returntrue;}returnfalse;}/***@returnthequats*/publicArrayListgetQuats(){returnquats;}/***@paramquats*thequatstoset*/publicvoidsetQuats(ArrayListquats){this.quats=quats;}}133 packagecom.signTable;/***符号表。**@author刘鑫伟**/publicclassSignTable{publicstaticfinalintINTLEN=1;publicstaticfinalintREALLEN=1;publicstaticfinalintCHARLEN=1;publicstaticfinalintBOOLLEN=1;//符号表总表。privateHashMapsynbTable=newHashMap<>();//数组表。privateListarrayTable=newArrayList<>();//结构表。privateListstrutsTable=newArrayList<>();//函数表。privateListfunctionTable=newArrayList<>();133 //活动记录表。privateStack>vallStack=newStack<>();privateArrayListglobalList=newArrayList<>();//执行状态。privateVallvall;privateStringstate;privateStringcode;WordScannerscanner=newWordScanner();Prioritypriority=newPriority();{dealWith();}publicvoiddealWith(){Stringword;if("while".equals(state)){code=scanner.getCode();}while(!"".equals(word=readWord())){133 if("var".equals(word)){dealWithBasicDefine();}elseif("if".equals(word)){state="if";word=readWord();Stringcode=getBooleanExpression(word);dealWithIf(judgeBooleanExpression(code));}elseif("else".equals(word)){return;}elseif("while".equals(word)){dealWithWhile(word);}elseif(synbTable.containsKey(word)&&":=".equals(readWord())){dealWithUse(word);}if("while".equals(state)&&"end".equals(word)){scanner.setCode(code);return;}}}133 publicvoiddealWithArray(){}/***处理基本类型声明。*/publicvoiddealWithBasicDefine(){Stringcode="";Stringword;Stringtype="";while(!";".equals(word=readWord())){if(":".equals(word)){type=readWord();continue;}code=code+word;if(!",".equals(word)){buildVallList("var"+word+"|"+word);}}String[]splits=code.split(",");133 if("integer".equals(type)){for(inti=0;i=")){splits=code.split(">=");left=splits[0];right=splits[1];leftResult=Double.parseDouble(calculateExpression(left));rightResult=Double.parseDouble(calculateExpression(right));isOK=leftResult>=rightResult;}elseif(code.contains("<=")){splits=code.split("<=");left=splits[0];right=splits[1];leftResult=Double.parseDouble(calculateExpression(left));133 rightResult=Double.parseDouble(calculateExpression(right));isOK=leftResult<=rightResult;}elseif(code.contains("<")){splits=code.split("<");left=splits[0];right=splits[1];leftResult=Double.parseDouble(calculateExpression(left));rightResult=Double.parseDouble(calculateExpression(right));isOK=leftResult")){splits=code.split(">");left=splits[0];right=splits[1];leftResult=Double.parseDouble(calculateExpression(left));rightResult=Double.parseDouble(calculateExpression(right));isOK=leftResult>rightResult;}returnisOK;133 }/***读当前第一个单词。**@return第一个单词。*/publicStringreadWord(){returnscanner.readWord();}/***判断是不是表达式。**@paramcode*带判断代码。*@return*/publicbooleanisExpression(Stringcode){if(code.contains("+")||code.contains("-")||code.contains("*")||code.contains("/")){returntrue;133 }returnfalse;}/***计算表达式。**@paramexpression*@return*/publicStringcalculateExpression(Stringexpression){Stringresult;expression=replaceVariableForExpression(expression);priority.dealConverseExpression(expression);result=priority.getQuats().get(priority.getQuats().size()-1).getFourth();result=""+(int)Double.parseDouble(result);returnresult;}/***替换变量。133 **@paramword*@return*/publicStringreplaceVariable(Stringword){if(synbTable.containsKey(word)){word=synbTable.get(word).getValue();}returnword;}/***将带变量的表达式转换为数字表达式。**@paramcode*@return*/publicStringreplaceVariableForExpression(Stringexpression){Stringresult="";WordScannerwordScanner=newWordScanner();ArrayListwords=wordScanner.readWord(expression);133 for(Stringword:words){result=result+replaceVariable(word);}returnresult;}/***构建活动记录。**@paramword*/publicvoidbuildVallList(Stringword){vall=newVall();String[]splits=word.split("\|");Stringaction=splits[0];word=splits[1];vall.setName(word);vall.setAction(action);if(synbTable.containsKey(word)){vall.setValue(synbTable.get(word).getValue());133 if(synbTable.get(word).getType()==Type.FUNCTION){}else{vall.setBelongs("global");}}else{vall.setBelongs("global");vall.setValue("null");}globalList.add(vall);}/***将单个活动记录表压入栈。*/publicvoidpushVallListToStack(){vallStack.push(globalList);}/***输出表。*/133 publicvoiddisplay(){ArrayListlist;pushVallListToStack();System.out.println("符号表总表:");for(Stringkey:synbTable.keySet()){System.out.println(synbTable.get(key).toString());}System.out.println("n活动记录表:");for(inti=vallStack.size();i>0;i--){list=vallStack.pop();for(Vallvall:list){System.out.println(vall.toString());}}}}packagecom.signTable;/**133 *符号表总表元素实体类。**@author刘鑫伟**/publicclassSynb{//名字,标识符源码。privateStringname;//值(新增项)。privateStringvalue;/**类型,指针,指向类型表相应项。:i(整型),r(实型),c(字符型),b(布尔型),a(数组型),*d(结构型)f(函数),c(常量),t(类型),d(域名),v,vn,vf(变量,换名形参,赋值形参)。*/privateTypetype;//数据长度。privateintlength;/***无参构造函数。*/133 publicSynb(){}/***有参构造函数。**@paramname*@paramtype*@paramlength*/publicSynb(Stringname,Typetype,intlength){super();this.name=name;this.type=type;this.length=length;}/***有参构造函数。**@paramname*@paramvalue*@paramtype*@paramcat133 *@paramlength*/publicSynb(Stringname,Stringvalue,Typetype,intlength){super();this.name=name;this.value=value;this.type=type;this.length=length;}/***@returnthename*/publicStringgetName(){returnname;}/***@paramname*thenametoset*/publicvoidsetName(Stringname){this.name=name;133 }/***@returnthevalue*/publicStringgetValue(){returnvalue;}/***@paramvalue*thevaluetoset*/publicvoidsetValue(Stringvalue){this.value=value;}/***@returnthetype*/publicTypegetType(){returntype;}133 /***@paramtype*thetypetoset*/publicvoidsetType(Typetype){this.type=type;}/***@returnthelength*/publicintgetLength(){returnlength;}/***@paramlength*thelengthtoset*/publicvoidsetLength(intlength){this.length=length;}/*133 *(non-Javadoc)**@seejava.lang.Object#toString()*/@OverridepublicStringtoString(){return"name="+name+",value="+value+",type="+type+",length="+length;}}packagecom.signTable;/***数组表元素实体类。**@author刘鑫伟**/publicclassArray{//数组的下界。133 privateStringlow;//数组的上界。privateStringup;//成分类型指针,指向该维数组成分类型(在类型表中的信息)。privateStringctp;//成分类型的长度,成分类型的数据所值单元的个数。privateStringclen;/***无参构造函数。*/publicArray(){}/***有参构造函数。**@paramlow*@paramup*@paramctp*@paramclen*/publicArray(Stringlow,Stringup,Stringctp,Stringclen){133 super();this.low=low;this.up=up;this.ctp=ctp;this.clen=clen;}/***@returnthelow*/publicStringgetLow(){returnlow;}/***@paramlow*thelowtoset*/publicvoidsetLow(Stringlow){this.low=low;}/***@returntheup133 */publicStringgetUp(){returnup;}/***@paramup*theuptoset*/publicvoidsetUp(Stringup){this.up=up;}/***@returnthectp*/publicStringgetCtp(){returnctp;}/***@paramctp*thectptoset*/133 publicvoidsetCtp(Stringctp){this.ctp=ctp;}/***@returntheclen*/publicStringgetClen(){returnclen;}/***@paramclen*theclentoset*/publicvoidsetClen(Stringclen){this.clen=clen;}}packagecom.signTable;/**133 *结构表元素实体类。**@author刘鑫伟**/publicclassStruts{//结构的域名。privateStringid;//区距。privateStringoff;//域成分类型指针,指向idk域成分类型(在类型表中的信息)。privateStringtp;/***无参构造函数。*/publicStruts(){}/***有参构造函数。**@paramid133 *@paramoff*@paramtp*/publicStruts(Stringid,Stringoff,Stringtp){super();this.id=id;this.off=off;this.tp=tp;}/***@returntheid*/publicStringgetId(){returnid;}/***@paramid*theidtoset*/publicvoidsetId(Stringid){this.id=id;}133 /***@returntheoff*/publicStringgetOff(){returnoff;}/***@paramoff*theofftoset*/publicvoidsetOff(Stringoff){this.off=off;}/***@returnthetp*/publicStringgetTp(){returntp;}/**133 *@paramtp*thetptoset*/publicvoidsetTp(Stringtp){this.tp=tp;}}packagecom.signTable;/***函数表元素实体类。**@author刘鑫伟**/publicclassFunction{//层次号,该过函静态层次嵌套号。privateStringlevel;//区距,该过函自身数据区起始单元相对该过函值区区头位置。privateStringoff;//参数个数,该过函的形式参数的个数。133 privateStringfn;//参数表,指向形参表。privateStringentry;//入口地址,该函数目标程序首地址(运行时填写)。privateStringparam;/***无参构造函数。*/publicFunction(){}/***有参构造函数。**@paramlevel*@paramoff*@paramfn*@paramentry*@paramparam*/publicFunction(Stringlevel,Stringoff,Stringfn,Stringentry,Stringparam){133 super();this.level=level;this.off=off;this.fn=fn;this.entry=entry;this.param=param;}/***@returnthelevel*/publicStringgetLevel(){returnlevel;}/***@paramlevel*theleveltoset*/publicvoidsetLevel(Stringlevel){this.level=level;}/**133 *@returntheoff*/publicStringgetOff(){returnoff;}/***@paramoff*theofftoset*/publicvoidsetOff(Stringoff){this.off=off;}/***@returnthefn*/publicStringgetFn(){returnfn;}/***@paramfn*thefntoset133 */publicvoidsetFn(Stringfn){this.fn=fn;}/***@returntheentry*/publicStringgetEntry(){returnentry;}/***@paramentry*theentrytoset*/publicvoidsetEntry(Stringentry){this.entry=entry;}/***@returntheparam*/publicStringgetParam(){133 returnparam;}/***@paramparam*theparamtoset*/publicvoidsetParam(Stringparam){this.param=param;}}packagecom.signTable;/***符号表数据枚举类型。**@author刘鑫伟**/publicenumType{INT,REAL,CHAR,BOOLEAN,ARRAY,STRUTS,FUNCTION;}133 packagecom.signTable;/***活动记录表元素实体类。**@author刘鑫伟**/publicclassVall{//从属于哪个活动记录块。privateStringbelongs;//局部数据区:用来存放局部变量、内情向量、临时单元。privateStringname;//形式单元:用来存放实参的值或地址。(值)privateStringvalue;//执行动作。privateStringaction;/***无参构造函数。*/publicVall(){133 }/***@parambelongs*@paramvalue*@paramname*/publicVall(Stringbelongs,StringlinkDataArea,Stringvalue){super();this.belongs=belongs;this.value=value;}/***@returnthebelongs*/publicStringgetBelongs(){returnbelongs;}/***@parambelongs*thebelongstoset133 */publicvoidsetBelongs(Stringbelongs){this.belongs=belongs;}/***@returnthename*/publicStringgetName(){returnname;}/***@paramname*thenametoset*/publicvoidsetName(Stringname){this.name=name;}/***@returnthevalue*/publicStringgetValue(){133 returnvalue;}/***@paramvalue*thevaluetoset*/publicvoidsetValue(Stringvalue){this.value=value;}/***@returntheaction*/publicStringgetAction(){returnaction;}/***@paramaction*theactiontoset*/publicvoidsetAction(Stringaction){this.action=action;133 }/**(non-Javadoc)**@seejava.lang.Object#toString()*/@OverridepublicStringtoString(){return"belongs="+belongs+",name="+name+",value="+value+",action="+action;}}4.3实验结果a.Token序列如图4-3-1所示。133 图4-3-1b.四元式如图4-3-2所示。133 图4-3-2c.符号表如图4-3-3所示。133 图4-3-35.结论本次实验我们采用了Java语言来编写一个Pacal的编译器前端,步骤按照先词法扫描同时生成Token序列,然后运用递归下降子程序进行语法分析,接着同步生成四元式与符号表构建。词法扫描是通过读文件模式,将代码和关键字表与界符表从文件读入Java的数据结构HashMap,采用键值对的形式存储。之后就是运用JavaAPI中独有的String类的各类函数对代码进行有限自动机处理,最终生成了Token。133 语法分析通过自建文法,采用递归子程序法,画出流程图然后一步一步实现在此之中生成了四元式,其中表达式的四元式是采用逆波兰式的方法生成的,于此同时完善符号表。其中的特色点有:语法分析阶段能够检测出错误,并且能指出错误在哪一行,具体为什么错误;表示式的四元式采用了逆波兰式的方法;同时像if-while,我们的编译器能判断其中的boolean表达式的真值,从而能采用正确的逻辑得出正确的结果;活动记录表阶段能够指出具体采取了什么动作,具体代码。6.参考文献1、陈火旺.《程序设计语言编译原理》(第3版).北京:国防工业出版社.2000.2、美AlfredV.AhoRaviSethiJeffreyD.Ullman著.李建中,姜守旭译.《编译原理》.北京:机械工业出版社.2003.3、美KennethC.Louden著.冯博琴等译.《编译原理及实践》.北京:机械工业出版社.2002.4、金成植著.《编译程序构造原理和实现技术》.北京:高等教育出版社.2002.7.收获、体会、建议7.1收获、体会133 刘鑫伟:本次课程设计是抱着做项目的心态来做的,而不是为了仅仅局限于编译原理的基础上,当初组建队伍的时候,专门找了几个不考研的好朋友,准备一起做一个稍微完整的项目。因此,我变在Github上托管了项目,并且使用了Github的版本控制功能,能够使我能四个人的项目随时同步。当然了,在编译原理知识我也花了不少心思,比如词法分析,语法分析,四元式,符号表的内容我都了解了,在队友们编写程序的时候我也经常一起讨论知识点,这样就进一步巩固了我的知识点。总之这次实验收获还是挺多的。肖辉:从一开始听到做编译器的实验的时候,心里是觉得有点难的,所以也像个无头苍蝇不知从哪里开始。后来老师通过开动员大会,实验时在一旁指导加上自我慢慢的分析,也开始知道怎么去做这个实验。先是组长给大家分了各自的工作,大家自己先按照小组定的总路线走,碰到了困难大家再来一起解决:这告诉我们一个工程或者一个项目不是一个人独立完成的,需要大家的紧密合作,并且需要一个清晰的行动路线才能让大家明白各自的工作。以前也做过课程设计,但从现在来看,我们的水平在不段的提升,想想以前的设计也会觉得不够完美或者太容易,通过这次课程设计,我加深了对这门课程的理解,也尝试着用我并不太了解得JAVA语言来写,在我看来收获的不仅仅是课程设计完成的喜悦。高八一:这次实验历时两个星期,时间虽短,但收获确是不少。通过这次试验,使我对编译器有了一定的了解,对自己所做的模块有了更深一步的认识。这次实验我们组用了Java来编写程序,在编写过程中又对Java中的知识的用途和使用方法有了新的认知,做好实验的同时也学习了一门语言,这是一举两得的事。在试验期间,组员间的相互讨论和帮助也是这一次试验中的一大亮点,特别是组长对我们的指导在整个过程133 中都起着重要的作用。在试验中学会相互协调,相互谅解,让这次实验在欢快中结束。虽然做的不是太完美,但我们都尽力去完成,每一行代码都是我们的成果,我们享受过程,结果也没使我们失望。袁宵:在着手开始编写之前,感觉一头雾水,把书上语义分析和四元式生成内容看了许多遍还是没有头绪。特别是看到其他组已经小有成果时,自己更加着急,觉得特别对不起自己组。后来组长和队友给我讲了他们写的程序,以及词法分析语法分析的思路,我自己有了感觉,就试着写写。后来发现困难是可以克服的,遇到Java编程问题不懂的就问组长,遇到算法思路问题就看书学习上网查资料,慢慢地终于写好了。只要迈出了第一步,后面的步数就是水到渠成了,所以我们不要被眼前的困难吓倒,要把巨大的困难分成一小块一小块依次击破,同时我们要团结起来讲更有信心。只要迈出了第一步,后面的事情就水到渠成了!7.2建议刘鑫伟:既然是课程设计,希望老师应该多给我们项目经验,如何开展一个项目,中间得注意些什么,毕竟大家大多数还是得进公司发展,比较贴近实际需求。同时也希望计算机学院方面重视同学们的实战经历,说实话,没有第一次的实战经历,同学们压根没有热情、没有兴趣开展编程、更谈不上学理论知识了。但是若是开展了第一次的实战项目,以后同学们不管学习什么科目,都会有兴趣学习理论知识,从而达到理论与实践相结合的目的。肖辉:这次的实验我看大家都是用自己的电脑来做,实验室发挥的作用非常有限,实验室电脑里面的编译软件和其他软件让大家不太能接受,所以我希望能改善一下实验室的“环境”,充分发挥实验室的作用。133 袁宵:对实验的评分除了看最后的结果,我觉得也应该关注实验程序是怎么来的,付出了多少。仅仅看结果,正是让那些投机取巧的学生“赚”得好成绩,而让一字一句写程序的同学心寒。133'