📄 midcode.cpp
字号:
// midcode.cpp: implementation of the Cmidcode class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "face.h"
#include "midcode.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Cmidcode::Cmidcode()
{
/*标号值,全局变量*/
Label = 0;
/*指向第一条中间代码*/
firstCode = NULL ;
/*指向当前最后一条中间代码*/
lastCode = NULL ;
/*主程序的noff偏移*/
mainOff = 0;
//TempOffset = 0;
}
Cmidcode::~Cmidcode()
{
}
/*******************实用函数的实现**************************/
/********************************************************/
/* 函数名 FindField */
/* 功 能 查找纪录的域名 */
/* 说 明 返回值为是否找到标志,变量Entry返回此域名在 */
/* 纪录的域表中的位置. */
/********************************************************/
bool Cmidcode::FindField(char * Id , fieldChain *head,fieldChain **Entry )
{
bool present =false;
/*记录当前节点*/
fieldChain *currentItem = head;
/*从表头开始查找这个标识符,直到找到或到达表尾*/
while ((currentItem!=NULL)&&( present==false))
{
if (strcmp(currentItem->id, Id )==0)
{ present= true;
if (Entry!=NULL)
(*Entry)=currentItem;
}
else currentItem=currentItem->Next;
}
return(present);
}
/********************************************************/
/* 函数名 NewTemp */
/* 功 能 产生一个新的临时变量的ARG结构 */
/* 说 明 临时变量的层数为-1,偏移为编号值,访问方式由 */
/* 参数确定 */
/********************************************************/
Cglobal::ArgRecord *Cmidcode::NewTemp (AccessKind access )
{
ArgRecord *newTemp=(ArgRecord *)malloc(sizeof(ArgRecord)) ;
/*填写临时变量的ARG内容*/
newTemp->form = AddrForm ;
newTemp->Attr.addr.dataLevel = -1 ;
newTemp->Attr.addr.dataOff=TempOffset ;
newTemp->Attr.addr.access= access;
/*临时变量编号加1*/
TempOffset++;
return (newTemp);
}
/********************************************************/
/* 函数名 NewLabel */
/* 功 能 产生一个新的标号值 */
/* 说 明 通过全局变量Label加1,产生新的标号值 */
/********************************************************/
int Cmidcode::NewLabel()
{ Label++;
return (Label);
}
/********************************************************/
/* 函数名 ARGAddr */
/* 功 能 对于给定的变量产生相应的ARG结构 */
/* 说 明 */
/********************************************************/
Cglobal::ArgRecord *Cmidcode::ARGAddr(char *id ,int level, int off, AccessKind access)
{
ArgRecord *arg = (ArgRecord *)malloc(sizeof(ArgRecord));
/*填写变量ARG结构的内容*/
arg->form = AddrForm ;
strcpy(arg->Attr.addr.name,id);
arg->Attr.addr.dataLevel=level;
arg->Attr.addr.dataOff=off;
arg->Attr.addr.access=access;
return (arg);
}
/********************************************************/
/* 函数名 ARGLabel */
/* 功 能 对于给定的标号产生相应的ARG结构 */
/* 说 明 */
/********************************************************/
Cglobal::ArgRecord *Cmidcode::ARGLabel(int label )
{ ArgRecord *arg = (ArgRecord *) malloc (sizeof(ArgRecord));
arg->form = LabelForm ;
arg->Attr.label = label ;
return (arg);
}
/********************************************************/
/* 函数名 ARGValue */
/* 功 能 对于给定的常数值产生相应的ARG结构 */
/* 说 明 */
/********************************************************/
Cglobal::ArgRecord *Cmidcode::ARGValue(int value)
{ ArgRecord *arg = (ArgRecord *) malloc (sizeof(ArgRecord));
arg->form = ValueForm ;
arg->Attr.value = value ;
return (arg);
}
/********************************************************/
/* 函数名 GenCode */
/* 功 能 根据给定参数,构造一条中间代码 */
/* 说 明 */
/********************************************************/
Cglobal::CodeFile *Cmidcode::GenCode (CodeKind codekind , ArgRecord *Arg1 ,
ArgRecord *Arg2 ,ArgRecord *Arg3 )
{
CodeFile *newCode = (CodeFile *) malloc (sizeof (CodeFile ));
/*填写代码的内容*/
newCode->codeR.codekind = codekind ;
newCode->codeR.arg1 = Arg1;
newCode->codeR.arg2 = Arg2;
newCode->codeR.arg3 = Arg3;
newCode->former = NULL;
newCode->next = NULL;
/*链入中间代码表中*/
if (firstCode==NULL)
firstCode = newCode ;
else
{ lastCode->next=newCode;
newCode->former = lastCode;
}
lastCode = newCode ;
return(newCode);
}
/********************************************************/
/* 函数名 PrintCodeName */
/* 功 能 打印代码的类别 */
/* 说 明 由函数PrintOneCode调用 */
/********************************************************/
void Cmidcode::PrintCodeName(CodeKind kind)
{
switch(kind)
{ case ADD: fprintf(listing ,"ADD"); break;
case SUB: fprintf(listing ,"SUB"); break;
case MULT: fprintf(listing ,"MULT"); break;
case DIV: fprintf(listing ,"DIV"); break;
case EQC: fprintf(listing ,"EQ"); break;
case LTC: fprintf(listing ,"LT"); break;
case READC: fprintf(listing ,"READ"); break;
case WRITEC: fprintf(listing ,"WRITE"); break;
case RETURNC: fprintf(listing ,"RETURN"); break;
case ASSIG: fprintf(listing ,"ASSIG"); break;
case AADD: fprintf(listing ,"AADD"); break;
case LABEL: fprintf(listing ,"LABEL"); break;
case JUMP0: fprintf(listing ,"JUMP0"); break;
case JUMP: fprintf(listing ,"JUMP"); break;
case CALL: fprintf(listing ,"CALL"); break;
case VARACT: fprintf(listing ,"VARACT"); break;
case VALACT: fprintf(listing ,"VALACT"); break;
case PENTRY: fprintf(listing ,"PENTRY"); break;
case ENDPROC: fprintf(listing ,"ENDPROC"); break;
case MENTRY: fprintf(listing ,"MENTRY"); break;
case WHILESTART: fprintf(listing ,"WHILESTART");break;
case ENDWHILE: fprintf(listing ,"ENDWHILE"); break;
default: break;
}
}
/********************************************************/
/* 函数名 PrintCotent */
/* 功 能 打印ARG结构的内容 */
/* 说 明 由函数PrintOneCode调用 */
/********************************************************/
void Cmidcode::PrintContent(ArgRecord *arg)
{
switch(arg->form)
{case LabelForm : fprintf(listing ,"%d",arg->Attr.label); break;
case ValueForm : fprintf(listing ,"%d",arg->Attr.value); break;
case AddrForm:
//d:fprintf(listing ,"(");
if (arg->Attr.addr.dataLevel!=-1)
fprintf(listing ,arg->Attr.addr.name);
else
{ fprintf(listing ,"temp");
fprintf(listing ,"%d",arg->Attr.addr.dataOff);
}
/*
fprintf(listing ," , ");
fprintf(listing ,"%d",arg->Attr.addr.dataLevel);
fprintf(listing ," , ");
fprintf(listing ,"%d",arg->Attr.addr.dataOff);
fprintf(listing ," , ");
switch( arg->Attr.addr.access)
{ case dir : fprintf(listing ,"dir"); break;
case indir: fprintf(listing ,"indir"); break;
default : break;
}
fprintf(listing ,")");
*/
break;
default: break;
}
}
/********************************************************/
/* 函数名 PrintOneCode */
/* 功 能 打印一条中间代码 */
/* 说 明 由函数PrintMidCode调用 */
/********************************************************/
void Cmidcode::PrintOneCode(CodeFile *code)
{
PrintCodeName(code->codeR.codekind);
fprintf(listing ," ");
if (code->codeR.arg1!=NULL)
PrintContent(code->codeR.arg1);
else fprintf(listing, " ");
fprintf(listing ," ");
if (code->codeR.arg2!=NULL)
PrintContent(code->codeR.arg2);
else fprintf(listing ," ");
fprintf(listing ," ");
if (code->codeR.arg3!=NULL)
PrintContent(code->codeR.arg3);
else fprintf(listing, " ");
}
/********************************************************/
/* 函数名 PrintMidCode */
/* 功 能 打印中间代码序列 */
/* 说 明 */
/********************************************************/
void Cmidcode::PrintMidCode(CodeFile *firstCode)
{ int i = 0;
CodeFile *code = firstCode ;
while (code!=NULL)
{ fprintf(listing ," ");
fprintf(listing ,"%d%s", i, ": ");
PrintOneCode(code);
fprintf(listing,"\n");
code = code ->next;
i++;
}
}
/**************中间代码生成的函数实现************************/
/********************************************************/
/* 函数名 GenMidCode */
/* 功 能 中间代码生成主函数 */
/* 说 明 若有过程声明,调用过程声明的代码声明函数; */
/* 调用程序体的代码生成函数 */
/********************************************************/
Cglobal::CodeFile * Cmidcode::GenMidCode(TreeNode *t,int StoreNoff)
{
/**********从构造函数拷贝,每次调用都要初始化**********/
/*标号值,全局变量*/
Label = 0;
/*指向第一条中间代码*/
firstCode = NULL ;
/*指向当前最后一条中间代码*/
lastCode = NULL ;
/*主程序的noff偏移*/
mainOff = 0;
//TempOffset = 0;
/**********************************************************/
/*若有过程声明,调用相应函数,产生过程声明的中间代码*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*display表相对于sp的偏移*/
ArgRecord *Noff = ARGValue(StoreNoff);
/*生成主程序入口声明代码*/
CodeFile *code = GenCode(MENTRY,NULL,NULL,Noff);
/*初始化临时变量的开始编号,为临时变量区的第一个地址*/
TempOffset = StoreNoff + 1;
/*调用语句序列的代码生成函数*/
GenBody(t->child[2]);
/*回填主程序的AR的大小到主程序入口中间代码*/
int size = TempOffset;
ArgRecord *sizeArg = ARGValue(size);
code->codeR.arg2= sizeArg;
return (firstCode) ;
}
/****************************************************/
/* 函数名 GenProcDec */
/* 功 能 过程声明中间代码生成函数 */
/* 说 明 生成过程入口中间代码,生成过程体的中间 */
/* 代码,生成过程出口的中间代码 */
/****************************************************/
void Cmidcode::GenProcDec(TreeNode *t)
{
/*得到过程的入口标号*/
int ProcEntry = NewLabel( );
/*过程名在符号表中的地址*/
SymbTable *Entry = t->table[0];
/*过程入口标号,回填入节点中*/
Entry->attrIR.More.ProcAttr.codeEntry = ProcEntry;
/*过程的display表的偏移量*/
int noff = Entry->attrIR.More.ProcAttr.nOff;
/*得到过程的层数及其ARG结构*/
int procLevel = Entry->attrIR.More.ProcAttr.level;
ArgRecord *levelArg = ARGValue(procLevel);
/*若过程内部仍有过程声明,调用相应函数,产生过程声明的中间代码*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*产生过程入口中间代码*/
ArgRecord *arg1=ARGLabel(ProcEntry);
CodeFile *code = GenCode(PENTRY,arg1,NULL,levelArg);
/*初始化临时变量的开始编号,为过程临时变量区的第一个地址*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -