⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 语义分析.txt

📁 这是编译原理的源代码
💻 TXT
📖 第 1 页 / 共 4 页
字号:
			/*判断识值参还是变参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 + -