CMM解释器项目文档
一、背景
完成小组的基本信息: 姓名
学号 分工内容 二、文法描述
粗体文字表示终结符,其余为非终结符,write (“(.)*”) ;为字符串输出,双引号内可以为除引号外任意字符 program -> block block -> { decls stmts } decls -> decls decl | ε decl –> type id ; type -> type[num] | basic stmts -> stmts stmt | ε stmt -> loc = bool; | if (bool) stmt | if (bool) stmt else stmt | while (bool) stmt | do stmt while (bool) ; | read (loc) ; | write (loc) ; | write (“(.)*”) ; | block loc -> loc [bool] | id bool -> bool || join | join join -> join && equality |equality equality ->equality == rel | equality<>rel | rel rel -> expr
1
factor -> (bool) | loc | num | real | true | false
三、系统分析和设计
包括系统的概要设计、详细设计和核心算法说明及分析,系统所采用的开发工具等。 1. 系统概要设计:本系统采用Java语言编写。系统源代码由五个包构成。inter包中
的代码用于解释执行cmm语言中用到的赋值、流程控制、输入输出语句和表达式运算。lexer包中的代码用于词法分析过程,包括cmm源代码的扫描,初始化cmm语言中的关键字、常用运算符,以及常量。main包中的代码用于生成可视化界面,包括初始的logo,welcome对话框以及主界面。parser包中的代码用于语法分析以及cmm源程序的解释执行。symbols包中的代码用于初始化cmm支持的基本类型,表示数组,以及记录已声明的变量和数组标识符。
2. 系统详细设计:inter包中除Node外所有类都继承抽象类Node,Node类中定义了
一个属性:即当前的行号,一个构造函数用于初始化行号,一个具体方法用于报告错误:error()以及一个抽象方法:getTreeNode()。Node类有两个抽象子类:Stmt类和Expr类,Stmt类中有抽象方法:execute(),Node类中有抽象方法:getValue()。所有对应语句的类,如:If、Else、While等都继承Stmt,并重写getTreeNode()和execute()方法。所有对应表达式的类,如:Arith、Constant、Id等都继承Expr,并重写getTreeNode()和getValue()方法。lexer包中共有6个类。Lexer类用于扫描输入框中输入的源代码并解析得到token完成词法分析。Num类和Real类分别用于实例化整数和实数,并记下相应的值。类Token用于实例化扫描到的token。Tag类用于初始化常用的token的标签,方便语法分析时的匹配。Word用于初始化CMM语言中的关键字和实例化扫描到的标识符。main包中共有5个类。CreatGUI中包含main()方法,是程序的入口。Editor用于生成主界面中支持语法高亮的编辑区。GUI完成对主界面的设计,包括页面布局以及事件监听器。ImageJPanel类用于生成程序启动时的logo。parser包中的Parser类用于语法分析和解释执行,通过调用lexer得到token,再递归下降对得到的token逐一匹配,定义的cmm语言的起始为一个block,调用语法分析得到的Block对象的getTreeNode()方法得到语法树的根结点,调用其execute()方法对cmm源程序解释执行。
语法分析主程序示意图
2
置初值 调用lexer读下一个单词符号 调用parser 结束
symbols包中有3个类。Type类用于初始化cmm语言中的基本类型,有两个静态方法:numeric()用于检验一个类型是否数值类型和max()用于确定运算中各数值类型的关系,如:整数和实数相加得到的结果是实数。Array继承Type类,用于实例化数组类型,记录了数组的类型和大小。Map类用于建立记录已声明变量标识符的哈希表。
3. 核心算法:编译原理中学到的递归下降分析法:对文法的每一非终结符号,都根据相应产生式各候选式的结构,为其编写一个子程序 (或函数),用来识别该非终结符号所表示的语法范畴。递归下降分析法是最常用到的自顶向下分析法。Java语言的面向对象思想:继承和多态。生成语法树和解释执行程序用到了java的继承和多态,在递归下降分析的过程中调用特定类的getTreeNode()方法获得树的结点,调用Stmt类的子类的execute()方法执行语句动作,Expr类的子类的getValue()方法来获得表达式的值。
4. 系统开发工具:MyEclipse 8.0
四、测试用例和测试结果
测试用例
//冒泡排序 {
int[10] x; int i,n; int j;
3
int temp; i = 10; n = 10; while(i>0){ read(x[10-i]); i=i-1; }
//**第一次输出** i=0;
write(\\
while (i < n) { write(x[i]);
i = i + 1; }
//**********冒泡排序************ i = 0; j = 0;
4