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

📄 semant.java

📁 编译原理大作业---tiger编译器 包括semant,translate,mipsframe,regalloc等所有phase 懂的人自会知道
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package Semant;import java.util.Vector;public class Semant {   Env env;   public int debflag;   public String recout; // per il debug dei campi del record   // variabile per il controllo del livello annidamento   // dei cicli while o for (per individuare le break legali!)   private int loopDepth = 0;   // LIVELLO CORRENTE   Translate.Level level;   // LIVELLO INIZIALE   Translate.Level levin;   // PER CONVERSIONE IN CODICE INTERMEDIO   public Translate.Translate trans;   // etichetta globale che rappresenta l'etichetta "done"   // del ciclo corrente (se esiste, altrimenti rimane = null)   // a cui saltera' l'istruzione break.   Temp.Label current_done = null;   // TIPI BASE   Types.Type INT;   Types.Type STRING;   Types.Type VOID;   Types.Type NIL;   // costruttori   public Semant(ErrorMsg.ErrorMsg err, Translate.Level lvl,int dflag) {      this(new Env(err,lvl), dflag);      trans = new Translate.Translate(err,lvl.frame,dflag);   }   Semant(Env e, int df) {      env=e;      debflag=df;      INT=e.inttemp;      STRING=e.stringtemp;      VOID=new Types.VOID();      NIL=new Types.NIL();      level=e.lev;      levin=e.lev;   }   // PROGRAMMA   // analisi semantica   public ExpTy transProg(Absyn.Exp exp) {      //stampaDeb(0,"Indirizzo del tipo INT: " + INT);      //stampaDeb(0,"Indirizzo del tipo STRING: " + STRING);      //stampaDeb(0,"Indirizzo del tipo VOID: " + VOID);      //stampaDeb(0,"Indirizzo del tipo NIL: " + NIL );      //stampaDeb(0,"Tabella dei tipi: " + env.tenv);      //stampaDeb(0,"Tabella delle variabili: " + env.venv + "\n");      ExpTy prg = transExp(exp);      if(debflag == 1) {         System.out.println("> Tipo finale del programma: " + nomeClasse(prg.ty));      }      // aggiunge un piccolo pezzo d'albero (utilizza il livello iniziale)      if(env.errorMsg.num_error == 0) prg.exp = trans.transProg(prg.exp, levin, (prg.ty == VOID) );      return prg;   }   /*******************************    *          VARIABILI          *    *******************************/   ExpTy transVar(Absyn.Var v) {      if(v instanceof Absyn.SimpleVar) return transVar((Absyn.SimpleVar)v);      if(v instanceof Absyn.SubscriptVar) return transVar((Absyn.SubscriptVar)v);      if(v instanceof Absyn.FieldVar) return transVar((Absyn.FieldVar)v);      throw new Error("transVar");  // da vedere se mantenere o no.   }   // SimpleVar   ExpTy transVar(Absyn.SimpleVar v) {      Entry x = (Entry)env.venv.get(v.name);      if (x instanceof VarEntry) { // controlla se e' una variabile         VarEntry ent = (VarEntry)x;         stampaDeb(v.pos,"SimpleVar: " + v.name + ": " + nomeClasse(ent.ty.actual()) + " isFor = " + ent.isFor);         // se non ci sono errori esegue Translate         if (env.errorMsg.num_error==0) {            // x.isFor serve per controllare se la variabile e' utilizzata            // come variabile di controlla all'interno di un ciclo for           return new ExpTy(trans.simpleVar(ent.access,level), ent.ty, ent.isFor);         }         else return new ExpTy(null,ent.ty);      }      else {         String out= "Variabile \"" + v.name + "\" indefinita";         env.errorMsg.error(v.pos, out);         return new ExpTy(null, INT);      }   }   // SubscriptVar   ExpTy transVar(Absyn.SubscriptVar v) {      Types.ARRAY temp=new Types.ARRAY(null);      boolean ok=true;      ExpTy i = transExp(v.index);      checkInt(i, v.index.pos); // l'exp tra [] deve essere intera      ExpTy vtemp = transVar(v.var); // analizza la variabile (ExpTy)      if(!(vtemp.ty.actual() instanceof Types.ARRAY)) {        env.errorMsg.error(v.pos, "Variabile di tipo ARRAY richiesta");        ok=false;      }      else {        // deve restituire il tipo degli elementi dell'array!        temp=(Types.ARRAY)vtemp.ty.actual();      }      stampaDeb(v.pos,"SubscriptVar: " + nomeClasse(temp.element));      if (ok) {         if (env.errorMsg.num_error==0) {            return new ExpTy(trans.subscriptVar(vtemp.exp,i.exp),temp.element);         }         else return new ExpTy(null,temp.element);      }      else return new ExpTy(null,INT);   }   // FieldVar   ExpTy transVar(Absyn.FieldVar v) {      Types.Type fieldtemp=INT;      boolean ok = false;      // usato per contare in che posizione si trova il campo      int fieldpos = -1;      ExpTy vtemp = transVar(v.var); // legge la variabile (ExpTy)      if (!(vtemp.ty.actual() instanceof Types.RECORD)) env.errorMsg.error(v.var.pos, "Variabile di tipo RECORD richiesta");      else {         // controlla, scorrendo il record, se esiste il campo         for (Types.RECORD temp=(Types.RECORD)vtemp.ty.actual(); temp !=null; temp=temp.tail) {             // incrementa la posizione del campo             fieldpos++;             if (v.field.toString().equals(temp.fieldName.toString())) {                ok = true;                fieldtemp = temp.fieldType.actual();                break;             }         }         if (!ok) env.errorMsg.error(v.var.pos, "Campo \"" + v.field.toString() +"\" del record indefinito");      }      if (env.errorMsg.num_error==0) {         return new ExpTy(trans.fieldVar(vtemp.exp,fieldpos),fieldtemp);      }      else return new ExpTy(null, fieldtemp);   }   /******************************    *         ESPRESSIONI        *    ******************************/   ExpTy transExp(Absyn.Exp e) {      if(e instanceof Absyn.LetExp) return transExp((Absyn.LetExp)e);      if(e instanceof Absyn.AssignExp) return transExp((Absyn.AssignExp)e);      if(e instanceof Absyn.OpExp) return transExp((Absyn.OpExp)e);      if(e instanceof Absyn.IfExp) return transExp((Absyn.IfExp)e);      if(e instanceof Absyn.ForExp) return transExp((Absyn.ForExp)e);      if(e instanceof Absyn.WhileExp) return transExp((Absyn.WhileExp)e);      if(e instanceof Absyn.NilExp) return transExp((Absyn.NilExp)e);      if(e instanceof Absyn.IntExp) return transExp((Absyn.IntExp)e);      if(e instanceof Absyn.StringExp) return transExp((Absyn.StringExp)e);      if(e instanceof Absyn.BreakExp) return transExp((Absyn.BreakExp)e);      if(e instanceof Absyn.CallExp) return transExp((Absyn.CallExp)e);      if(e instanceof Absyn.RecordExp) return transExp((Absyn.RecordExp)e);      if(e instanceof Absyn.VarExp) return transExp((Absyn.VarExp)e);      if(e instanceof Absyn.SeqExp) return transExp((Absyn.SeqExp)e);      if(e instanceof Absyn.ArrayExp) return transExp((Absyn.ArrayExp)e);      throw new Error("transExp: " + e);  // mantenere ???.   }   // LetExp   ExpTy transExp(Absyn.LetExp e) {      if(debflag==1) System.out.println(""); // per lasciare una riga di spazio      stampaDeb(e.pos,"Inizio costrutto LET ... IN ... END\n");      // utilizzato per mantenere la lista delle dichiarazioni      Vector decs = new Vector();      env.venv.beginScope();      env.tenv.beginScope();      for(Absyn.DecList p=e.decs; p!=null; p=p.tail) { decs.addElement(transDec(p.head)); }      ExpTy et = transExp(e.body);      //  prima di chiudere lo scope stampa gli ambienti (in mod. debug)      if ((debflag == 1) && (env.errorMsg.num_error == 0)) {         System.out.println("\n\n*****  Stampa degli ambienti (in uscita dallo 'scope' attuale)  *****");         stampaTenv();         stampaVenv();      }      env.venv.endScope();      env.tenv.endScope();      stampaDeb(e.pos,"Fine costrutto LET ... IN ... END\n");      if (env.errorMsg.num_error==0) {         return new ExpTy(trans.letExp(decs,et.exp), et.ty);      }      else return new ExpTy(null, et.ty);   }   // AssignExp   ExpTy transExp(Absyn.AssignExp e) {      ExpTy vt = transVar(e.var);      ExpTy et = transExp(e.exp);      // controlla se i due tipi coincidono      if (!(vt.ty.actual()==et.ty.actual())) {         // caso RECORD ---> NIL         if (!((vt.ty.actual() instanceof Types.RECORD)&&(et.ty.actual()==NIL))) {            String out="Non puoi assegnare alla var. di tipo \"" + nomeClasse(vt.ty.actual()) + "\" il tipo \"" + nomeClasse(et.ty.actual())+ "\"";           env.errorMsg.error(e.pos, out);         }      }      // bisogna evitare che la variabile di controllo di un ciclo for      // vegna assegnata nel corpo del ciclo stesso.      if (vt.isFor) {         Absyn.SimpleVar v=(Absyn.SimpleVar)e.var;         String out="La variabile \"" + v.name + "\" non puo' essere assegnata nel corpo del ciclo FOR.";         env.errorMsg.error(v.pos+1, out);      }      // restituisce un tipo VOID. (cosi' (a:=b)+c e' illegale!)      if (env.errorMsg.num_error==0) {         stampaDeb(e.pos,"AssignExp: "  + nomeClasse(vt.ty.actual()) + ":=" + nomeClasse(et.ty.actual()) );         return new ExpTy(trans.assignExp(vt.exp, et.exp), VOID);      }      else return new ExpTy(null, VOID);   }   // OpExp   ExpTy transExp(Absyn.OpExp e) {    ExpTy left=transExp(e.left);    ExpTy right=transExp(e.right);    switch(e.oper) {    // Plus, Minus, Mul, Div    case Absyn.OpExp.PLUS: case Absyn.OpExp.MINUS: case Absyn.OpExp.MUL: case Absyn.OpExp.DIV:       {          checkInt(left, e.left.pos);        checkInt(right, e.right.pos);        if(env.errorMsg.num_error==0) {           return new ExpTy( trans.opExp(e.oper,                          left.exp,                          right.exp,                          ((left.ty.actual() instanceof Types.STRING)&&(right.ty.actual() instanceof Types.STRING))                          ),                     INT               );        }        else return new ExpTy(null, INT );       }    // EQ, NE    case Absyn.OpExp.EQ: case Absyn.OpExp.NE:       {        checkEq(e.pos,left,right,"=");        if(env.errorMsg.num_error==0) {           return new ExpTy( trans.opExp(e.oper,                          left.exp,                          right.exp,                          ((left.ty.actual() instanceof Types.STRING)&&(right.ty.actual() instanceof Types.STRING))                          ),                     INT               );        }        else return new ExpTy(null, INT );       }    // LT,LE,GT,GE    case Absyn.OpExp.LT: case Absyn.OpExp.LE: case Absyn.OpExp.GT: case Absyn.OpExp.GE:       {        checkComp(e.pos,left,right,"<");        if(env.errorMsg.num_error==0) {           return new ExpTy( trans.opExp(e.oper,                          left.exp,                          right.exp,                          ((left.ty.actual() instanceof Types.STRING)&&(right.ty.actual() instanceof Types.STRING))                          ),                     INT               );        }        else return new ExpTy(null, INT );       }    }    throw new Error("OpExp");  // mantenere ???   }   // ForExp   ExpTy transExp(Absyn.ForExp e) {      // crea una nuova etichetta e la salva in old_done      // il valore di current_done.      Temp.Label new_done = new Temp.Label();      Temp.Label old_done = current_done;      // aggiorna current_done alla nuova etichetta      current_done = new_done;      // incrementa il contatore dei cicli      loopDepth++;      env.venv.beginScope();      Absyn.VarDec lo=(Absyn.VarDec)e.var;      // controlla "lo"      ExpTy loexp = transExp(lo.init);      // memorizza l'accesso alla variabile      Translate.Access acc = level.allocLocal(lo.escape);      env.venv.put(lo.name, new VarEntry(acc,loexp.ty,true));      if (!(loexp.ty==INT)) {         env.errorMsg.error(e.var.pos,"La variabile di controllo del ciclo FOR deve essere di tipo INT");      }      // controlla "hi"      ExpTy hiexp = transExp(e.hi);      if (!(hiexp.ty==INT)) env.errorMsg.error(e.hi.pos,"Exp di uscita ciclo FOR deve essere di tipo INT");      // processa il corpo e ripristina il valore precedente di current_done      ExpTy et = transExp(e.body);      current_done = old_done;      // controlla che il corpo della FOR abbia Tipo restituito VOID      if (!(et.ty==VOID)) {         env.errorMsg.error(e.body.pos,"Il corpo della FOR deve essere ti tipo VOID");      }      env.venv.endScope();      // decrementa il contatore dei cicli      loopDepth--;      if (env.errorMsg.num_error==0) {         stampaDeb(e.pos,"ForExp: Frame/Livello = " + level.frame.name );         return new ExpTy(trans.forExp(acc,level,loexp.exp,hiexp.exp,et.exp,new_done),et.ty);      }      return new ExpTy(null,et.ty);   }   // IfExp   ExpTy transExp(Absyn.IfExp e) {      ExpTy elsec=null;      // controlla il tipo della exp di test ...      ExpTy check=transExp(e.test);      if (!(check.ty==INT)) env.errorMsg.error(e.test.pos,"Il test dell'IF deve essere di tipo INT");      ExpTy thenc = transExp(e.thenclause);      String out = "IfExp: " + nomeClasse(check.ty.actual()) + " then " + nomeClasse(thenc.ty.actual());      // controlla il tipo di then ed else (deve essere lo stesso)      if (e.elseclause != null) {         elsec = transExp(e.elseclause);         out = out + " else " + nomeClasse(elsec.ty.actual());         // ricava i tipi del then e dell'else         if (!(thenc.ty.actual()==elsec.ty.actual())) {            if (!( ((thenc.ty.actual() instanceof Types.RECORD) && (elsec.ty.actual()==NIL)) ||               ((thenc.ty.actual()==NIL) && (elsec.ty.actual() instanceof Types.RECORD)) )) {               String err="Tipo then \"" + nomeClasse(thenc.ty.actual()) + "\" diverso dal tipo else \"" + nomeClasse(elsec.ty.actual())+ "\"";               env.errorMsg.error(e.elseclause.pos,err);            }         }      }      else { // se e' della forma corta (if-then)         // controlla che l'if-then abbia Tipo restituito VOID         if (!(thenc.ty==VOID)) {            env.errorMsg.error(e.thenclause.pos,"If-then deve avere tipo VOID");         }         else {            if (env.errorMsg.num_error==0) {               return new ExpTy(trans.ifExp(check.exp,thenc.exp,trans.nullInstr()), thenc.ty);            }            else return new ExpTy(null, thenc.ty);         }

⌨️ 快捷键说明

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