📄 semant.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 + -