cmm编译器试验报告.doc

上传人:scccc 文档编号:11233048 上传时间:2021-07-16 格式:DOC 页数:25 大小:261.50KB
返回 下载 相关 举报
cmm编译器试验报告.doc_第1页
第1页 / 共25页
cmm编译器试验报告.doc_第2页
第2页 / 共25页
cmm编译器试验报告.doc_第3页
第3页 / 共25页
cmm编译器试验报告.doc_第4页
第4页 / 共25页
cmm编译器试验报告.doc_第5页
第5页 / 共25页
点击查看更多>>
资源描述

《cmm编译器试验报告.doc》由会员分享,可在线阅读,更多相关《cmm编译器试验报告.doc(25页珍藏版)》请在三一文库上搜索。

1、CMM编译器试验报告 目录小组成员-P2Chapter 1编译器流程-P2Chapter 2编译器词法说明-P3Chapter 3编译器语法和语义说明-P3Chapter 4编译器中间代码生成说明-P5Chapter 5编译器执行中间代码说明-P8附录(源代码):Part 0界面-P10Form1.cs Form2.csPart 1词法-P10WordAnalyzer.cs Part 2语法&语义 -P11fenxi.cs Part 3符号表 -P15BStable.cs LStable.cs SZtable.cs Part 4中间代码 -P17MiddleCode.cs MCode.csPa

2、rt 5执行 -P21CompileMidCode.cs MidCodeAccessTABLE.cs Part 6测试-P24小组说明:小组成员成员信息分工完成否小组组长:王嘉学号: 200532580318班级:10班设计文档,试验报告,小组分工, Part5代码编写开发组长:朱雯学号: 200532580297班级:9班代码设计和分工,Part 1&2&4代码编写开发组员:周磊学号: 200732580327班级:10班界面设计 Part 0&2&3代码编写测试组长:陈依媛学号: 200532580292班级:9班测试文档,功能测试行号编写, Part6编写Chapter1: CMM编译器

3、流程说明:在最初的设计时,本来打算语法和语义分开,语义和中间代码放在一起执行的,不过后来我们采取了语法和语义一起执行,然后生成中间代码,最后执行得到结果,编译可能会有错误,我们进行了一定的错误处理。以下是我们的最终CMM编译器程序执行流程图:CMM编译器的程序执行流程图:输入CMM源文件N输出词法错误词法分析Y语法分析语义分析N输出语法错误Y生成中间代码输出中间代码输出编译错误N运行中间代码Y得到执行结果Y:执行正确N:执行错误Chapter2 编译器词法说明【词法分析】:对输入的CMM源文件进行词法分析,下面是可识别的词法分析表关键字if else while read write int

4、real标识符A a56 a_23 a_23dty实数1.2 0.23 92.00整数12 0 3490关系运算符= 赋值符=算数运算符+ - * / 逻辑运算符( )注释符/* */数组符号 嵌套符号 语句结束符;Chapter3 编译器语法说明【语法分析】&【语义分析】:由于语法和语义是一起进行的.先列出文法对输入的CMM源文件进行文法分析,下面是CMM文法终极版:Program := stmt-sequenceStmt-sequence := statement statementstatement := if-stmt | while-stmt| read-stmt | write-s

5、tmt | int-stmt | real-stmtIf-stmt := if (condition) Stmt-sequence | if (condition) Stmt-sequence else Stmt-sequencewhile-stmt := while (condition) Stmt-sequence read-stmt := read identifier|array;write-stmt := write expression;int-stmt := int array | int identifier = expressionreal-stmt := real arra

6、y | real identifier = expressionassign-stmt := identifier|array = expression ;condition := expression comparison-op expressioncomparison-op := | = | expression := term addop term addop := + | -term := factor mulop facror mulop := * | /factor := (expression) | int | real | identifier |arrayarray := i

7、dentifierint | identifier语义的步骤:1进行语义检查对输入的CMM源文件进行语义分析,下面是CMM的语义检查表:检查解决方案是否完成1.每个使用性标识符是否都有申明?在符号表中查找 是否存在 已完成2.运算符的分量类型是否相同?在符号表中查找 是否相同 此项在生成中间代码时完成3.赋值语句的左右部的类型是否相等?在符号表中查找 是否相等,若将int型的值赋給real,则先转换,否则就报错 此项在生成中间代码时完成4.在同层中有无标识符被申明多次?在符号表中查找 是否申明过 已完成5.if,while语句的()中是否是一个布尔类型的结果()里是不是只含有一个关系运算符的表

8、达式 已完成6.write语句后面跟的是否是标识符? 已完成7.read后面跟的是否是标识符,或是变量申明?read后面只可以接标识符和数组 已完成8.数组的下标是否是正整数?在符号表中查找 是否是正整数 已完成2在扫描声明部分时构造标识符的符号表所有构造用到的符号表如下:标识符符号表BStableBStable_nameBStable_typeBStable_levelBStable_valuedBStable_value标识符的名称标识符的类型标识符所在层标识符是否被赋值标识符的值数组符号表SZtableSZtable_nameSZtable_typeSZtable_lengthSZtab

9、le_levelSZtable_valuedSZtable_element数组的名称数则的类型数则的长度数则的层数组组员是否赋值数组组员的值临时变量符号表LStableLStable_nameLStable_typeLStable_levelLStable_valuedLStable_value临时变量的名称临时变量的类型临时变量的层临时变量是否被赋值临时变量的值Chapter4 中间代码生成说明【中间代码】2.4.1【4元式形式】:中间代码采用3地址代码的4元式:4元式形式表:运算符运算分量运算分量运算结果oparg1arg2resulta+bADDI (+)abt1a-bSUBI (-)a

10、bt1a*bMULTI (*)abt1a/bDIVIDI (/)abt1abLT ()abt1a=bET (=)abt1abUNET ()abt1read aREADIa-t1write aWRITEIa-t11+1.1real1-t1a=bMOVE (=)ab-If a把E的结果计算出来,得到的值放在一个临时变量里1 如果E是INT,V是REAL,首先要进行类型转换2 达到可赋值条件的时候,生成(ASSIGN,arg1,arg2,-)【2】是数组1有下标的情形,将赋值式左边的形式转化为 SARG(TARG(j)2同样需比较赋值符号左右参数类型是否一致3达到可赋值条件的时候,生成(ASSIGN

11、,arg1,arg2,-)4】 If-else语句的中间代码的生成:Sif (E) Selse S E.code (JUMP0,E.arg,ElseL,-) S1.code ( JUMP ,-,OutL,-) (LABEL,ElseL,-,-) S2.code(LABEL,OutL,-,-)步骤:1】E.code 为关系运算表达式的中间代码,生成(LT/ET/UNET,arg1,arg2,VARG(tn)2】产生一条 跳转语句的 中间代码,(JUMP0,E.arg,ElseL,-) ,如果 result为假, 跳转到,标签指示的位置,一般为并行的else语句处.3】S1.code 为 if条件

12、满足时 继续运行的代码, 按源代码,顺序产生相应的中间代码.4】S1.code的中间代码产生完毕后, 产生一条 跳转语句的中间代码 跳初该 if-else结构语句( JUMP ,-,OutL,-)5】遇到else 产生一条 标签的 中间代码, (LABEL,ElseL,-,-),用于跳转语句 备注: 在这里无论有没有ELSE,我们都会生成ELSE的LABEL一个标签6】产生S2.code 的中间代码7】在 if-else 结构的结尾处,产生一条标签的 中间代码, (LABEL,OutL,-,-),用于跳出。5】 While语句的中间代码生成:Swhile E S (LABEL,InL,-,-)

13、 E.code (JUMP0,E.arg,OutL,-)S.code (JUMP,-,InL,-)(LABEL,OutL,-,-)步骤:1】产生一条 标签 的中间代码, (LABEL,InL,-,-) ,用于进入循环体.2】E.code关系运算表达式的中间代码,执行后可以得到一个结果result为true|false3】产生一条 跳转语句的 中间代码,(JUMP0,E.arg,OutL,-) ,如果 result为假, 跳处循环体4】S.code为 条件满足时 继续运行的代码, 按源代码,顺序产生相应的中间代码.5】S.code的中间代码产生完毕后, 产生一条 跳转语句的中间代码( JUMP

14、,-,InL,-), 用于 跳转到循环的进口处 。6】在while循环体的末尾处加上 一条 标签 的中间代码,(LABEL,OutL,-,-)用于离开循环体。6】 表达式的中间代码生成: (这里我们请朱雯同学详细解说)J首先,表达式中间代码的生成总体思想是采用递归向下来实现的。由文法:expression := term + | - term term := factor * | / facror factor := (expression) | int | real | identifier |array一步步由表达式到项,到因子,再一步步递归返回。步骤:1】 先执行项的中间代码生成,得到项

15、的中间代码最后生成的result(有可能只是VARG(标识符变量名),SARG(数组变量),也有可能是得到了项的中间代码生成的TARG(临时变量名). 将result加一个空格存储在string型变量s2中。2】 扫描后面是否还有“+”或“-”,若有,就将运算符加一个空格添加到一个string型变量s1中,然后执行项的递归运算,得到最后的result, 将result加一个空格添加到s2末尾。3】 利用循环继续扫描,直到项后不再为“+”或“-”,即后面不再属于表达式部分4】 将s1,s2中字符串以空格隔开分割得到的子字符串依次存储在数组p1,p2中。第一次从p2中取前2个字符串,从p1中取一个

16、符号,+对应 ADDI,-对应SUBI,生成中间代码得到临时变量存到result中。然后每次从p2,p1中取一个字符串,和前面生成的result对应生成一条中间代码,并得到临时变量result,直到表达式结束。5】 Term的中间代码生成思想和expression一致。这样,运算符的优先级会通过递归实现。Chapter5 执行中间代码说明【中间代码的执行】中间代码,依次处理中间代码生成的4元式,得到结果.为每条4元式的构造的方法如下表:名称参数1参数2运算结果作用备注oparg1arg2resultADDI (+)arg1arg2Result计算arg1, arg2的和,赋值result,返回

17、resultSUBI (-)arg1arg2Result计算arg1, arg2的差,赋值result,返回resultMULTI (*)arg1arg2Result计算arg1, arg2的积,赋值result,返回result做减运算符的时候如果结果为负,会报错.DIVIDI (/)arg1arg2Result计算arg1, arg2的除,赋值result,返回result做除运算符的时候如果除数为负,回报错LT ()arg1arg2Result(true| false)判断arg1是否小于arg2,返回Result=true| falseET (=)arg1arg2Result(true

18、| false)判断arg1是否等于arg2,返回Result=true| falseUNET ()arg1arg2Result(true| false)判断arg1是否不等于arg2,返回Result=true| falseREADIargTOKEN-接受屏幕输入TOKEN,并把值赋给arg考虑到读入数据类型,如果类型不匹配,报错WRITEIarg-在屏幕上输出arg.VALUE这里我们使用控制台,输出显示.realarg-result把arg.vlaue赋值给临时变量resultASSIGN (=)Arg1Arg2-修改arg1的VARG, 把arg2.value赋给arg1.valueL

19、ABEL ( ) arg L1=ElseL|OutL |InL -做为跳转语句的标签JUMP0t1-L1=ElseL|OutL当t1值为true时,跳转到标签L1=ElseL|OutL中间代码处JUMP-L2=OutL|InL无条件立即跳转到标签L2=OutL| InL的中间代码备注:1 定义一个变量作为指针,每执行一条4元式后指向下一条指针.如果编译错误,指针指向最后一条跳出.2 每次使用变量时,会对2个变量进行ERROR操作.IfError(string arg1,string arg2, string a,string b)此方法对数组越界,调用没有赋值的参数,和除数为0,还有负结果处理

20、,会屏幕打印错误的位置和类型.3 对每个符号表的参数的存取和修改都有相应的操作,单独放在另一个类中.45 这里的结果输出和输入最终采用控制台的方案,操作比较简单,实现结果也不错.附录(源代码):说明:这里只把类的方法和方法的解释列出,详细代码请对应查看项目Part 0界面(所有功能按钮见源码)Part 1词法详细见WordAnalyzer 类class WordAnalyzer /定义成员变量 public static string sourceCode; public string tokenStr = null; public string formatStr=null; public

21、string errStr = null; public int errornum = 0; int n = 0; string str; / 基本保留字 public static string keyWords = (if|else|while|read|write|int|while|real)$; public static bool isBound(char str) public static bool isOperators(char str) /判断是否为字母 public static bool isChar(char str) /判断是否为空格或回车,换行,或tab pub

22、lic static bool isBlank(char str) /判断是否为整数 public static bool isNumber(char str) /getCha( int n)方法,用于返回一个字符串中第n个位置的字符 public static char getCha( int n) /* * 扫描分析程序 */ public string Analyze(string s) Part 2语法&语义详细见源码,这里只列出所有方法。class fenxi #region 全局声明变量 public string next = null; public string token;

23、 public string format; public int n; public int level = 1; public ArrayList BSlist = new ArrayList();/变量表 public ArrayList BStablelist = new ArrayList(); public ArrayList LSlist = new ArrayList();/临时变量表 public ArrayList LStablelist = new ArrayList(); public ArrayList LZlist = new ArrayList();/临时数组表

24、public ArrayList LZtablelist = new ArrayList(); public ArrayList SZlist = new ArrayList();/数组表 public ArrayList SZtablelist = new ArrayList(); public string errortxt; int tmp; #endregion public string getToken(ref int n) / / 判断是不是为expression / private bool isExpression() / / 判断是不是为term / private boo

25、l isTerm() / / 判断是不是为facter :(expression)|int | identifier |real|array / private bool isFactor() /判断是不是数组: identifierint | identifier private bool isArray() /判断是不是条件expression comparison-op expression private bool isCondition() /是否为赋值语句identifier|array = expression private bool isAssignStmt() /是否为语句

26、 private bool isStatement() /If-stmt:if (exp) Stmt-sequence else Stmt-sequence private bool isIfStmt() /while-stmt: while (condition) Stmt-sequence private bool isWhileStmt() /read-stmt := read identifier; private bool isReadStmt() /write-stmt := write factor2; private bool isWriteStmt() /int-stmt :

27、= int identifier | int assign-stmt /real-stmt := real identifier | real assign-stmt private bool isIntOrRealStmt() / Stmt-sequence := statement statement private bool isStmtSequence() public bool scan() /扫描前先将之前的数据恢复为/*/ public void clear() / / 变量是否声明过(声明过为false)声明语句中用 / / / / private bool SM1(strin

28、g next, int n) / / 变量是否声明过(声明过为false) / / / / private bool SM(string next,int n) if (BSlist.Contains(next) | SZlist.Contains(next)/变量是否已经声明过 / / 赋值语句中,检查被赋值变量是否声明(声明过为true,并将其放入临时变量表中) / / / private bool toLS(string next,int n) / / 清理临时变量表中的成员 / private void clsLS() / / 把临时数组表中的成员加入到SZtable中 / priva

29、te void toSZ() / / 判断临时变量表中的成员是不是real类型(如果是real,返回true) / / private bool isReal() / / 等号两边的变量类型是否相同(相同为true)(等号左边为real时,肯定为true) / / / private bool isType(int n) / / 给变量赋值的时候,将其在变量表中的valued改为true / private void toValue() / / 给变量赋值的时候,将其在变量表中的valued改为true / private bool toValueSM(int n) / / 给数组某个下标变量赋值的时候,将其下标添加进在数组表中对应的valued / private bool toSZvalue(int n) / / read时,将read的变量的valued改为true / / private void toValueRead(int n) / / 退出嵌套时,删除嵌套内声明的变量和数组 / / private void clsLevel(int level) / / 是否超出数组下界 / / / private bool SZdow

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1