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

📄 semant.java

📁 本设计Tiger语言为源语言
💻 JAVA
字号:
package Semant;

import java.util.ArrayList;
import Translate.Exp;



public class Semant {
	Env env;
	public Semant(ErrorMsg.ErrorMsg err){
		this(new Env(err));
	}
	Semant(Env e){env=e;}
	
	public void transProg(Absyn.Exp exp){
		System.out.println("Semant Begin");
		transExp(exp);
	}
	

	public ExpTy transExp(Absyn.Exp exp){
		//VarExp,NilExp,IntExp,StringExp,CallExp,OpExp,RecordExp,SeqExp
		//AssignExp,IfExp,IfExp,WhileExp,ForExp,BreakExp,LetExp,ArrayExp

		if(exp instanceof Absyn.VarExp)		return transExp((Absyn.VarExp)exp);
		if(exp instanceof Absyn.NilExp)		return transExp((Absyn.NilExp)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.CallExp)	return transExp((Absyn.CallExp)exp);
		if(exp instanceof Absyn.OpExp)		return transExp((Absyn.OpExp)exp);
		if(exp instanceof Absyn.RecordExp)	return transExp((Absyn.RecordExp)exp);
		if(exp instanceof Absyn.SeqExp)		return transExp((Absyn.SeqExp)exp);
		if(exp instanceof Absyn.AssignExp)	return transExp((Absyn.AssignExp)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.BreakExp)	return transExp((Absyn.BreakExp)exp);
		if(exp instanceof Absyn.LetExp)		return transExp((Absyn.LetExp)exp);
		if(exp instanceof Absyn.ArrayExp)	return transExp((Absyn.ArrayExp)exp);
		
		env.report_error(exp.pos, "Unknown expression");
		return new ExpTy(null,new Types.VOID());
	}
	
	
	ExpTy transExp(Absyn.VarExp exp){
		return (transExp(exp.var));
	}
	
	ExpTy transExp(Absyn.CallExp exp){
		Entry e=(Entry)env.venv.get(exp.func);
		if(e==null){
			env.report_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.report_error(exp.pos, "function parameter [index:"+index+"] is not matched");
			}	
		}
		if(!(i==null && el==null))
			env.report_error(exp.pos, "function parameter number is not matched");
			return new ExpTy(null,fe.result);
		}else 
			{
			env.report_error(exp.pos, "unknown function call");
			return new ExpTy(null,((VarEntry)e).ty);
			}
	}
	
	ExpTy transExp(Absyn.OpExp exp){
		ExpTy l,r;
		switch(exp.oper){

		case Absyn.OpExp.EQ:
		case Absyn.OpExp.NE:
			l=transExp(exp.left);
			r=transExp(exp.right);
			if(l.ty.coerceTo(r.ty)==false){
				if(!(l.ty instanceof Types.NIL ||r.ty instanceof Types.NIL)){
					env.report_error(exp.pos, "Variable type is not suitble");
				}
			}else if (l.ty instanceof Types.VOID || r.ty instanceof Types.VOID){
				env.report_error(exp.pos, "Variable can\'t be VOID");
			}
			break;
		default:
			l=transExp(exp.left);
			r=transExp(exp.right);
			boolean t1=!(l.ty instanceof Types.INT && r.ty instanceof Types.INT);
			boolean t2=!(l.ty instanceof Types.STRING && r.ty instanceof Types.STRING);
			//System.out.println(t1);
			//System.out.println(t2);
			if(t1&&t2){
				env.report_error(exp.pos, "the type are not both Integer or String");
			}
			break;
		}
		return new ExpTy(null,new Types.INT());
	}

	
	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.report_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.report_error(exp.pos, "variable is not an array");
		ExpTy t=transExp(exp.index);
		if(!(t.ty instanceof Types.INT))
			env.report_error(exp.pos, "array index is not 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.report_error(exp.pos, "("+exp.field+") is not in the Type");
			else
				return new ExpTy(null,r.fieldType);
		}else
			env.report_error(exp.pos, "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.BreakExp exp){
		if (break_num==0) env.report_error(exp.pos, "No While or For expression to break");
		return new ExpTy(null,new Types.VOID());
	}
	ExpTy transExp(Absyn.IfExp exp){
		ExpTy et=transExp(exp.test);
		if(!(et.ty instanceof Types.INT))
			env.report_error(exp.pos, "IF_Exp :is not an integer");
		ExpTy et1=transExp(exp.thenclause);
		if(exp.elseclause!=null){
			ExpTy et2=transExp(exp.elseclause);
			if(!et1.ty.coerceTo(et2.ty)) {
				env.report_error(exp.pos, "if then exp:unmatched type");
			}
		}
		return et1;
	}
	int break_num=0;
	ExpTy transExp(Absyn.WhileExp exp){
		break_num++;
		ExpTy et=transExp(exp.test);
		if(!(et.ty instanceof Types.INT))
			env.report_error(exp.pos, "while exp: is not an integer");
		ExpTy et1 =transExp(exp.body);
		break_num--;

		return new ExpTy(null,new Types.VOID());//et1;
	}
	ExpTy transExp(Absyn.ForExp exp){
		break_num++;
		env.venv.beginScope();
		transDec(exp.var);
		
		Entry e=(Entry)env.venv.get(exp.var.name);
		if(!(e instanceof VarEntry)){
			env.report_error(exp.pos, "("+exp.var.name+") is not a variable");
		}else{
			if(!(((VarEntry)e).ty instanceof Types.INT))
				env.report_error(exp.pos, "("+exp.var.name+") is not an integer");
		}
		ExpTy et=transExp(exp.hi);
		if(!(et.ty instanceof Types.INT))
			env.report_error(exp.pos, "for to is not an integer");
		ExpTy whilebody =transExp(exp.body);

		break_num--;
		env.venv.endScope();
		return new ExpTy(null,new Types.VOID());//et1;
	}


	ExpTy transExp(Absyn.ArrayExp exp){
		ExpTy et=transExp(exp.size);
		Types.Type ty=(Types.Type)env.tenv.get(exp.typ);
	    if(!(ty instanceof Types.NAME && ty.actual() instanceof Types.ARRAY)){
			env.report_error(exp.pos, "("+exp.typ+")is not an array");
			return et;
		}
		if(!(et.ty instanceof Types.INT))
			env.report_error(exp.pos, "array index is not an integer");
		Types.Type a=ty;
		if(ty instanceof Types.NAME)a=ty.actual();
		if(a instanceof Types.ARRAY)
		if(!((Types.ARRAY)a).element.coerceTo(transExp(exp.init).ty)){
			env.report_error(exp.pos, "array inital value type and element type is not the same");
		}
		return new ExpTy(null,a);
	}

	ExpTy transExp(Absyn.AssignExp exp){
		ExpTy e1=transExp(exp.exp);
		ExpTy e2=transExp(exp.var);
		if(!e1.ty.coerceTo(e2.ty))
			env.report_error(exp.pos, "The Expession between := is different type");
		return e2;
	}
	
	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;

			for(;r!=null&&f!=null;r=r.tail,f=f.tail){
				if(!f.name.equals(r.fieldName))
					env.report_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.report_error(exp.pos, "unmatched type ("+r.fieldName+")");
			}
			if(r!=null || f!=null)
				env.report_error(exp.pos, "unmatched type");
				
			return new ExpTy(null,e);
		}else{
			env.report_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;

	}

	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);
	}
	
	ExpTy transVar(Absyn.Var var){
		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.report_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.report_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.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.report_error(dec.pos, "type is not matched");
			}
		}
		else if(t.ty instanceof Types.NIL)
				env.report_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.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.report_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){
			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.report_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.report_error(d.pos, "undefined type ("+f.typ+")");
				env.venv.put(f.name, new VarEntry(ty));
			}
			if(!re.actual().coerceTo(transExp(d.body).ty.actual()))
				env.report_error(d.pos, "function return type is not matched");
			env.venv.endScope();
		}
		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.report_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.report_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.report_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.report_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.report_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.report_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 + -