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

📄 semant.java

📁 tiger编译器的Java实现
💻 JAVA
字号:
package Semant;

import java.util.ArrayList;

import Translate.*;

public class Semant {
Env env;

public Semant(ErrorMsg.ErrorMsg err,String t){this(new Env(err,t));}
Semant(Env e){env=e;}
ExpTy transVar(Absyn.Var var)
{
	return null;
}
public ExpTy transExp(Absyn.Exp exp)
{
	
	if(exp instanceof Absyn.VarExp)
		return transExp((Absyn.VarExp)exp);
	if(exp instanceof Absyn.IntExp)
		return transExp((Absyn.IntExp)exp);
	if(exp instanceof Absyn.StringExp)
		return transExp((Absyn.StringExp)exp);
	if(exp instanceof Absyn.NilExp)
		return transExp((Absyn.NilExp)exp);
	if(exp instanceof Absyn.CallExp)
		return transExp((Absyn.CallExp)exp);
	if(exp instanceof Absyn.OpExp)
		return transExp((Absyn.OpExp)exp);
	if(exp instanceof Absyn.IfExp)
		return transExp((Absyn.IfExp)exp);
	if(exp instanceof Absyn.WhileExp)
		return transExp((Absyn.WhileExp)exp);
	if(exp instanceof Absyn.ForExp)
		return transExp((Absyn.ForExp)exp);
	if(exp instanceof Absyn.ArrayExp)
		return transExp((Absyn.ArrayExp)exp);
	if(exp instanceof Absyn.RecordExp)
			return transExp((Absyn.RecordExp)exp);
	if(exp instanceof Absyn.AssignExp)
		return transExp((Absyn.AssignExp)exp);
	if(exp instanceof Absyn.LetExp)
		return transExp((Absyn.LetExp)exp);
	if(exp instanceof Absyn.SeqExp)
		return transExp((Absyn.SeqExp)exp);
	env.error(exp.pos, "unknown exp");
	return new ExpTy(null,new Types.VOID());
}
ExpTy transExp(Absyn.CallExp exp)
{
	Entry e=(Entry)env.venv.get(exp.func);
	//System.out.println("-------------------call "+exp.func);
	if(e==null)
	{
		env.error(exp.pos, "function ["+exp.func+"] is not defined");
		return new ExpTy(null,new Types.VOID());
	}
	if(e instanceof FunEntry){
		FunEntry fe=(FunEntry)e;
	Types.RECORD tr=fe.formals;
	Types.RECORD i=tr;Absyn.ExpList el=exp.args;
	
	int index=0;
	for(;i!=null && el!=null;i=i.tail,el=el.tail)
	{
		index++;
		ExpTy ty=transExp(el.head);
		if(!ty.ty.coerceTo(i.fieldType))
		{
			env.error(exp.pos, "function parameter [index:"+index+"] is not matched");
		}	
	}
	if(!(i==null && el==null))
		env.error(exp.pos, "function parameter number is not matched");
	return new ExpTy(null,fe.result);
	}else 
		{
		env.error(exp.pos, "unknown function call");
		return new ExpTy(null,((VarEntry)e).ty);
		}
}
ExpTy transExp(Absyn.OpExp exp)
{
	ExpTy left,right;
	switch(exp.oper)
	{
	case Absyn.OpExp.UMINUS:
		right=transExp(exp.right);
		if(!(right.ty instanceof Types.INT ))
		    env.error(exp.pos, "oper["+getOperName(exp.oper)+"]integer required");
		break;
	case Absyn.OpExp.EQ:
	case Absyn.OpExp.NE:
		left=transExp(exp.left);
		right=transExp(exp.right);
		if(!left.ty.coerceTo(right.ty))
		{
			if(!(left.ty instanceof Types.NIL ||right.ty instanceof Types.NIL))
			{
				env.error(exp.pos, "oper["+getOperName(exp.oper)+"] variable type is not suitble!");
			}
		}
		break;
		default:
		left=transExp(exp.left);
		right=transExp(exp.right);
		if(!(left.ty instanceof Types.INT ) || !(right.ty instanceof Types.INT ))
		{
			env.error(exp.pos, "oper["+getOperName(exp.oper)+"]integer required");
		}
			break;
	}
	return new ExpTy(null,new Types.INT());
}
String getOperName(int t)
{
	switch(t)
	{
	case Absyn.OpExp.AND:
		return "&";
	case Absyn.OpExp.DIV:
		return "/";
	case Absyn.OpExp.EQ:
		return "=";
	case Absyn.OpExp.GE:
		return ">=";
	case Absyn.OpExp.GT:
		return ">";
	case Absyn.OpExp.LE:
		return "<=";
	case Absyn.OpExp.LT:
		return "<=";
	case Absyn.OpExp.MINUS:
		return "-";
	case Absyn.OpExp.MUL:
		return "*";
	case Absyn.OpExp.NE:
		return "<>";
	case Absyn.OpExp.OR:
		return "|";
	case Absyn.OpExp.PLUS:
		return "+";
	case Absyn.OpExp.UMINUS:
		return "u-";
		default:
			return "unknown oper";
	}
}
ExpTy transExp(Absyn.VarExp exp)
{
		return (transExp(exp.var));
}
ExpTy transExp(Absyn.Var exp)
{
	if(exp instanceof Absyn.SimpleVar)
		return (transExp((Absyn.SimpleVar)exp));
	if(exp instanceof Absyn.SubscriptVar)
		return (transExp((Absyn.SubscriptVar)exp));
	if(exp instanceof Absyn.FieldVar)
		return (transExp((Absyn.FieldVar)exp));
	return new ExpTy(null,new Types.INT());
}
ExpTy transExp(Absyn.SimpleVar exp)
{
	Entry x=(Entry)env.venv.get(exp.name);
	if(x instanceof VarEntry)
	{
		VarEntry ent = (VarEntry)x;
		return new ExpTy(null,ent.ty);
	}else{
		env.error(exp.pos, "undefined variable ["+exp.name+"]");
	return new ExpTy(null,new Types.INT());
	}
}
ExpTy transExp(Absyn.SubscriptVar exp)
{
	ExpTy r=transExp(exp.var);
	Types.Type n=r.ty;
	if(r.ty instanceof Types.NAME) n=r.ty.actual();
	if(!(n instanceof Types.ARRAY))
		env.error(exp.pos, "variable is not an array");
	ExpTy t=transExp(exp.index);
	if(!(t.ty instanceof Types.INT))
		env.error(exp.pos, "array index must be an integer");
	if(!(n instanceof Types.ARRAY))
		return  new ExpTy(null,n);
	else 
		return new ExpTy(null,((Types.ARRAY)n).element);
}
ExpTy transExp(Absyn.FieldVar exp)
{
	ExpTy t=transExp(exp.var);
	if(t.ty instanceof Types.NAME)
	{
		Types.RECORD r=(Types.RECORD)t.ty.actual();
		for(;r!=null;r=r.tail)
		{
			if(r.fieldName.equals(exp.field))
			{
				break;
			}
		}
		if(r==null)
			env.error(exp.pos, "["+exp.field+"] is not a member");
		else
			return new ExpTy(null,r.fieldType);
	}else
		env.error(exp.pos, "it is not a lvalue");

	return new ExpTy(null,new Types.VOID());
}
ExpTy transExp(Absyn.IntExp exp)
{
	return new ExpTy(null,new Types.INT());
}
ExpTy transExp(Absyn.NilExp exp)
{
	return new ExpTy(null,new Types.NIL());
}
ExpTy transExp(Absyn.StringExp exp)
{
	return new ExpTy(null,new Types.STRING());
}
ExpTy transExp(Absyn.IfExp exp)
{
	ExpTy et=transExp(exp.test);
	if(!(et.ty instanceof Types.INT))
		env.error(exp.pos, "if case must be an integer");
	ExpTy et1=transExp(exp.thenclause);
	if(exp.elseclause!=null)
	{
		  ExpTy et2=transExp(exp.elseclause);
		  if(!et1.ty.coerceTo(et2.ty))
		  {
			  if(!(et1.ty instanceof Types.NIL || et2.ty instanceof Types.NIL))
		     env.error(exp.pos, "if then exp must be same type");
		  }
	}
	return et1;
}
ExpTy transExp(Absyn.WhileExp exp)
{
	ExpTy et=transExp(exp.test);
	if(!(et.ty instanceof Types.INT))
		env.error(exp.pos, "while case must be an integer");
	transExp(exp.body);
	return new ExpTy(null,new Types.VOID());//et1;
}
ExpTy transExp(Absyn.ForExp exp)
{
	env.venv.beginScope();
	transDec(exp.var);
	
	Entry e=(Entry)env.venv.get(exp.var.name);
	if(!(e instanceof VarEntry))
	{
		env.error(exp.pos, "["+exp.var.name+"] must be a variable");
	}else
	{
		if(!(((VarEntry)e).ty instanceof Types.INT))
			env.error(exp.pos, "["+exp.var.name+"] must be an integer");
	}
	ExpTy et=transExp(exp.hi);
	if(!(et.ty instanceof Types.INT))
		env.error(exp.pos, "for to must be an integer");
	transExp(exp.body);
	env.venv.endScope();
	return new ExpTy(null,new Types.VOID());//et1;
}
ExpTy transExp(Absyn.BreakExp exp)
{
	return new ExpTy(null,new Types.VOID());
}
ExpTy transExp(Absyn.AssignExp exp)
{
	ExpTy et1=transExp(exp.exp);
	ExpTy et2=transExp(exp.var);
	if(!et1.ty.coerceTo(et2.ty))
		env.error(exp.pos, "assign different type");
	return et2;
}
ExpTy transExp(Absyn.ArrayExp exp)
{
	ExpTy et=transExp(exp.size);
	if(!(et.ty instanceof Types.INT))
		env.error(exp.pos, "array index must be an integer");
	Types.Type t=(Types.Type)env.tenv.get(exp.typ);
    if(!(t instanceof Types.NAME) || !(t.actual() instanceof Types.ARRAY))
	{
		env.error(exp.pos, "["+exp.typ+"]is not an array");
		return et;
	}
	Types.Type a=t;
	if(t instanceof Types.NAME)a=t.actual();
	if(a instanceof Types.ARRAY)
	if(!((Types.ARRAY)a).element.coerceTo(transExp(exp.init).ty))
	{
		env.error(exp.pos, "array inital value type and element type is not same");
	}
	return new ExpTy(null,a);
}

ExpTy transExp(Absyn.RecordExp exp)
{
	Types.Type e=(Types.Type)env.tenv.get(exp.typ);
	if(e instanceof Types.NAME)
	{
		Types.RECORD r=(Types.RECORD)e.actual();
		Absyn.FieldExpList f=exp.fields;
		//if(f==null)env.error(exp.pos, "["+exp.typ+"]is not an array");
		for(;r!=null&&f!=null;r=r.tail,f=f.tail)
		{
				if(!f.name.equals(r.fieldName))
					env.error(exp.pos, "undefined feild ["+f.name+"]");
				Types.Type t=r.fieldType;
				if(r.fieldType instanceof Types.NAME)
					t=((Types.NAME)r.fieldType).actual();
				if(!t.coerceTo(transExp(f.init).ty) &&
						!(transExp(f.init).ty instanceof Types.NIL))
					env.error(exp.pos, "unmatched type ["+r.fieldName+"]");
		}
		if(r!=null || f!=null)
			env.error(exp.pos, "unmatched type");
			
		return new ExpTy(null,e);
	}else
	{
		env.error(exp.pos, "undefined type ["+exp.typ+"]");
	}
	return new ExpTy(null,new Types.VOID());
}
ExpTy transExp(Absyn.SeqExp exp)
{
   if(exp==null || exp.list==null)
	   return new ExpTy(null,new Types.VOID());
        ExpTy t = null;
		for(Absyn.ExpList s=exp.list;s!=null;s=s.tail)
		{
			t=transExp(s.head);
		}
		
		return t;

	//return transExp(exp.list.head);
}

ExpTy transExp(Absyn.LetExp exp)
{
	env.venv.beginScope();
	env.tenv.beginScope();

	for(Absyn.DecList p=exp.decs;p!=null;p=p.tail)
	{
		transDec(p.head);
	}

	
	ExpTy t=transExp(exp.body);
	env.venv.endScope();
	env.tenv.endScope();
	return new ExpTy(null,t.ty);
}


Exp transDec(Absyn.VarDec dec)
{
	ExpTy t=transExp(dec.init);

	if(dec.typ !=null)
	{
		Types.Type t1=transTy(dec.typ);
		if(t1 instanceof Types.NAME)t1=t1.actual();
		
		if(!t.ty.coerceTo(t1))
		{
			if((!(t1 instanceof Types.NAME)||!(t1 instanceof Types.NAME))
					&& !(t.ty instanceof Types.NIL) )
			{
				env.error(dec.pos, "type is not matched");
			}
		}
	}
	else
		if(t.ty instanceof Types.NIL)
			env.error(dec.pos, "variable ["+dec.name+"] initialed as nil");
	env.venv.put(dec.name, new VarEntry(transExp(dec.init).ty));
	return null;
}

Exp transDec(Absyn.TypeDec dec)
{
	 ArrayList<String> list =new ArrayList<String>();
   for(Absyn.TypeDec d=dec;d!=null;d=d.next)
   {
	   
	   if(list.contains(d.name.toString()))
		    env.error(d.pos, "type ["+d.name+"] already defined");
	   list.add(d.name.toString());
		env.tenv.put(d.name,new Types.NAME(d.name));
   }
   list.clear();
   for(Absyn.TypeDec d=dec;d!=null;d=d.next)
   {
		if(d.ty==null)
			((Types.NAME)env.tenv.get(d.name)).bind(new Types.NAME(d.name));
		else
		((Types.NAME)env.tenv.get(d.name)).bind(transTy(d.ty));
   }
   for(Absyn.TypeDec d=dec;d!=null;d=d.next)
		if(((Types.NAME)env.tenv.get(d.name)).isLoop())
			 env.error(d.pos, "type ["+d.name+"] is undefined");
	
   for(Absyn.TypeDec d=dec;d!=null;d=d.next)
		if(((Types.NAME)env.tenv.get(d.name)).isLoop())
			((Types.NAME)env.tenv.get(d.name)).bind(new Types.VOID());

	return null;
}

Exp transDec(Absyn.FunctionDec dec)
{
	 ArrayList<String> list =new ArrayList<String>();
	for(Absyn.FunctionDec d=dec;d!=null;d=d.next)
	{
	Types.Type re=transTy(d.result);
	Types.RECORD rc=transTypeFeilds(d.params);
		
	if(list.contains(d.name.toString()))
		env.error(d.pos, "function ["+d.name+"] already defined");	
	list.add(d.name.toString());
	
	env.venv.put(d.name, new FunEntry(rc,re));
	}
	list.clear();
   
	for(Absyn.FunctionDec d=dec;d!=null;d=d.next)
	{
		//System.out.println("\n+++++++++++++++++++");
		 env.venv.beginScope();
		 
		Types.Type re=transTy(d.result);
		
		list.clear();
		for(Absyn.FieldList f=d.params;f!=null;f=f.tail)
		{
			if(list.contains(f.name.toString()))
				env.error(d.pos, "function parameter ["+f.name+"] already defined ");
	
			list.add(f.name.toString());
			Types.Type ty=(Types.Type)env.tenv.get(f.typ);
			if(ty==null)
				env.error(d.pos, "undefined type ["+f.typ+"]");
	
			env.venv.put(f.name, new VarEntry(ty));
			//System.out.println(f.name+" funciotn para+++++++++++++++++++");
		}
		//System.out.println("+++++++++++++++++++trans "+((Absyn.SeqExp)d.body).list.tail.head.getClass());
		if(!re.actual().coerceTo(transExp(d.body).ty.actual()))
			env.error(d.pos, "function return type is not matched");
		
		env.venv.endScope();//System.out.println("+++++++++++++++++++\n");
	}
	
	//for(Absyn.FunctionDec d=dec;d!=null;d=d.next)
	//{
		
	//}
	return null;
}
Types.RECORD transTypeFeilds(Absyn.FieldList dec)
{
	if(dec==null)return null;
	Types.RECORD rc=new Types.RECORD(dec.name,(Types.Type)env.tenv.get(dec.typ),null);
	Types.RECORD tmp=null;
	tmp=rc;
	for(Absyn.FieldList f=dec.tail;f!=null;f=f.tail)
	{
		rc.tail=new Types.RECORD(f.name,(Types.Type)env.tenv.get(f.typ),null);
		rc=rc.tail;
	}
	return tmp;
}
Exp transDec(Absyn.Dec dec)
{
	if(dec instanceof Absyn.FunctionDec)
		return transDec((Absyn.FunctionDec)dec);
	if(dec instanceof Absyn.TypeDec)
		return transDec((Absyn.TypeDec)dec);
	if(dec instanceof Absyn.VarDec)
		return transDec((Absyn.VarDec)dec);
	env.error(dec.pos, "unknow declare");
	return null;
}
Types.Type transTy(Absyn.Ty ty)
{
	if(ty instanceof Absyn.RecordTy)
		{
		return transTy((Absyn.RecordTy) ty);
		}
	if(ty instanceof Absyn.ArrayTy)
	{
	return transTy((Absyn.ArrayTy) ty);
	}
	if(ty instanceof Absyn.NameTy)
	{
	return transTy((Absyn.NameTy) ty);
	}
	env.error(ty.pos, "unknow type");
	return null;
}
Types.Type transTy(Absyn.RecordTy ty)
{
	Types.RECORD rc=null,tmp=null;
	if(env.tenv.get(ty.fields.typ)==null)
		env.error(ty.pos, "undefined type ["+ty.fields.typ+"]");
	rc=new Types.RECORD(ty.fields.name,(Types.Type)env.tenv.get(ty.fields.typ),null);
	ArrayList<String>list=new ArrayList<String>();
	list.add(ty.fields.name.toString());
	tmp=rc;
	env.venv.beginScope();

	for(Absyn.FieldList f=ty.fields.tail;f!=null;f=f.tail)
	{
		if(list.contains(f.name.toString()))
			env.error(ty.pos, "feild ["+f.name+"] already defined");
		else list.add(f.name.toString());

		Types.Type t=(Types.Type)env.tenv.get(f.typ);
		if(t==null)
		{
			env.error(ty.pos, "undefined type ["+f.typ+"]");
		}
		
		env.venv.put(f.name, new VarEntry(t));
		tmp.tail=new Types.RECORD(f.name,t,null);
		tmp=tmp.tail;
	}
	env.venv.endScope();
     
     return rc;
}
Types.Type transTy(Absyn.ArrayTy ty)
{
	Types.Type t=(Types.Type)env.tenv.get(ty.typ); 
	if(t==null)env.error(ty.pos, "undefined type ["+ty.typ+"]");
	return new Types.ARRAY(t);
}
Types.Type transTy(Absyn.NameTy ty)
{
	if(ty==null)
		return new Types.VOID();
	Types.Type t=(Types.Type)env.tenv.get(ty.name);

	return t;
}


}

⌨️ 快捷键说明

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