基于扩展C0文法的编译器设计(Part2)

来源:互联网 发布:c语言头文件有哪些 编辑:程序博客网 时间:2024/05/12 02:09

2.类/方法/函数功能

词法分析部分:

函数名 功能 Int isSpace()等 判断相关字符种类 void getch() 读取一个字符 void getsym() 读取一个标识符(词) ###***语法分析和语义分析***函数名功能 void declHead() 声明头部子程序 void constDef() 常量定义子程序void constDecl() 常量声明子程序void varDef() 变量定义子程序void varDecl() 变量声明子程序void compoundSta() 复合语句子程序void mianFunc() 主函数子程序void expr() 表达式子程序void item() 项子程序void factor() 因子子程序void state() 语句子程序void conditionSta() 条件语句子程序void codition() 条件void loopSta() 循环语句子程序void valueOfPara() 值参数子程序void paraTable 参数子程序void states() 语句列子程序void readSta() 读语句子程序void writeSta() 写语句子程序void returnSta() 返回语句子程序void funcWithRetVlaDef() 有返回值函数定义void funcWithNotRetValDef() 无返回值函数定义void program() 程序子程序void init() 变量初始化函数void stt() Debug输出函数 void insertSymTab(char* name,int type, int value, int address, int para) 符号表插入函数void insertPara(int para) 参数值修改函数int searchSymTab(char* name, int flag) 符号表检索函数int arrLength(char* name) 数组长度检索函数

中间代码生成:

函数名 功能void genMidCode(char* op,char* a, int b, char* result) 生成四元式void genMidCode(char* op,char* a, char* b, char* result) 生成四元式char* int2array(int a) 整型转换为字符型char* genLab() 生成新标签char* genVar() 生成新变量名int isNumber(char*a, int len) 判断一个数组是否代表一个数

目标程序生成:

由于笔者选择mips作为最终的目标代码,因此对文法分析后判断需要实现的mips指令表如下:

指令名 指令格式指令意义系统调用 syscall 根据c0参数不同功能不同取立即数 li s1,100 s1 = 100取地址 la $t1, array1 $t1 = array1的首地址加 add s1,s2,s3 s1 = s2 + s3减 sub s1,s2,s3 s1 = s2 – s3乘 mult s1,s2 hi,lo = s1*s2除 div s1,s2 lo = s1/s2, hi = s1mod s2立即数加 addi s1,s2,100 s1 = s2 + 100立即数减 subi s1,s2,100 s1 = s2 - 100mfhi mfhi a a = [hi]mflo mflo a a = [lo]movemove s1 s2 s1 = s2取字lw $t2,4($t1) $t2 = [$t1+1]存字sw $t2,4($t1) [$t1+1] = $t2相等跳转beq s1,s2,label if(s1==s2) goto label不等跳转bne s1,s2,label if(s1!=s2) goto label小于跳转blt s1,s2,labelif(s1 小于 s2 ) goto label大于跳转 bgt s1,s2,label if(s1>s2) goto label小于等于跳转 ble s1,s2,label if(s1不大于s2) goto label大于等于跳转 bge s1,s2,label if(s1>=s2) goto labelj j label goto labeljr jr $ra goto [$ra]jal jal label goto and link label
由上表可以得到一部分汇编相关的函数:
函数名 功能int findaddr(char* name) 寻找变量在运行栈中的位置void insertaddr(char* name) 在运行栈中插入变量位置void globalcondef() 全局常量定义生成void globalvardef() 全局变量定义生成void initasm() 预处理整个目标代码int isNum() 判断是否是数字字符void func_mips() 函数目标吗生成void myend_mips() 用于数组结束判断void ret_mips() 返回目标码生成void ints_mips() 整型变量目标码生成void chars_mips() 字符型变量目标码生成void inta_mips() 整型数组目标码生成void chara_mips() 字符型数组目标码生成void add_mips() 加指令目标码生成void sub_mips() 减指令目标码生成void mul_mips() 乘指令目标码生成void div_mips() 除指令目标码生成void prtf_mips() 输出指令目标码生成void scf_mips() 读指令目标码生成void lab_mips() 标签目标码生成void paraop_mips() 函数指参传递指令目标码生成void calpara_mips() 函数调用参数目标码生成void call_mips() 函数调用指令目标码生成void jmp_mips() 跳转指令目标码生成void jne_mips() 跳转目的指令生成void ass_mipa() 普通赋值语句目标码生成void bt_mips() 大于指令目标码生成void st_mips() 小于指令目标码生成void eql_mips() 等于指令目标码生成void neq_mips() 不等于指令目标码生成void nbt_mips() 不大于指令目标码生成void nst_mips() 不小于指令目标码生成void assignA_mips() 赋值数组指令目标码生成void aAssign_mips() 数组赋值指令目标码生成void exit_mips() 退出指令目标码生成void run() 运行函数

错误处理:

函数名 功能error(int errorcode, itn indexInFile) 打印错误信息

优化部分:

函数名 功能void combine() 常数合并void replace(char* result, char*a) 对固定的字符串做替换

3.调用依赖关系

这里写图片描述

4.符号表管理

为了便于实现,这里采用无序符号表的组织方式。
具体的符号表数据结构如下:
这里写图片描述

5.存储分配方案

原计划寄存器分配采用启发式图着色算法。采用该方法的主要目的是为了避免因引用计数法带来的全局寄存器前中后期分配不均问题。具体实现时,采用了固定寄存器分配(只使用t1,t2两个临时寄存器,随用随取)。
运行栈设计采用课本介绍的经典动态存储分配方式,图示如下:
这里写图片描述

6. 解释执行程序

本程序不采用解释执行程序,而是编译执行。

7. 四元式设计

对于整个文法而言,可能出现的有关数据的操作和对应的四元式设计如下表:

操作种类 四元式设计int a; int,,,achar b; char,,,bint a[10]; int,,10,achar b[10] char,,10,bconst int a = 5; const,int,5,aconst char b = 6; const,char,6,ba = b; =,b,,aa[i] = b; []=,b,i,aa = b[i]; aassi,b,i,a//array assigna = f();//有返回值函数调用call,f,,af();//无返回值函数调用 call,f,,a 不大于 b 不大于,,a,ba 小于 b 小于,,a,ba >= b >=,,a,ba > b >,,a,ba == b ==,,a,ba != b !=,,a,bif(!true) jne,,,labelif(true) jmp,,,labelset label lab:,,,labelreturn ; ret,,,return a; ret,,,ascanf(a); scf,,,aprintf(“a”,b) prtf,a,b,symint f() func,int,,fchar f() func,char,,ff(int a,…) para,int,,a

8. 目标代码生成方案

目标代码生成的主要任务包括:从中间代码到目标代码的转换过程中进行指令选择,目标代码地址空间的划分,目标体系结构上寄存器和内存单元的分配和指派,目标代码序列的生成等。在这一过程中,主要考虑:

1. 如何为中间代码选择语义等价且运行效率高的目标指令;
2. 为目标代码、局部变量、全局变量、静态变量、临时变量、常量等指定和划分地址空间;
3. 由于源程序和中间代码中的变量和数据结构的显示定义都将消失,取而代之的是具体的寄存器编号和内存空间地址等,因此需要准确合理的将这些寄存器和内存单元分配给不同类型和结构的变量;
4. 生成和输出目标代码序列到文件。在这一过程中,目标代码的序列和输入的中间代码序列在顺序上可以一致,也可以不一致,在保证语义不变的前提下,尽量选择更高执行效率或者更小存储空间的代码序列。

9. 优化方案

1.窥孔优化(未实现)
在采用中间代码到目标代码逐条生成的过程中,目标代码中经常会出现代码的冗余或者低效率的指令,为了消除这种指令,我们采用窥孔优化的方式处理。窥孔优化关注在目标指令的一个较短序列上,通过删除冗余代码或者替换更高效和简洁的代码来使得最终得到的目标代码是高质量的。
2.常数合并
如果在编译的时候,对于某些表达式的部分或者全部操作数的值,则此表达式就会被优化,将已知值的操作数进行可以进行的运算后再与变量进行运算。
3.常量替换
在编译之初就将所有常量替换为值,不在对常量进行取址等操作。
4.消除公共子表达式(未实现)

10. 出错处理

错误处理方案:

#define FILEOPEN_ERROR -1 //file open failed
#define ZEROSTART_ERROR 0 //
#define UNDEFFUNC_ERROR 1
#define UNDEFCHAR_ERROR 2 //undefined IDEN
#define UNMATCHSQ_ERROR 3 //unmatched singal quoto
#define UNMATCHDQ_ERROR 4 // unmatched double quoto
#define OUTOFTABINDEXX_ERROR 5 // out of table max length
#define FUNCNAMECOMPLICT_ERROR 6 // function name conplict
#define VARNAMECOMPLICT_ERROR 7 //variable name complict
#define NAMECOMPLICTGLOBAL_ERROR 8 //name can not complict with global
#define DELHEAD_IDMIS_ERROR 9 // id missed in delcare head part
#define AFTERASS_NOTIDEN_ERROR 10 // after a assign symbol should be a dientifier symbol
#define CONSTDEF_ASSMIS_ERROR 11 // in a const defination assign symbol missed
#define CONSTDEF_TYPE_ERROR 12 // const defination have only two type
#define SEMICSYMMIS_ERROR 13 // ; missed
#define VARDEF_ARRAYINDEX_ERROR 14 //an array index should be number in variable defination
#define VARDEF_TYPE_ERROR 15 // in a vardefine, identifier type error
#define MAINSYM_ERROR 16 // in a main function, name must be ”
#define LPARENSYMMIS_ERROR 17 // main ( missed
#define RPARENSYMMIS_ERROR 18 // main ) missed
#define LBPARENSYMMIS_ERROR 19 // mian {
#define RBPARENSYMMIS_ERROR 20 // main }
#define RMPARENSYMMIS_ERROR 21 // ] missed
#define AFTEROP_NUMMIS_ERROR 22 // -56 ok, -b not accepted
#define FACTOR_ERROR 23 // factor type error
#define ASSIGNSTATUS_ERROR 24 // assign status error
#define STATUS_ERROR 25 // status error
#define CONDITIONOP_ERROR 26 // condition status error
#define WHILESYMMIS_ERROR 27 // while symbol missed
#define IDSYMMIS_ERROR 28 // in a for loop, identifier missed in initial
#define FORASSIGNMIS_ERROR 29 // int a for loop initial, assign symbol must appeare
#define VARTYPE_ERROR 30 // in a for loop, loop variable should not be a const
#define FOROPMIS_ERROR 31 // in for loop step part, op(+/-) missed
#define FORDIGSYM_ERROR 32 // in for loop step part, digital missed
#define VOIDSYMMIS_ERROR 33 // in main function, void symbol missed
#define PARANUM_ERROR 34 // paramenter number error
#define UNEXCEPTRETURNVAL_ERROR 35 // void function return value
#define READARRAY_ERROR 36 // read an array name

错误处理方式:

1.递归子程序发现错误立即调用error()并传递出错信号;
2.error函数通过接收到的出错信号打印出出错信息和位置信息;
3.通过出错类型型号和位置判断应该如何进行跳读;
4.继续编译,直到文件结束。

三.操作说明

1.运行环境

运行环境为32位Win7系统,运行软件为CodeBlocks13.12版本。

2.操作步骤

打开final.cbp文件,输入目标文件所在位置(绝对位置或者相对位置均可)。

四.测试

内容略,已经过集成测试

0 0
原创粉丝点击