📄 语义分析.txt
字号:
/*判断识值参还是变参acess(dir,indir)*/
if(t->attr.ProcAttr.paramt == varparamType)
{
attrIr.More.VarAttr.access = indir;
attrIr.More.VarAttr.level = Level;
/*计算形参的偏移*/
attrIr.More.VarAttr.off = Off;
Off = Off+1;
}/*如果是变参,则偏移加1*/
else
{
attrIr.More.VarAttr.access = dir;
attrIr.More.VarAttr.level = Level;
/*计算值参的偏移*/
if(attrIr.idtype!=NULL)
{
attrIr.More.VarAttr.off = Off;
Off = Off + (attrIr.idtype->size);
}
}/*其他情况均为值参,偏移加变量类型的size*/
/*登记该变量的属性及名字,并返回其类型内部指针*/
present = Enter(t->name[i],&attrIr,&entry);
if(present!=FALSE)
{
ErrorPrompt(t->lineno,t->name[i]," is defined repetation!\n");
}
else
t->table[i] = entry;
}
if(t!=NULL)
t = t->sibling;
}
/*如果是主程序,则记录此时偏移,用于目标代码生成时的displayOff*/
if(Level==0)
{
//mainOff = Off;
/*存储主程序AR的display表的偏移到全局变量*/
StoreNoff = Off;
}
/*如果不是主程序,则记录此时偏移,用于下面填写过程信息表的noff信息*/
else
savedOff = Off;
}
/************************************************************/
/* 函数名 procDec */
/* 功 能 该函数处理过程声明的语义分析 */
/* 说 明 在当前层符号表中填写过程标识符的属性;在新层符号 */
/* 表中填写形参标识符的属性。 */
/************************************************************/
void Canalyze::procDecPart(TreeNode * t)
{
TreeNode * p =t;
SymbTable * entry = HeadProcess(t); /*处理过程头*/
t = t->child[1];
/*如果过程内部存在声明部分,则处理声明部分*/
while (t!=NULL)
{
switch ( t->nodekind )
{
case TypeK: TypeDecPart(t->child[0]); break ;
case VarK : VarDecPart(t->child[0]); break ;
/*如果声明部分有函数声明,则跳出循环,先填写noff和moff等信息,*
*再处理函数声明的循环处理,否则无法保存noff和moff的值。 */
case ProcDecK: break;
default:
ErrorPrompt(t->lineno,"","no this node kind in syntax tree!");
break;
}
if(t->nodekind==ProcDecK)
break;
else
t=t->sibling ;
}
entry->attrIR.More.ProcAttr.nOff = savedOff;
entry->attrIR.More.ProcAttr.mOff = entry->attrIR.More.ProcAttr.nOff + entry->attrIR.More.ProcAttr.level+1;
/*过程活动记录的长度等于nOff加上display表的长度*
*diplay表的长度等于过程所在层数加一 */
/*处理程序的声明部分*/
while(t!=NULL)
{
procDecPart(t);
t = t->sibling;
}
t = p;
Body(t->child[2]);/*处理Block*/
/*函数部分结束,删除进入形参时,新建立的符号表*/
if ( Level!=-1)
DestroyTable();/*结束当前scope*/
}
/************************************************************/
/* 函数名 HeadProcess */
/* 功 能 该函数处理函数头的语义分析 */
/* 说 明 在当前层符号表中填写函数标识符的属性;在新层符号 */
/* 表中填写形参标识符的属性。其中过程的大小和代码都 */
/* 需以后回填。 */
/************************************************************/
Cglobal::SymbTable * Canalyze::HeadProcess(TreeNode * t)
{
AttributeIR attrIr ;
int present = FALSE;
SymbTable * entry = NULL;
/*填属性*/
attrIr.kind = procKind;
attrIr.idtype = NULL;
attrIr.More.ProcAttr.level = Level+1;
if(t!=NULL)
{
/*登记函数的符号表项*/
present = Enter(t->name[0],&attrIr,&entry);
t->table[0] = entry;
/*处理形参声明表*/
}
entry->attrIR.More.ProcAttr.param = ParaDecList(t);
return entry;
}
/************************************************************/
/* 函数名 ParaDecList */
/* 功 能 该函数处理函数头中的参数声明的语义分析 */
/* 说 明 在新的符号表中登记所有形参的表项,构造形参表项的 */
/* 地址表,并有para指向其。 */
/************************************************************/
Cglobal::ParamTable * Canalyze::ParaDecList(TreeNode * t)
{
TreeNode * p = NULL;
ParamTable * Ptr1 = NULL;
ParamTable * Ptr2 = NULL;
ParamTable * head = NULL;
if(t!=NULL)
{
if(t->child[0]!=NULL)
p = t->child[0]; /*程序声明节点的第一个儿子节点*/
CreatTable(); /*进入新的局部化区*/
Off = 7; /*子程序中的变量初始偏移设为8*/
VarDecPart(p); /*变量声明部分*/
SymbTable * Ptr0 = scope[Level];
while(Ptr0 != NULL) /*只要不为空,就访问其兄弟节点*/
{
/*构造形参符号表,并使其连接至符号表的param项*/
Ptr2 = NewParam();
if(head == NULL)
head = Ptr1 = Ptr2;
//Ptr0->attrIR.More.VarAttr.isParam = true;
Ptr2->entry = Ptr0;
Ptr2->next = NULL;
if(Ptr2 != Ptr1)
{
Ptr1->next = Ptr2;
Ptr1 = Ptr2;
}
Ptr0 = Ptr0->next;
}
}
return head; /*返回形参符号表的头指针*/
}
/*******************执行体部分的语义分析*********************/
/************************************************************/
/* 函数名 Body */
/* 功 能 该函数处理执行体部分的语义分析 */
/* 说 明 TINY编译系统的执行体部分即为语句序列,故只需处理 */
/* 语句序列部分。 */
/************************************************************/
void Canalyze::Body(TreeNode * t)
{
if (t->nodekind==StmLK)
{
TreeNode * p = t->child[0];
while(p != NULL)
{
statement (p); /*调用语句状态处理函数*/
p=p->sibling; /*依次读入语法树语句序列的兄弟节点*/
}
}
}
/************************************************************/
/* 函数名 statement */
/* 功 能 该函数处理语句状态 */
/* 说 明 根据语法树节点中的kind项判断应该转向处理哪个语句 */
/* 类型函数。 */
/************************************************************/
void Canalyze::statement (TreeNode * t)
{
switch(t->kind.stmt)
{
case IfK: ifstatment(t); break;
case WhileK: whilestatement(t); break;
case AssignK: assignstatement(t); break;
case ReadK: readstatement(t); break;
case WriteK: writestatement(t);break;
case CallK: callstatement(t); break;
case ReturnK: returnstatement(t); break;
default :
ErrorPrompt(t->lineno,"","statement type error!\n");
break;
}
}
/************************************************************/
/* 函数名 Expr */
/* 功 能 该函数处理表达式的分析 */
/* 说 明 表达式语义分析的重点是检查运算分量的类型相容性, */
/* 求表达式的类型。其中参数Ekind用来表示实参是变参 */
/* 还是值参。 */
/************************************************************/
Cglobal::TypeIR * Canalyze::Expr(TreeNode * t,AccessKind * Ekind)
{
int present = FALSE;
SymbTable * entry = NULL;
TypeIR * Eptr0 = NULL;
TypeIR * Eptr1 = NULL;
TypeIR * Eptr = NULL;
if(t!=NULL)
switch(t->kind.exp)
{
case ConstK:
Eptr = TypeProcess (t,IntegerK);
Eptr->kind = intTy;
if(Ekind!=NULL)
(*Ekind ) = dir; /*直接变量*/
break;
case VariK:
/*Var = id的情形*/
if(t->child[0]==NULL)
{
/*在符号表中查找此标识符*/
present = FindEntry(t->name[0],&entry);
t->table[0] = entry;
if(present!=FALSE)
{ /*id不是变量*/
if (FindAttr(entry).kind!=varKind)
{
ErrorPrompt(t->lineno,t->name[0],"is not variable error!\n");
Eptr = NULL;
}
else
{
Eptr = entry->attrIR.idtype;
if (Ekind!=NULL)
(*Ekind) = indir; /*间接变量*/
}
}
else /*标识符无声明*/
{
ErrorPrompt(t->lineno,t->name[0],"is not declarations!\n");
}
}
else/*Var = Var0[E]的情形*/
{ if(t->attr.ExpAttr.varkind==ArrayMembV)
Eptr = arrayVar(t);
else /*Var = Var0.id的情形*/
if(t->attr.ExpAttr.varkind==FieldMembV)
Eptr = recordVar(t);
}
break;
case OpK:
/*递归调用儿子节点*/
Eptr0 = Expr(t->child[0],NULL);
if(Eptr0==NULL)
return NULL;
Eptr1 = Expr(t->child[1],NULL);
if(Eptr1==NULL)
return NULL;
/*类型判别*/
present = Compat(Eptr0,Eptr1);
if ( present != FALSE )
{
switch(t->attr.ExpAttr.op)
{
case LT:
case EQ:
Eptr = boolPtr;
break; /*条件表达式*/
case PLUS:
case MINUS:
case TIMES:
case OVER:
Eptr = intPtr;
break; /*算数表达式*/
}
if(Ekind !=NULL)
(*Ekind) = dir; /*直接变量*/
}
else
ErrorPrompt(t->lineno,"","operator is not compat!\n");
break;
}
return Eptr;
}
/************************************************************/
/* 函数名 arrayVar */
/* 功 能 该函数处理数组变量的下标分析 */
/* 说 明 检查var := var0[E]中var0是不是数组类型变量,E是不*/
/* 是和数组的下标变量类型匹配。 */
/************************************************************/
Cglobal::TypeIR * Canalyze::arrayVar(TreeNode * t)
{
int present = FALSE;
SymbTable * entry = NULL;
TypeIR * Eptr0 = NULL;
TypeIR * Eptr1 = NULL;
TypeIR * Eptr = NULL;
/*在符号表中查找此标识符*/
present = FindEntry(t->name[0],&entry);
t->table[0] = entry;
/*找到*/
if(present!=FALSE)
{
/*Var0不是变量*/
if (FindAttr(entry).kind!=varKind)
{
ErrorPrompt(t->lineno,t->name[0],"is not variable error!\n");
Eptr = NULL;
}
else/*Var0不是数组类型变量*/
if(FindAttr(entry).idtype!=NULL)
if(FindAttr(entry).idtype->kind!=arrayTy)
{
ErrorPrompt(t->lineno,t->name[0],"is not array variable error !\n");
Eptr = NULL;
}
else
{
/*检查E的类型是否与下标类型相符*/
Eptr0 = entry->attrIR.idtype->More.ArrayAttr.indexTy;
if(Eptr0==NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -