diff options
Diffstat (limited to 'src/minijava/symboltable')
-rw-r--r-- | src/minijava/symboltable/MClass.java | 47 | ||||
-rw-r--r-- | src/minijava/symboltable/MClasses.java | 64 | ||||
-rw-r--r-- | src/minijava/symboltable/MExpression.java | 87 | ||||
-rw-r--r-- | src/minijava/symboltable/MIdentifier.java | 2 | ||||
-rw-r--r-- | src/minijava/symboltable/MMethod.java | 71 | ||||
-rw-r--r-- | src/minijava/symboltable/MPrimaryExpr.java | 44 | ||||
-rw-r--r-- | src/minijava/symboltable/MStatement.java | 84 | ||||
-rw-r--r-- | src/minijava/symboltable/MStatementList.java | 7 |
8 files changed, 397 insertions, 9 deletions
diff --git a/src/minijava/symboltable/MClass.java b/src/minijava/symboltable/MClass.java index 37bfcfb..10354a8 100644 --- a/src/minijava/symboltable/MClass.java +++ b/src/minijava/symboltable/MClass.java @@ -6,9 +6,11 @@ package minijava.symboltable; import minijava.typecheck.PrintError; public class MClass extends MLocalVarType { - public MClasses all_classes; // 所有类的列表 + public MClasses all_classes; // 所有类的列表,在建立符号表时完成 public boolean isDeclared = false; // 是否已声明,用于检查符号表 - public String extend_class_name = null; // 所继承的类 + public String extend_class_name = null; // 所继承的类名 + public MClass extend_class = null; // 所继承的类,在符号表建立完成后才能求得 + public int extend_tag = 0; // 检测循环继承时用,0表示未检测 public MMethodList methods; public MClass(String v_name, MClasses all, int m_line, int m_column) { @@ -36,9 +38,50 @@ public class MClass extends MLocalVarType { return "Method double declaration " + "\"" + method_name + "\"."; } methods.addMethod(method); + method.method_class = this; return null; } + // 检测类型名是否有效 + public boolean validType(String s_type) { + if (s_type==MIdentifier.intType + || s_type==MIdentifier.boolType + || s_type==MIdentifier.arrType + || s_type==MIdentifier.voidType + || s_type==MIdentifier.sArrayType) { + return true; + } + + if (all_classes.findClassByName(s_type)!=null) { + return true; + } + + return false; + } + + // 对类进行类型检查 + public boolean classVarCheck() { + boolean result = true; + for (int i=0; i<methods.size(); i++) { + result &= methods.methods.elementAt(i).validVars(); + } + return result; + } + + public boolean classFuncCheck() { + boolean result = true; + for (int i=0; i<methods.size(); i++) { + result &= methods.methods.elementAt(i).validFunc(); + } + return result; + } + + public void classStatementCheck() { + for (int i=0; i<methods.size(); i++) { + methods.methods.elementAt(i).checkStatements(); + } + } + // 调试输出: 打印该类的信息 public void printClass(int spaces) { String ps = OutputFormat.spaces(spaces); diff --git a/src/minijava/symboltable/MClasses.java b/src/minijava/symboltable/MClasses.java index 2df2ba8..10bd009 100644 --- a/src/minijava/symboltable/MClasses.java +++ b/src/minijava/symboltable/MClasses.java @@ -5,9 +5,20 @@ package minijava.symboltable; import java.util.Vector; +import minijava.typecheck.PrintError; + public class MClasses extends MType { public Vector<MClass> mj_classes = new Vector<MClass>(); // 用于存放类 + MClass findClassByName(String c_name) { + for (int i=0; i<mj_classes.size(); i++) { + if (mj_classes.elementAt(i).getName().equals(c_name)) { + return mj_classes.elementAt(i); + } + } + return null; + } + // 在表中插入类 public String InsertClass(MClass v_class) { String class_name = v_class.getName(); @@ -28,6 +39,59 @@ public class MClasses extends MType { return false; } + public void buildClassRelation() { + // 通过extend_class_name确定extend_class, 并查找循环继承 + for (int i=0; i<mj_classes.size(); i++) { + MClass m_class = mj_classes.elementAt(i); + String ext_name = m_class.extend_class_name; + if (ext_name!=null) { + m_class.extend_class = findClassByName(ext_name); + } + } + int tag = 1; // 扫描循环继承的标记 + for (int i=0; i<mj_classes.size(); i++) { + MClass m_class = mj_classes.elementAt(i); + if (m_class.extend_tag==0) { + m_class.extend_tag = tag; + while (m_class.extend_class!=null) { + m_class = m_class.extend_class; + if (m_class.extend_tag==tag) { // 循环继承 + PrintError.print(m_class.line, m_class.column, + "Circular extend in class"+m_class.name); + break; // error + } else if (m_class.extend_tag==0) { + m_class.extend_tag = tag; + } else { + break; // no error + } + } + tag++; + } + } + } + + public boolean checkAllVars() { + boolean result = true; + for (int i=0; i<mj_classes.size(); i++) { + result &= mj_classes.elementAt(i).classVarCheck(); + } + return result; + } + + public boolean checkAllFuncs() { + boolean result = true; + for (int i=0; i<mj_classes.size(); i++) { + result &= mj_classes.elementAt(i).classFuncCheck(); + } + return result; + } + + public void checkAllStatements() { + for (int i=0; i<mj_classes.size(); i++) { + mj_classes.elementAt(i).classStatementCheck(); + } + } + // 调试输出: 打印所有的类的信息 public void printClasses(int spaces) { for (int i=0; i<mj_classes.size(); i++) { diff --git a/src/minijava/symboltable/MExpression.java b/src/minijava/symboltable/MExpression.java index 17d6db8..4cf4724 100644 --- a/src/minijava/symboltable/MExpression.java +++ b/src/minijava/symboltable/MExpression.java @@ -1,5 +1,8 @@ package minijava.symboltable; +import minijava.syntaxtree.Identifier; +import minijava.typecheck.PrintError; + public class MExpression extends MType { public enum Operator { And, Smaller, Plus, Minus, Times, ArrayLookup, @@ -15,12 +18,90 @@ public class MExpression extends MType { // Expression value (for primary expression) public String e_val; - public MExpression(Operator op) { + public MExpression(int line, int column, Operator op) { + super(line, column); e_op = op; e_exp = new MPrimaryExpr(); e_list = new MExpressionList(); } + public String exprType(MMethod m) { + switch (e_op) { + case And: + if (first.exprType(m)==MIdentifier.boolType + && second.exprType(m)==MIdentifier.boolType) { + return MIdentifier.boolType; + } else { + PrintError.print(line, column, "Type mismatch"); + return null; + } + case ArrayLen: + if (first.exprType(m)==MIdentifier.arrType) { + return MIdentifier.intType; + } else { + PrintError.print(line, column, "Type mismatch"); + return null; + } + case ArrayLookup: + if (first.exprType(m)==MIdentifier.arrType + && second.exprType(m)==MIdentifier.intType) { + return MIdentifier.intType; + } else { + PrintError.print(line, column, "Type mismatch"); + return null; + } + case Smaller: + if (first.exprType(m)==MIdentifier.intType + && second.exprType(m)==MIdentifier.intType) { + return MIdentifier.boolType; + } else { + PrintError.print(line, column, "Type mismatch"); + return null; + } + case Plus: + case Minus: + case Times: + if (first.exprType(m)==MIdentifier.intType + && second.exprType(m)==MIdentifier.intType) { + return MIdentifier.intType; + } else { + PrintError.print(line, column, "Type mismatch"); + return null; + } + case MsgSend: + // expr.id(expr*) + String c_type = first.exprType(m); + MClass m_class = m.method_class.all_classes.findClassByName(c_type); + if (m_class==null) { + PrintError.print(line, column, "no class found in a message send expression"); + return null; + } + int idx = m_class.methods.findMethod(e_id.name); + if (idx==-1) { + PrintError.print(line, column, "method " + e_id.name + " not found"); + return null; + } + MMethod m_method = m_class.methods.methods.elementAt(idx); + if (e_list.size()!=m_method.paramList.size()) { + PrintError.print(line, column, "Method param size mismatch!"); + return null; + } + for (int i=0; i<e_list.size(); i++) { + String t1 = e_list.e_list.elementAt(i).exprType(m); + String t2 = m_method.paramList.varlist.elementAt(i).typename; + if (!t1.equals(t2)) { + PrintError.print(line, column, "Method param type mismatch!"); + return null; + } + } + return m_method.ret_type_name; + case Primary: + return e_exp.primExprType(m); + default: + return null; + } + } + public void printExpr(int spaces) { System.err.print(OutputFormat.spaces(spaces)); @@ -54,6 +135,10 @@ public class MExpression extends MType { second.printExpr(0); break; case ArrayLookup: + first.printExpr(0); + System.err.print("["); + second.printExpr(0); + System.err.print("]"); case ArrayLen: case MsgSend: } diff --git a/src/minijava/symboltable/MIdentifier.java b/src/minijava/symboltable/MIdentifier.java index 45340ac..5b3f88a 100644 --- a/src/minijava/symboltable/MIdentifier.java +++ b/src/minijava/symboltable/MIdentifier.java @@ -8,6 +8,8 @@ public class MIdentifier extends MType { public static final String arrType = "int[]"; public static final String intType = "int"; public static final String boolType = "boolean"; + public static final String voidType = "void"; + public static final String sArrayType = "String[]"; public MIdentifier(String v_name, int v_line, int v_column) { super(v_line, v_column); diff --git a/src/minijava/symboltable/MMethod.java b/src/minijava/symboltable/MMethod.java index 7f57a40..2d2dc24 100644 --- a/src/minijava/symboltable/MMethod.java +++ b/src/minijava/symboltable/MMethod.java @@ -1,9 +1,11 @@ package minijava.symboltable; +import minijava.typecheck.PrintError; + public class MMethod extends MLocalVarType { MVarList params; String ret_type_name; - MClass method_class; + public MClass method_class; MVarList paramList; public MStatementList statements; public MExpression ret_expr; @@ -37,6 +39,73 @@ public class MMethod extends MLocalVarType { return null; } + // 检测函数的返回类型,参数类型,局部变量类型是否为有效类型 + public boolean validVars() { + if (method_class.validType(ret_type_name)==false) { + PrintError.print(this.line, this.column, "Return type of method "+this.name+" invalid"); + return false; + } + + for (int i=0; i<paramList.size(); i++) { + MVariable p_var = paramList.varlist.elementAt(i); + if (method_class.validType(p_var.typename)==false) { + PrintError.print(p_var.line, p_var.column, "Type "+p_var.typename+" invalid"); + return false; + } + } + + for (int i=0; i<vars.size(); i++) { + MVariable m_var = vars.varlist.elementAt(i); + if (method_class.validType(m_var.typename)==false) { + PrintError.print(m_var.line, m_var.column, "Type "+m_var.typename+" invalid"); + return false; + } + } + + return true; + } + + // 检查方法自身是否复合方法覆盖条件 + public boolean validFunc() { + MClass m_class = method_class; + while (m_class.extend_class!=null) { + m_class = m_class.extend_class; + int idx = m_class.methods.findMethod(this.name); + if (idx!=-1) { + // 找到同名方法,检测是否能覆盖 + if (this.ret_type_name. + equals(m_class.methods.methods.elementAt(idx))==false) { + PrintError.print(line, column, "Method " + + this.name + " has type different from the one in its parent class"); + return false; + } + } + } + return true; + } + + // 从局部变量,参数表,类变量中查找变量 + public MVariable findVarByName(String s) { + int idx; + idx = vars.findVar(s); + if (idx!=-1) { + return vars.varlist.elementAt(idx); + } + idx = paramList.findVar(s); + if (idx!=-1) { + return paramList.varlist.elementAt(idx); + } + idx = method_class.vars.findVar(s); + if (idx!=-1) { + return method_class.vars.varlist.elementAt(idx); + } + return null; + } + + public void checkStatements() { + statements.checkStatements(this); + } + public void printMethod(int spaces) { String ps = OutputFormat.spaces(spaces); System.err.print(ps + this.ret_type_name + " " + this.name + "("); diff --git a/src/minijava/symboltable/MPrimaryExpr.java b/src/minijava/symboltable/MPrimaryExpr.java index ce4113c..ba233b5 100644 --- a/src/minijava/symboltable/MPrimaryExpr.java +++ b/src/minijava/symboltable/MPrimaryExpr.java @@ -1,5 +1,7 @@ package minijava.symboltable; +import minijava.typecheck.PrintError; + public class MPrimaryExpr extends MType { /** * f0 -> IntegerLiteral() @@ -35,6 +37,40 @@ public class MPrimaryExpr extends MType { } } + public String primExprType(MMethod m) { + switch (e_type) { + case Int: + return MIdentifier.intType; + case Alloc: + return e_id.getName(); + case ArrayAlloc: + return MIdentifier.arrType; + case Braket: + return e_exp.exprType(m); + case True: + case False: + return MIdentifier.boolType; + case Id: + MVariable m_var = m.findVarByName(e_id.name); + if (m_var!=null) { + return m_var.typename; + } else { + return null; + } + case Not: + if (e_exp.exprType(m)==MIdentifier.boolType) { + return MIdentifier.boolType; + } else { + PrintError.print(getLine(), getColumn(), "A non boolean expr after '!' operator"); + return null; + } + case This: + return m.method_class.name; + default: + return null; + } + } + public void printPrimExpr(int spaces) { System.err.print(OutputFormat.spaces(spaces)); @@ -49,6 +85,14 @@ public class MPrimaryExpr extends MType { case Id: System.err.print(e_id.getName()); break; + case Alloc: + System.err.print("new "+e_id.getName()+"()"); + break; + case ArrayAlloc: + System.err.print("new int["); + e_exp.printExpr(0); + System.err.print("]"); + break; } } } diff --git a/src/minijava/symboltable/MStatement.java b/src/minijava/symboltable/MStatement.java index 6410ca0..3610719 100644 --- a/src/minijava/symboltable/MStatement.java +++ b/src/minijava/symboltable/MStatement.java @@ -1,5 +1,7 @@ package minijava.symboltable; +import minijava.typecheck.PrintError; + public class MStatement extends MType { public enum Keyword { Block, Assign, ArrAssign, If, While, Print; @@ -10,7 +12,8 @@ public class MStatement extends MType { public MExpression e_first, e_second; // for assign(e_first), array assign, if, while, print public MStatement s_first, s_second; // for if, while - public MStatement(Keyword keyw) { + public MStatement(int s_line, int s_column, Keyword keyw) { + super(s_line, s_column); s_type = keyw; s_list = null; s_id = null; @@ -18,6 +21,63 @@ public class MStatement extends MType { s_first = s_second = null; } + public void checkStatement(MMethod m) { + switch (s_type) { + case ArrAssign: + // id[expr] = expr + if (m.findVarByName(s_id.name).typename==MIdentifier.arrType + && e_first.exprType(m)==MIdentifier.intType + && e_second.exprType(m)==MIdentifier.intType) { + return; + } else { + PrintError.print(line, column, "type mismatch in array assign statement"); + } + break; + case Assign: + // id = expr + MVariable m_var = m.findVarByName(s_id.name); + if (m_var==null) { + PrintError.print(line, column, "variable "+s_id.name+" not exist!"); + return; + } else if (m_var.typename.equals(e_first.exprType(m))) { + return; + } else { + PrintError.print(line, column, "type mismatch in assign statement"); + } + break; + case Block: + s_list.checkStatements(m); + break; + case If: + if (e_first.exprType(m)==MIdentifier.boolType) { + s_first.checkStatement(m); + s_second.checkStatement(m); + } else { + PrintError.print(line, column, "invalid type in if statement."); + } + break; + case Print: + if (e_first.exprType(m)!=null) { + return; + } else { + PrintError.print(line, column, "Invalid type in print statement"); + } + break; + case While: + // while (expr) state + if (e_first.exprType(m)==MIdentifier.boolType) { + s_first.checkStatement(m); + } else { + PrintError.print(line, column, "invalid type in while statement."); + } + break; + default: + break; + + } + + } + public void printStatement(int spaces) { String sp = OutputFormat.spaces(spaces); @@ -31,17 +91,31 @@ public class MStatement extends MType { System.err.println(")"); break; case ArrAssign: - System.err.println(sp+"[]="); + System.err.println(sp+"[]= ("+s_id.getName()+") ("); + e_first.printExpr(0); + System.err.print(") ("); + e_second.printExpr(0); + System.err.println(")"); break; case If: - System.err.println(sp+"if"); + System.err.println(sp+"if ("); + e_first.printExpr(0); + System.err.println(")"); + s_first.printStatement(spaces+2); + s_second.printStatement(spaces+2); break; case While: - System.err.println(sp+"while"); + System.err.println(sp+"while ("); + e_first.printExpr(0); + System.err.println(")"); + s_first.printStatement(spaces+2); break; case Print: - System.err.println(sp+"print"); + System.err.println(sp+"print ("); + e_first.printExpr(0); + System.err.println(")"); break; } } + } diff --git a/src/minijava/symboltable/MStatementList.java b/src/minijava/symboltable/MStatementList.java index 034bc8b..3cb3b02 100644 --- a/src/minijava/symboltable/MStatementList.java +++ b/src/minijava/symboltable/MStatementList.java @@ -23,4 +23,11 @@ public class MStatementList extends MType { s_list.elementAt(i).printStatement(spaces); } } + + public void checkStatements(MMethod m) { + for (int i=0; i<s_list.size(); i++) { + s_list.elementAt(i).checkStatement(m); + } + } + } |