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

📄 analyze.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/****************************************************/
/* 文件 analyze.cpp				  					*/
/* 说明 类PASCAL语言编译器语义分析程序  			*/
/* 主题 编译器结构:原理和实例						*/	
/****************************************************/

/***********  该文件所包含的头文件  ****************/

#include "globals.h"	

#include "util.h"

#include "symbTable.h"		

#include "scanner.h"	

#include "parse.h"

#include "analyze.h"		

#include "string.h"

/*scope栈的层数*/
int Level=-1;

/*在同层的变量偏移*/
int Off;

/*主程序的noff偏移*/
int mainOff;


SymbTable * scope[SCOPESIZE];   /*scope栈*/

TypeIR * intPtr = NULL;			/*该指针一直指向整数类型的内部表示*/

TypeIR * charPtr = NULL;		/*该指针一直指向字符类型的内部表示*/
	
TypeIR * boolPtr = NULL;		/*该指针一直指向布尔类型的内部表示*/

static TypeIR * arrayVar(TreeNode * t);
								/*该函数用于处理数组类型变量*/

static TypeIR * recordVar(TreeNode * t);
								/*该函数用于处理记录类型变量*/

/***********************类型处理*****************************/



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

	charPtr = NewTy(charTy);

	boolPtr = NewTy(boolTy);

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

/************************************************************/
/* 函数名  TypeProcess                                      */
/* 功  能  该函数用来完成类型分析的工作                     */
/* 说  明  处理语法树的当前结点类型。构造出当前类型的内部表 */
/*         示,并将其地址返回给Ptr类型内部表示的地址.       */
/************************************************************/
TypeIR  * 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,则发生无声明错误。*/
/*         如果符号表中的该标识符的属性信息不是类型,则非类 */
/*         型标识符。该函数返回指针指向符号表中的该标识符的 */
/*	       类型内部表示。								    */
/************************************************************/
TypeIR * 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                                        */
/* 功  能  该函数处理数组类型的内部表示                     */
/* 说  明  类型为数组类型时,需要检查下标是否合法。         */
/************************************************************/
TypeIR  * 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。记录类型中的  */
/*		   域名都是标识符的定义性出现,因此需要记录其属性。 */
/************************************************************/	
TypeIR * 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 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 VarDecPart(TreeNode * t)
{
	 varDecList(t);
}

/************************************************************/
/* 函数名  varDecList                                       */
/* 功  能  该函数处理变量声明的语义分析                     */
/* 说  明  当遇到变量表识符id时,把id登记到符号表中;检查重 */
/*         复性定义;遇到类型时,构造其内部表示。           */
/************************************************************/
void  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);
			
			/*判断识值参还是变参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;
	}

⌨️ 快捷键说明

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