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

📄 语义分析.txt

📁 这是编译原理的源代码
💻 TXT
📖 第 1 页 / 共 4 页
字号:
			case charTy:
			case boolTy:
				table->kind = kind;
				table->size = 1;
				break;
			case arrayTy:
				table->kind = arrayTy;
				table->More.ArrayAttr.indexTy = NULL;
				table->More.ArrayAttr.elemTy = NULL;
				break;
			case recordTy:
				table->kind = recordTy;
				table->More.body = NULL;
				break;
		}
	return table;
}

/***********************************************************/
/* 函数名 NewBody                                          */
/* 功  能 创建当前空记录类型中域的链表                     */
/* 说  明 函数返回该类型的新的链表的单元地址               */
/***********************************************************/
Cglobal::fieldChain * Canalyze::NewBody(void)
{
	fieldChain * Ptr = (fieldChain *) malloc(sizeof(fieldChain));

	if (Ptr==NULL)
	{
		fprintf(listing,"Out of memory error !");
		Error = TRUE;
	}
	else
	{
		Ptr->Next = NULL;
		Ptr->off = 0;
		Ptr->UnitType = NULL;
	}
	return Ptr;
}

/***********************************************************/
/* 函数名 NewParam	                                       */
/* 功  能 创建当前空形参链表                               */
/* 说  明 函数返回新申请的单元地址                         */
/***********************************************************/
Cglobal::ParamTable * Canalyze::NewParam(void)
{
	ParamTable * Ptr = (ParamTable *) malloc(sizeof(ParamTable));

    if (Ptr==NULL)
	{
		fprintf(listing,"Out of memory error !");
		Error = TRUE;
	}
	else
	{
		Ptr->entry = NULL;
		Ptr->next = NULL;
	}
		
	return Ptr;
}

/***********************************************************/
/* 函数名 ErrorPrompt                                      */
/* 功  能 错误提示                                         */
/* 说  明 在输出文件中显示错误提示,并给全局量Error赋值为1 */
/***********************************************************/
void Canalyze::ErrorPrompt(int line,char * name,char * message)
{
	fprintf(listing,">>>Line: %d, %s %s",line,name,message);
	Error = TRUE;
	//exit(0);
}


/***********************************************************/
/* 函数名 printTab                                         */
/* 功  能 打印空格                                         */
/* 说  明 在输出文件中打印个数为参数tabnum的空格           */
/***********************************************************/
void Canalyze::printTab(int tabnum)
{
	for(int i=0;i<tabnum;i++)
		fprintf(listing," ");
}


/********************************************************/
/* 函数名  FindField	  								*/
/* 功  能  查找纪录的域名								*/
/* 说  明  返回值为是否找到标志,变量Entry返回此域名在  */
/*		   纪录的域表中的位置.							*/
/********************************************************/
bool  Canalyze::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);
}


/********************语义分析函数实现*******************************/

/*************************************************************/
/* 函数名  initialize                                        */
/* 功  能  该函数初始化整数类型,字符类型,布尔类型的内部表示*/
/* 说  明  由于这三种类型均为基本类型,内部表示固定。        */
/*************************************************************/
void Canalyze::initialize(void)
{
	intPtr = NewTy(intTy);

	charPtr = NewTy(charTy);

	boolPtr = NewTy(boolTy);

    /*scope栈的各层指针设为空*/
	for (int i=0;i<SCOPESIZE;i++)
		scope[i] = NULL;
}

/************************************************************/
/* 函数名  TypeProcess                                      */
/* 功  能  该函数用来完成类型分析的工作                     */
/* 说  明  处理语法树的当前结点类型。构造出当前类型的内部表 */
/*         示,并将其地址返回给Ptr类型内部表示的地址.       */
/************************************************************/
Cglobal::TypeIR  * Canalyze::TypeProcess(TreeNode * t,DecKind deckind)
{
	TypeIR  *  Ptr = NULL;
	switch (deckind)
	{
	case IdK:  
		Ptr = nameType(t);break;         /*类型为自定义标识符*/
	case ArrayK:
		Ptr = arrayType(t);break;        /*类型为数组类型*/
	case RecordK:
		Ptr = recordType(t);break;       /*类型为记录类型*/
	case IntegerK:
		Ptr = intPtr;break;              /*类型为整数类型*/
	case CharK:
		Ptr = charPtr;break;             /*类型为字符类型*/
	}
	return Ptr;
}

/************************************************************/
/* 函数名  nameType                                         */
/* 功  能  该函数用来在符号表中寻找已定义的类型名字         */
/* 说  明  调用寻找表项地址函数FindEntry,返回找到的表项地址*/
/*		   指针entry。如果present为FALSE,则发生无声明错误。*/
/*         如果符号表中的该标识符的属性信息不是类型,则非类 */
/*         型标识符。该函数返回指针指向符号表中的该标识符的 */
/*	       类型内部表示。								    */
/************************************************************/
Cglobal::TypeIR * Canalyze::nameType(TreeNode * t)
{
	TypeIR * Ptr=NULL;
	SymbTable * entry = NULL;
	int present;


	/*类型标识符也需要往前层查找*/
	present = FindEntry(t->attr.type_name,&entry);
								
	if(present == TRUE)
	{
		/*检查该标识符是否为类型标识符*/
		if(entry->attrIR.kind != typeKind)
			ErrorPrompt(t->lineno,t->attr.type_name,"used before typed!\n");
		else
			Ptr = entry->attrIR.idtype;
	}
	else/*没有找到该标识符*/
	{
		ErrorPrompt(t->lineno,t->attr.type_name,"type name is not declared!\n");
	}
	return Ptr;
}

/************************************************************/
/* 函数名  arrayType                                        */
/* 功  能  该函数处理数组类型的内部表示                     */
/* 说  明  类型为数组类型时,需要检查下标是否合法。         */
/************************************************************/
Cglobal::TypeIR  * Canalyze::arrayType(TreeNode * t)
{
	TypeIR  * Ptr0 = NULL;
	TypeIR  * Ptr1 = NULL;
	TypeIR  * Ptr = NULL;

    /*检查数组上界是否小于下界*/
	if ((t->attr.ArrayAttr.low)>( t->attr.ArrayAttr.up))
	{
		ErrorPrompt(t->lineno,"","array subscript error!\n");
		Error = TRUE;
	}
	else
	{
		Ptr0 = TypeProcess(t,IntegerK);			
								/*调用类型分析函数,处理下标类型*/
		Ptr1 = TypeProcess(t,t->attr.ArrayAttr.childtype);
								/*调用类型分析函数,处理元素类型*/
		Ptr = NewTy(arrayTy);    
								/*指向一新创建的类型信息表*/
		Ptr->size = ((t->attr.ArrayAttr.up)-(t->attr.ArrayAttr.low)+1)*(Ptr1->size);
								/*计算本类型长度*/

		/*填写其他信息*/
		Ptr->More.ArrayAttr.indexTy = Ptr0;
		Ptr->More.ArrayAttr.elemTy = Ptr1;
		Ptr->More.ArrayAttr.low = t->attr.ArrayAttr.low;
		Ptr->More.ArrayAttr.up = t->attr.ArrayAttr.up;
	}
	return Ptr;				
}


/************************************************************/
/* 函数名  recordType                                       */
/* 功  能  该函数处理记录类型的内部表示                     */
/* 说  明  类型为记录类型时,是由记录体组成的。其内部节点需 */
/*		   要包括3个信息:一是空间大小size;二是类型种类标志 */
/*		   recordTy;三是体部分的节点地址body。记录类型中的  */
/*		   域名都是标识符的定义性出现,因此需要记录其属性。 */
/************************************************************/	
Cglobal::TypeIR * Canalyze::recordType(TreeNode * t)
{
	TypeIR  * Ptr=NewTy(recordTy);  /*新建记录类型的节点*/
	
	t = t->child[0];                /*从语法数的儿子节点读取域信息*/


    fieldChain  *  Ptr2 = NULL;
	fieldChain  *  Ptr1 = NULL;

	fieldChain  *  body = NULL;

	while (t != NULL)				/*循环处理*/
	{
		/*填写ptr2指向的内容节点*
		 *此处循环是处理此种情况int a,b; */
		for(int i=0 ; i < t->idnum ; i++)
		{     
			/*申请新的域类型单元结构Ptr2*/  
	        Ptr2 = NewBody();            
			if(body == NULL)
				body = Ptr1 = Ptr2;
			
			/*填写Ptr2的各个成员内容*/
			strcpy(Ptr2->id,t->name[i]);
			Ptr2->UnitType = TypeProcess(t,t->kind.dec);
			
			Ptr2->Next = NULL;			 
	    
			/*如果Ptr1!=Ptr2,那么将指针后移*/
			if(Ptr2 != Ptr1)          
			{
				/*计算新申请的单元off*/
				Ptr2->off = (Ptr1->off) + (Ptr1->UnitType->size);
				Ptr1->Next = Ptr2;
				Ptr1 = Ptr2;
			}
		}
		/*处理完同类型的变量后,取语法树的兄弟节点*/
		t = t->sibling;
	}
	
	/*处理记录类型内部结构*/
	
	/*取Ptr2的off为最后整个记录的size*/
	Ptr->size = Ptr2->off + (Ptr2->UnitType->size);
	/*将域链链入记录类型的body部分*/   
    Ptr->More.body = body;   

	return Ptr;
}



/************************************************************/



/*********************声明的语义分析*************************/

/************************************************************/
/* 函数名  TypeDecPart                                      */
/* 功  能  该函数处理类型声明的语义分析                     */
/* 说  明  遇到类型T时,构造其内部节点TPtr;对于"idname=T"构*/
/*		   造符号表项;检查本层类型声明中是否有重复定义错误.*/
/************************************************************/
void Canalyze::TypeDecPart(TreeNode * t)
{
	int present = FALSE;

	AttributeIR  attrIr;

	SymbTable * entry = NULL;
	
	/*添属性作为参数*/
	attrIr.kind = typeKind; 
		
	/*遍历语法树的兄弟节点*/
	while (t!=NULL)   
	{
		/*调用记录属性函数,返回是否重复声明错和入口地址*/
		present = Enter(t->name[0],&attrIr,&entry);	
	
		if (present!=FALSE)
		{
			ErrorPrompt(t->lineno,t->name[0],"is repetation declared!\n");
			entry = NULL;
		}
		else 
			entry->attrIR.idtype = TypeProcess(t,t->kind.dec);
		t = t->sibling;
	}
}


/************************************************************/
/* 函数名  VarDecPart                                       */
/* 功  能  该函数处理变量声明的语义分析                     */
/* 说  明  调用变量处理分析函数                             */
/************************************************************/
void Canalyze::VarDecPart(TreeNode * t)
{
	 varDecList(t);
}

/************************************************************/
/* 函数名  varDecList                                       */
/* 功  能  该函数处理变量声明的语义分析                     */
/* 说  明  当遇到变量表识符id时,把id登记到符号表中;检查重 */
/*         复性定义;遇到类型时,构造其内部表示。           */
/************************************************************/
void  Canalyze::varDecList(TreeNode * t)
{
	AttributeIR  attrIr;
	int present = FALSE;

	SymbTable * entry = NULL;
	
	while(t!=NULL)	/*循环过程*/
	{
		attrIr.kind = varKind;
		for(int i=0;i<(t->idnum);i++)
		{
			attrIr.idtype = TypeProcess(t,t->kind.dec);
			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -