From 92f91d3e9bce1aaf581baa9339744266d7eb0c1a Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Mon, 13 Oct 2014 07:34:34 +0800 Subject: final version --- src/minijava/symboltable/MClasses.java | 3 +++ src/minijava/symboltable/MExpression.java | 17 +++++++++++- src/minijava/symboltable/MMethod.java | 33 +++++++++++++++++++---- src/minijava/symboltable/MPrimaryExpr.java | 4 +++ src/minijava/symboltable/MStatement.java | 22 ++++++++++++--- src/minijava/typecheck/Main.java | 2 ++ src/minijava/typecheck/PrintError.java | 10 ++++++- src/minijava/visitor/BuildSymbolTableVisitor.java | 20 ++++++++------ 8 files changed, 93 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/minijava/symboltable/MClasses.java b/src/minijava/symboltable/MClasses.java index 10bd009..34601a5 100644 --- a/src/minijava/symboltable/MClasses.java +++ b/src/minijava/symboltable/MClasses.java @@ -46,6 +46,9 @@ public class MClasses extends MType { String ext_name = m_class.extend_class_name; if (ext_name!=null) { m_class.extend_class = findClassByName(ext_name); + if (m_class.extend_class==null) { + PrintError.print(m_class.line, m_class.column, "Extend class not exist!"); + } } } int tag = 1; // 扫描循环继承的标记 diff --git a/src/minijava/symboltable/MExpression.java b/src/minijava/symboltable/MExpression.java index 4cf4724..a5dc0ba 100644 --- a/src/minijava/symboltable/MExpression.java +++ b/src/minijava/symboltable/MExpression.java @@ -76,7 +76,15 @@ public class MExpression extends MType { PrintError.print(line, column, "no class found in a message send expression"); return null; } - int idx = m_class.methods.findMethod(e_id.name); + int idx=-1; + while (m_class!=null) { + idx = m_class.methods.findMethod(e_id.name); + if (idx==-1) { + m_class = m_class.extend_class; // 本类无该方法,从父类继续找 + } else { + break; + } + } if (idx==-1) { PrintError.print(line, column, "method " + e_id.name + " not found"); return null; @@ -141,6 +149,13 @@ public class MExpression extends MType { System.err.print("]"); case ArrayLen: case MsgSend: + first.printExpr(0); + System.err.print("."+e_id.name+"("); + for (int i=0; i0) System.err.print(","); + e_list.e_list.elementAt(i).printExpr(0); + } + System.err.print(")"); } } } diff --git a/src/minijava/symboltable/MMethod.java b/src/minijava/symboltable/MMethod.java index 2d2dc24..9e770a3 100644 --- a/src/minijava/symboltable/MMethod.java +++ b/src/minijava/symboltable/MMethod.java @@ -4,7 +4,7 @@ import minijava.typecheck.PrintError; public class MMethod extends MLocalVarType { MVarList params; - String ret_type_name; + public String ret_type_name; public MClass method_class; MVarList paramList; public MStatementList statements; @@ -74,9 +74,10 @@ public class MMethod extends MLocalVarType { if (idx!=-1) { // 找到同名方法,检测是否能覆盖 if (this.ret_type_name. - equals(m_class.methods.methods.elementAt(idx))==false) { + equals(m_class.methods.methods.elementAt(idx).ret_type_name)==false) { PrintError.print(line, column, "Method " + - this.name + " has type different from the one in its parent class"); + this.name + " has type different from the one in its parent class " + + m_class.name); return false; } } @@ -95,15 +96,37 @@ public class MMethod extends MLocalVarType { if (idx!=-1) { return paramList.varlist.elementAt(idx); } - idx = method_class.vars.findVar(s); + MClass m_class = method_class; + idx = m_class.vars.findVar(s); + while (idx==-1 && m_class.extend_class!=null) { + // 在父类继续查找 + m_class = m_class.extend_class; + idx = m_class.vars.findVar(s); + } if (idx!=-1) { - return method_class.vars.varlist.elementAt(idx); + return m_class.vars.varlist.elementAt(idx); } return null; } public void checkStatements() { statements.checkStatements(this); + // 检查返回类型是否和返回值匹配 + if (ret_type_name==MIdentifier.voidType && ret_expr==null) { + // ok + } else if (!ret_type_name.equals(ret_expr.exprType(this))) { + MClasses all = this.method_class.all_classes; + MClass t1 = all.findClassByName(ret_type_name); + MClass t2 = all.findClassByName(ret_expr.exprType(this)); + if (t1!=null) { + while (t2!=null && t2!=t1) { + t2 = t2.extend_class; + } + } + if (t1!=t2) { + PrintError.print(line, column, "return expression and return type mismatch!"); + } + } } public void printMethod(int spaces) { diff --git a/src/minijava/symboltable/MPrimaryExpr.java b/src/minijava/symboltable/MPrimaryExpr.java index ba233b5..246ac93 100644 --- a/src/minijava/symboltable/MPrimaryExpr.java +++ b/src/minijava/symboltable/MPrimaryExpr.java @@ -44,6 +44,10 @@ public class MPrimaryExpr extends MType { case Alloc: return e_id.getName(); case ArrayAlloc: + if (e_exp.exprType(m)!=MIdentifier.intType) { + PrintError.print(getLine(), getColumn(), "wrong type of expression in array alloc"); + return null; + } return MIdentifier.arrType; case Braket: return e_exp.exprType(m); diff --git a/src/minijava/symboltable/MStatement.java b/src/minijava/symboltable/MStatement.java index 3610719..5169097 100644 --- a/src/minijava/symboltable/MStatement.java +++ b/src/minijava/symboltable/MStatement.java @@ -36,13 +36,29 @@ public class MStatement extends MType { case Assign: // id = expr MVariable m_var = m.findVarByName(s_id.name); + String expr_type = e_first.exprType(m); + //System.err.println(s_id.name + " " + expr_type); 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))) { + } else if (m_var.typename.equals(expr_type)) { return; } else { - PrintError.print(line, column, "type mismatch in assign statement"); + MClasses all = m.method_class.all_classes; + MClass id_class = all.findClassByName(m_var.typename); + MClass expr_class = all.findClassByName(expr_type); + if (id_class==null) { // id本身不是类 + PrintError.print(line, column, "type mismatch in assign statement"); + return; + } + while (expr_class!=id_class && expr_class!=null) { // 从expr的类找父类 + expr_class = expr_class.extend_class; + } + if (expr_class!=id_class) { + PrintError.print(line, column, "type mismatch in assign statement"); + } else { + return; + } } break; case Block: @@ -57,7 +73,7 @@ public class MStatement extends MType { } break; case Print: - if (e_first.exprType(m)!=null) { + if (e_first.exprType(m)==MIdentifier.intType) { return; } else { PrintError.print(line, column, "Invalid type in print statement"); diff --git a/src/minijava/typecheck/Main.java b/src/minijava/typecheck/Main.java index 1c069ba..0dbc2d8 100644 --- a/src/minijava/typecheck/Main.java +++ b/src/minijava/typecheck/Main.java @@ -43,6 +43,8 @@ public class Main { // 打印错误信息 PrintError.printAll(); + + PrintError.outputResult(); } catch (TokenMgrError e) { // Handle Lexical Errors diff --git a/src/minijava/typecheck/PrintError.java b/src/minijava/typecheck/PrintError.java index a5a5157..24754f9 100644 --- a/src/minijava/typecheck/PrintError.java +++ b/src/minijava/typecheck/PrintError.java @@ -17,7 +17,15 @@ public class PrintError { public static void printAll() { int sz = errors.size(); for (int i = 0; i < sz; i++) { - System.out.println(errors.elementAt(i)); + System.err.println(errors.elementAt(i)); + } + } + + public static void outputResult() { + if (errors.size()>0) { + System.out.println("Type error"); + } else { + System.out.println("Program type checked successfully"); } } } diff --git a/src/minijava/visitor/BuildSymbolTableVisitor.java b/src/minijava/visitor/BuildSymbolTableVisitor.java index c99d0ab..4de3383 100644 --- a/src/minijava/visitor/BuildSymbolTableVisitor.java +++ b/src/minijava/visitor/BuildSymbolTableVisitor.java @@ -112,6 +112,7 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { // 往main class中添加main方法 MMethod main_method = new MMethod("main", MIdentifier.voidType, n.f6.beginLine, n.f6.beginColumn); + //main_method.ret_type_name = MIdentifier.voidType; MIdentifier argid = (MIdentifier) n.f11.accept(this, null); MVariable param = new MVariable(argid.getName(), MIdentifier.sArrayType, argid.getLine(), argid.getColumn()); @@ -627,10 +628,12 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f1 -> ( ExpressionRest() )* */ public MType visit(ExpressionList n, MType argu) { - MType _ret=null; - n.f0.accept(this, argu); - n.f1.accept(this, argu); - return _ret; + if (argu!=null) { + MExpressionList m_elist = (MExpressionList)argu; + m_elist.add_expr((MExpression)n.f0.accept(this,null)); + n.f1.accept(this, m_elist); + } + return null; } /** @@ -638,10 +641,11 @@ public class BuildSymbolTableVisitor extends GJDepthFirst { * f1 -> Expression() */ public MType visit(ExpressionRest n, MType argu) { - MType _ret=null; - n.f0.accept(this, argu); - n.f1.accept(this, argu); - return _ret; + if (argu!=null) { + MExpressionList m_elist = (MExpressionList)argu; + m_elist.add_expr((MExpression)n.f1.accept(this,null)); + } + return null; } /** -- cgit v1.2.3