在前几篇文章中,我们已经实现了 C-Minus 语法的词法分析、语法分析及语义分析,这次我们将编写一个程序对使用类C语言书写的源代码翻译为中间代码/目标代码,并打印翻译结果。
程序要能够检查源代码中可能包含的词法错误:
对上述目标,本文实现的内容如下:
由于在代码中已经对各个函数功能、过程进行了详细的注释,因此在代码分析章节中会减少文字叙述。
在本文中,我采用线性中间代码双链表的存储方式,在语法分析结束后进行中间代码的生成。
对单条中间代码可以将代码类型和操作数分别进行存储,数据结构定义如下:
typedef struct _OperandStru // 操作数
{
enum
{
VARIABLE, // 变量 x
TEMPVAR, // 临时变量 t1
LABLE, // 标签 lable1
CONSTANT, // 常数 #1
ADDRESS, // 取地址 &x
VALUE, // 读取地址的值 *x
FUNC, // 函数
} kind;
union {
int tempvar; // 临时变量
int lable; // 标签
int value; // 常数的值
char *name; // 语义值,变量名称、函数名称
} operand;
int value;
} OperandStru, *Operand;
对操作数进行存储时,需要区分操作数的类型;对于不同类型的中间代码,其操作数的数量也是不同的,因此使用union进行存储。同时为了实现对函数声明、函数调用语句的翻译,定义了函数参数列表的数据结构,在递归调用的翻译过程中存储所有的参数。
typedef struct _InterCodeStru // 中间代码
{
// 代码类型
enum
{
_LABLE, // 定义标号
_FUNCTION, // 定义函数
_ASSIGN, // =
_ADD, // +
_SUB, // -
_MUL, // *
_DIV, // /
_GOTO, // 无条件跳转
_IFGOTO, // 判断跳转
_RETURN, // 函数返回
_ARG, // 传实参
_CALL, // 函数调用
_PARAM, // 函数参数声明
_READ, // 从控制台读取x
_WRITE, // 向控制台打印x
_NULL // 空的
} kind;
// 操作数
union {
struct
{ // 赋值 取地址 函数调用等
Operand left, right;
} assign;
struct
{ // 双目运算 + = * /
Operand result, op1, op2;
} binop;
struct
{ // GOTO 和 IF...GOTO
Operand lable, op1, op2;
char *relop;
} jump;
// 函数声明、参数声明、标签、传实参、函数返回、读取x、打印x
Operand var;
} operands;
struct _InterCodeStru *prev, *next;
} InterCodeStru, *InterCode;
// 函数参数列表
typedef struct _ArgListStru
{
int num;
Operand list[10];
} ArgListStru, *ArgList;
InterCode CodesHead, CodesTail; // 全局变量,线性IR双链表的首尾
在中间代码中,我们需要声明很多临时变量和标签作为操作数,这里设置了全局变量用于存储生成的临时变量,同时为了进行中间代码优化,我将每个临时变量所表示的操作数进行存储
// 临时变量t1和标签lable1
int tempvar[100];
Operand temp_Operands[100];
int lables[100];
本次实验中我采用自顶向下遍历语法分析树的方式生成中间代码,减少了模块的耦合性。
为了生成中间代码,我编写了许多中间函数,简化了分析过程
// 初始化双链表
void init_InterCode();
// 创建一个新的操作数
Operand new_Operand();
// 创建一个新的变量
Operand new_Variable(char *name);
// 创建一个新的常量
Operand new_Const(float value);
// 创建一条新的中间代码
InterCode new_Code();
// 创建一条lable声明的中间代码
InterCode new_lable_Code(Operand lable);
// 创建一条跳转语句的中间代码
InterCode new_goto_Code(Operand lable);
// 创建一条赋值的中间代码
InterCode new_assign_Code(Operand left, Operand right);
// 打印一条中间代码
void print_Code(InterCode code);
// 打印一个操作数
void print_Operand(Operand op);
// 打印一段中间代码
void print_Codes(InterCode codes);
// 获取链表的尾部
InterCode get_Tail(InterCode codes);
// 在链表末尾加上另一条链表
InterCode add_Codes(int num, ...);
临时变量与新的标签生成方式如下:
Operand new_tempvar()
{
int i;
for (i = 0; i < 100; i++)
{
if (tempvar[i] == -1)
{
tempvar[i] = 1;
break;
}
}
if (i >= 100)
return NULL;
Operand result = new_Operand();
result->kind = TEMPVAR;
result->operand.tempvar = i + 1;
temp_Operands[i] = result;
return result;
}
Operand new_lable()
{
int i;
for (i = 0; i < 100; i++)
{
if (lables[i] == -1)
{
lables[i] = 1;
break;
}
}
if (i >= 100)
return NULL;
Operand result = new_Operand();
result->kind = LABLE;
result->operand.lable = i + 1;
return result;
}
同时为了减少对临时变量的重复声明,在翻译基本表达式、条件表达式以及一些语句时,进行变量表的遍历,对于存储相同值的临时变量直接使用即可,不再重复生成:
// 当Exp的翻译模式为INT、ID、MINUS Exp时,可以获取已经申明过的操作数
Operand get_Operand(tnode Exp)
{
// INT
if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "INT"))
{
return find_Const((int)((Exp->cld)[0]->value));
}
// ID
else if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "ID"))
{
Operand variable = new_Variable((Exp->cld)[0]->content);
return variable;
}
// MINUS Exp (Exp:INT)
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "MINUS"))
{
if (!strcmp(((Exp->cld)[1]->cld)[0]->name, "INT"))
{
int value = -(int)(((Exp->cld)[1]->cld)[0]->value);
Operand result = find_Const(value);
if (result == NULL)
return new_Const(value);
else
return result;
}
}
return NULL;
}
// 查看是否已经声明过同一个常数值的临时变量
Operand find_Const(int value)
{
int i;
for (i = 0; i < 100; i++)
{
if (tempvar[i] == -1)
break;
if (temp_Operands[i]->kind == TEMPVAR && temp_Operands[i]->value == value)
return temp_Operands[i];
}
return NULL;
}
由于采用双向链表的存储方式,可以在递归分析过程中进行中间代码的拼接,add_Code函数采用变长参数,简化了生成过程:
// 获取链表的尾部
InterCode get_Tail(InterCode codes)
{
InterCode temp = codes;
while (temp->next)
{
temp = temp->next;
}
return temp;
}
// 在链表末尾加上另一条链表
InterCode add_Codes(int num, ...)
{
int i;
// 参数列表,详见 stdarg.h 用法
va_list list;
// 初始化参数列表
va_start(list, num);
// 拼接中间代码
InterCode code = va_arg(list, InterCode);
InterCode temp = new_Code();
InterCode tail = new_Code();
for (i = 1; i < num; i++)
{
temp = va_arg(list, InterCode);
tail = get_Tail(code);
tail->next = temp;
temp->prev = tail;
}
return code;
}
在生成代码后,对于不同类型的中间代码和操作数,采用不同的打印方式:
// 打印一条中间代码
void print_Code(InterCode code)
{
if (code == NULL)
{
printf("Error, InterCode is NULL\n");
return;
}
switch (code->kind)
{
case _NULL: // 代码为空
// printf("Code NULL");
break;
case _LABLE: // 定义标号
printf("LABLE ");
print_Operand(code->operands.var);
break;
case _FUNCTION: // 定义函数
printf("FUNCTION ");
print_Operand(code->operands.var);
break;
case _ASSIGN: // =
print_Operand(code->operands.assign.left);
printf(" := ");
print_Operand(code->operands.assign.right);
break;
case _ADD: // +
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" + ");
print_Operand(code->operands.binop.op2);
break;
case _SUB: // -
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" - ");
print_Operand(code->operands.binop.op2);
break;
case _MUL: // *
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" * ");
print_Operand(code->operands.binop.op2);
break;
case _DIV: // /
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" / ");
print_Operand(code->operands.binop.op2);
break;
case _GOTO: // 无条件跳转
printf("GOTO ");
print_Operand(code->operands.jump.lable);
break;
case _IFGOTO: // 判断跳转
printf("IF ");
print_Operand(code->operands.jump.op1);
printf(" %s ", code->operands.jump.relop);
print_Operand(code->operands.jump.op2);
printf(" GOTO ");
print_Operand(code->operands.jump.lable);
break;
case _RETURN: // 函数返回
printf("RETURN ");
print_Operand(code->operands.var);
break;
case _ARG: // 传实参
printf("ARG ");
print_Operand(code->operands.var);
break;
case _CALL: // 函数调用
if (code->operands.assign.left == NULL)
{
printf("CALL ");
}
else
{
print_Operand(code->operands.assign.left);
printf(" := CALL ");
}
print_Operand(code->operands.assign.right);
break;
case _PARAM: // 函数参数声明
printf("PARAM ");
print_Operand(code->operands.var);
break;
case _READ: // 从控制台读取x
printf("READ ");
print_Operand(code->operands.var);
break;
case _WRITE: // 向控制台打印x
printf("WRITE ");
print_Operand(code->operands.var);
break;
default:
printf("Code Error");
break;
}
if (code->kind != _NULL)
printf("\n");
}
// 打印一个操作数
void print_Operand(Operand op)
{
if (op == NULL)
{
printf("Error, Operand is NULL\n");
return;
}
switch (op->kind)
{
case VARIABLE:
case FUNC:
printf("%s", op->operand.name);
break;
case TEMPVAR:
printf("t%d", op->operand.tempvar);
break;
case LABLE:
printf("lable%d", op->operand.lable);
break;
case CONSTANT:
printf("#%d", op->operand.value);
break;
case ADDRESS:
printf("&%s", op->operand.name);
break;
case VALUE:
printf("#%s", op->operand.name);
break;
default:
printf("Operand Error");
break;
}
}
由于中间代码是对语法树进行分析,因此需要完成对不同节点类型的生成函数。本次实验我实现了对于大部分类型的语法分析树节点的翻译:
// 整体程序的翻译模式
InterCode translate_Program(tnode Program);
InterCode translate_ExtDefList(tnode ExtDefList);
InterCode translate_ExtDef(tnode ExtDef);
// 变量、函数声明的翻译模式
InterCode translate_FunDec(tnode FunDec);
InterCode translate_VarList(tnode VarList);
InterCode translate_ParamDec(tnode ParamDec);
// 作用域的翻译模式
InterCode translate_CompSt(tnode ComSt);
// 语句列表的翻译模式
InterCode translate_StmtList(tnode);
// 语句的翻译模式
InterCode translate_Stmt(tnode Stmt);
// 变量声明、初始化的翻译模式
InterCode translate_DefList(tnode DefList);
InterCode translate_Def(tnode Def);
InterCode translate_DecList(tnode DecList);
InterCode translate_Dec(tnode Dec);
// 基本表达式的翻译模式
InterCode translate_Exp(tnode Exp, Operand place);
// 条件表达式的翻译模式
InterCode translate_Cond(tnode Exp, Operand lable_true, Operand lable_false);
// 函数参数的翻译模式
InterCode translate_Args(tnode Args, ArgList arg_list);
下面主要对语句、基本表达式、条件表达式、函数参数的翻译模式进行分析。
语句的翻译模式如下:
// 语句的翻译模式
InterCode translate_Stmt(tnode Stmt)
{
// Exp SEMI
if (Stmt->ncld == 2 && !strcmp((Stmt->cld)[1]->name, "SEMI"))
{
return translate_Exp((Stmt->cld)[0], NULL);
}
// Compst
else if (Stmt->ncld == 1 && !strcmp((Stmt->cld)[0]->name, "Compst"))
{
// Preorder((Stmt->cld)[0],0);
return translate_CompSt((Stmt->cld)[0]);
}
// RETURN Exp SEMI
else if (Stmt->ncld == 3 && !strcmp((Stmt->cld)[0]->name, "RETURN"))
{
// 中间代码优化
Operand existOp = get_Operand((Stmt->cld)[1]);
if (existOp == NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Stmt->cld)[1], t1);
InterCode code2 = new_Code();
code2->kind = _RETURN;
code2->operands.var = t1;
return add_Codes(2, code1, code2);
}
else
{
InterCode code1 = new_Code();
code1->kind = _RETURN;
code1->operands.var = existOp;
return code1;
}
}
// IF LP Exp RP Stmt
else if (Stmt->ncld == 5 && !strcmp((Stmt->cld)[0]->name, "IF"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable1, lable2);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
return add_Codes(4, code1, new_lable_Code(lable1), code2, new_lable_Code(lable2));
}
// IF LP Exp RP Stmt ELSE Stmt
else if (Stmt->ncld == 7 && !strcmp((Stmt->cld)[0]->name, "IF"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
Operand lable3 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable1, lable2);
// print_Codes(code1);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
InterCode code3 = translate_Stmt((Stmt->cld)[6]);
return add_Codes(7, code1, new_lable_Code(lable1), code2, new_goto_Code(lable3), new_lable_Code(lable2), code3, new_lable_Code(lable3));
}
// WHILE LP Exp RP Stmt
else if (Stmt->ncld == 5 && !strcmp((Stmt->cld)[0]->name, "WHILE"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
Operand lable3 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable2, lable3);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
return add_Codes(6, new_lable_Code(lable1), code1, new_lable_Code(lable2), code2, new_goto_Code(lable1), new_lable_Code(lable3));
}
return new_Code();
}
对于基本表达式的翻译模式参考下图实现:
在进行基本表达式的翻译时可以实现中间代码的优化,对于变量类型、常数类型的操作数不再申请临时变量对其进行存储,直接输出即可,对于临时变量,查看临时变量表中是否有存有同样值的临时变量,如果有直接使用即可。
如果Exp产生了一个整数INT,那么我们只需要为传入的 place变量赋值成前面加上一个“#”的相应数值即可。
如果Exp产生了一个标识符ID,那么我们只需要为传入的 place变量赋值成ID对应的变量名(或该变量对应的中间代码中的名字)即可。
如果Exp产生了赋值表达式Exp1 ASSIGNOP Exp22,由于之前提到过作为左值的Exp1只能是三种情况之一(单个变量访问、数组元素访问或结构体特定域的访问)我们需要通过查表找到ID对应的变量,然后对Exp2进行翻译,将运算结果储存在临时变量t1中,再将t1中的值赋于ID所对应的变量并将结果再存 place,最后把刚翻译好的这两段代码合并随后返回即可。
// 基本表达式的翻译模式
InterCode translate_Exp(tnode Exp, Operand place)
{
int isCond = 0;
// INT
if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "INT"))
{
Operand value = new_Const((Exp->cld)[0]->value);
InterCode code = new_assign_Code(place, value);
return code;
}
// ID
else if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "ID"))
{
Operand variable = new_Variable((Exp->cld)[0]->content);
InterCode code = new_assign_Code(place, variable);
return code;
}
// Exp1 ASSIGNOP Exp2
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "ASSIGNOP"))
{
// Exp1 -> ID
if ((Exp->cld)[0]->ncld == 1 && !strcmp(((Exp->cld)[0]->cld)[0]->name, "ID"))
{
Operand variable = new_Variable(((Exp->cld)[0]->cld)[0]->content);
Operand existOp = get_Operand((Exp->cld)[2]);
// 中间代码优化
if (existOp == NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[2], t1);
InterCode code2 = new_assign_Code(variable, t1);
if (place == NULL)
return add_Codes(2, code1, code2);
else
{
InterCode code3 = new_assign_Code(place, variable);
return add_Codes(3, code1, code2, code3);
}
}
else
{
return new_assign_Code(variable, existOp);
}
}
}
四则运算(加减乘处)采用同样的翻译方式,先对Exp1进行翻译,运算结果储存在临时变量t1中,再对Exp2行翻译 (运算结果储存在临时变量t2中,最后生成一句中间代码 place=t1+t2,并将刚翻译好的这三段代码合并后返回即可:
// Exp PLUS Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "PLUS"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
if (op1 != NULL && op2 != NULL)
{
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = op2;
return code3;
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = op2;
return add_Codes(2, code1, code3);
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = t2;
return add_Codes(2, code2, code3);
}
else
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = t2;
return add_Codes(3, code1, code2, code3);
}
}
如果Exp产生了取MINUS负表达式 Expl1,则先对Exp进行翻译(运算结果储存在临时变量t1中),再生成一句中间代码 place: =#0-1从而实现对t1取负,最后将翻译好的这两段代码合并后返回:
// MINUS Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "MINUS"))
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[1], t1);
InterCode code2 = new_Code();
code2->kind = _SUB;
code2->operands.binop.result = place;
code2->operands.binop.op1 = new_Const(0);
code2->operands.binop.op2 = t1;
return add_Codes(2, code1, code2);
}
如果Exp产生了条件表达式(包括与、或、非运算以及比较运算的表达式),我们则会调用 translate_Cond函数进行(短路) 翻译。如果条件表达式为真,那么为 place赋值1;否则,为其赋值0:
// Exp RELOP Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "RELOP"))
{
isCond = 1;
}
// NOT Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "NOT"))
{
isCond = 1;
}
// Exp AND Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "AND"))
{
isCond = 1;
}
// Exp OR Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "OR"))
{
isCond = 1;
}
if (isCond)
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
InterCode code0 = new_assign_Code(place, new_Const(0));
InterCode code1 = translate_Cond(Exp, lable1, lable2);
InterCode code2 = add_Codes(2, new_lable_Code(lable1), new_assign_Code(place, new_Const(1)));
return add_Codes(4, code0, code1, code2, new_lable_Code(lable2));
}
// 条件表达式的翻译模式
InterCode translate_Cond(tnode Exp, Operand lable_true, Operand lable_false)
{
// Exp RELOP Exp
if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "RELOP"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
InterCode code3 = new_Code();
code3->kind = _IFGOTO;
code3->operands.jump.lable = lable_true;
code3->operands.jump.relop = (Exp->cld)[1]->content;
// 中间代码优化
if (op1 == NULL && op2 == NULL)
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
code3->operands.jump.op1 = t1;
code3->operands.jump.op2 = t2;
return add_Codes(4, code1, code2, code3, new_goto_Code(lable_false));
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
code3->operands.jump.op1 = t1;
code3->operands.jump.op2 = op2;
return add_Codes(3, code1, code3, new_goto_Code(lable_false));
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
code3->operands.jump.op1 = op1;
code3->operands.jump.op2 = t2;
return add_Codes(3, code2, code3, new_goto_Code(lable_false));
}
else if (op1 != NULL && op2 != NULL)
{
code3->operands.jump.op1 = op1;
code3->operands.jump.op2 = op2;
return add_Codes(2, code3, new_goto_Code(lable_false));
}
}
// NOT Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "NOT"))
{
return translate_Cond((Exp->cld)[1], lable_false, lable_true);
}
// Exp AND Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "AND"))
{
Operand lable1 = new_lable();
InterCode code1 = translate_Cond((Exp->cld)[0], lable1, lable_false);
InterCode code2 = translate_Cond((Exp->cld)[2], lable_true, lable_false);
return add_Codes(3, code1, new_lable_Code(lable1), code2);
}
// Exp OR Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "OR"))
{
Operand lable1 = new_lable();
InterCode code1 = translate_Cond((Exp->cld)[0], lable_true, lable1);
InterCode code2 = translate_Cond((Exp->cld)[2], lable_true, lable_false);
return add_Codes(3, code1, new_lable_Code(lable1), code2);
}
// orther cases
else
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp(Exp, t1);
InterCode code2 = new_Code();
char *relop = "!=";
code2->kind = _IFGOTO;
code2->operands.jump.lable = lable_true;
code2->operands.jump.relop = relop;
code2->operands.jump.op1 = t1;
code2->operands.jump.op2 = new_Const(0);
return add_Codes(3, code1, code2, new_goto_Code(lable_false));
}
}
函数调用分为有参调用、无参调用,需要分别进行翻译,对于函数调用的翻译模式如下:
// ID LP RP
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "LP"))
{
Operand function = new_Operand();
function->kind = FUNC;
function->operand.name = (Exp->cld)[0]->content;
if (!strcmp(function->operand.name, "read"))
{
// READ函数处理
InterCode code = new_Code();
code->kind = _READ;
code->operands.var = place;
return code;
}
else
{
// 其他函数处理
InterCode code = new_Code();
code->kind = _CALL;
code->operands.assign.left = place;
code->operands.assign.right = function;
return code;
}
}
// ID LP Args RP
else if (Exp->ncld == 4 && !strcmp((Exp->cld)[2]->name, "Args"))
{
int i;
Operand function = new_Operand();
function->kind = FUNC;
function->operand.name = (Exp->cld)[0]->content;
ArgList arg_list = (ArgList)malloc(sizeof(ArgListStru));
arg_list->num = 0;
InterCode code1 = translate_Args((Exp->cld)[2], arg_list);
InterCode code2, code3;
if (!strcmp(function->operand.name, "write"))
{
code2 = new_Code();
code2->kind = _WRITE;
code2->operands.var = (arg_list->list)[0];
return add_Codes(2, code1, code2);
}
else
{
for (i = 0; i < arg_list->num; i++)
{
code2 = new_Code();
code2->kind = _ARG;
code2->operands.var = (arg_list->list)[i];
code1 = add_Codes(2, code1, code2);
}
code3 = new_Code();
code3->kind = _CALL;
code3->operands.assign.left = place;
code3->operands.assign.right = function;
return add_Codes(2, code1, code3);
}
}
进行有参调用时,需要将函数的参数传入,其对应的翻译模式如下:
// 函数参数的翻译模式
InterCode translate_Args(tnode Args, ArgList arg_list)
{
// Exp
if (Args->ncld == 1)
{
Operand existOp = get_Operand((Args->cld)[0]);
if (existOp != NULL)
{
if (existOp->kind == CONSTANT)
{
Operand t1 = new_tempvar();
InterCode code1 = new_assign_Code(t1, existOp);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
return code1;
}
arg_list->list[arg_list->num] = existOp;
arg_list->num++;
return new_Code();
}
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Args->cld)[0], t1);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
return code1;
}
// Exp COMMA Args
else if (Args->ncld == 3)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Args->cld)[0], t1);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
InterCode code2 = translate_Args((Args->cld)[2], arg_list);
return add_Codes(2, code1, code2);
}
return new_Code();
}
其他翻译模式技术含量较少,因此不做分析。
在完成中间代码的生成以及优化后就可以进行目标代码的生成工作。在linux中没有itoa函数,因此手动编写int类型转char*类型的函数。假设有20个可以进行分配的寄存器(实际上由于进行了代码优化用不了太多寄存器),对于中间代码中的变量、临时变量、常量都需要存储到寄存器中再进行调用:
/**********************目标代码**************************/
// 整数转字符串
char* Int2String(int num,char *str);
// 20个寄存器所存储的内容
Operand regs[20];
int reg_num;
// 分配寄存器
char* allocate_reg(Operand op);
// 根据中间代码生成mips代码
void generate_MIPS_Codes(InterCode codes);
void generate_MIPS_Code(InterCode code);
分配寄存器的操作,返回的字符串是 t 0 − t0- t0−t20以及 z e r o , 对 于 常 数 或 者 临 时 变 量 值 为 0 的 直 接 返 回 zero,对于常数或者临时变量值为0的直接返回 zero,对于常数或者临时变量值为0的直接返回zero,否则查找寄存器中是否已经为该操作数进行了分配,如果已经分配就返回所在寄存器,如果没有就为其分配一个:
// 分配寄存器
char *allocate_reg(Operand op)
{
int i;
char *regnumber = (char *)malloc(sizeof(char) * 10);
char *regname = (char *)malloc(sizeof(char) * 10);
strcat(regname, "$t");
// 常数0 寄存器
if (op->kind == CONSTANT && op->operand.value == 0)
return "$zero";
else if (op->kind == TEMPVAR && op->value == 0)
return "$zero";
// 寻找存储该操作数的寄存器
int find = 0;
for (i = 0; i < reg_num; i++)
{
if (regs[i] == NULL || regs[i]->kind != op->kind)
continue;
if (regs[i]->kind == CONSTANT && regs[i]->operand.value == op->operand.value)
{
find = 1;
break;
}
else if (regs[i]->kind == TEMPVAR && regs[i]->operand.tempvar == op->operand.tempvar)
{
find = 1;
break;
}
else if (regs[i]->kind == VARIABLE && !strcmp(regs[i]->operand.name, op->operand.name))
{
find = 1;
break;
}
}
if (find)
{
Int2String(i, regnumber);
strcat(regname, regnumber);
return regname;
}
else
{
Int2String(reg_num, regnumber);
strcat(regname, regnumber);
regs[reg_num] = op;
reg_num++;
return regname;
}
}
生成目标代码,本次实验中实现了read、write函数的目标代码生成:
// 根据中间代码生成mips代码
void generate_MIPS_Codes(InterCode codes)
{
printf("\n目标代码打印:\n");
// 声明部分
printf(".data\n_prompt: .asciiz \"Enter an integer:\"\n");
printf("_ret: .asciiz \"\\n\"\n.globl main\n.text\n");
// read函数
printf("read:\n\tli $v0, 4\n\tla $a0, _prompt\n\tsyscall\n");
printf("\tli $v0, 5\n\tsyscall\n\tjr $ra\n\n");
// write函数
printf("write:\n\tli $v0, 1\n\tsyscall\n\tli $v0, 4\n\tla $a0, _ret\n");
printf("\tsyscall\n\tmove $v0, $0\n\tjr $ra\n\n");
InterCode temp = new_Code();
temp = codes;
while (temp != NULL)
{
generate_MIPS_Code(temp);
temp = temp->next;
}
printf("打印完毕\n");
}
对单条中间代码进行目标代码的生成,生成方法如下:
// 翻译单条中间代码
void generate_MIPS_Code(InterCode code)
{
if (code == NULL)
{
printf("Error, MIPS is NULL\n");
return;
}
switch (code->kind)
{
case _NULL:
break;
case _LABLE:
{
print_Operand(code->operands.var);
printf(":\n");
break;
}
case _FUNCTION:
{
print_Operand(code->operands.var);
printf(":\n");
break;
}
case _ASSIGN:
{
Operand left = code->operands.assign.left;
Operand right = code->operands.assign.right;
if (right->kind == CONSTANT)
{
// 如果将0赋给一个临时变量,则不需要输出该mips代码
if (left->kind == TEMPVAR && right->value == 0)
break;
else
printf("\tli %s, %d\n", allocate_reg(left), right->operand.value);
}
else
{
printf("\tmove %s, %s\n", allocate_reg(left), allocate_reg(right));
}
break;
}
case _ADD:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
if (op2->kind == CONSTANT)
{
printf("\taddi %s, %s, %d\n", allocate_reg(result), allocate_reg(op1), op2->value);
}
else
{
printf("\tadd %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
}
break;
}
case _SUB:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
if (op2->kind == CONSTANT)
{
printf("\taddi %s, %s, %d\n", allocate_reg(result), allocate_reg(op1), -(op2->value));
}
else
{
printf("\tsub %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
}
break;
}
case _MUL:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
printf("\tmul %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
break;
}
case _DIV:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
printf("\tdiv %s, %s\n", allocate_reg(op1), allocate_reg(op2));
printf("\tmflo %s\n", allocate_reg(result));
break;
}
case _GOTO:
{
Operand lable = code->operands.jump.lable;
printf("\tj ");
print_Operand(lable);
printf("\n");
break;
}
case _CALL:
{
break;
}
case _READ:
{
Operand op = code->operands.var;
printf("\taddi $sp, $sp, -4\n");
printf("\tsw $ra, 0($sp)\n");
printf("\tjal read\n");
printf("\tlw $ra, 0($sp)\n");
printf("\taddi $sp, $sp, 4\n");
printf("\tmove %s, $v0\n", allocate_reg(op));
break;
}
case _WRITE:
{
Operand op = code->operands.var;
printf("\tmove $a0, %s\n", allocate_reg(op));
printf("\taddi $sp, $sp, -4\n");
printf("\tsw $ra, 0($sp)\n");
printf("\tjal write\n");
printf("\tlw $ra, 0($sp)\n");
printf("\taddi $sp, $sp, 4\n");
break;
}
case _RETURN:
{
Operand res = code->operands.var;
printf("\tmove $v0, %s\n", allocate_reg(res));
printf("\tjr $ra\n");
break;
}
case _IFGOTO:
{
char *op = code->operands.jump.relop;
Operand lable = code->operands.jump.lable;
Operand op1 = code->operands.jump.op1;
Operand op2 = code->operands.jump.op2;
if (!strcmp(op, "=="))
{
printf("\tbeq %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "!="))
{
printf("\tbne %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, ">"))
{
printf("\tbgt %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "<"))
{
printf("\tblt %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, ">="))
{
printf("\tbge %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "<="))
{
printf("\tble %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
break;
}
default:
break;
}
}
主要代码分析完毕。
程序代码编译过程:
bison -d syntax_tree.y
flex syntax_tree.l
gcc syntax_tree.tab.c syntax_tree.c lex.yy.c -lfl -ly -o parser
主要用于测试read、write函数,测试条件跳转语句,test.c文件内容:
int main()
{
int n;
n = read();
if (n > 10)
write(1);
else if (n < 10)
write(-1);
else
write(0);
return 0;
}
运行可执行文件:
./parser test.c
输出语法分析树:
输出中间代码:
输出目标代码:
将输出的MIPS代码复制到test.s中,并使用QtMips打开,运行结果如下:
根据test.c文件中的代码内容分析,当输入值小于10就输出-1,等于10就输出0,大于10就输出1,可知Mips代码成功运行。
主要用于测试四则运算、while循环语句,test.c内容如下:
int main()
{
int a,b,c;
a = 3+4;
write(a);
b = 3*4;
write(b);
c=3-4;
write(c);
while(c<a)
c=c+1;
write(c);
return 0;
}
根据分析可知,程序会先后输出7、12、-1、7。
输出中间代码:
输出目标代码:
在QtMips中运行该目标代码,结果如下:
对比可知代码运行正确。
#include
#include
#include
#include // 变长参数函数 头文件
/**********************语法分析**************************/
// 行数
extern int yylineno;
// 文本
extern char *yytext;
// 错误处理
void yyerror(char *msg);
// 抽象语法树
typedef struct treeNode
{
// 行数
int line;
// Token类型
char *name;
// 1变量 2函数 3常数 4数组 5结构体
int tag;
// 使用孩子数组表示法
struct treeNode *cld[10];
int ncld;
// 语义值
char *content;
// 数据类型 int 或 float
char *type;
// 变量的值
float value;
} * Ast, *tnode;
// 构造抽象语法树(节点)
Ast newAst(char *name, int num, ...);
// 先序遍历语法树
void Preorder(Ast ast, int level);
// 所有节点数量
int nodeNum;
// 存放所有节点
tnode nodeList[5000];
int nodeIsChild[5000];
// 设置节点打印状态
void setChildTag(tnode node);
// bison是否有词法语法错误
int hasFault;
/**********************语义分析**************************/
// 分析语法树,建立符号表
void analysis(tnode val);
// 变量符号表的结点
typedef struct var_
{
char *name;
char *type;
// 是否为结构体域
int inStruc;
// 所属的结构体编号
int strucNum;
struct var_ *next;
} var;
var *varhead, *vartail;
char* curType;
// 建立变量符号
void newvar(int num, ...);
// 变量是否已经定义
int findvar(tnode val);
// 变量类型
char *typevar(tnode val);
// 这样赋值号左边仅能出现ID、Exp LB Exp RB 以及 Exp DOT ID
int checkleft(tnode val);
// 函数符号表的结点
typedef struct func_
{
int tag; //0表示未定义,1表示定义
char *name;
char *type;
// 是否为结构体域
int inStruc;
// 所属的结构体编号
int strucNum;
char *rtype; //声明返回值类型
int va_num; //记录函数形参个数
char *va_type[10];
struct func_ *next;
} func;
func *funchead, *functail;
// 记录函数实参
int va_num;
char *va_type[10];
void getdetype(tnode val); //定义的参数
void getretype(tnode val); //实际的参数
void getargs(tnode Args); //获取实参
int checkrtype(tnode ID, tnode Args); //检查形参与实参是否一致
// 建立函数符号
void newfunc(int num, ...);
// 函数是否已经定义
int findfunc(tnode val);
// 函数类型
char *typefunc(tnode val);
// 函数的形参个数
int numfunc(tnode val);
// 函数实际返回值类型
char *rtype[10];
int rnum;
void getrtype(tnode val);
// 数组符号表的结点
typedef struct array_
{
char *name;
char *type;
// 是否为结构体域
int inStruc;
// 所属的结构体编号
int strucNum;
struct array_ *next;
} array;
array *arrayhead, *arraytail;
// 建立数组符号
void newarray(int num, ...);
// 查找数组是否已经定义
int findarray(tnode val);
// 数组类型
char *typearray(tnode val);
// 结构体符号表的结点
typedef struct struc_
{
char *name;
char *type;
// 是否为结构体域
int inStruc;
// 所属的结构体编号
int strucNum;
struct struc_ *next;
} struc;
struc *struchead, *structail;
// 建立结构体符号
void newstruc(int num, ...);
// 查找结构体是否已经定义
int findstruc(tnode val);
// 当前是结构体域
int inStruc;
// 判断结构体域,{ 和 }是否抵消
int LCnum;
// 当前是第几个结构体
int strucNum;
/**********************中间代码**************************/
// 中间代码数据结构
typedef struct _OperandStru // 操作数
{
enum
{
VARIABLE, // 变量 x
TEMPVAR, // 临时变量 t1
LABLE, // 标签 lable1
CONSTANT, // 常数 #1
ADDRESS, // 取地址 &x
VALUE, // 读取地址的值 *x
FUNC, // 函数
} kind;
union {
int tempvar; // 临时变量
int lable; // 标签
int value; // 常数的值
char *name; // 语义值,变量名称、函数名称
} operand;
int value;
} OperandStru, *Operand;
typedef struct _InterCodeStru // 中间代码
{
// 代码类型
enum
{
_LABLE, // 定义标号
_FUNCTION, // 定义函数
_ASSIGN, // =
_ADD, // +
_SUB, // -
_MUL, // *
_DIV, // /
_GOTO, // 无条件跳转
_IFGOTO, // 判断跳转
_RETURN, // 函数返回
_ARG, // 传实参
_CALL, // 函数调用
_PARAM, // 函数参数声明
_READ, // 从控制台读取x
_WRITE, // 向控制台打印x
_NULL // 空的
} kind;
// 操作数
union {
struct
{ // 赋值 取地址 函数调用等
Operand left, right;
} assign;
struct
{ // 双目运算 + = * /
Operand result, op1, op2;
} binop;
struct
{ // GOTO 和 IF...GOTO
Operand lable, op1, op2;
char *relop;
} jump;
// 函数声明、参数声明、标签、传实参、函数返回、读取x、打印x
Operand var;
} operands;
struct _InterCodeStru *prev, *next;
} InterCodeStru, *InterCode;
// 函数参数列表
typedef struct _ArgListStru
{
int num;
Operand list[10];
} ArgListStru, *ArgList;
InterCode CodesHead, CodesTail; // 全局变量,线性IR双链表的首尾
// 临时变量t1和标签lable1
int tempvar[100];
Operand temp_Operands[100];
int lables[100];
Operand new_tempvar();
Operand new_lable();
void init_tempvar_lable();
// 当Exp的翻译模式为INT、ID、MINUS Exp时,可以获取已经申明过的操作数
Operand get_Operand(tnode Exp);
// 查看是否已经声明过同一个常数值的操作数
Operand find_Const(int value);
// 初始化双链表
void init_InterCode();
// 创建一个新的操作数
Operand new_Operand();
// 创建一个新的变量
Operand new_Variable(char *name);
// 创建一个新的常量
Operand new_Const(float value);
// 创建一条新的中间代码
InterCode new_Code();
// 创建一条lable声明的中间代码
InterCode new_lable_Code(Operand lable);
// 创建一条跳转语句的中间代码
InterCode new_goto_Code(Operand lable);
// 创建一条赋值的中间代码
InterCode new_assign_Code(Operand left, Operand right);
// 打印一条中间代码
void print_Code(InterCode code);
// 打印一个操作数
void print_Operand(Operand op);
// 打印一段中间代码
void print_Codes(InterCode codes);
// 获取链表的尾部
InterCode get_Tail(InterCode codes);
// 在链表末尾加上另一条链表
InterCode add_Codes(int num, ...);
// 整体程序的翻译模式
InterCode translate_Program(tnode Program);
InterCode translate_ExtDefList(tnode ExtDefList);
InterCode translate_ExtDef(tnode ExtDef);
// 变量、函数声明的翻译模式
InterCode translate_FunDec(tnode FunDec);
InterCode translate_VarList(tnode VarList);
InterCode translate_ParamDec(tnode ParamDec);
// 作用域的翻译模式
InterCode translate_CompSt(tnode ComSt);
// 语句列表的翻译模式
InterCode translate_StmtList(tnode);
// 语句的翻译模式
InterCode translate_Stmt(tnode Stmt);
// 变量声明、初始化的翻译模式
InterCode translate_DefList(tnode DefList);
InterCode translate_Def(tnode Def);
InterCode translate_DecList(tnode DecList);
InterCode translate_Dec(tnode Dec);
// 基本表达式的翻译模式
InterCode translate_Exp(tnode Exp, Operand place);
// 条件表达式的翻译模式
InterCode translate_Cond(tnode Exp, Operand lable_true, Operand lable_false);
// 函数参数的翻译模式
InterCode translate_Args(tnode Args, ArgList arg_list);
/**********************目标代码**************************/
// 整数转字符串
char* Int2String(int num,char *str);
// 20个寄存器所存储的内容
Operand regs[20];
int reg_num;
// 分配寄存器
char* allocate_reg(Operand op);
// 根据中间代码生成mips代码
void generate_MIPS_Codes(InterCode codes);
void generate_MIPS_Code(InterCode code);
#include "syntax_tree.h"
// 用于遍历
int i;
Ast newAst(char *name, int num, ...)
{
// 生成父节点
tnode father = (tnode)malloc(sizeof(struct treeNode));
// 添加子节点
tnode temp = (tnode)malloc(sizeof(struct treeNode));
if (!father)
{
yyerror("create treenode error");
exit(0);
}
father->name = name;
father->type = NULL;
// 参数列表,详见 stdarg.h 用法
va_list list;
// 初始化参数列表
va_start(list, num);
// 表示当前节点不是终结符号,还有子节点
if (num > 0)
{
father->ncld = num;
// 第一个孩子节点
temp = va_arg(list, tnode);
(father->cld)[0] = temp;
setChildTag(temp);
// 父节点行号为第一个孩子节点的行号
father->line = temp->line;
father->type = temp->type;
if (num == 1)
{
//父节点的语义值等于左孩子的语义值
father->content = temp->content;
father->tag = temp->tag;
}
else
{
for (i = 1; i < num; i++)
{
temp = va_arg(list, tnode);
(father->cld)[i] = temp;
// 该节点为其他节点的子节点
setChildTag(temp);
}
}
}
else //表示当前节点是终结符(叶节点)或者空的语法单元,此时num表示行号(空单元为-1)
{
father->ncld = 0;
father->line = va_arg(list, int);
// strcmp()==0 表示相同
if (!strcmp(name, "INT"))
{
father->type = "int";
father->value = atoi(yytext);
}
else if (!strcmp(name, "FLOAT"))
{
father->type = "float";
father->value = atof(yytext);
}
else
{
father->type = curType;
// 存储词法单元语义值
char *str;
str = (char *)malloc(sizeof(char) * 40);
strcpy(str, yytext);
father->content = str;
}
}
nodeList[nodeNum] = father;
nodeNum++;
// Preorder(father,0);
return father;
}
// 父节点->左子节点->右子节点....
void Preorder(Ast ast, int level)
{
if (!strcmp(ast->name, "Program"))
printf("语法分析树打印:\n");
int i;
if (ast != NULL)
{
// 空节点不打印
if (ast->line != -1)
{
// 层级结构缩进
for (i = 0; i < level; ++i)
{
printf(" ");
}
// 打印节点类型
printf("%s", ast->name);
// 根据不同类型打印节点数据
if ((!strcmp(ast->name, "ID")) || (!strcmp(ast->name, "TYPE")))
{
printf(": %s", ast->content);
}
else if (!strcmp(ast->name, "INT"))
{
printf(": %d", (int)(ast->value));
}
else if (!strcmp(ast->name, "FLOAT"))
{
printf(": %f", ast->value);
}
else
{
// 非叶节点打印行号
printf("(%d)", ast->line);
}
printf("\n");
}
for (i = 0; i < ast->ncld; i++)
{
Preorder((ast->cld)[i], level + 1);
}
}
else
{
return;
}
if (!strcmp(ast->name, "Program"))
printf("打印完毕\n");
}
// 错误处理
void yyerror(char *msg)
{
hasFault = 1;
fprintf(stderr, "Error type B at Line %d: %s before %s\n", yylineno, msg, yytext);
}
// 设置节点打印状态 该节点为子节点
void setChildTag(tnode node)
{
int i;
for (i = 0; i < nodeNum; i++)
{
if (nodeList[i] == node)
{
nodeIsChild[i] = 1;
}
}
}
// 先序遍历分析
void analysis(Ast ast)
{
int i;
if (ast != NULL)
{
for (i = 0; i < ast->ncld; ++i)
{
analysis((ast->cld)[i]);
}
}
else
return;
}
// 建立变量符号
void newvar(int num, ...)
{
va_list valist;
va_start(valist, num);
var *res = (var *)malloc(sizeof(var));
tnode temp = (tnode)malloc(sizeof(tnode));
if (inStruc && LCnum)
{
// 是结构体的域
res->inStruc = 1;
res->strucNum = strucNum;
}
else
{
res->inStruc = 0;
res->strucNum = 0;
}
// 变量声明 int i,j
res->type = curType;
temp = va_arg(valist, tnode);
res->name = temp->content;
vartail->next = res;
vartail = res;
}
// 查找变量
int findvar(tnode val)
{
var *temp = (var *)malloc(sizeof(var *));
temp = varhead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
{
if (inStruc && LCnum) // 当前变量是结构体域
{
if (!temp->inStruc)
{
// 结构体域与变量重名
printf("Error type 9 at Line %d:Struct Field and Variable use the same name.\n", yylineno);
}
else if (temp->inStruc && temp->strucNum != strucNum)
{
// 不同结构体中的域重名
printf("Error type 10 at Line %d:Struct Fields use the same name.\n", yylineno);
}
else
{
// 同一结构体中域名重复
return 1;
}
}
else // 当前变量是全局变量
{
if (temp->inStruc)
{
// 变量与结构体域重名
printf("Error type 9 at Line %d:Struct Field and Variable use the same name.\n", yylineno);
}
else
{
// 变量与变量重名,即重复定义
return 1;
}
}
}
temp = temp->next;
}
return 0;
}
// 变量类型
char *typevar(tnode val)
{
var *temp = (var *)malloc(sizeof(var *));
temp = varhead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return temp->type; //返回变量类型
temp = temp->next;
}
return NULL;
}
// 赋值号左边只能出现ID、Exp LB Exp RB 以及 Exp DOT ID
int checkleft(tnode val)
{
if (val->ncld == 1 && !strcmp((val->cld)[0]->name, "ID"))
return 1;
else if (val->ncld == 4 && !strcmp((val->cld)[0]->name, "Exp") && !strcmp((val->cld)[1]->name, "LB") && !strcmp((val->cld)[2]->name, "Exp") && !strcmp((val->cld)[3]->name, "RB"))
return 1;
else if (val->ncld == 3 && !strcmp((val->cld)[0]->name, "Exp") && !strcmp((val->cld)[1]->name, "DOT") && !strcmp((val->cld)[2]->name, "ID"))
return 1;
else
return 0;
}
// 创建函数符号
void newfunc(int num, ...)
{
int i;
va_list valist;
va_start(valist, num);
tnode temp = (tnode)malloc(sizeof(struct treeNode));
switch (num)
{
case 1:
if (inStruc && LCnum)
{
// 是结构体的域
functail->inStruc = 1;
functail->strucNum = strucNum;
}
else
{
functail->inStruc = 0;
functail->strucNum = 0;
}
//设置函数返回值类型
temp = va_arg(valist, tnode);
functail->rtype = temp->content;
functail->type = temp->type;
for (i = 0; i < rnum; i++)
{
if (rtype[i] == NULL || strcmp(rtype[i], functail->rtype))
printf("Error type 12 at Line %d:Func return type error.\n", yylineno);
}
functail->tag = 1; //标志为已定义
func *new = (func *)malloc(sizeof(func));
functail->next = new; //尾指针指向下一个空结点
functail = new;
break;
case 2:
//记录函数名
temp = va_arg(valist, tnode);
functail->name = temp->content;
//设置函数声明时的参数
temp = va_arg(valist, tnode);
functail->va_num = 0;
getdetype(temp);
break;
default:
break;
}
}
//定义的参数
void getdetype(tnode val)
{
int i;
if (val != NULL)
{
if (!strcmp(val->name, "ParamDec"))
{
functail->va_type[functail->va_num] = (val->cld)[0]->content;
functail->va_num++;
return;
}
for (i = 0; i < val->ncld; ++i)
{
getdetype((val->cld)[i]);
}
}
else
return;
}
//实际的参数
void getretype(tnode val)
{
int i;
if (val != NULL)
{
if (!strcmp(val->name, "Exp"))
{
va_type[va_num] = val->type;
va_num++;
return;
}
for (i = 0; i < val->ncld; ++i)
{
getretype((val->cld)[i]);
}
}
else
return;
}
//函数实际返回值类型
void getrtype(tnode val)
{
rtype[rnum] = val->type;
rnum++;
}
//检查形参与实参是否一致,没有错误返回0
int checkrtype(tnode ID, tnode Args)
{
int i;
va_num = 0;
getretype(Args);
func *temp = (func *)malloc(sizeof(func *));
temp = funchead->next;
while (temp != NULL && temp->name != NULL && temp->tag == 1)
{
if (!strcmp(temp->name, ID->content))
break;
temp = temp->next;
}
if (va_num != temp->va_num)
return 1;
for (i = 0; i < temp->va_num; i++)
{
if (temp->va_type[i] == NULL || va_type[i] == NULL || strcmp(temp->va_type[i], va_type[i]) != 0)
return 1;
}
return 0;
}
// 函数是否已经定义
int findfunc(tnode val)
{
func *temp = (func *)malloc(sizeof(func *));
temp = funchead->next;
while (temp != NULL && temp->name != NULL && temp->tag == 1)
{
if (!strcmp(temp->name, val->content))
{
if (inStruc && LCnum) // 当前变量是结构体域
{
if (!temp->inStruc)
{
// 结构体域与变量重名
printf("Error type 9 at Line %d:Struct Field and Variable use the same name.\n", yylineno);
}
else if (temp->inStruc && temp->strucNum != strucNum)
{
// 不同结构体中的域重名
printf("Error type 10 at Line %d:Struct Fields use the same name.\n", yylineno);
}
else
{
// 同一结构体中域名重复
return 1;
}
}
else // 当前变量是全局变量
{
if (temp->inStruc)
{
// 变量与结构体域重名
printf("Error type 9 at Line %d:Struct Field and Variable use the same name.\n", yylineno);
}
else
{
// 变量与变量重名,即重复定义
return 1;
}
}
}
temp = temp->next;
}
return 0;
}
// 函数类型
char *typefunc(tnode val)
{
func *temp = (func *)malloc(sizeof(func *));
temp = funchead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return temp->rtype; //返回函数类型
temp = temp->next;
}
return NULL;
}
// 形参个数
int numfunc(tnode val)
{
func *temp = (func *)malloc(sizeof(func *));
temp = funchead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return temp->va_num; //返回形参个数
temp = temp->next;
}
}
// 创建数组符号表
void newarray(int num, ...)
{
va_list valist;
va_start(valist, num);
array *res = (array *)malloc(sizeof(array));
tnode temp = (tnode)malloc(sizeof(struct treeNode));
if (inStruc && LCnum)
{
// 是结构体的域
res->inStruc = 1;
res->strucNum = strucNum;
}
else
{
res->inStruc = 0;
res->strucNum = 0;
}
// int a[10]
res->type = curType;
temp = va_arg(valist, tnode);
res->name = temp->content;
arraytail->next = res;
arraytail = res;
}
// 数组是否已经定义
int findarray(tnode val)
{
array *temp = (array *)malloc(sizeof(array *));
temp = arrayhead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return 1;
temp = temp->next;
}
return 0;
}
// 数组类型
char *typearray(tnode val)
{
array *temp = (array *)malloc(sizeof(array *));
temp = arrayhead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return temp->type; //返回数组类型
temp = temp->next;
}
return NULL;
}
// 创建结构体符号表
void newstruc(int num, ...)
{
va_list valist;
va_start(valist, num);
struc *res = (struc *)malloc(sizeof(struc));
tnode temp = (tnode)malloc(sizeof(struct treeNode));
// struct name{}
temp = va_arg(valist, tnode);
res->name = temp->content;
structail->next = res;
structail = res;
}
// 结构体是否和结构体或变量的名字重复
int findstruc(tnode val)
{
struc *temp = (struc *)malloc(sizeof(struc *));
temp = struchead->next;
while (temp != NULL)
{
if (!strcmp(temp->name, val->content))
return 1;
temp = temp->next;
}
if (findvar(val) == 1)
return 1;
return 0;
}
// 主函数 扫描文件并且分析
// 为bison会自己调用yylex(),所以在main函数中不需要再调用它了
// bison使用yyparse()进行语法分析,所以需要我们在main函数中调用yyparse()和yyrestart()
int main(int argc, char **argv)
{
int j, tem;
if (argc < 2)
{
return 1;
}
for (i = 1; i < argc; i++)
{
// 初始化,用于记录结构体域
inStruc = 0;
LCnum = 0;
strucNum = 0;
// 初始化符号表
varhead = (var *)malloc(sizeof(var));
vartail = varhead;
funchead = (func *)malloc(sizeof(func));
functail = (func *)malloc(sizeof(func));
funchead->next = functail;
functail->va_num = 0;
arrayhead = (array *)malloc(sizeof(array));
arraytail = arrayhead;
struchead = (struc *)malloc(sizeof(struc));
structail = struchead;
rnum = 0;
// 初始化节点记录列表
nodeNum = 0;
memset(nodeList, 0, sizeof(tnode) * 5000);
memset(nodeIsChild, 0, sizeof(int) * 5000);
hasFault = 0;
// 初始化临时变量、标签数组
init_tempvar_lable();
// 添加read、write函数到符号表
char *read = "read";
char *write = "write";
char *typeInt = "int";
// read函数
functail->tag = 1;
functail->name = read;
functail->type = typeInt;
functail->rtype = typeInt;
functail->va_num = 0;
functail->inStruc = 0;
functail->strucNum = 0;
// 新建节点
func *new = (func *)malloc(sizeof(func));
functail->next = new; //尾指针指向下一个空结点
functail = new;
// write函数
functail->tag = 1;
functail->name = write;
functail->va_num = 1;
(functail->va_type)[0] = typeInt;
functail->inStruc = 0;
functail->strucNum = 0;
// 新建节点
new = (func *)malloc(sizeof(func));
functail->next = new; //尾指针指向下一个空结点
functail = new;
// 设置已经分配的寄存器数量
reg_num = 0;
FILE *f = fopen(argv[i], "r");
if (!f)
{
perror(argv[i]);
return 1;
}
yyrestart(f);
yyparse();
fclose(f);
// 遍历所有非子节点的节点
if (hasFault)
continue;
for (j = 0; j < nodeNum; j++)
{
if (nodeIsChild[j] != 1)
{
Preorder(nodeList[j], 0);
InterCode codes = translate_Program(nodeList[j]);
print_Codes(codes);
generate_MIPS_Codes(codes);
}
}
}
}
// int main()
// {
// int j, tem;
// // 初始化,用于记录结构体域
// inStruc = 0;
// LCnum = 0;
// strucNum = 0;
// // 初始化符号表
// varhead = (var *)malloc(sizeof(var));
// vartail = varhead;
// funchead = (func *)malloc(sizeof(func));
// functail = (func *)malloc(sizeof(func));
// funchead->next = functail;
// functail->va_num = 0;
// arrayhead = (array *)malloc(sizeof(array));
// arraytail = arrayhead;
// struchead = (struc *)malloc(sizeof(struc));
// structail = struchead;
// rnum = 0;
// // 初始化节点记录列表
// nodeNum = 0;
// memset(nodeList, 0, sizeof(tnode) * 5000);
// memset(nodeIsChild, 0, sizeof(int) * 5000);
// hasFault = 0;
// // 初始化临时变量、标签数组
// init_tempvar_lable();
// // 添加read、write函数到符号表
// char *read = "read";
// char *write = "write";
// char *typeInt = "int";
// // read函数
// functail->tag = 1;
// functail->name = read;
// functail->type = typeInt;
// functail->rtype = typeInt;
// functail->va_num = 0;
// functail->inStruc = 0;
// functail->strucNum = 0;
// // 新建节点
// func *new = (func *)malloc(sizeof(func));
// functail->next = new; //尾指针指向下一个空结点
// functail = new;
// // write函数
// functail->tag = 1;
// functail->name = write;
// functail->va_num = 1;
// (functail->va_type)[0] = typeInt;
// functail->inStruc = 0;
// functail->strucNum = 0;
// // 新建节点
// new = (func *)malloc(sizeof(func));
// functail->next = new; //尾指针指向下一个空结点
// functail = new;
// // 设置已经分配的寄存器数量
// reg_num = 0;
// FILE *f = fopen("test.c", "r");
// if (!f)
// {
// perror("error");
// return 1;
// }
// yyrestart(f);
// yyparse();
// fclose(f);
// // 遍历所有非子节点的节点
// if (hasFault)
// return 0;
// for (j = 0; j < nodeNum; j++)
// {
// if (nodeIsChild[j] != 1)
// {
// Preorder(nodeList[j], 0);
// InterCode codes = translate_Program(nodeList[j]);
// print_Codes(codes);
// generate_MIPS_Codes(codes);
// }
// }
// }
/**********************中间代码**************************/
// 临时变量以及标签
void init_tempvar_lable()
{
int i;
for (i = 0; i < 100; i++)
{
// -1表示该临时变量\标签还未被使用
tempvar[i] = -1;
lables[i] = -1;
}
}
Operand new_tempvar()
{
int i;
for (i = 0; i < 100; i++)
{
if (tempvar[i] == -1)
{
tempvar[i] = 1;
break;
}
}
if (i >= 100)
return NULL;
Operand result = new_Operand();
result->kind = TEMPVAR;
result->operand.tempvar = i + 1;
temp_Operands[i] = result;
return result;
}
Operand new_lable()
{
int i;
for (i = 0; i < 100; i++)
{
if (lables[i] == -1)
{
lables[i] = 1;
break;
}
}
if (i >= 100)
return NULL;
Operand result = new_Operand();
result->kind = LABLE;
result->operand.lable = i + 1;
return result;
}
// 创建一个新的操作数
Operand new_Operand()
{
Operand result = (Operand)malloc(sizeof(OperandStru));
result->value = -10000;
return result;
}
// 创建一个新的变量
Operand new_Variable(char *name)
{
Operand result = new_Operand();
result->kind = VARIABLE;
result->operand.name = name;
return result;
}
// 创建一个新的常量
Operand new_Const(float value)
{
Operand result = new_Operand();
result->kind = CONSTANT;
result->operand.value = (int)value;
result->value = (int)value;
return result;
}
// 创建一条新的中间代码
InterCode new_Code()
{
InterCode result = (InterCode)malloc(sizeof(InterCodeStru));
result->kind = _NULL;
result->prev = NULL;
result->next = NULL;
return result;
}
// 创建一条lable声明的中间代码
InterCode new_lable_Code(Operand lable)
{
InterCode result = new_Code();
result->kind = _LABLE;
result->operands.var = lable;
return result;
}
// 创建一条跳转语句的中间代码
InterCode new_goto_Code(Operand lable)
{
InterCode result = new_Code();
result->kind = _GOTO;
result->operands.jump.lable = lable;
return result;
}
// 创建一条赋值的中间代码
InterCode new_assign_Code(Operand left, Operand right)
{
left->value = right->value;
InterCode result = new_Code();
result->kind = _ASSIGN;
result->operands.assign.left = left;
result->operands.assign.right = right;
return result;
}
// 打印一条中间代码
void print_Code(InterCode code)
{
if (code == NULL)
{
printf("Error, InterCode is NULL\n");
return;
}
switch (code->kind)
{
case _NULL: // 代码为空
// printf("Code NULL");
break;
case _LABLE: // 定义标号
printf("LABLE ");
print_Operand(code->operands.var);
break;
case _FUNCTION: // 定义函数
printf("FUNCTION ");
print_Operand(code->operands.var);
break;
case _ASSIGN: // =
print_Operand(code->operands.assign.left);
printf(" := ");
print_Operand(code->operands.assign.right);
break;
case _ADD: // +
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" + ");
print_Operand(code->operands.binop.op2);
break;
case _SUB: // -
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" - ");
print_Operand(code->operands.binop.op2);
break;
case _MUL: // *
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" * ");
print_Operand(code->operands.binop.op2);
break;
case _DIV: // /
print_Operand(code->operands.binop.result);
printf(" := ");
print_Operand(code->operands.binop.op1);
printf(" / ");
print_Operand(code->operands.binop.op2);
break;
case _GOTO: // 无条件跳转
printf("GOTO ");
print_Operand(code->operands.jump.lable);
break;
case _IFGOTO: // 判断跳转
printf("IF ");
print_Operand(code->operands.jump.op1);
printf(" %s ", code->operands.jump.relop);
print_Operand(code->operands.jump.op2);
printf(" GOTO ");
print_Operand(code->operands.jump.lable);
break;
case _RETURN: // 函数返回
printf("RETURN ");
print_Operand(code->operands.var);
break;
case _ARG: // 传实参
printf("ARG ");
print_Operand(code->operands.var);
break;
case _CALL: // 函数调用
if (code->operands.assign.left == NULL)
{
printf("CALL ");
}
else
{
print_Operand(code->operands.assign.left);
printf(" := CALL ");
}
print_Operand(code->operands.assign.right);
break;
case _PARAM: // 函数参数声明
printf("PARAM ");
print_Operand(code->operands.var);
break;
case _READ: // 从控制台读取x
printf("READ ");
print_Operand(code->operands.var);
break;
case _WRITE: // 向控制台打印x
printf("WRITE ");
print_Operand(code->operands.var);
break;
default:
printf("Code Error");
break;
}
if (code->kind != _NULL)
printf("\n");
}
// 打印一个操作数
void print_Operand(Operand op)
{
if (op == NULL)
{
printf("Error, Operand is NULL\n");
return;
}
switch (op->kind)
{
case VARIABLE:
case FUNC:
printf("%s", op->operand.name);
break;
case TEMPVAR:
printf("t%d", op->operand.tempvar);
break;
case LABLE:
printf("lable%d", op->operand.lable);
break;
case CONSTANT:
printf("#%d", op->operand.value);
break;
case ADDRESS:
printf("&%s", op->operand.name);
break;
case VALUE:
printf("#%s", op->operand.name);
break;
default:
printf("Operand Error");
break;
}
}
// 打印一段中间代码
void print_Codes(InterCode codes)
{
printf("\n中间代码打印:\n");
// InterCode temp = new_Code();
// temp = codes;
InterCode temp = codes;
while (temp)
{
print_Code(temp);
temp = temp->next;
}
printf("打印完毕\n");
}
// 获取链表的尾部
InterCode get_Tail(InterCode codes)
{
InterCode temp = codes;
while (temp->next)
{
temp = temp->next;
}
return temp;
}
// 在链表末尾加上另一条链表
InterCode add_Codes(int num, ...)
{
int i;
// 参数列表,详见 stdarg.h 用法
va_list list;
// 初始化参数列表
va_start(list, num);
// 拼接中间代码
InterCode code = va_arg(list, InterCode);
InterCode temp = new_Code();
InterCode tail = new_Code();
for (i = 1; i < num; i++)
{
temp = va_arg(list, InterCode);
tail = get_Tail(code);
tail->next = temp;
temp->prev = tail;
}
return code;
}
// 整体程序的翻译模式
InterCode translate_Program(tnode Program)
{
// ExtDefList
if (Program->ncld == 1)
{
return translate_ExtDefList((Program->cld)[0]);
}
return new_Code();
}
InterCode translate_ExtDefList(tnode ExtDefList)
{
// ExtDef ExtDefList
if (ExtDefList->ncld == 2)
{
InterCode code1 = translate_ExtDef((ExtDefList->cld)[0]);
InterCode code2 = translate_ExtDefList((ExtDefList->cld)[1]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
InterCode translate_ExtDef(tnode ExtDef)
{
// Specifire ExtDecList SEMI
if (ExtDef->ncld == 3 && !strcmp((ExtDef->cld)[1]->name, "ExtDecList"))
{
// 函数外变量声明、结构体定义不进行处理
}
// Specifire SEMI
else if (ExtDef->ncld == 2 && !strcmp((ExtDef->cld)[1]->name, "SEMI"))
{
// 函数外变量声明、结构体定义不进行处理
}
// Specifire FunDec Compst
else if (ExtDef->ncld == 3 && !strcmp((ExtDef->cld)[1]->name, "FunDec"))
{
InterCode code1 = translate_FunDec((ExtDef->cld)[1]);
InterCode code2 = translate_CompSt((ExtDef->cld)[2]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
// 变量、函数声明的翻译模式
InterCode translate_FunDec(tnode FunDec)
{
// ID LP VarList RP
if (FunDec->ncld == 4)
{
Operand function = new_Variable((FunDec->cld)[0]->content);
InterCode code1 = new_Code();
code1->kind = _FUNCTION;
code1->operands.var = function;
InterCode code2 = translate_VarList((FunDec->cld)[2]);
return add_Codes(2, code1, code2);
}
// ID LP RP
else if (FunDec->ncld == 3)
{
Operand function = new_Variable((FunDec->cld)[0]->content);
InterCode code1 = new_Code();
code1->kind = _FUNCTION;
code1->operands.var = function;
return code1;
}
return new_Code();
}
InterCode translate_VarList(tnode VarList)
{
// ParamDec
if (VarList->ncld == 1)
{
return translate_ParamDec((VarList->cld)[0]);
}
// ParamDec COMMA VarList
else if (VarList->ncld == 3)
{
InterCode code1 = translate_ParamDec((VarList->cld)[0]);
InterCode code2 = translate_VarList((VarList->cld)[2]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
InterCode translate_ParamDec(tnode ParamDec)
{
// Specifire VarDec
if (ParamDec->ncld == 2)
{
// VarDec:ID
// 忽略数组的情况
tnode ID = ((ParamDec->cld)[1]->cld)[0];
InterCode code1 = new_Code();
code1->kind = _PARAM;
code1->operands.var = new_Variable(ID->content);
return code1;
}
return new_Code();
}
// 作用域的翻译模式
InterCode translate_CompSt(tnode ComSt)
{
// printf("%d\n",ComSt->ncld);
// LC DefList StmtList RC
if (ComSt->ncld == 4)
{
InterCode code1 = translate_DefList((ComSt->cld)[1]);
InterCode code2 = translate_StmtList((ComSt->cld)[2]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
// 语句列表的翻译模式
InterCode translate_StmtList(tnode StmtList)
{
// Stmt StmtList
if (StmtList->ncld == 2)
{
InterCode code1 = translate_Stmt((StmtList->cld)[0]);
InterCode code2 = translate_StmtList((StmtList->cld)[1]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
// 语句的翻译模式
InterCode translate_Stmt(tnode Stmt)
{
// Exp SEMI
if (Stmt->ncld == 2 && !strcmp((Stmt->cld)[1]->name, "SEMI"))
{
return translate_Exp((Stmt->cld)[0], NULL);
}
// Compst
else if (Stmt->ncld == 1 && !strcmp((Stmt->cld)[0]->name, "Compst"))
{
// Preorder((Stmt->cld)[0],0);
return translate_CompSt((Stmt->cld)[0]);
}
// RETURN Exp SEMI
else if (Stmt->ncld == 3 && !strcmp((Stmt->cld)[0]->name, "RETURN"))
{
// 中间代码优化
Operand existOp = get_Operand((Stmt->cld)[1]);
if (existOp == NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Stmt->cld)[1], t1);
InterCode code2 = new_Code();
code2->kind = _RETURN;
code2->operands.var = t1;
return add_Codes(2, code1, code2);
}
else
{
InterCode code1 = new_Code();
code1->kind = _RETURN;
code1->operands.var = existOp;
return code1;
}
}
// IF LP Exp RP Stmt
else if (Stmt->ncld == 5 && !strcmp((Stmt->cld)[0]->name, "IF"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable1, lable2);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
return add_Codes(4, code1, new_lable_Code(lable1), code2, new_lable_Code(lable2));
}
// IF LP Exp RP Stmt ELSE Stmt
else if (Stmt->ncld == 7 && !strcmp((Stmt->cld)[0]->name, "IF"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
Operand lable3 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable1, lable2);
// print_Codes(code1);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
InterCode code3 = translate_Stmt((Stmt->cld)[6]);
return add_Codes(7, code1, new_lable_Code(lable1), code2, new_goto_Code(lable3), new_lable_Code(lable2), code3, new_lable_Code(lable3));
}
// WHILE LP Exp RP Stmt
else if (Stmt->ncld == 5 && !strcmp((Stmt->cld)[0]->name, "WHILE"))
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
Operand lable3 = new_lable();
InterCode code1 = translate_Cond((Stmt->cld)[2], lable2, lable3);
InterCode code2 = translate_Stmt((Stmt->cld)[4]);
return add_Codes(6, new_lable_Code(lable1), code1, new_lable_Code(lable2), code2, new_goto_Code(lable1), new_lable_Code(lable3));
}
return new_Code();
}
// 变量声明、初始化的翻译模式
InterCode translate_DefList(tnode DefList)
{
// Def DefList
if (DefList->ncld == 2)
{
InterCode code1 = translate_Def((DefList->cld)[0]);
InterCode code2 = translate_DefList((DefList->cld)[1]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
InterCode translate_Def(tnode Def)
{
// Specifire DecList SEMI
if (Def->ncld == 3)
{
return translate_DecList((Def->cld)[1]);
}
return new_Code();
}
InterCode translate_DecList(tnode DecList)
{
// Dec
if (DecList->ncld == 1)
{
return translate_Dec((DecList->cld)[0]);
}
// Dec COMMA DecList
else if (DecList->ncld == 3)
{
InterCode code1 = translate_Dec((DecList->cld)[0]);
InterCode code2 = translate_DecList((DecList->cld)[2]);
return add_Codes(2, code1, code2);
}
return new_Code();
}
InterCode translate_Dec(tnode Dec)
{
// VarDec ASSIGNOP Exp
if (Dec->ncld == 3)
{
// 没有处理数组
// VarDec:ID
tnode ID = ((Dec->cld)[0]->cld)[0];
Operand variable = new_Variable(ID->content);
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Dec->cld)[2], t1);
InterCode code2 = new_assign_Code(variable, t1);
return add_Codes(2, code1, code2);
}
// VarDec
return new_Code();
}
// 当Exp的翻译模式为INT、ID、MINUS Exp时,可以获取已经申明过的操作数
Operand get_Operand(tnode Exp)
{
// INT
if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "INT"))
{
return find_Const((int)((Exp->cld)[0]->value));
}
// ID
else if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "ID"))
{
Operand variable = new_Variable((Exp->cld)[0]->content);
return variable;
}
// MINUS Exp (Exp:INT)
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "MINUS"))
{
if (!strcmp(((Exp->cld)[1]->cld)[0]->name, "INT"))
{
int value = -(int)(((Exp->cld)[1]->cld)[0]->value);
Operand result = find_Const(value);
if (result == NULL)
return new_Const(value);
else
return result;
}
}
return NULL;
}
// 查看是否已经声明过同一个常数值的临时变量
Operand find_Const(int value)
{
int i;
for (i = 0; i < 100; i++)
{
if (tempvar[i] == -1)
break;
if (temp_Operands[i]->kind == TEMPVAR && temp_Operands[i]->value == value)
return temp_Operands[i];
}
return NULL;
}
// 基本表达式的翻译模式
InterCode translate_Exp(tnode Exp, Operand place)
{
int isCond = 0;
// INT
if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "INT"))
{
Operand value = new_Const((Exp->cld)[0]->value);
InterCode code = new_assign_Code(place, value);
return code;
}
// ID
else if (Exp->ncld == 1 && !strcmp((Exp->cld)[0]->name, "ID"))
{
Operand variable = new_Variable((Exp->cld)[0]->content);
InterCode code = new_assign_Code(place, variable);
return code;
}
// Exp1 ASSIGNOP Exp2
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "ASSIGNOP"))
{
// Exp1 -> ID
if ((Exp->cld)[0]->ncld == 1 && !strcmp(((Exp->cld)[0]->cld)[0]->name, "ID"))
{
Operand variable = new_Variable(((Exp->cld)[0]->cld)[0]->content);
Operand existOp = get_Operand((Exp->cld)[2]);
// 中间代码优化
if (existOp == NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[2], t1);
InterCode code2 = new_assign_Code(variable, t1);
if (place == NULL)
return add_Codes(2, code1, code2);
else
{
InterCode code3 = new_assign_Code(place, variable);
return add_Codes(3, code1, code2, code3);
}
}
else
{
return new_assign_Code(variable, existOp);
}
}
}
// Exp PLUS Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "PLUS"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
if (op1 != NULL && op2 != NULL)
{
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = op2;
return code3;
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = op2;
return add_Codes(2, code1, code3);
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = t2;
return add_Codes(2, code2, code3);
}
else
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _ADD;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = t2;
return add_Codes(3, code1, code2, code3);
}
}
// Exp MINUS Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "MINUS"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
if (op1 != NULL && op2 != NULL)
{
InterCode code3 = new_Code();
code3->kind = _SUB;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = op2;
return code3;
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code3 = new_Code();
code3->kind = _SUB;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = op2;
return add_Codes(2, code1, code3);
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _SUB;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = t2;
return add_Codes(2, code2, code3);
}
else
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _SUB;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = t2;
return add_Codes(3, code1, code2, code3);
}
}
// Exp STAR Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "STAR"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
if (op1 != NULL && op2 != NULL)
{
InterCode code3 = new_Code();
code3->kind = _MUL;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = op2;
return code3;
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code3 = new_Code();
code3->kind = _MUL;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = op2;
return add_Codes(2, code1, code3);
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _MUL;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = t2;
return add_Codes(2, code2, code3);
}
else
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _MUL;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = t2;
return add_Codes(3, code1, code2, code3);
}
}
// Exp DIV Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "DIV"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
if (op1 != NULL && op2 != NULL)
{
InterCode code3 = new_Code();
code3->kind = _DIV;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = op2;
return code3;
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code3 = new_Code();
code3->kind = _DIV;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = op2;
return add_Codes(2, code1, code3);
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _DIV;
code3->operands.binop.result = place;
code3->operands.binop.op1 = op1;
code3->operands.binop.op2 = t2;
return add_Codes(2, code2, code3);
}
else
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
InterCode code3 = new_Code();
code3->kind = _DIV;
code3->operands.binop.result = place;
code3->operands.binop.op1 = t1;
code3->operands.binop.op2 = t2;
return add_Codes(3, code1, code2, code3);
}
}
// MINUS Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "MINUS"))
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[1], t1);
InterCode code2 = new_Code();
code2->kind = _SUB;
code2->operands.binop.result = place;
code2->operands.binop.op1 = new_Const(0);
code2->operands.binop.op2 = t1;
return add_Codes(2, code1, code2);
}
// Exp RELOP Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "RELOP"))
{
isCond = 1;
}
// NOT Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "NOT"))
{
isCond = 1;
}
// Exp AND Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "AND"))
{
isCond = 1;
}
// Exp OR Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "OR"))
{
isCond = 1;
}
// ID LP RP
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "LP"))
{
Operand function = new_Operand();
function->kind = FUNC;
function->operand.name = (Exp->cld)[0]->content;
if (!strcmp(function->operand.name, "read"))
{
// READ函数处理
InterCode code = new_Code();
code->kind = _READ;
code->operands.var = place;
return code;
}
else
{
// 其他函数处理
InterCode code = new_Code();
code->kind = _CALL;
code->operands.assign.left = place;
code->operands.assign.right = function;
return code;
}
}
// ID LP Args RP
else if (Exp->ncld == 4 && !strcmp((Exp->cld)[2]->name, "Args"))
{
int i;
Operand function = new_Operand();
function->kind = FUNC;
function->operand.name = (Exp->cld)[0]->content;
ArgList arg_list = (ArgList)malloc(sizeof(ArgListStru));
arg_list->num = 0;
InterCode code1 = translate_Args((Exp->cld)[2], arg_list);
InterCode code2, code3;
if (!strcmp(function->operand.name, "write"))
{
code2 = new_Code();
code2->kind = _WRITE;
code2->operands.var = (arg_list->list)[0];
return add_Codes(2, code1, code2);
}
else
{
for (i = 0; i < arg_list->num; i++)
{
code2 = new_Code();
code2->kind = _ARG;
code2->operands.var = (arg_list->list)[i];
code1 = add_Codes(2, code1, code2);
}
code3 = new_Code();
code3->kind = _CALL;
code3->operands.assign.left = place;
code3->operands.assign.right = function;
return add_Codes(2, code1, code3);
}
}
else
{
printf("不能处理该类型的语句\n");
}
if (isCond)
{
Operand lable1 = new_lable();
Operand lable2 = new_lable();
InterCode code0 = new_assign_Code(place, new_Const(0));
InterCode code1 = translate_Cond(Exp, lable1, lable2);
InterCode code2 = add_Codes(2, new_lable_Code(lable1), new_assign_Code(place, new_Const(1)));
return add_Codes(4, code0, code1, code2, new_lable_Code(lable2));
}
return new_Code();
}
// 条件表达式的翻译模式
InterCode translate_Cond(tnode Exp, Operand lable_true, Operand lable_false)
{
// Exp RELOP Exp
if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "RELOP"))
{
Operand op1 = get_Operand((Exp->cld)[0]);
Operand op2 = get_Operand((Exp->cld)[2]);
InterCode code3 = new_Code();
code3->kind = _IFGOTO;
code3->operands.jump.lable = lable_true;
code3->operands.jump.relop = (Exp->cld)[1]->content;
// 中间代码优化
if (op1 == NULL && op2 == NULL)
{
Operand t1 = new_tempvar();
Operand t2 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
code3->operands.jump.op1 = t1;
code3->operands.jump.op2 = t2;
return add_Codes(4, code1, code2, code3, new_goto_Code(lable_false));
}
else if (op1 == NULL && op2 != NULL)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Exp->cld)[0], t1);
code3->operands.jump.op1 = t1;
code3->operands.jump.op2 = op2;
return add_Codes(3, code1, code3, new_goto_Code(lable_false));
}
else if (op1 != NULL && op2 == NULL)
{
Operand t2 = new_tempvar();
InterCode code2 = translate_Exp((Exp->cld)[2], t2);
code3->operands.jump.op1 = op1;
code3->operands.jump.op2 = t2;
return add_Codes(3, code2, code3, new_goto_Code(lable_false));
}
else if (op1 != NULL && op2 != NULL)
{
code3->operands.jump.op1 = op1;
code3->operands.jump.op2 = op2;
return add_Codes(2, code3, new_goto_Code(lable_false));
}
}
// NOT Exp
else if (Exp->ncld == 2 && !strcmp((Exp->cld)[0]->name, "NOT"))
{
return translate_Cond((Exp->cld)[1], lable_false, lable_true);
}
// Exp AND Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "AND"))
{
Operand lable1 = new_lable();
InterCode code1 = translate_Cond((Exp->cld)[0], lable1, lable_false);
InterCode code2 = translate_Cond((Exp->cld)[2], lable_true, lable_false);
return add_Codes(3, code1, new_lable_Code(lable1), code2);
}
// Exp OR Exp
else if (Exp->ncld == 3 && !strcmp((Exp->cld)[1]->name, "OR"))
{
Operand lable1 = new_lable();
InterCode code1 = translate_Cond((Exp->cld)[0], lable_true, lable1);
InterCode code2 = translate_Cond((Exp->cld)[2], lable_true, lable_false);
return add_Codes(3, code1, new_lable_Code(lable1), code2);
}
// orther cases
else
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp(Exp, t1);
InterCode code2 = new_Code();
char *relop = "!=";
code2->kind = _IFGOTO;
code2->operands.jump.lable = lable_true;
code2->operands.jump.relop = relop;
code2->operands.jump.op1 = t1;
code2->operands.jump.op2 = new_Const(0);
return add_Codes(3, code1, code2, new_goto_Code(lable_false));
}
}
// 函数参数的翻译模式
InterCode translate_Args(tnode Args, ArgList arg_list)
{
// Exp
if (Args->ncld == 1)
{
Operand existOp = get_Operand((Args->cld)[0]);
if (existOp != NULL)
{
if (existOp->kind == CONSTANT)
{
Operand t1 = new_tempvar();
InterCode code1 = new_assign_Code(t1, existOp);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
return code1;
}
arg_list->list[arg_list->num] = existOp;
arg_list->num++;
return new_Code();
}
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Args->cld)[0], t1);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
return code1;
}
// Exp COMMA Args
else if (Args->ncld == 3)
{
Operand t1 = new_tempvar();
InterCode code1 = translate_Exp((Args->cld)[0], t1);
arg_list->list[arg_list->num] = t1;
arg_list->num++;
InterCode code2 = translate_Args((Args->cld)[2], arg_list);
return add_Codes(2, code1, code2);
}
return new_Code();
}
/**********************目标代码**************************/
char *Int2String(int num, char *str) //10进制
{
int i = 0; //指示填充str
if (num < 0) //如果num为负数,将num变正
{
num = -num;
str[i++] = '-';
}
//转换
do
{
str[i++] = num % 10 + 48; //取num最低位 字符0~9的ASCII码是48~57;简单来说数字0+48=48,ASCII码对应字符'0'
num /= 10; //去掉最低位
} while (num); //num不为0继续循环
str[i] = '\0';
//确定开始调整的位置
int j = 0;
if (str[0] == '-') //如果有负号,负号不用调整
{
j = 1; //从第二位开始调整
++i; //由于有负号,所以交换的对称轴也要后移1位
}
//对称交换
for (; j < i / 2; j++)
{
//对称交换两端的值 其实就是省下中间变量交换a+b的值:a=a+b;b=a-b;a=a-b;
str[j] = str[j] + str[i - 1 - j];
str[i - 1 - j] = str[j] - str[i - 1 - j];
str[j] = str[j] - str[i - 1 - j];
}
return str; //返回转换后的值
}
// 分配寄存器
char *allocate_reg(Operand op)
{
int i;
char *regnumber = (char *)malloc(sizeof(char) * 10);
char *regname = (char *)malloc(sizeof(char) * 10);
strcat(regname, "$t");
// 常数0 寄存器
if (op->kind == CONSTANT && op->operand.value == 0)
return "$zero";
else if (op->kind == TEMPVAR && op->value == 0)
return "$zero";
// 寻找存储该操作数的寄存器
int find = 0;
for (i = 0; i < reg_num; i++)
{
if (regs[i] == NULL || regs[i]->kind != op->kind)
continue;
if (regs[i]->kind == CONSTANT && regs[i]->operand.value == op->operand.value)
{
find = 1;
break;
}
else if (regs[i]->kind == TEMPVAR && regs[i]->operand.tempvar == op->operand.tempvar)
{
find = 1;
break;
}
else if (regs[i]->kind == VARIABLE && !strcmp(regs[i]->operand.name, op->operand.name))
{
find = 1;
break;
}
}
if (find)
{
Int2String(i, regnumber);
strcat(regname, regnumber);
return regname;
}
else
{
Int2String(reg_num, regnumber);
strcat(regname, regnumber);
regs[reg_num] = op;
reg_num++;
return regname;
}
}
// 根据中间代码生成mips代码
void generate_MIPS_Codes(InterCode codes)
{
printf("\n目标代码打印:\n");
// 声明部分
printf(".data\n_prompt: .asciiz \"Enter an integer:\"\n");
printf("_ret: .asciiz \"\\n\"\n.globl main\n.text\n");
// read函数
printf("read:\n\tli $v0, 4\n\tla $a0, _prompt\n\tsyscall\n");
printf("\tli $v0, 5\n\tsyscall\n\tjr $ra\n\n");
// write函数
printf("write:\n\tli $v0, 1\n\tsyscall\n\tli $v0, 4\n\tla $a0, _ret\n");
printf("\tsyscall\n\tmove $v0, $0\n\tjr $ra\n\n");
InterCode temp = new_Code();
temp = codes;
while (temp != NULL)
{
generate_MIPS_Code(temp);
temp = temp->next;
}
printf("打印完毕\n");
}
// 翻译单条中间代码
void generate_MIPS_Code(InterCode code)
{
if (code == NULL)
{
printf("Error, MIPS is NULL\n");
return;
}
switch (code->kind)
{
case _NULL:
break;
case _LABLE:
{
print_Operand(code->operands.var);
printf(":\n");
break;
}
case _FUNCTION:
{
print_Operand(code->operands.var);
printf(":\n");
break;
}
case _ASSIGN:
{
Operand left = code->operands.assign.left;
Operand right = code->operands.assign.right;
if (right->kind == CONSTANT)
{
// 如果将0赋给一个临时变量,则不需要输出该mips代码
if (left->kind == TEMPVAR && right->value == 0)
break;
else
printf("\tli %s, %d\n", allocate_reg(left), right->operand.value);
}
else
{
printf("\tmove %s, %s\n", allocate_reg(left), allocate_reg(right));
}
break;
}
case _ADD:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
if (op2->kind == CONSTANT)
{
printf("\taddi %s, %s, %d\n", allocate_reg(result), allocate_reg(op1), op2->value);
}
else
{
printf("\tadd %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
}
break;
}
case _SUB:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
if (op2->kind == CONSTANT)
{
printf("\taddi %s, %s, %d\n", allocate_reg(result), allocate_reg(op1), -(op2->value));
}
else
{
printf("\tsub %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
}
break;
}
case _MUL:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
printf("\tmul %s, %s, %s\n", allocate_reg(result), allocate_reg(op1), allocate_reg(op2));
break;
}
case _DIV:
{
Operand result = code->operands.binop.result;
Operand op1 = code->operands.binop.op1;
Operand op2 = code->operands.binop.op2;
printf("\tdiv %s, %s\n", allocate_reg(op1), allocate_reg(op2));
printf("\tmflo %s\n", allocate_reg(result));
break;
}
case _GOTO:
{
Operand lable = code->operands.jump.lable;
printf("\tj ");
print_Operand(lable);
printf("\n");
break;
}
case _CALL:
{
break;
}
case _READ:
{
Operand op = code->operands.var;
printf("\taddi $sp, $sp, -4\n");
printf("\tsw $ra, 0($sp)\n");
printf("\tjal read\n");
printf("\tlw $ra, 0($sp)\n");
printf("\taddi $sp, $sp, 4\n");
printf("\tmove %s, $v0\n", allocate_reg(op));
break;
}
case _WRITE:
{
Operand op = code->operands.var;
printf("\tmove $a0, %s\n", allocate_reg(op));
printf("\taddi $sp, $sp, -4\n");
printf("\tsw $ra, 0($sp)\n");
printf("\tjal write\n");
printf("\tlw $ra, 0($sp)\n");
printf("\taddi $sp, $sp, 4\n");
break;
}
case _RETURN:
{
Operand res = code->operands.var;
printf("\tmove $v0, %s\n", allocate_reg(res));
printf("\tjr $ra\n");
break;
}
case _IFGOTO:
{
char *op = code->operands.jump.relop;
Operand lable = code->operands.jump.lable;
Operand op1 = code->operands.jump.op1;
Operand op2 = code->operands.jump.op2;
if (!strcmp(op, "=="))
{
printf("\tbeq %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "!="))
{
printf("\tbne %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, ">"))
{
printf("\tbgt %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "<"))
{
printf("\tblt %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, ">="))
{
printf("\tbge %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
else if (!strcmp(op, "<="))
{
printf("\tble %s, %s, ", allocate_reg(op1), allocate_reg(op2));
print_Operand(lable);
printf("\n");
}
break;
}
default:
break;
}
}
/*
按照C-Tokens文件中要求定义
对终结符建立叶子结点,返回Token
19-10-26
*/
/*第一部分 头文件和变量*/
%{
#include
#include
#include "syntax_tree.h"
#include "syntax_tree.tab.h"
%}
/*flex属性,记录符号所在行号*/
%option yylineno
/*第二部分 定义正则表达式*/
/*十进制*/
INT_DEC [-+]?0|[1-9][0-9]*
/*十六进制*/
INT_HEX 0[xX][a-fA-F0-9]+
/*八进制*/
INT_OCT 0[1-7][0-7]*
/*二进制*/
INT_BIN 0[bB][01]+
/*INT类型汇总*/
INT {INT_HEX}|{INT_DEC}|{INT_OCT}|{INT_BIN}|{INT_HEX_ERROR}|{INT_OCT_ERROR}|{INT_BIN_ERROR}
/*浮点数-科学计数法*/
FLOAT [-+]?((([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)|INT)[Ee][-+]?[0-9]+)|({INT}\.[0-9])
/*词法分析输出错误,但是语法分析当做INT进行处理*/
/*十六进制错误*/
INT_HEX_ERROR 0[xX][a-fA-F0-9]*[g-zG-Z]+[a-fA-F0-9]*
/*八进制错误*/
INT_OCT_ERROR 0[0-7]*[89]+[0-7]*
/*二进制错误*/
INT_BIN_ERROR 0[bB][01]*[2-9]+[01]*
/*标识符*/
ID [a-z_A-Z][a-z_A-Z0-9]*
/*关键字*/
STRUCT struct
RETURN return
IF if
ELSE else
WHILE while
TYPE int|float
/*符号*/
SEMI ;
COMMA ,
ASSIGNOP =
PLUS \+
MINUS \-
STAR \*
DIV \/
AND &&
OR \|\|
DOT \.
NOT \!
LP \(
RP \)
LB \[
RB \]
LC \{
RC \}
RELOP >|<|>=|<=|==|!=
/*注释*/
COMMENT ("//".*)|("/*"([*]*(([^*/])+([/])*)*)*"*/")
/*空白符*/
SPACE [ \f\r\t\v]+
/*换行*/
EOL \n
/*未定义字符*/
AERROR .
/*第三部分 操作 action 这里面的注释必须顶格一个空格*/
%%
/*跳过空白和注释*/
{SPACE} {}
{COMMENT} {}
{EOL} {}
/*关键字*/
{TYPE} {yylval.type_tnode=newAst("TYPE",0,yylineno);
char *str;
str = (char *)malloc(sizeof(char) * 40);
strcpy(str, yytext);
curType = str;
return TYPE;}
{STRUCT} {
yylval.type_tnode=newAst("STRUCT",0,yylineno);
// 结构体数加一
strucNum++;
// 开始扫描结构体定义内容
inStruc=1;
return STRUCT;}
{RETURN} {yylval.type_tnode=newAst("RETURN",0,yylineno); return RETURN;}
{IF} {yylval.type_tnode=newAst("IF",0,yylineno);return IF;}
{ELSE} {yylval.type_tnode=newAst("ELSE",0,yylineno); return ELSE;}
{WHILE} {yylval.type_tnode=newAst("WHILE",0,yylineno); return WHILE;}
/*数字类型错误*/
{INT_HEX_ERROR} {printf("INT_HEX_ERROR at line %d: charachters \"%s\"\n",yylineno,yytext);}
{INT_OCT_ERROR} {printf("INT_OCT_ERROR at line %d: charachters \"%s\"\n",yylineno,yytext);}
{INT_BIN_ERROR} {printf("INT_BIN_ERROR at line %d: charachters \"%s\"\n",yylineno,yytext);}
/*数字类型表示*/
{INT} {yylval.type_tnode=newAst("INT",0,yylineno); return INT;}
{FLOAT} {yylval.type_tnode=newAst("FLOAT",0,yylineno); return FLOAT;}
/*符号*/
{SEMI} {yylval.type_tnode=newAst("SEMI",0,yylineno); return SEMI;}
{COMMA} {yylval.type_tnode=newAst("COMMA",0,yylineno); return COMMA;}
{ASSIGNOP} {yylval.type_tnode=newAst("ASSIGNOP",0,yylineno); return ASSIGNOP;}
{PLUS} {yylval.type_tnode=newAst("PLUS",0,yylineno); return PLUS;}
{MINUS} {yylval.type_tnode=newAst("MINUS",0,yylineno); return MINUS;}
{STAR} {yylval.type_tnode=newAst("STAR",0,yylineno); return STAR;}
{DIV} {yylval.type_tnode=newAst("DIV",0,yylineno); return DIV;}
{AND} {yylval.type_tnode=newAst("AND",0,yylineno); return AND;}
{OR} {yylval.type_tnode=newAst("OR",0,yylineno); return OR;}
{DOT} {yylval.type_tnode=newAst("DOT",0,yylineno); return DOT;}
{NOT} {yylval.type_tnode=newAst("NOT",0,yylineno); return NOT;}
{LP} {yylval.type_tnode=newAst("LP",0,yylineno); return LP;}
{RP} {yylval.type_tnode=newAst("RP",0,yylineno); return RP;}
{LB} {yylval.type_tnode=newAst("LB",0,yylineno); return LB;}
{RB} {yylval.type_tnode=newAst("RB",0,yylineno); return RB;}
{LC} {
yylval.type_tnode=newAst("LC",0,yylineno);
if(inStruc){
// 结构体定义内部存在LC左花括号
LCnum++;
}
return LC;}
{RC} {
yylval.type_tnode=newAst("RC",0,yylineno);
if(inStruc){
// 结构体定义内部存在RC右花括号
LCnum--;
}
return RC;}
{RELOP} {yylval.type_tnode=newAst("RELOP",0,yylineno); return RELOP;}
/*标识符*/
{ID} {yylval.type_tnode=newAst("ID",0,yylineno); return ID;}
/*错误*/
{AERROR} {
hasFault=1;
printf("Error type A at line %d: Mystirious charachter '%s'\n",yylineno,yytext);
}
%%
/*第四部分 函数 function*/
int yywrap()
{
/*此函数必须由用户提供,或者声明 %option noyywrap
当词法分析程序遇到文件结尾时,它调用例程yywrap()来找出下一步要做什么
如果返回0,扫描程序继续扫描,如果返回1,扫描程序就返回报告文件结尾*/
return 1;
}
/*
*bison语法分析,对每条规则 按照孩子兄弟表示法建立语法结点
*/
%{
#include
#include
#include "syntax_tree.h"
%}
%union{
tnode type_tnode;
// 这里声明double是为了防止出现指针错误(segmentation fault)
double d;
}
/*声明记号*/
%token <type_tnode> INT FLOAT
%token <type_tnode> TYPE STRUCT RETURN IF ELSE WHILE ID COMMENT SPACE SEMI COMMA ASSIGNOP PLUS
%token <type_tnode> MINUS STAR DIV AND OR DOT NOT LP RP LB RB LC RC AERROR RELOP EOL
%type <type_tnode> Program ExtDefList ExtDef ExtDecList Specifire StructSpecifire
%type <type_tnode> OptTag Tag VarDec FunDec VarList ParamDec Compst StmtList Stmt DefList Def DecList Dec Exp Args
/*优先级*/
/*C-minus中定义的运算符的优先级,并没有包括所有C语言的*/
%nonassoc LOWER_THAN_ELSE
%nonassoc ELSE
%left COMMA
%right ASSIGNOP
%left OR
%left AND
%left RELOP
%left PLUS MINUS
%left STAR DIV
%right NOT
%left LP RP LB RB DOT
/*产生式*/
/*$$表示左表达式 ${num}表示右边的第几个表达式*/
%%
/*High-level Definitions*/
Program:ExtDefList {$$=newAst("Program",1,$1); }
;
ExtDefList:ExtDef ExtDefList {$$=newAst("ExtDefList",2,$1,$2); }
| {$$=newAst("ExtDefList",0,-1); }
;
ExtDef:Specifire ExtDecList SEMI {$$=newAst("ExtDef",3,$1,$2,$3);}
|Specifire SEMI {$$=newAst("ExtDef",2,$1,$2); }
|Specifire FunDec Compst {
$$=newAst("ExtDef",3,$1,$2,$3);
// 设置函数声明的返回值类型并检查返回类型错误
newfunc(1,$1);
}
;
ExtDecList:VarDec {
$$=newAst("ExtDecList",1,$1);
// 错误类型7:变量出现重复定义
if(findvar($1))
printf("Error type 7 at Line %d:Redefined Variable '%s'\n",yylineno,$1->content);
else newvar(1,$1);
}
|VarDec COMMA ExtDecList {$$=newAst("ExtDecList",3,$1,$2,$3); }
;
/*Specifire*/
Specifire:TYPE {$$=newAst("Specifire",1,$1);}
|StructSpecifire {$$=newAst("Specifire",1,$1); }
;
StructSpecifire:STRUCT OptTag LC DefList RC {
// 结构体定义完成,当前在结构体定义外部
inStruc = 0;
$$=newAst("StructSpecifire",5,$1,$2,$3,$4,$5);
// 错误类型11:结构体的名字与前面定义过的结构体或变量的名字重复
if(findstruc($2))
printf("Error type 11 at Line %d:Duplicated name '%s'\n",yylineno,$2->content);
else newstruc(1,$2);
}
|STRUCT Tag {$$=newAst("StructSpecifire",2,$1,$2); }
;
OptTag:ID {$$=newAst("OptTag",1,$1); }
|{$$=newAst("OptTag",0,-1); }
;
Tag:ID {$$=newAst("Tag",1,$1); }
;
/*Declarators*/
VarDec:ID {$$=newAst("VarDec",1,$1); $$->tag=1;$$->content=$1->content;}
|VarDec LB INT RB {$$=newAst("VarDec",4,$1,$2,$3,$4); $$->content=$1->content;$$->tag=4;}
;
FunDec:ID LP VarList RP {
$$=newAst("FunDec",4,$1,$2,$3,$4); $$->content=$1->content;
// 错误类型8:函数出现重复定义(即同样的函数名出现了不止一次定义)
if(findfunc($1))
printf("Error type 8 at Line %d:Redefined Function '%s'\n",yylineno,$1->content);
// 设置函数名称以及参数列表
else newfunc(2,$1,$3);
}
|ID LP RP {
$$=newAst("FunDec",3,$1,$2,$3); $$->content=$1->content;
// 错误类型8:函数出现重复定义(即同样的函数名出现了不止一次定义)
if(findfunc($1))
printf("Error type 8 at Line %d:Redefined Function '%s'\n",yylineno,$1->content);
// 设置函数名称以及参数列表
else newfunc(2,$1,$3);
}
;
VarList:ParamDec COMMA VarList {$$=newAst("VarList",3,$1,$2,$3); }
|ParamDec {$$=newAst("VarList",1,$1); }
;
ParamDec:Specifire VarDec {
$$=newAst("ParamDec",2,$1,$2);
// 错误类型7:变量出现重复定义
if(findvar($2)||findarray($2))
printf("Error type 7 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content);
else if($2->tag==4)
newarray(1,$2);
else
newvar(1,$2);
}
;
/*Statement*/
Compst:LC DefList StmtList RC {$$=newAst("Compst",4,$1,$2,$3,$4); }
;
StmtList:Stmt StmtList{$$=newAst("StmtList",2,$1,$2); }
| {$$=newAst("StmtList",0,-1); }
;
Stmt:Exp SEMI { $$=newAst("Stmt",2,$1,$2); }
|Compst { $$=newAst("Stmt",1,$1); }
|RETURN Exp SEMI {
$$=newAst("Stmt",3,$1,$2,$3);
getrtype($2);
}
|IF LP Exp RP Stmt %prec LOWER_THAN_ELSE {$$=newAst("Stmt",5,$1,$2,$3,$4,$5); }
|IF LP Exp RP Stmt ELSE Stmt %prec ELSE {$$=newAst("Stmt",7,$1,$2,$3,$4,$5,$6,$7); }
|WHILE LP Exp RP Stmt {$$=newAst("Stmt",5,$1,$2,$3,$4,$5); }
;
/*Local Definitions*/
DefList:Def DefList{$$=newAst("DefList",2,$1,$2); }
| {$$=newAst("DefList",0,-1); }
;
Def:Specifire DecList SEMI {
$$=newAst("Def",3,$1,$2,$3);
}
;
DecList:Dec {$$=newAst("DecList",1,$1); }
|Dec COMMA DecList {$$=newAst("DecList",3,$1,$2,$3); $$->tag=$3->tag;}
;
Dec:VarDec {
$$=newAst("Dec",1,$1);
// 错误类型7:变量出现重复定义
if(findvar($1)||findarray($1))
printf("Error type 7 at Line %d:Redefined Variable '%s'\n",yylineno,$1->content);
else if($1->tag==4)
newarray(1,$1);
else
newvar(1,$1);
}
|VarDec ASSIGNOP Exp {
$$=newAst("Dec",3,$1,$2,$3);
$$->content=$1->content;
if(findvar($1)||findarray($1))
printf("Error type 7 at Line %d:Redefined Variable '%s'\n",yylineno,$1->content);
else if($1->tag==4)
newarray(1,$1);
else
newvar(1,$1);
}
;
/*Expressions*/
Exp:Exp ASSIGNOP Exp{
$$=newAst("Exp",3,$1,$2,$3);
// 当有一边变量是未定义时,不进行处理
if($1->type==NULL || $3->type==NULL){
// 不进行任何操作
// 这里不能用return,否则就会推出bison分析过程
}else{
// 错误类型2:赋值号两边的表达式类型不匹配
if(strcmp($1->type,$3->type))
printf("Error type 2 at Line %d:Type mismatched for assignment.%s,%s\n",yylineno,$1->type,$3->type);
// 错误类型3:赋值号左边出现一个只有右值的表达式
if(!checkleft($1))
printf("Error type 3 at Line %d:The left-hand side of an assignment must be a variable.\n",yylineno);
}
}
|Exp AND Exp{$$=newAst("Exp",3,$1,$2,$3); }
|Exp OR Exp{$$=newAst("Exp",3,$1,$2,$3); }
|Exp RELOP Exp{$$=newAst("Exp",3,$1,$2,$3); }
|Exp PLUS Exp{
$$=newAst("Exp",3,$1,$2,$3);
// 错误类型6:操作数类型不匹配或操作数类型与操作符不匹配
if(strcmp($1->type,$3->type)){
printf("Error type 6 at Line %d:Type mismatched for operands.\n",yylineno);
}
}
|Exp MINUS Exp{
$$=newAst("Exp",3,$1,$2,$3);
// 错误类型6:操作数类型不匹配或操作数类型与操作符不匹配
if(strcmp($1->type,$3->type))
printf("Error type 6 at Line %d:Type mismatched for operands.\n",yylineno);
}
|Exp STAR Exp{
$$=newAst("Exp",3,$1,$2,$3);
// 错误类型6:操作数类型不匹配或操作数类型与操作符不匹配
if(strcmp($1->type,$3->type))
printf("Error type 6 at Line %d:Type mismatched for operands.\n",yylineno);
}
|Exp DIV Exp{
$$=newAst("Exp",3,$1,$2,$3);
// 错误类型6:操作数类型不匹配或操作数类型与操作符不匹配
if(strcmp($1->type,$3->type))
printf("Error type 6 at Line %d:Type mismatched for operands.\n",yylineno);
}
|LP Exp RP{$$=newAst("Exp",3,$1,$2,$3); }
|MINUS Exp {$$=newAst("Exp",2,$1,$2); }
|NOT Exp {$$=newAst("Exp",2,$1,$2); }
|ID LP Args RP {
$$=newAst("Exp",4,$1,$2,$3,$4);
// 错误类型4:对普通变量使用“(...)”或“()”(函数调用)操作符
if(!findfunc($1) && (findvar($1)||findarray($1)))
printf("Error type 4 at Line %d:'%s' is not a function.\n",yylineno,$1->content);
// 错误类型5:函数在调用时未经定义
else if(!findfunc($1))
printf("Error type 5 at Line %d:Undefined function %s\n",yylineno,$1->content);
// 函数实参和形参类型不一致
else if(checkrtype($1,$3)){
printf("Error type 13 at Line %d:Function parameter type error.\n",yylineno);
}else{
$$->type=typefunc($1);
}
}
|ID LP RP {
$$=newAst("Exp",3,$1,$2,$3);
// 错误类型4:对普通变量使用“(...)”或“()”(函数调用)操作符
if(!findfunc($1) && (findvar($1)||findarray($1)))
printf("Error type 4 at Line %d:'%s' is not a function.\n",yylineno,$1->content);
// 错误类型5:函数在调用时未经定义
else if(!findfunc($1))
printf("Error type 5 at Line %d:Undefined function %s\n",yylineno,$1->content);
else {
$$->type=typefunc($1);
}
}
|Exp LB Exp RB {$$=newAst("Exp",4,$1,$2,$3,$4); }
|Exp DOT ID {$$=newAst("Exp",3,$1,$2,$3); }
|ID {
$$=newAst("Exp",1,$1);
// 错误类型1:变量在使用时未经定义
if(!findvar($1)&&!findarray($1))
printf("Error type 1 at Line %d:undefined variable %s\n",yylineno,$1->content);
else
$$->type=typevar($1);
}
|INT {$$=newAst("Exp",1,$1); $$->tag=3;$$->value=$1->value;}
|FLOAT{$$=newAst("Exp",1,$1); $$->tag=3;$$->value=$1->value;}
;
Args:Exp COMMA Args {$$=newAst("Args",3,$1,$2,$3);}
|Exp {$$=newAst("Args",1,$1);}
;
%%