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

📄 analyuyi.java

📁 这是编译原理的语义分析器的java代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* 说  明  处理一个声明节点中声明的所有标识符,	    */	
/*	   将相关信息添入符号表中,若是形参,还要   */
/*	   构造一个参数信息表,各个标识符在符号表的 */
/*	   位置存储在表中,返回参数表的表头指针     */					
/****************************************************/
void varDecList(TreeNode t)
{ 
    boolean present = false;
    SymbTable  Entry=new SymbTable();
    /*纪录变量的属性*/
    AttributeIR Attrib=new AttributeIR();

    while(t!=null)	/*循环过程*/
    {
	Attrib.kind="varkind";  
	for(int i=0;i<(t.idnum);i++)
	{
	    Attrib.idtype=TYPEA(t,t.kind);
			
	    /*判断识值参还是变参acess(dir,indir)*/	
	    if((t.attr.procAttr!=null)&&(t.attr.procAttr.paramt.equals("varparamType")))
	    {
                Attrib.var = new Var();
		Attrib.var.access = "indir";
		Attrib.var.level = Level;
		/*计算形参的偏移*/
				
		Attrib.var.off = Off;
		Off = Off+1;
	    }/*如果是变参,则偏移加1*/
	    else
	    {
                Attrib.var = new Var();
		Attrib.var.access = "dir";
		Attrib.var.level = Level;
		/*计算值参的偏移*/
		if(Attrib.idtype.size!=0)				
		{
		    Attrib.var.off = Off;
		    Off = Off + (Attrib.idtype.size);
		}
	    }/*其他情况均为值参,偏移加变量类型的size*/
			
	    /*登记该变量的属性及名字,并返回其类型内部指针*/
	    present = Enter(t.name[i],Attrib,Entry);	
	    if(present)
	        AnalyzeError(t," id repeat  declaration ",t.name[0]);
	    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;
} 
/****************************************************/
/* 函数名  procDecPart				    */
/* 功  能  一个过程声明的语义分析  		    */
/* 说  明  处理过程头,声明,过程体		    */	
/****************************************************/
void procDecPart(TreeNode t)
{ 
    TreeNode p =t;
    SymbTable entry = HeadProcess(t);   /*处理过程头*/
		
    t = t.child[1];
    /*如果过程内部存在声明部分,则处理声明部分*/	
    while (t!=null) 
    {
	if ( t.nodekind.equals("TypeK") ) 
	    TypeDecPart(t.child[0]); 
        else if ( t.nodekind.equals("VarK") )  
            VarDecPart(t.child[0]);  

	/*如果声明部分有函数声明,则跳出循环,先填写noff和moff等信息,*
	*再处理函数声明的循环处理,否则无法保存noff和moff的值。      */
	else if ( t.nodekind.equals("ProcDecK") )  {}
	else
	    AnalyzeError(t,"no this node kind in syntax tree!",null);
				
	if(t.nodekind.equals("ProcDecK"))
            break;
	else
            t=t.sibling ;
    }
    entry.attrIR.proc.nOff = savedOff;
    entry.attrIR.proc.mOff = entry.attrIR.proc.nOff + entry.attrIR.proc.level+1;
    /*过程活动记录的长度等于nOff加上display表的长度*
    *diplay表的长度等于过程所在层数加一           */

    /*处理程序的声明部分*/
    while(t!=null)
    {
	procDecPart(t);
	t = t.sibling;
    }
    t = p;
    BodyA(t.child[2]);/*处理Block*/

    /*函数部分结束,删除进入形参时,新建立的符号表*/
    if ( Level!=-1)
	DestroySymbTable();/*结束当前scope*/
}
/****************************************************/
/* 函数名  HeadProcess				    */
/* 功  能  形参处理函数         		    */
/* 说  明  循环处理各个节点,并将处理每个节点得到   */
/*	   的参数表连接起来,组成整个形参链表,返回 */
/*         这个表的指针				    */	
/****************************************************/
SymbTable HeadProcess(TreeNode t)
{ 
    AttributeIR attrIr = new AttributeIR();
    boolean present = false;
    SymbTable entry = new SymbTable();
		
    /*填属性*/
    attrIr.kind = "prockind";
    attrIr.idtype = null; 
    attrIr.proc = new Proc();
    attrIr.proc.param = new ParamTable();
    attrIr.proc.level = Level+1;	
	
    if(t!=null)
    {
	/*登记函数的符号表项*/		
	present = Enter(t.name[0],attrIr,entry);
	t.table[0] = entry;
	/*处理形参声明表*/
    }
    entry.attrIR.proc.param = ParaDecList(t);

    return entry;
}   
/****************************************************/
/* 函数名  ParaDecList				    */
/* 功  能  处理一个形参节点        		    */
/* 说  明  根据参数是形参还是变参,分别调用变量声明 */
/*	   节点的处理函数,另一个实参是Add,表示处理*/
/*	   的是函数的形参。			    */	
/****************************************************/
ParamTable 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];   	/*程序声明节点的第一个儿子节点*/
	
	CreatSymbTable();		/*进入新的局部化区*/
	Off = 7;                /*子程序中的变量初始偏移设为8*/

	VarDecPart(p);			/*变量声明部分*/

	SymbTable Ptr0 = scope[Level];      		 
                                    
	while(Ptr0 != null)         /*只要不为空,就访问其兄弟节点*/
	{
	    /*构造形参符号表,并使其连接至符号表的param项*/
	    Ptr2 = new ParamTable();
	    if(head == null)
            {
		head = Ptr2;
                Ptr1 = Ptr2;
            }
	    //Ptr0.attrIR.var.isParam = true;
	    copy(Ptr2.entry,Ptr0);
			
	    if(Ptr2 != Ptr1)          
	    {
		Ptr1.next = Ptr2;
		Ptr1 = Ptr2;
	    }
	    Ptr0 = Ptr0.next;
	}
    }
    return head;   /*返回形参符号表的头指针*/
}
/****************************************************/
/* 函数名  BodyA				    */
/* 功  能  语句序列处理函数        		    */
/* 说  明  用于处理过程体或者程序体,		    */
/*	  循环处理各个语句			    */	
/****************************************************/
void BodyA(TreeNode t)
{  
    /*令指针指向第一条语句*/
    if (t.nodekind.equals("StmLK"))
	t=t.child[0];

    /*处理语句序列*/
    while (t!=null)
    { 
        /*调用语句处理函数*/
	StatementA(t);
        t= t.sibling;
    }
}
/****************************************************/
/* 函数名  StatementA				    */
/* 功  能  语句处理函数	        		    */
/* 说  明  根据语句的具体类型,分别调用相应的       */
/*	   语句处理函数				    */
/****************************************************/
void StatementA(TreeNode t) 
{  
    if (t.kind.equals("AssignK"))
	AssignSA(t);  
    else if (t.kind.equals("CallK"))      
        CallSA(t);   
    else if (t.kind.equals("ReadK"))     
        ReadSA(t);    
    else if (t.kind.equals("WriteK"))     
        WriteSA(t);	 
    else if (t.kind.equals("IfK"))     
        IfSA(t);	  
    else if (t.kind.equals("WhileK"))	
        WhileSA(t);	  
    else if (t.kind.equals("ReturnK")) 	
        ReturnSA(t);  
    else
        AnalyzeError(t," bug:no this statement in syntax tree ",null);	
}
/****************************************************/
/* 函数名  AssignSA				    */
/* 功  能  赋值语句处理函数	       		    */
/* 说  明  检查左部标识符,调用表达式处理函数,	    */	
/*	   并检查标识符未声明错,非期望标识符错,   */
/*	   赋值不兼容错				    */
/****************************************************/
void AssignSA(TreeNode t)
{ 
    SymbTable entry = new SymbTable();
	
    boolean present = false;
    TypeIR ptr = null;
    TypeIR Eptr = null;
	
    TreeNode child1;
    TreeNode child2;

    child1 = t.child[0];
    child2 = t.child[1];

    if(child1.child[0]==null)
    {	
	/*在符号表中查找此标识符*/
	present = FindEntry(child1.name[0],entry);
		
	if(present)
	{   /*id不是变量*/
            if (!(entry.attrIR.kind.equals("varkind")))
	    {				
                AnalyzeError(t," left and right is not compatible in assign ",null);				                      Eptr = null;
	    }
	    else
            {
	        Eptr = entry.attrIR.idtype;
		child1.table[0] = entry;
            }
	} 
	else /*标识符无声明*/
	    AnalyzeError(t,"is not declarations!",child1.name[0]);
	}
	else/*Var0[E]的情形*/
	{	
            if(child1.attr.expAttr.varkind.equals("ArrayMembV"))
		Eptr = arrayVar(child1);	
	    else /*Var0.id的情形*/
		if(child1.attr.expAttr.varkind.equals("FieldMembV"))
		    Eptr = recordVar(child1);
	}
	if(Eptr != null)
	{	
	    if((t.nodekind.equals("StmtK"))&&(t.kind.equals("AssignK")))
	    {
		/*检查是不是赋值号两侧 类型等价*/
		ptr = Expr(child2,null);
		if (!Compat(ptr,Eptr)) 
		    AnalyzeError(t,"ass_expression error!",child2.name[0]);
	    }
	    /*赋值语句中不能出现函数调用*/
	}
}
/***********************************************************/
/* 函数名 Compat                                           */
/* 功  能 判断类型是否相容                                 */
/* 说  明 由于TINY语言中只有整数类型、字符类型、数组类型和 */
/*        记录类型,故类型相容等于类型等价,只需判断每个结 */
/*        构类型的内部表示产生的指针值是否相同即可。       */
/***********************************************************/
boolean Compat(TypeIR tp1,TypeIR tp2)
{
    boolean  present; 
    if (tp1!=tp2)
	present = false;  /*类型不等*/
    else
	present = true;   /*类型等价*/
    return present;
}

/************************************************************/
/* 函数名  Expr                                             */
/* 功  能  该函数处理表达式的分析                           */
/* 说  明  表达式语义分析的重点是检查运算分量的类型相容性, */
/*         求表达式的类型。其中参数Ekind用来表示实参是变参  */
/*         还是值参。    	                            */
/************************************************************/
TypeIR Expr(TreeNode t,String Ekind)
{
    boolean present = false;
    SymbTable entry = new SymbTable();

    TypeIR Eptr0=null;
    TypeIR Eptr1=null;
    TypeIR Eptr = null;
    if(t!=null)
    {
        if(t.kind.equals("ConstK"))
        { 
	    Eptr = intptr;
	    Eptr.kind = "intTy";
	    if(Ekind!=null)
	        Ekind = "dir";   /*直接变量*/ 
        }
        else if(t.kind.equals("VariK"))
        {
	    /*Var = id的情形*/
	    if(t.child[0]==null)
	    {	
		/*在符号表中查找此标识符*/
		present = FindEntry(t.name[0],entry);				
		t.table[0] = entry;

		if(present)
		{   /*id不是变量*/
		    if (!(entry.attrIR.kind.equals("varkind")))
		    {
			AnalyzeError(t," syntax bug: no this kind of exp ",t.name[0]);				                              Eptr = null;
		    }
		    else
		    {
			Eptr = entry.attrIR.idtype;	
			if (Ekind!=null)
			    Ekind = "indir";  /*间接变量*/						
		    }
		} 
		else /*标识符无声明*/
		    AnalyzeError(t,"is not declarations!",t.name[0]);				
	    }
	    else/*Var = Var0[E]的情形*/
	    {	
                if(t.attr.expAttr.varkind.equals("ArrayMembV"))
		    Eptr = arrayVar(t);	
		/*Var = Var0.id的情形*/
		else if(t.attr.expAttr.varkind.equals("FieldMembV"))
		    Eptr = recordVar(t);
	    }
	}
        else if(t.kind.equals("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)
	    {
		if((t.attr.expAttr.op.equals("LT"))||(t.attr.expAttr.op.equals("EQ")))
		    Eptr = boolptr;
                else if((t.attr.expAttr.op.equals("PLUS"))||(t.attr.expAttr.op.equals("MINUS"))||(t.attr.expAttr.op.equals("TIMES"))||(t.attr.expAttr.op.equals("OVER")))  
		    Eptr = intptr;
                                /*算数表达式*/
		if(Ekind != null)
	            Ekind = "dir"; /*直接变量*/
	    }

⌨️ 快捷键说明

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